diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index 40b0f4a0..86648edc 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -3,6 +3,8 @@ description: Report a reproducible bug labels: - requires triage - bug +title: "bug: " +type: "Bug" body: - type: markdown attributes: diff --git a/.github/ISSUE_TEMPLATE/documentation-issue.yml b/.github/ISSUE_TEMPLATE/documentation-issue.yml index 53e74a4f..cb663555 100644 --- a/.github/ISSUE_TEMPLATE/documentation-issue.yml +++ b/.github/ISSUE_TEMPLATE/documentation-issue.yml @@ -3,6 +3,8 @@ description: Documentation is unclear or otherwise insufficient. labels: - requires triage - documentation +title: "docs: " +type: "Documentation" body: - type: markdown attributes: diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml index c0ec58c2..6752cd11 100644 --- a/.github/ISSUE_TEMPLATE/feature-request.yml +++ b/.github/ISSUE_TEMPLATE/feature-request.yml @@ -3,6 +3,8 @@ description: Suggest an new idea for this project labels: - requires triage - new feature +title: "feat: " +type: "Feature" body: - type: markdown attributes: diff --git a/.gitignore b/.gitignore index 8eda1fd0..3dfe5583 100644 --- a/.gitignore +++ b/.gitignore @@ -14,8 +14,10 @@ node_modules /.vitepress/.cache /test/.models /test/temp +/test/.temp /temp /coverage +/test-runner-profile /llama/compile_commands.json /llama/llama.cpp diff --git a/.vitepress/config.ts b/.vitepress/config.ts index 46a66c45..f3b7fab2 100644 --- a/.vitepress/config.ts +++ b/.vitepress/config.ts @@ -470,8 +470,6 @@ export default defineConfig({ } }, sidebar: { - "/api/": getApiReferenceSidebar(), - "/guide/": [{ text: "Guide", base: "/guide", @@ -550,7 +548,9 @@ export default defineConfig({ ] } ] - }] + }], + + "/api/": getApiReferenceSidebar() }, socialLinks: [ {icon: "npm", link: "https://www.npmjs.com/package/node-llama-cpp"}, diff --git a/docs/cli/pull.md b/docs/cli/pull.md index 80157308..25cfd51d 100644 --- a/docs/cli/pull.md +++ b/docs/cli/pull.md @@ -20,7 +20,7 @@ If a file already exists and its size matches the expected size, it will not be The supported URI schemes are: - **HTTP:** `https://`, `http://` -- **Hugging Face:** `hf:/:` (`#` is optional, [but recommended](../guide/downloading-models.md#hf-scheme-specify-quant)) +- **Hugging Face:** `hf:/:` (`:` is optional, [but recommended](../guide/downloading-models.md#hf-scheme-specify-quant)) - **Hugging Face:** `hf://#` (`#` is optional) Learn more about using model URIs in the [Downloading Models guide](../guide/downloading-models.md#model-uris). diff --git a/docs/guide/CUDA.md b/docs/guide/CUDA.md index 07ee283d..07e1baa9 100644 --- a/docs/guide/CUDA.md +++ b/docs/guide/CUDA.md @@ -114,6 +114,33 @@ set NODE_LLAMA_CPP_CMAKE_OPTION_CMAKE_GENERATOR_TOOLSET=%CUDA_PATH% Then run the build command again to check whether setting the `CMAKE_GENERATOR_TOOLSET` cmake option fixed the issue. +### Fix the `forward compatibility was attempted on non supported HW` Error {#fix-cuda-forward-compatibility} +This error usually happens when the CUDA version you have installed on your machine is older than the CUDA version used in the prebuilt binaries supplied by `node-llama-cpp`. + +To resolve this issue, you can either [update your CUDA installation](https://developer.nvidia.com/cuda-downloads) to the latest version (recommended) or [build `node-llama-cpp` on your machine](#building) against the CUDA version you have installed. + +### Fix the `Binary GPU type mismatch. Expected: cuda, got: false` Error {#fix-cuda-gpu-type-mismatch} +This error usually happens when you have multiple conflicting CUDA versions installed on your machine. + +To fix it, uninstall older CUDA versions and restart your machine (important). + +:::: details Check which CUDA libraries are picked up by `node-llama-cpp`'s prebuilt binaries on your machine + +Run this command inside of your project: + +::: code-group +```shell [Linux] +ldd ./node_modules/@node-llama-cpp/linux-x64-cuda/bins/linux-x64-cuda/libggml-cuda.so +``` + +```cmd [Windows] +"C:\Program Files\Git\usr\bin\ldd.exe" node_modules\@node-llama-cpp\win-x64-cuda\bins\win-x64-cuda\ggml-cuda.dll +``` +::: + +:::: + + ## Using `node-llama-cpp` With CUDA It's recommended to use [`getLlama`](../api/functions/getLlama) without specifying a GPU type, so it'll detect the available GPU types and use the best one automatically. diff --git a/docs/guide/awesome.md b/docs/guide/awesome.md index d9ce458d..c290928c 100644 --- a/docs/guide/awesome.md +++ b/docs/guide/awesome.md @@ -2,17 +2,32 @@ description: Awesome projects that use node-llama-cpp --- # Awesome `node-llama-cpp` -Awesome projects that use `node-llama-cpp`. +:sunglasses: Awesome projects that use `node-llama-cpp`. + + ## Open Source * [CatAI](https://github.com/withcatai/catai) - a simplified AI assistant API for Node.js, with REST API support +
+ +* [Manzoni](https://manzoni.app/) ([GitHub](https://github.com/gems-platforms/manzoni-app)) - a text editor running local LLMs +
+ ## Proprietary -> List your project here! +* [BashBuddy](https://bashbuddy.run) ([GitHub](https://github.com/wosherco/bashbuddy)) - write bash commands with natural language +
+ +* [nutshell](https://withnutshell.com) - Private AI meeting notes processed completely on your device +
--- +> To add a project to this list, [open a PR](https://github.com/withcatai/node-llama-cpp/edit/master/docs/guide/awesome.md). +> > To have a project listed here, it should clearly state that it uses `node-llama-cpp`. diff --git a/docs/guide/chat-session.md b/docs/guide/chat-session.md index a9c77e98..992a6487 100644 --- a/docs/guide/chat-session.md +++ b/docs/guide/chat-session.md @@ -446,6 +446,87 @@ console.log("AI: " + a2); ``` ::: +:::: details Saving and restoring a context sequence evaluation state {#save-and-restore-with-context-sequence-state} +You can also save and restore the context sequence evaluation state to avoid re-evaluating the chat history +when you load it on a new context sequence. + +Please note that context sequence state files can get very large (109MB for only 1K tokens). +Using this feature is only recommended when the chat history is very long and you plan to load it often, +or when the evaluation is too slow due to hardware limitations. + +::: warning +When loading a context sequence state from a file, +always ensure that the model used to create the context sequence is exactly the same as the one used to save the state file. + +Loading a state file created from a different model can crash the process, +thus you have to pass `{acceptRisk: true}` to the [`loadStateFromFile`](../api/classes/LlamaContextSequence.md#loadstatefromfile) method to use it. + +Use with caution. +::: + +::: code-group +```typescript [Save chat history and context sequence state] +import {fileURLToPath} from "url"; +import path from "path"; +import fs from "fs/promises"; +import {getLlama, LlamaChatSession} from "node-llama-cpp"; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +const llama = await getLlama(); +const model = await llama.loadModel({ + modelPath: path.join(__dirname, "models", "Meta-Llama-3.1-8B-Instruct.Q4_K_M.gguf") +}); +const context = await model.createContext(); +const contextSequence = context.getSequence(); +const session = new LlamaChatSession({contextSequence}); + + +const q1 = "Hi there, how are you?"; +console.log("User: " + q1); + +const a1 = await session.prompt(q1); +console.log("AI: " + a1); + +const chatHistory = session.getChatHistory();// [!code highlight] +await Promise.all([// [!code highlight] + contextSequence.saveStateToFile("state.bin"),// [!code highlight] + fs.writeFile("chatHistory.json", JSON.stringify(chatHistory), "utf8")// [!code highlight] +]);// [!code highlight] +``` +::: + +::: code-group +```typescript [Restore chat history and context sequence state] +import {fileURLToPath} from "url"; +import path from "path"; +import fs from "fs/promises"; +import {getLlama, LlamaChatSession} from "node-llama-cpp"; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +// ---cut--- +const llama = await getLlama(); +const model = await llama.loadModel({ + modelPath: path.join(__dirname, "models", "Meta-Llama-3.1-8B-Instruct.Q4_K_M.gguf") +}); +const context = await model.createContext(); +const contextSequence = context.getSequence(); +const session = new LlamaChatSession({contextSequence}); + +await contextSequence.loadStateFromFile("state.bin", {acceptRisk: true});// [!code highlight] +const chatHistory = JSON.parse(await fs.readFile("chatHistory.json", "utf8"));// [!code highlight] +session.setChatHistory(chatHistory);// [!code highlight] + +const q2 = "Summarize what you said"; +console.log("User: " + q2); + +const a2 = await session.prompt(q2); +console.log("AI: " + a2); +``` +::: + +:::: + ## Prompt Without Updating Chat History {#prompt-without-updating-chat-history} Prompt without saving the prompt to the chat history. diff --git a/docs/guide/cmakeOptions.data.ts b/docs/guide/cmakeOptions.data.ts index badf286e..ff46c11e 100644 --- a/docs/guide/cmakeOptions.data.ts +++ b/docs/guide/cmakeOptions.data.ts @@ -90,6 +90,12 @@ function parseCmakeOptions(cmakeListsTxt: string, optionFilter: ((key: string) = } } else if (option.defaultValue === "${BUILD_SHARED_LIBS_DEFAULT}") option.defaultValue = htmlEscapeWithCodeMarkdown("`OFF` on MinGW, `ON` otherwise"); + else if (option.defaultValue === "${GGML_CUDA_GRAPHS_DEFAULT}") + option.defaultValue = htmlEscapeWithCodeMarkdown("`ON`"); + else if (option.defaultValue === "${GGML_NATIVE_DEFAULT}") + option.defaultValue = htmlEscapeWithCodeMarkdown("`OFF` when building for a different architecture,\n`ON` otherwise"); + else if (option.key === "LLAMA_CURL") + option.defaultValue = htmlEscapeWithCodeMarkdown("`OFF`"); else option.defaultValue = htmlEscapeWithCodeMarkdown( option.defaultValue != null diff --git a/docs/guide/downloading-models.md b/docs/guide/downloading-models.md index 7982e1c6..2a930d3d 100644 --- a/docs/guide/downloading-models.md +++ b/docs/guide/downloading-models.md @@ -76,7 +76,7 @@ You can reference models using a URI instead of their full download URL when usi When downloading a model from a URI, the model files will be prefixed with a corresponding adaptation of the URI. To reference a model from Hugging Face, you can use one of these schemes: -* `hf:/:` (`#` is optional, [but recommended](#hf-scheme-specify-quant)) +* `hf:/:` (`:` is optional, [but recommended](#hf-scheme-specify-quant)) * `hf://#` (`#` is optional) Here are example usages of the Hugging Face URI scheme: diff --git a/docs/guide/index.md b/docs/guide/index.md index 7f7eb6f0..b157e2e8 100644 --- a/docs/guide/index.md +++ b/docs/guide/index.md @@ -316,4 +316,5 @@ Explore the [API reference](../api/functions/getLlama.md) to learn more about th and use the search bar (press /) to find documentation for a specific topic or API. Check out the [roadmap](https://github.com/orgs/withcatai/projects/1) to see what's coming next,
+visit the [awesome list](./awesome.md) to find great projects that use `node-llama-cpp`,
and consider [sponsoring `node-llama-cpp`](https://github.com/sponsors/giladgd) to accelerate the development of new features. diff --git a/docs/guide/low-level-api.md b/docs/guide/low-level-api.md index bf478af1..48a53ab5 100644 --- a/docs/guide/low-level-api.md +++ b/docs/guide/low-level-api.md @@ -391,3 +391,85 @@ console.log( newTokens ); ``` + +### Save and Restore State {#save-and-restore-state} +You can save the evaluation state of a context sequence to then later load it back. + +This is useful for avoiding the evaluation of tokens that you've already evaluated in the past. + +::: warning +When loading a context sequence state from a file, +always ensure that the model used to create the context sequence is exactly the same as the one used to save the state file. + +Loading a state file created from a different model can crash the process, +thus you have to pass `{acceptRisk: true}` to the [`loadStateFromFile`](../api/classes/LlamaContextSequence.md#loadstatefromfile) method to use it. + +Use with caution. +::: + +::: code-group +```typescript [Save state] +import {fileURLToPath} from "url"; +import path from "path"; +import {getLlama} from "node-llama-cpp"; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +const llama = await getLlama(); +const model = await llama.loadModel({ + modelPath: path.join(__dirname, "models", "Meta-Llama-3-8B-Instruct.Q4_K_M.gguf") +}); +const context = await model.createContext(); +const sequence = context.getSequence(); + +const input = "The best way to"; +const tokens = model.tokenize(input); +await sequence.evaluateWithoutGeneratingNewTokens(tokens); + +console.log( + "Current state:", + model.detokenize(sequence.contextTokens, true), + sequence.contextTokens +); + +await sequence.saveStateToFile("state.bin");// [!code highlight] +``` +::: + +::: code-group +```typescript [Load state] +import {fileURLToPath} from "url"; +import path from "path"; +import {getLlama, Token} from "node-llama-cpp"; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +// ---cut--- +const llama = await getLlama(); +const model = await llama.loadModel({ + modelPath: path.join(__dirname, "models", "Meta-Llama-3-8B-Instruct.Q4_K_M.gguf") +}); +const context = await model.createContext(); +const sequence = context.getSequence(); + +await sequence.loadStateFromFile("state.bin", {acceptRisk: true});// [!code highlight] + +console.log( + "Loaded state:", + model.detokenize(sequence.contextTokens, true), + sequence.contextTokens +); + +const input = " find"; +const inputTokens = model.tokenize(input); +const maxTokens = 10; +const res: Token[] = []; +for await (const token of sequence.evaluate(inputTokens)) { + res.push(token); + + if (res.length >= maxTokens) + break; +} + +console.log("Result:", model.detokenize(res)); +``` +::: diff --git a/llama/CMakeLists.txt b/llama/CMakeLists.txt index f0db83ec..e6bc9109 100644 --- a/llama/CMakeLists.txt +++ b/llama/CMakeLists.txt @@ -1,9 +1,17 @@ -cmake_minimum_required(VERSION 3.14) +cmake_minimum_required(VERSION 3.19) if (NLC_CURRENT_PLATFORM STREQUAL "win-x64" OR NLC_CURRENT_PLATFORM STREQUAL "win-arm64") set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) endif() +if (NLC_CURRENT_PLATFORM STREQUAL "win-x64") + if (CMAKE_BUILD_TYPE STREQUAL "Debug") + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDebugDLL" CACHE STRING "" FORCE) + else() + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDLL" CACHE STRING "" FORCE) + endif() +endif() + if (NLC_TARGET_PLATFORM STREQUAL "win-arm64" AND (CMAKE_GENERATOR STREQUAL "Ninja" OR CMAKE_GENERATOR STREQUAL "Ninja Multi-Config") AND NOT MINGW) if(NLC_CURRENT_PLATFORM STREQUAL "win-x64") include("./profiles/llvm.win32.host-x64.target-arm64.cmake") @@ -70,6 +78,9 @@ add_subdirectory("llama.cpp") include_directories("llama.cpp") include_directories("./llama.cpp/common") +# This is needed to use methods in "llama-grammar.h" and "unicode.h" +target_include_directories(llama PUBLIC "./llama.cpp/src") + unset(GPU_INFO_HEADERS) unset(GPU_INFO_SOURCES) unset(GPU_INFO_EXTRA_LIBS) diff --git a/llama/addon/AddonContext.cpp b/llama/addon/AddonContext.cpp index 53b39cad..1f8a8726 100644 --- a/llama/addon/AddonContext.cpp +++ b/llama/addon/AddonContext.cpp @@ -2,7 +2,6 @@ #include #include #include "common/common.h" -#include "llama-grammar.h" #include "llama.h" #include "addonGlobals.h" @@ -703,6 +702,143 @@ Napi::Value AddonContext::SetThreads(const Napi::CallbackInfo& info) { return info.Env().Undefined(); } +class AddonContextSaveSequenceStateToFileWorker : public Napi::AsyncWorker { + public: + AddonContext* context; + std::string filepath; + llama_seq_id sequenceId; + std::vector tokens; + size_t savedFileSize = 0; + + AddonContextSaveSequenceStateToFileWorker(const Napi::CallbackInfo& info, AddonContext* context) + : Napi::AsyncWorker(info.Env(), "AddonContextSaveSequenceStateToFileWorker"), + context(context), + deferred(Napi::Promise::Deferred::New(info.Env())) { + context->Ref(); + + filepath = info[0].As().Utf8Value(); + sequenceId = info[1].As().Int32Value(); + Napi::Uint32Array inputTokens = info[2].As(); + + tokens.resize(inputTokens.ElementLength()); + for (size_t i = 0; i < tokens.size(); i++) { + tokens[i] = inputTokens[i]; + } + } + ~AddonContextSaveSequenceStateToFileWorker() { + context->Unref(); + } + + Napi::Promise GetPromise() { + return deferred.Promise(); + } + + protected: + Napi::Promise::Deferred deferred; + + void Execute() { + try { + savedFileSize = llama_state_seq_save_file(context->ctx, filepath.c_str(), sequenceId, tokens.data(), tokens.size()); + if (savedFileSize == 0) { + SetError("Failed to save state to file"); + return; + } + } catch (const std::exception& e) { + SetError(e.what()); + } catch(...) { + SetError("Unknown error when calling \"llama_state_seq_save_file\""); + } + } + void OnOK() { + deferred.Resolve(Napi::Number::New(Env(), savedFileSize)); + } + void OnError(const Napi::Error& err) { + deferred.Reject(err.Value()); + } +}; +Napi::Value AddonContext::SaveSequenceStateToFile(const Napi::CallbackInfo& info) { + if (disposed) { + Napi::Error::New(info.Env(), "Context is disposed").ThrowAsJavaScriptException(); + return info.Env().Undefined(); + } + + AddonContextSaveSequenceStateToFileWorker* worker = new AddonContextSaveSequenceStateToFileWorker(info, this); + worker->Queue(); + return worker->GetPromise(); +} + +class AddonContextLoadSequenceStateFromFileWorker : public Napi::AsyncWorker { + public: + AddonContext* context; + std::string filepath; + llama_seq_id sequenceId; + size_t maxContextSize; + std::vector tokens; + + AddonContextLoadSequenceStateFromFileWorker(const Napi::CallbackInfo& info, AddonContext* context) + : Napi::AsyncWorker(info.Env(), "AddonContextLoadSequenceStateFromFileWorker"), + context(context), + deferred(Napi::Promise::Deferred::New(info.Env())) { + context->Ref(); + + filepath = info[0].As().Utf8Value(); + sequenceId = info[1].As().Int32Value(); + maxContextSize = info[2].As().Uint32Value(); + + tokens.resize(maxContextSize); + } + ~AddonContextLoadSequenceStateFromFileWorker() { + context->Unref(); + } + + Napi::Promise GetPromise() { + return deferred.Promise(); + } + + protected: + Napi::Promise::Deferred deferred; + + void Execute() { + try { + size_t tokenCount = 0; + const size_t fileSize = llama_state_seq_load_file(context->ctx, filepath.c_str(), sequenceId, tokens.data(), tokens.size(), &tokenCount); + if (fileSize == 0) { + SetError("Failed to load state from file. Current context sequence size may be smaller that the state of the file"); + return; + } + + tokens.resize(tokenCount); + } catch (const std::exception& e) { + SetError(e.what()); + } catch(...) { + SetError("Unknown error when calling \"llama_state_seq_load_file\""); + } + } + void OnOK() { + size_t tokenCount = tokens.size(); + Napi::Uint32Array result = Napi::Uint32Array::New(Env(), tokenCount); + + for (size_t i = 0; i < tokenCount; i++) { + result[i] = tokens[i]; + } + + deferred.Resolve(result); + } + void OnError(const Napi::Error& err) { + deferred.Reject(err.Value()); + } +}; +Napi::Value AddonContext::LoadSequenceStateFromFile(const Napi::CallbackInfo& info) { + if (disposed) { + Napi::Error::New(info.Env(), "Context is disposed").ThrowAsJavaScriptException(); + return info.Env().Undefined(); + } + + AddonContextLoadSequenceStateFromFileWorker* worker = new AddonContextLoadSequenceStateFromFileWorker(info, this); + worker->Queue(); + return worker->GetPromise(); +} + Napi::Value AddonContext::PrintTimings(const Napi::CallbackInfo& info) { llama_perf_context_print(ctx); llama_perf_context_reset(ctx); @@ -798,6 +934,8 @@ void AddonContext::init(Napi::Object exports) { InstanceMethod("setThreads", &AddonContext::SetThreads), InstanceMethod("printTimings", &AddonContext::PrintTimings), InstanceMethod("ensureDraftContextIsCompatibleForSpeculative", &AddonContext::EnsureDraftContextIsCompatibleForSpeculative), + InstanceMethod("saveSequenceStateToFile", &AddonContext::SaveSequenceStateToFile), + InstanceMethod("loadSequenceStateFromFile", &AddonContext::LoadSequenceStateFromFile), InstanceMethod("setLora", &AddonContext::SetLora), InstanceMethod("dispose", &AddonContext::Dispose), } diff --git a/llama/addon/AddonContext.h b/llama/addon/AddonContext.h index b86a4f2f..933ba8f0 100644 --- a/llama/addon/AddonContext.h +++ b/llama/addon/AddonContext.h @@ -44,6 +44,9 @@ class AddonContext : public Napi::ObjectWrap { Napi::Value GetThreads(const Napi::CallbackInfo& info); Napi::Value SetThreads(const Napi::CallbackInfo& info); + Napi::Value SaveSequenceStateToFile(const Napi::CallbackInfo& info); + Napi::Value LoadSequenceStateFromFile(const Napi::CallbackInfo& info); + Napi::Value PrintTimings(const Napi::CallbackInfo& info); Napi::Value EnsureDraftContextIsCompatibleForSpeculative(const Napi::CallbackInfo& info); diff --git a/llama/addon/AddonSampler.cpp b/llama/addon/AddonSampler.cpp index f0c1b6ec..12c9a1ab 100644 --- a/llama/addon/AddonSampler.cpp +++ b/llama/addon/AddonSampler.cpp @@ -1,6 +1,5 @@ #include #include "common/common.h" -#include "llama-grammar.h" #include "llama.h" #include "AddonGrammarEvaluationState.h" diff --git a/llama/gpuInfo/vulkan-gpu-info.cpp b/llama/gpuInfo/vulkan-gpu-info.cpp index d9bf40f6..c1c42316 100644 --- a/llama/gpuInfo/vulkan-gpu-info.cpp +++ b/llama/gpuInfo/vulkan-gpu-info.cpp @@ -66,7 +66,6 @@ static bool enumerateVulkanDevices(size_t* total, size_t* used, size_t* unifiedM features2.pNext = &vk11Features; vkGetPhysicalDeviceFeatures2(physicalDevice, &features2); - VkPhysicalDeviceFeatures2 device_features2; if (!vk11Features.storageBuffer16BitAccess) { *checkSupported = false; diff --git a/package-lock.json b/package-lock.json index bde90819..72578ac6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,25 +10,25 @@ "hasInstallScript": true, "license": "MIT", "dependencies": { - "@huggingface/jinja": "^0.3.3", + "@huggingface/jinja": "^0.5.0", "async-retry": "^1.3.3", "bytes": "^3.1.2", "chalk": "^5.4.1", "chmodrp": "^1.0.2", - "cmake-js": "^7.3.0", + "cmake-js": "^7.3.1", "cross-env": "^7.0.3", "cross-spawn": "^7.0.6", "env-var": "^7.5.0", "filenamify": "^6.0.0", "fs-extra": "^11.3.0", - "ignore": "^7.0.0", + "ignore": "^7.0.4", "ipull": "^3.9.2", "is-unicode-supported": "^2.1.0", "lifecycle-utils": "^2.0.0", "log-symbols": "^7.0.0", "nanoid": "^5.1.5", "node-addon-api": "^8.3.1", - "octokit": "^4.1.2", + "octokit": "^4.1.3", "ora": "^8.2.0", "pretty-ms": "^9.2.0", "proper-lockfile": "^4.1.2", @@ -46,53 +46,53 @@ "node-llama-cpp": "dist/cli/cli.js" }, "devDependencies": { - "@commitlint/cli": "^19.8.0", - "@commitlint/config-conventional": "^19.8.0", - "@eslint/compat": "^1.2.7", + "@commitlint/cli": "^19.8.1", + "@commitlint/config-conventional": "^19.8.1", + "@eslint/compat": "^1.2.9", "@fontsource/inter": "^5.2.5", - "@nolebase/vitepress-plugin-git-changelog": "^2.15.1", - "@nolebase/vitepress-plugin-og-image": "^2.15.1", + "@nolebase/vitepress-plugin-git-changelog": "^2.17.0", + "@nolebase/vitepress-plugin-og-image": "^2.17.0", "@resvg/resvg-js": "^2.6.2", - "@semantic-release/exec": "^7.0.3", - "@semantic-release/github": "11.0.1", + "@semantic-release/exec": "^7.1.0", + "@semantic-release/github": "11.0.2", "@semantic-release/npm": "12.0.1", - "@shikijs/vitepress-twoslash": "^3.2.1", + "@shikijs/vitepress-twoslash": "^3.4.0", "@stylistic/eslint-plugin": "^4.2.0", "@types/async-retry": "^1.4.9", "@types/bytes": "^3.1.5", "@types/cross-spawn": "^6.0.6", "@types/fs-extra": "^11.0.4", - "@types/node": "^22.13.11", + "@types/node": "^22.15.17", "@types/proper-lockfile": "^4.1.4", - "@types/semver": "^7.5.8", + "@types/semver": "^7.7.0", "@types/validate-npm-package-name": "^4.0.2", "@types/which": "^3.0.4", "@types/yargs": "^17.0.33", - "@vitest/coverage-v8": "^3.0.9", - "@vitest/ui": "^3.0.9", - "electron": "^35.0.3", - "eslint": "^9.23.0", - "eslint-import-resolver-typescript": "^4.2.2", + "@vitest/coverage-v8": "^3.1.3", + "@vitest/ui": "^3.1.3", + "electron": "^36.2.0", + "eslint": "^9.26.0", + "eslint-import-resolver-typescript": "^4.3.4", "eslint-plugin-import": "^2.31.0", - "eslint-plugin-jsdoc": "^50.6.8", - "eslint-plugin-n": "^17.16.2", - "feed": "^4.2.2", + "eslint-plugin-jsdoc": "^50.6.14", + "eslint-plugin-n": "^17.18.0", + "feed": "^5.0.0", "husky": "^9.1.7", "rehype": "^13.0.2", "rimraf": "^6.0.1", "semantic-release": "^24.2.3", - "sharp": "^0.33.5", + "sharp": "^0.34.1", "tslib": "^2.8.1", - "typedoc": "^0.28.1", - "typedoc-plugin-markdown": "^4.5.2", - "typedoc-plugin-mdn-links": "^5.0.1", + "typedoc": "^0.28.4", + "typedoc-plugin-markdown": "^4.6.3", + "typedoc-plugin-mdn-links": "^5.0.2", "typedoc-vitepress-theme": "^1.1.2", - "typescript": "^5.8.2", - "typescript-eslint": "^8.27.0", - "vite-node": "^3.0.9", + "typescript": "^5.8.3", + "typescript-eslint": "^8.32.0", + "vite-node": "^3.1.3", "vitepress": "^1.6.3", - "vitest": "^3.0.9", - "zx": "^8.4.1" + "vitest": "^3.1.3", + "zx": "^8.5.4" }, "engines": { "node": ">=20.0.0" @@ -466,18 +466,18 @@ } }, "node_modules/@commitlint/cli": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-19.8.0.tgz", - "integrity": "sha512-t/fCrLVu+Ru01h0DtlgHZXbHV2Y8gKocTR5elDOqIRUzQd0/6hpt2VIWOj9b3NDo7y4/gfxeR2zRtXq/qO6iUg==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-19.8.1.tgz", + "integrity": "sha512-LXUdNIkspyxrlV6VDHWBmCZRtkEVRpBKxi2Gtw3J54cGWhLCTouVD/Q6ZSaSvd2YaDObWK8mDjrz3TIKtaQMAA==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/format": "^19.8.0", - "@commitlint/lint": "^19.8.0", - "@commitlint/load": "^19.8.0", - "@commitlint/read": "^19.8.0", - "@commitlint/types": "^19.8.0", - "tinyexec": "^0.3.0", + "@commitlint/format": "^19.8.1", + "@commitlint/lint": "^19.8.1", + "@commitlint/load": "^19.8.1", + "@commitlint/read": "^19.8.1", + "@commitlint/types": "^19.8.1", + "tinyexec": "^1.0.0", "yargs": "^17.0.0" }, "bin": { @@ -488,13 +488,13 @@ } }, "node_modules/@commitlint/config-conventional": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-19.8.0.tgz", - "integrity": "sha512-9I2kKJwcAPwMoAj38hwqFXG0CzS2Kj+SAByPUQ0SlHTfb7VUhYVmo7G2w2tBrqmOf7PFd6MpZ/a1GQJo8na8kw==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-19.8.1.tgz", + "integrity": "sha512-/AZHJL6F6B/G959CsMAzrPKKZjeEiAVifRyEwXxcT6qtqbPwGw+iQxmNS+Bu+i09OCtdNRW6pNpBvgPrtMr9EQ==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/types": "^19.8.0", + "@commitlint/types": "^19.8.1", "conventional-changelog-conventionalcommits": "^7.0.2" }, "engines": { @@ -502,13 +502,13 @@ } }, "node_modules/@commitlint/config-validator": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-19.8.0.tgz", - "integrity": "sha512-+r5ZvD/0hQC3w5VOHJhGcCooiAVdynFlCe2d6I9dU+PvXdV3O+fU4vipVg+6hyLbQUuCH82mz3HnT/cBQTYYuA==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-19.8.1.tgz", + "integrity": "sha512-0jvJ4u+eqGPBIzzSdqKNX1rvdbSU1lPNYlfQQRIFnBgLy26BtC0cFnr7c/AyuzExMxWsMOte6MkTi9I3SQ3iGQ==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/types": "^19.8.0", + "@commitlint/types": "^19.8.1", "ajv": "^8.11.0" }, "engines": { @@ -516,13 +516,13 @@ } }, "node_modules/@commitlint/ensure": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-19.8.0.tgz", - "integrity": "sha512-kNiNU4/bhEQ/wutI1tp1pVW1mQ0QbAjfPRo5v8SaxoVV+ARhkB8Wjg3BSseNYECPzWWfg/WDqQGIfV1RaBFQZg==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-19.8.1.tgz", + "integrity": "sha512-mXDnlJdvDzSObafjYrOSvZBwkD01cqB4gbnnFuVyNpGUM5ijwU/r/6uqUmBXAAOKRfyEjpkGVZxaDsCVnHAgyw==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/types": "^19.8.0", + "@commitlint/types": "^19.8.1", "lodash.camelcase": "^4.3.0", "lodash.kebabcase": "^4.1.1", "lodash.snakecase": "^4.1.1", @@ -534,9 +534,9 @@ } }, "node_modules/@commitlint/execute-rule": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-19.8.0.tgz", - "integrity": "sha512-fuLeI+EZ9x2v/+TXKAjplBJWI9CNrHnyi5nvUQGQt4WRkww/d95oVRsc9ajpt4xFrFmqMZkd/xBQHZDvALIY7A==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-19.8.1.tgz", + "integrity": "sha512-YfJyIqIKWI64Mgvn/sE7FXvVMQER/Cd+s3hZke6cI1xgNT/f6ZAz5heND0QtffH+KbcqAwXDEE1/5niYayYaQA==", "dev": true, "license": "MIT", "engines": { @@ -544,13 +544,13 @@ } }, "node_modules/@commitlint/format": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-19.8.0.tgz", - "integrity": "sha512-EOpA8IERpQstxwp/WGnDArA7S+wlZDeTeKi98WMOvaDLKbjptuHWdOYYr790iO7kTCif/z971PKPI2PkWMfOxg==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-19.8.1.tgz", + "integrity": "sha512-kSJj34Rp10ItP+Eh9oCItiuN/HwGQMXBnIRk69jdOwEW9llW9FlyqcWYbHPSGofmjsqeoxa38UaEA5tsbm2JWw==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/types": "^19.8.0", + "@commitlint/types": "^19.8.1", "chalk": "^5.3.0" }, "engines": { @@ -558,13 +558,13 @@ } }, "node_modules/@commitlint/is-ignored": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-19.8.0.tgz", - "integrity": "sha512-L2Jv9yUg/I+jF3zikOV0rdiHUul9X3a/oU5HIXhAJLE2+TXTnEBfqYP9G5yMw/Yb40SnR764g4fyDK6WR2xtpw==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-19.8.1.tgz", + "integrity": "sha512-AceOhEhekBUQ5dzrVhDDsbMaY5LqtN8s1mqSnT2Kz1ERvVZkNihrs3Sfk1Je/rxRNbXYFzKZSHaPsEJJDJV8dg==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/types": "^19.8.0", + "@commitlint/types": "^19.8.1", "semver": "^7.6.0" }, "engines": { @@ -572,32 +572,32 @@ } }, "node_modules/@commitlint/lint": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-19.8.0.tgz", - "integrity": "sha512-+/NZKyWKSf39FeNpqhfMebmaLa1P90i1Nrb1SrA7oSU5GNN/lksA4z6+ZTnsft01YfhRZSYMbgGsARXvkr/VLQ==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-19.8.1.tgz", + "integrity": "sha512-52PFbsl+1EvMuokZXLRlOsdcLHf10isTPlWwoY1FQIidTsTvjKXVXYb7AvtpWkDzRO2ZsqIgPK7bI98x8LRUEw==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/is-ignored": "^19.8.0", - "@commitlint/parse": "^19.8.0", - "@commitlint/rules": "^19.8.0", - "@commitlint/types": "^19.8.0" + "@commitlint/is-ignored": "^19.8.1", + "@commitlint/parse": "^19.8.1", + "@commitlint/rules": "^19.8.1", + "@commitlint/types": "^19.8.1" }, "engines": { "node": ">=v18" } }, "node_modules/@commitlint/load": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-19.8.0.tgz", - "integrity": "sha512-4rvmm3ff81Sfb+mcWT5WKlyOa+Hd33WSbirTVUer0wjS1Hv/Hzr07Uv1ULIV9DkimZKNyOwXn593c+h8lsDQPQ==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-19.8.1.tgz", + "integrity": "sha512-9V99EKG3u7z+FEoe4ikgq7YGRCSukAcvmKQuTtUyiYPnOd9a2/H9Ak1J9nJA1HChRQp9OA/sIKPugGS+FK/k1A==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/config-validator": "^19.8.0", - "@commitlint/execute-rule": "^19.8.0", - "@commitlint/resolve-extends": "^19.8.0", - "@commitlint/types": "^19.8.0", + "@commitlint/config-validator": "^19.8.1", + "@commitlint/execute-rule": "^19.8.1", + "@commitlint/resolve-extends": "^19.8.1", + "@commitlint/types": "^19.8.1", "chalk": "^5.3.0", "cosmiconfig": "^9.0.0", "cosmiconfig-typescript-loader": "^6.1.0", @@ -610,9 +610,9 @@ } }, "node_modules/@commitlint/message": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-19.8.0.tgz", - "integrity": "sha512-qs/5Vi9bYjf+ZV40bvdCyBn5DvbuelhR6qewLE8Bh476F7KnNyLfdM/ETJ4cp96WgeeHo6tesA2TMXS0sh5X4A==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-19.8.1.tgz", + "integrity": "sha512-+PMLQvjRXiU+Ae0Wc+p99EoGEutzSXFVwQfa3jRNUZLNW5odZAyseb92OSBTKCu+9gGZiJASt76Cj3dLTtcTdg==", "dev": true, "license": "MIT", "engines": { @@ -620,13 +620,13 @@ } }, "node_modules/@commitlint/parse": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-19.8.0.tgz", - "integrity": "sha512-YNIKAc4EXvNeAvyeEnzgvm1VyAe0/b3Wax7pjJSwXuhqIQ1/t2hD3OYRXb6D5/GffIvaX82RbjD+nWtMZCLL7Q==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-19.8.1.tgz", + "integrity": "sha512-mmAHYcMBmAgJDKWdkjIGq50X4yB0pSGpxyOODwYmoexxxiUCy5JJT99t1+PEMK7KtsCtzuWYIAXYAiKR+k+/Jw==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/types": "^19.8.0", + "@commitlint/types": "^19.8.1", "conventional-changelog-angular": "^7.0.0", "conventional-commits-parser": "^5.0.0" }, @@ -635,31 +635,31 @@ } }, "node_modules/@commitlint/read": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-19.8.0.tgz", - "integrity": "sha512-6ywxOGYajcxK1y1MfzrOnwsXO6nnErna88gRWEl3qqOOP8MDu/DTeRkGLXBFIZuRZ7mm5yyxU5BmeUvMpNte5w==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-19.8.1.tgz", + "integrity": "sha512-03Jbjb1MqluaVXKHKRuGhcKWtSgh3Jizqy2lJCRbRrnWpcM06MYm8th59Xcns8EqBYvo0Xqb+2DoZFlga97uXQ==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/top-level": "^19.8.0", - "@commitlint/types": "^19.8.0", + "@commitlint/top-level": "^19.8.1", + "@commitlint/types": "^19.8.1", "git-raw-commits": "^4.0.0", "minimist": "^1.2.8", - "tinyexec": "^0.3.0" + "tinyexec": "^1.0.0" }, "engines": { "node": ">=v18" } }, "node_modules/@commitlint/resolve-extends": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-19.8.0.tgz", - "integrity": "sha512-CLanRQwuG2LPfFVvrkTrBR/L/DMy3+ETsgBqW1OvRxmzp/bbVJW0Xw23LnnExgYcsaFtos967lul1CsbsnJlzQ==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-19.8.1.tgz", + "integrity": "sha512-GM0mAhFk49I+T/5UCYns5ayGStkTt4XFFrjjf0L4S26xoMTSkdCf9ZRO8en1kuopC4isDFuEm7ZOm/WRVeElVg==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/config-validator": "^19.8.0", - "@commitlint/types": "^19.8.0", + "@commitlint/config-validator": "^19.8.1", + "@commitlint/types": "^19.8.1", "global-directory": "^4.0.1", "import-meta-resolve": "^4.0.0", "lodash.mergewith": "^4.6.2", @@ -670,25 +670,25 @@ } }, "node_modules/@commitlint/rules": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-19.8.0.tgz", - "integrity": "sha512-IZ5IE90h6DSWNuNK/cwjABLAKdy8tP8OgGVGbXe1noBEX5hSsu00uRlLu6JuruiXjWJz2dZc+YSw3H0UZyl/mA==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-19.8.1.tgz", + "integrity": "sha512-Hnlhd9DyvGiGwjfjfToMi1dsnw1EXKGJNLTcsuGORHz6SS9swRgkBsou33MQ2n51/boIDrbsg4tIBbRpEWK2kw==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/ensure": "^19.8.0", - "@commitlint/message": "^19.8.0", - "@commitlint/to-lines": "^19.8.0", - "@commitlint/types": "^19.8.0" + "@commitlint/ensure": "^19.8.1", + "@commitlint/message": "^19.8.1", + "@commitlint/to-lines": "^19.8.1", + "@commitlint/types": "^19.8.1" }, "engines": { "node": ">=v18" } }, "node_modules/@commitlint/to-lines": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-19.8.0.tgz", - "integrity": "sha512-3CKLUw41Cur8VMjh16y8LcsOaKbmQjAKCWlXx6B0vOUREplp6em9uIVhI8Cv934qiwkbi2+uv+mVZPnXJi1o9A==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-19.8.1.tgz", + "integrity": "sha512-98Mm5inzbWTKuZQr2aW4SReY6WUukdWXuZhrqf1QdKPZBCCsXuG87c+iP0bwtD6DBnmVVQjgp4whoHRVixyPBg==", "dev": true, "license": "MIT", "engines": { @@ -696,9 +696,9 @@ } }, "node_modules/@commitlint/top-level": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-19.8.0.tgz", - "integrity": "sha512-Rphgoc/omYZisoNkcfaBRPQr4myZEHhLPx2/vTXNLjiCw4RgfPR1wEgUpJ9OOmDCiv5ZyIExhprNLhteqH4FuQ==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-19.8.1.tgz", + "integrity": "sha512-Ph8IN1IOHPSDhURCSXBz44+CIu+60duFwRsg6HqaISFHQHbmBtxVw4ZrFNIYUzEP7WwrNPxa2/5qJ//NK1FGcw==", "dev": true, "license": "MIT", "dependencies": { @@ -709,9 +709,9 @@ } }, "node_modules/@commitlint/types": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-19.8.0.tgz", - "integrity": "sha512-LRjP623jPyf3Poyfb0ohMj8I3ORyBDOwXAgxxVPbSD0unJuW2mJWeiRfaQinjtccMqC5Wy1HOMfa4btKjbNxbg==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-19.8.1.tgz", + "integrity": "sha512-/yCrWGCoA1SVKOks25EGadP9Pnj0oAIHGpl2wH2M2Y46dPM2ueb8wyCVOD7O3WCTkaJ0IkKvzhl1JY7+uCT2Dw==", "dev": true, "license": "MIT", "dependencies": { @@ -841,21 +841,21 @@ } }, "node_modules/@emnapi/core": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.3.1.tgz", - "integrity": "sha512-pVGjBIt1Y6gg3EJN8jTcfpP/+uuRksIo055oE/OBkDNcjZqVbfkWCksG1Jp4yZnj3iKWyWX8fdG/j6UDYPbFog==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.3.tgz", + "integrity": "sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==", "dev": true, "license": "MIT", "optional": true, "dependencies": { - "@emnapi/wasi-threads": "1.0.1", + "@emnapi/wasi-threads": "1.0.2", "tslib": "^2.4.0" } }, "node_modules/@emnapi/runtime": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.3.1.tgz", - "integrity": "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.3.tgz", + "integrity": "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==", "dev": true, "license": "MIT", "optional": true, @@ -864,9 +864,9 @@ } }, "node_modules/@emnapi/wasi-threads": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.1.tgz", - "integrity": "sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.2.tgz", + "integrity": "sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==", "dev": true, "license": "MIT", "optional": true, @@ -1281,9 +1281,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", - "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", "dev": true, "license": "MIT", "dependencies": { @@ -1323,9 +1323,9 @@ } }, "node_modules/@eslint/compat": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.2.7.tgz", - "integrity": "sha512-xvv7hJE32yhegJ8xNAnb62ggiAwTYHBpUCWhRxEj/ksvgDJuSXfoDkBcRYaYNFiJ+jH0IE3K16hd+xXzhBgNbg==", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.2.9.tgz", + "integrity": "sha512-gCdSY54n7k+driCadyMNv8JSPzYLeDVM/ikZRtvtROBpRdFSkS8W9A82MqsaY7lZuwL0wiapgD0NT1xT0hyJsA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1341,9 +1341,9 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz", - "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==", + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz", + "integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1380,9 +1380,9 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.0.tgz", - "integrity": "sha512-yJLLmLexii32mGrhW29qvU3QBVTu0GUmEf/J4XsBtVhp4JkIUFN/BjWqTF63yRvGApIDpZm5fa97LtYtINmfeQ==", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.2.tgz", + "integrity": "sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1390,9 +1390,9 @@ } }, "node_modules/@eslint/core": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz", - "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz", + "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1485,9 +1485,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.23.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.23.0.tgz", - "integrity": "sha512-35MJ8vCPU0ZMxo7zfev2pypqTwWTofFZO6m4KAtdoFhRpLJUpHTZZ+KB3C7Hb1d7bULYwO4lJXGCi5Se+8OMbw==", + "version": "9.26.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.26.0.tgz", + "integrity": "sha512-I9XlJawFdSMvWjDt6wksMCrgns5ggLNfFwFvnShsleWruvXM514Qxk8V246efTw+eo9JABvVz+u3q2RiAowKxQ==", "dev": true, "license": "MIT", "engines": { @@ -1505,13 +1505,13 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.7.tgz", - "integrity": "sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==", + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz", + "integrity": "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.12.0", + "@eslint/core": "^0.13.0", "levn": "^0.4.1" }, "engines": { @@ -1556,32 +1556,54 @@ } }, "node_modules/@gerrit0/mini-shiki": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-3.2.1.tgz", - "integrity": "sha512-HbzRC6MKB6U8kQhczz0APKPIzFHTrcqhaC7es2EXInq1SpjPVnpVSIsBe6hNoLWqqCx1n5VKiPXq6PfXnHZKOQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-3.4.0.tgz", + "integrity": "sha512-48lKoQegmfJ0iyR/jRz5OrYOSM3WewG9YWCPqUvYFEC54shQO8RsAaspaK/2PRHVVnjekRqfAFvq8pwCpIo5ig==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/engine-oniguruma": "^3.2.1", - "@shikijs/types": "^3.2.1", + "@shikijs/engine-oniguruma": "^3.4.0", + "@shikijs/langs": "^3.4.0", + "@shikijs/themes": "^3.4.0", + "@shikijs/types": "^3.4.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "node_modules/@gerrit0/mini-shiki/node_modules/@shikijs/engine-oniguruma": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.2.1.tgz", - "integrity": "sha512-wZZAkayEn6qu2+YjenEoFqj0OyQI64EWsNR6/71d1EkG4sxEOFooowKivsWPpaWNBu3sxAG+zPz5kzBL/SsreQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.4.0.tgz", + "integrity": "sha512-zwcWlZ4OQuJ/+1t32ClTtyTU1AiDkK1lhtviRWoq/hFqPjCNyLj22bIg9rB7BfoZKOEOfrsGz7No33BPCf+WlQ==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "3.2.1", + "@shikijs/types": "3.4.0", "@shikijs/vscode-textmate": "^10.0.2" } }, + "node_modules/@gerrit0/mini-shiki/node_modules/@shikijs/langs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.4.0.tgz", + "integrity": "sha512-bQkR+8LllaM2duU9BBRQU0GqFTx7TuF5kKlw/7uiGKoK140n1xlLAwCgXwSxAjJ7Htk9tXTFwnnsJTCU5nDPXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.4.0" + } + }, + "node_modules/@gerrit0/mini-shiki/node_modules/@shikijs/themes": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.4.0.tgz", + "integrity": "sha512-YPP4PKNFcFGLxItpbU0ZW1Osyuk8AyZ24YEFaq04CFsuCbcqydMvMUTi40V2dkc0qs1U2uZFrnU6s5zI6IH+uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.4.0" + } + }, "node_modules/@gerrit0/mini-shiki/node_modules/@shikijs/types": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.2.1.tgz", - "integrity": "sha512-/NTWAk4KE2M8uac0RhOsIhYQf4pdU0OywQuYDGIGAJ6Mjunxl2cGiuLkvu4HLCMn+OTTLRWkjZITp+aYJv60yA==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.4.0.tgz", + "integrity": "sha512-EUT/0lGiE//7j5N/yTMNMT3eCWNcHJLrRKxT0NDXWIfdfSmFJKfPX7nMmRBrQnWboAzIsUziCThrYMMhjbMS1A==", "dev": true, "license": "MIT", "dependencies": { @@ -1590,9 +1612,9 @@ } }, "node_modules/@huggingface/jinja": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@huggingface/jinja/-/jinja-0.3.3.tgz", - "integrity": "sha512-vQQr2JyWvVFba3Lj9es4q9vCl1sAc74fdgnEMoX8qHrXtswap9ge9uO3ONDzQB0cQ0PUyaKY2N6HaVbTBvSXvw==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@huggingface/jinja/-/jinja-0.5.0.tgz", + "integrity": "sha512-Ptc03/jGRiYRoi0bUYKZ14MkDslsBRT24oxmsvUlfYrvQMldrxCevhPnT+hfX8awKTT8/f/0ZBBWldoeAcMHdQ==", "license": "MIT", "engines": { "node": ">=18" @@ -1692,9 +1714,9 @@ "license": "MIT" }, "node_modules/@img/sharp-darwin-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", - "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.1.tgz", + "integrity": "sha512-pn44xgBtgpEbZsu+lWf2KNb6OAf70X68k+yk69Ic2Xz11zHR/w24/U49XT7AeRwJ0Px+mhALhU5LPci1Aymk7A==", "cpu": [ "arm64" ], @@ -1711,13 +1733,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.0.4" + "@img/sharp-libvips-darwin-arm64": "1.1.0" } }, "node_modules/@img/sharp-darwin-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", - "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.1.tgz", + "integrity": "sha512-VfuYgG2r8BpYiOUN+BfYeFo69nP/MIwAtSJ7/Zpxc5QF3KS22z8Pvg3FkrSFJBPNQ7mmcUcYQFBmEQp7eu1F8Q==", "cpu": [ "x64" ], @@ -1734,13 +1756,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.0.4" + "@img/sharp-libvips-darwin-x64": "1.1.0" } }, "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", - "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.1.0.tgz", + "integrity": "sha512-HZ/JUmPwrJSoM4DIQPv/BfNh9yrOA8tlBbqbLz4JZ5uew2+o22Ik+tHQJcih7QJuSa0zo5coHTfD5J8inqj9DA==", "cpu": [ "arm64" ], @@ -1755,9 +1777,9 @@ } }, "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", - "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.1.0.tgz", + "integrity": "sha512-Xzc2ToEmHN+hfvsl9wja0RlnXEgpKNmftriQp6XzY/RaSfwD9th+MSh0WQKzUreLKKINb3afirxW7A0fz2YWuQ==", "cpu": [ "x64" ], @@ -1772,9 +1794,9 @@ } }, "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", - "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.1.0.tgz", + "integrity": "sha512-s8BAd0lwUIvYCJyRdFqvsj+BJIpDBSxs6ivrOPm/R7piTs5UIwY5OjXrP2bqXC9/moGsyRa37eYWYCOGVXxVrA==", "cpu": [ "arm" ], @@ -1789,9 +1811,9 @@ } }, "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", - "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.1.0.tgz", + "integrity": "sha512-IVfGJa7gjChDET1dK9SekxFFdflarnUB8PwW8aGwEoF3oAsSDuNUTYS+SKDOyOJxQyDC1aPFMuRYLoDInyV9Ew==", "cpu": [ "arm64" ], @@ -1805,10 +1827,27 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.1.0.tgz", + "integrity": "sha512-tiXxFZFbhnkWE2LA8oQj7KYR+bWBkiV2nilRldT7bqoEZ4HiDOcePr9wVDAZPi/Id5fT1oY9iGnDq20cwUz8lQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", - "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.1.0.tgz", + "integrity": "sha512-xukSwvhguw7COyzvmjydRb3x/09+21HykyapcZchiCUkTThEQEOMtBj9UhkaBRLuBrgLFzQ2wbxdeCCJW/jgJA==", "cpu": [ "s390x" ], @@ -1823,9 +1862,9 @@ } }, "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", - "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.1.0.tgz", + "integrity": "sha512-yRj2+reB8iMg9W5sULM3S74jVS7zqSzHG3Ol/twnAAkAhnGQnpjj6e4ayUz7V+FpKypwgs82xbRdYtchTTUB+Q==", "cpu": [ "x64" ], @@ -1840,9 +1879,9 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", - "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.1.0.tgz", + "integrity": "sha512-jYZdG+whg0MDK+q2COKbYidaqW/WTz0cc1E+tMAusiDygrM4ypmSCjOJPmFTvHHJ8j/6cAGyeDWZOsK06tP33w==", "cpu": [ "arm64" ], @@ -1857,9 +1896,9 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", - "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.1.0.tgz", + "integrity": "sha512-wK7SBdwrAiycjXdkPnGCPLjYb9lD4l6Ze2gSdAGVZrEL05AOUJESWU2lhlC+Ffn5/G+VKuSm6zzbQSzFX/P65A==", "cpu": [ "x64" ], @@ -1874,9 +1913,9 @@ } }, "node_modules/@img/sharp-linux-arm": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", - "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.1.tgz", + "integrity": "sha512-anKiszvACti2sGy9CirTlNyk7BjjZPiML1jt2ZkTdcvpLU1YH6CXwRAZCA2UmRXnhiIftXQ7+Oh62Ji25W72jA==", "cpu": [ "arm" ], @@ -1893,13 +1932,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.0.5" + "@img/sharp-libvips-linux-arm": "1.1.0" } }, "node_modules/@img/sharp-linux-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", - "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.1.tgz", + "integrity": "sha512-kX2c+vbvaXC6vly1RDf/IWNXxrlxLNpBVWkdpRq5Ka7OOKj6nr66etKy2IENf6FtOgklkg9ZdGpEu9kwdlcwOQ==", "cpu": [ "arm64" ], @@ -1916,13 +1955,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.0.4" + "@img/sharp-libvips-linux-arm64": "1.1.0" } }, "node_modules/@img/sharp-linux-s390x": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", - "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.1.tgz", + "integrity": "sha512-7s0KX2tI9mZI2buRipKIw2X1ufdTeaRgwmRabt5bi9chYfhur+/C1OXg3TKg/eag1W+6CCWLVmSauV1owmRPxA==", "cpu": [ "s390x" ], @@ -1939,13 +1978,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.0.4" + "@img/sharp-libvips-linux-s390x": "1.1.0" } }, "node_modules/@img/sharp-linux-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", - "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.1.tgz", + "integrity": "sha512-wExv7SH9nmoBW3Wr2gvQopX1k8q2g5V5Iag8Zk6AVENsjwd+3adjwxtp3Dcu2QhOXr8W9NusBU6XcQUohBZ5MA==", "cpu": [ "x64" ], @@ -1962,13 +2001,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.0.4" + "@img/sharp-libvips-linux-x64": "1.1.0" } }, "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", - "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.1.tgz", + "integrity": "sha512-DfvyxzHxw4WGdPiTF0SOHnm11Xv4aQexvqhRDAoD00MzHekAj9a/jADXeXYCDFH/DzYruwHbXU7uz+H+nWmSOQ==", "cpu": [ "arm64" ], @@ -1985,13 +2024,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" + "@img/sharp-libvips-linuxmusl-arm64": "1.1.0" } }, "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", - "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.1.tgz", + "integrity": "sha512-pax/kTR407vNb9qaSIiWVnQplPcGU8LRIJpDT5o8PdAx5aAA7AS3X9PS8Isw1/WfqgQorPotjrZL3Pqh6C5EBg==", "cpu": [ "x64" ], @@ -2008,13 +2047,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.0.4" + "@img/sharp-libvips-linuxmusl-x64": "1.1.0" } }, "node_modules/@img/sharp-wasm32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", - "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.1.tgz", + "integrity": "sha512-YDybQnYrLQfEpzGOQe7OKcyLUCML4YOXl428gOOzBgN6Gw0rv8dpsJ7PqTHxBnXnwXr8S1mYFSLSa727tpz0xg==", "cpu": [ "wasm32" ], @@ -2022,7 +2061,7 @@ "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, "dependencies": { - "@emnapi/runtime": "^1.2.0" + "@emnapi/runtime": "^1.4.0" }, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" @@ -2032,9 +2071,9 @@ } }, "node_modules/@img/sharp-win32-ia32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", - "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.1.tgz", + "integrity": "sha512-WKf/NAZITnonBf3U1LfdjoMgNO5JYRSlhovhRhMxXVdvWYveM4kM3L8m35onYIdh75cOMCo1BexgVQcCDzyoWw==", "cpu": [ "ia32" ], @@ -2052,9 +2091,9 @@ } }, "node_modules/@img/sharp-win32-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", - "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.1.tgz", + "integrity": "sha512-hw1iIAHpNE8q3uMIRCgGOeDoz9KtFNarFLQclLxr/LK1VBkj8nby18RjFvr6aP7USRYAjTZW6yisnBWMX571Tw==", "cpu": [ "x64" ], @@ -2192,16 +2231,38 @@ "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", "license": "MIT" }, + "node_modules/@modelcontextprotocol/sdk": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.11.1.tgz", + "integrity": "sha512-9LfmxKTb1v+vUS1/emSk1f5ePmTLkb9Le9AxOB5T0XM59EUumwcS45z05h7aiZx3GI0Bl7mjb3FMEglYj+acuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "cors": "^2.8.5", + "cross-spawn": "^7.0.3", + "eventsource": "^3.0.2", + "express": "^5.0.1", + "express-rate-limit": "^7.5.0", + "pkce-challenge": "^5.0.0", + "raw-body": "^3.0.0", + "zod": "^3.23.8", + "zod-to-json-schema": "^3.24.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.7.tgz", - "integrity": "sha512-5yximcFK5FNompXfJFoWanu5l8v1hNGqNHh9du1xETp9HWk/B/PzvchX55WYOPaIeNglG8++68AAiauBAtbnzw==", + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.9.tgz", + "integrity": "sha512-OKRBiajrrxB9ATokgEQoG87Z25c67pCpYcCwmXYX8PBftC9pBfN18gnm/fh1wurSLEKIAt+QRFLFCQISrb66Jg==", "dev": true, "license": "MIT", "optional": true, "dependencies": { - "@emnapi/core": "^1.3.1", - "@emnapi/runtime": "^1.3.1", + "@emnapi/core": "^1.4.0", + "@emnapi/runtime": "^1.4.0", "@tybys/wasm-util": "^0.9.0" } }, @@ -2244,14 +2305,14 @@ } }, "node_modules/@nolebase/ui": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/@nolebase/ui/-/ui-2.15.1.tgz", - "integrity": "sha512-IiKX2HQ8Ey7M3Nd27GZdoTrURTIq6DtkGOXc6mxrZV2REbMTYqYlby1Xwx6sfyOcSsDD7Ge62PlZze/yVIZsWg==", + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@nolebase/ui/-/ui-2.17.0.tgz", + "integrity": "sha512-t0zr9FiUMju7W/iL/BzX+JuZZz0UgAC1ZMN4VKAOtRIUaQhPjE3LZMqfOrrsWhKNT8uTY7CVIcIzSulPuAe1og==", "dev": true, "license": "MIT", "dependencies": { "@iconify-json/octicon": "^1.2.5", - "less": "^4.2.2", + "less": "^4.3.0", "vue": "^3.5.13" }, "peerDependencies": { @@ -2259,22 +2320,22 @@ } }, "node_modules/@nolebase/vitepress-plugin-git-changelog": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/@nolebase/vitepress-plugin-git-changelog/-/vitepress-plugin-git-changelog-2.15.1.tgz", - "integrity": "sha512-CG2rQNTvil+DztNe2/Z5tMLi+vNLIN0A/HE6YbyWdUup9965FqzdNxv5XKO1qVfb6hqCIMmPeIRTUJIq/SZfxw==", + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@nolebase/vitepress-plugin-git-changelog/-/vitepress-plugin-git-changelog-2.17.0.tgz", + "integrity": "sha512-XuJY/rVOltgKvfnjTtkCOTcgNsYPIAlAtUAz3kAmyVs9OQ5/26bBNhmAlcoOm5knQ6jffTTXLqSFQJcpA52Q0Q==", "dev": true, "license": "MIT", "dependencies": { "@iconify-json/octicon": "^1.2.5", - "@nolebase/ui": "^2.15.1", + "@nolebase/ui": "^2.17.0", "colorette": "^2.0.20", "date-fns": "^4.1.0", "defu": "^6.1.4", - "es-toolkit": "^1.33.0", + "es-toolkit": "^1.36.0", "execa": "^9.5.2", "globby": "^14.1.0", "gray-matter": "^4.0.3", - "less": "^4.2.2", + "less": "^4.3.0", "uncrypto": "^0.1.3" }, "peerDependencies": { @@ -2282,9 +2343,9 @@ } }, "node_modules/@nolebase/vitepress-plugin-og-image": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/@nolebase/vitepress-plugin-og-image/-/vitepress-plugin-og-image-2.15.1.tgz", - "integrity": "sha512-QWfHVzXtxwCRJtYKpQsXSx8uZWGPIjlM6acjxugZ+uVQtvOGej1MKAkIrhb27lfgYpndaNchryBjKmNKL3XPQA==", + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@nolebase/vitepress-plugin-og-image/-/vitepress-plugin-og-image-2.17.0.tgz", + "integrity": "sha512-HDsScMZkFCFNrrdPMJGMfLAcs5qKJk/v5K/m7cBBRE5Zdl/Ykh2AADMefGpjp1YBwD4KyiCJM2cuCDwquEbZBw==", "dev": true, "license": "MIT", "dependencies": { @@ -2299,7 +2360,7 @@ "rehype-meta": "^4.0.1", "rehype-parse": "^9.0.1", "rehype-stringify": "^10.0.1", - "tinyglobby": "^0.2.12", + "tinyglobby": "^0.2.13", "unified": "^11.0.5", "unist-util-visit": "^5.0.0" }, @@ -2308,17 +2369,17 @@ } }, "node_modules/@octokit/app": { - "version": "15.1.5", - "resolved": "https://registry.npmjs.org/@octokit/app/-/app-15.1.5.tgz", - "integrity": "sha512-6cxLT9U8x7GGQ7lNWsKtFr4ccg9oLkGvowk373sX9HvX5U37kql5d55SzaQUxPE8PwgX2cqkzDm5NF5aPKevqg==", + "version": "15.1.6", + "resolved": "https://registry.npmjs.org/@octokit/app/-/app-15.1.6.tgz", + "integrity": "sha512-WELCamoCJo9SN0lf3SWZccf68CF0sBNPQuLYmZ/n87p5qvBJDe9aBtr5dHkh7T9nxWZ608pizwsUbypSzZAiUw==", "license": "MIT", "dependencies": { - "@octokit/auth-app": "^7.1.5", - "@octokit/auth-unauthenticated": "^6.1.2", - "@octokit/core": "^6.1.4", + "@octokit/auth-app": "^7.2.1", + "@octokit/auth-unauthenticated": "^6.1.3", + "@octokit/core": "^6.1.5", "@octokit/oauth-app": "^7.1.6", - "@octokit/plugin-paginate-rest": "^11.4.2", - "@octokit/types": "^13.8.0", + "@octokit/plugin-paginate-rest": "^12.0.0", + "@octokit/types": "^14.0.0", "@octokit/webhooks": "^13.6.1" }, "engines": { @@ -2326,16 +2387,16 @@ } }, "node_modules/@octokit/auth-app": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/@octokit/auth-app/-/auth-app-7.1.5.tgz", - "integrity": "sha512-boklS4E6LpbA3nRx+SU2fRKRGZJdOGoSZne/i3Y0B5rfHOcGwFgcXrwDLdtbv4igfDSnAkZaoNBv1GYjPDKRNw==", + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@octokit/auth-app/-/auth-app-7.2.1.tgz", + "integrity": "sha512-4jaopCVOtWN0V8qCx/1s2pkRqC6tcvIQM3kFB99eIpsP53GfsoIKO08D94b83n/V3iGihHmxWR2lXzE0NicUGg==", "license": "MIT", "dependencies": { - "@octokit/auth-oauth-app": "^8.1.3", - "@octokit/auth-oauth-user": "^5.1.3", - "@octokit/request": "^9.2.1", - "@octokit/request-error": "^6.1.7", - "@octokit/types": "^13.8.0", + "@octokit/auth-oauth-app": "^8.1.4", + "@octokit/auth-oauth-user": "^5.1.4", + "@octokit/request": "^9.2.3", + "@octokit/request-error": "^6.1.8", + "@octokit/types": "^14.0.0", "toad-cache": "^3.7.0", "universal-github-app-jwt": "^2.2.0", "universal-user-agent": "^7.0.0" @@ -2345,15 +2406,15 @@ } }, "node_modules/@octokit/auth-oauth-app": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-app/-/auth-oauth-app-8.1.3.tgz", - "integrity": "sha512-4e6OjVe5rZ8yBe8w7byBjpKtSXFuro7gqeGAAZc7QYltOF8wB93rJl2FE0a4U1Mt88xxPv/mS+25/0DuLk0Ewg==", + "version": "8.1.4", + "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-app/-/auth-oauth-app-8.1.4.tgz", + "integrity": "sha512-71iBa5SflSXcclk/OL3lJzdt4iFs56OJdpBGEBl1wULp7C58uiswZLV6TdRaiAzHP1LT8ezpbHlKuxADb+4NkQ==", "license": "MIT", "dependencies": { - "@octokit/auth-oauth-device": "^7.1.3", - "@octokit/auth-oauth-user": "^5.1.3", - "@octokit/request": "^9.2.1", - "@octokit/types": "^13.6.2", + "@octokit/auth-oauth-device": "^7.1.5", + "@octokit/auth-oauth-user": "^5.1.4", + "@octokit/request": "^9.2.3", + "@octokit/types": "^14.0.0", "universal-user-agent": "^7.0.0" }, "engines": { @@ -2361,14 +2422,14 @@ } }, "node_modules/@octokit/auth-oauth-device": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-device/-/auth-oauth-device-7.1.4.tgz", - "integrity": "sha512-yK35I9VGDGjYxu0NPZ9Rl+zXM/+DO/Hu1VR5FUNz+ZsU6i8B8oQ43TPwci9nuH8bAF6rQrKDNR9F0r0+kzYJhA==", + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-device/-/auth-oauth-device-7.1.5.tgz", + "integrity": "sha512-lR00+k7+N6xeECj0JuXeULQ2TSBB/zjTAmNF2+vyGPDEFx1dgk1hTDmL13MjbSmzusuAmuJD8Pu39rjp9jH6yw==", "license": "MIT", "dependencies": { - "@octokit/oauth-methods": "^5.1.4", - "@octokit/request": "^9.2.1", - "@octokit/types": "^13.6.2", + "@octokit/oauth-methods": "^5.1.5", + "@octokit/request": "^9.2.3", + "@octokit/types": "^14.0.0", "universal-user-agent": "^7.0.0" }, "engines": { @@ -2376,15 +2437,15 @@ } }, "node_modules/@octokit/auth-oauth-user": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-user/-/auth-oauth-user-5.1.3.tgz", - "integrity": "sha512-zNPByPn9K7TC+OOHKGxU+MxrE9SZAN11UHYEFLsK2NRn3akJN2LHRl85q+Eypr3tuB2GrKx3rfj2phJdkYCvzw==", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-user/-/auth-oauth-user-5.1.4.tgz", + "integrity": "sha512-4tJRofMHm6ZCd3O2PVgboBbQ/lNtacREeaihet0+wCATZmvPK+jjg2K6NjBfY69An3yzQdmkcMeiaOOoxOPr7Q==", "license": "MIT", "dependencies": { - "@octokit/auth-oauth-device": "^7.1.3", - "@octokit/oauth-methods": "^5.1.3", - "@octokit/request": "^9.2.1", - "@octokit/types": "^13.6.2", + "@octokit/auth-oauth-device": "^7.1.5", + "@octokit/oauth-methods": "^5.1.5", + "@octokit/request": "^9.2.3", + "@octokit/types": "^14.0.0", "universal-user-agent": "^7.0.0" }, "engines": { @@ -2401,29 +2462,29 @@ } }, "node_modules/@octokit/auth-unauthenticated": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@octokit/auth-unauthenticated/-/auth-unauthenticated-6.1.2.tgz", - "integrity": "sha512-07DlUGcz/AAVdzu3EYfi/dOyMSHp9YsOxPl/MPmtlVXWiD//GlV8HgZsPhud94DEyx+RfrW0wSl46Lx+AWbOlg==", + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@octokit/auth-unauthenticated/-/auth-unauthenticated-6.1.3.tgz", + "integrity": "sha512-d5gWJla3WdSl1yjbfMpET+hUSFCE15qM0KVSB0H1shyuJihf/RL1KqWoZMIaonHvlNojkL9XtLFp8QeLe+1iwA==", "license": "MIT", "dependencies": { - "@octokit/request-error": "^6.1.7", - "@octokit/types": "^13.6.2" + "@octokit/request-error": "^6.1.8", + "@octokit/types": "^14.0.0" }, "engines": { "node": ">= 18" } }, "node_modules/@octokit/core": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.4.tgz", - "integrity": "sha512-lAS9k7d6I0MPN+gb9bKDt7X8SdxknYqAMh44S5L+lNqIN2NuV8nvv3g8rPp7MuRxcOpxpUIATWprO0C34a8Qmg==", + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.5.tgz", + "integrity": "sha512-vvmsN0r7rguA+FySiCsbaTTobSftpIDIpPW81trAmsv9TGxg3YCujAxRYp/Uy8xmDgYCzzgulG62H7KYUFmeIg==", "license": "MIT", "dependencies": { "@octokit/auth-token": "^5.0.0", - "@octokit/graphql": "^8.1.2", - "@octokit/request": "^9.2.1", - "@octokit/request-error": "^6.1.7", - "@octokit/types": "^13.6.2", + "@octokit/graphql": "^8.2.2", + "@octokit/request": "^9.2.3", + "@octokit/request-error": "^6.1.8", + "@octokit/types": "^14.0.0", "before-after-hook": "^3.0.2", "universal-user-agent": "^7.0.0" }, @@ -2432,12 +2493,12 @@ } }, "node_modules/@octokit/endpoint": { - "version": "10.1.3", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.3.tgz", - "integrity": "sha512-nBRBMpKPhQUxCsQQeW+rCJ/OPSMcj3g0nfHn01zGYZXuNDvvXudF/TYY6APj5THlurerpFN4a/dQAIAaM6BYhA==", + "version": "10.1.4", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.4.tgz", + "integrity": "sha512-OlYOlZIsfEVZm5HCSR8aSg02T2lbUWOsCQoPKfTXJwDzcHQBrVBGdGXb89dv2Kw2ToZaRtudp8O3ZIYoaOjKlA==", "license": "MIT", "dependencies": { - "@octokit/types": "^13.6.2", + "@octokit/types": "^14.0.0", "universal-user-agent": "^7.0.2" }, "engines": { @@ -2445,13 +2506,13 @@ } }, "node_modules/@octokit/graphql": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.1.2.tgz", - "integrity": "sha512-bdlj/CJVjpaz06NBpfHhp4kGJaRZfz7AzC+6EwUImRtrwIw8dIgJ63Xg0OzV9pRn3rIzrt5c2sa++BL0JJ8GLw==", + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.2.2.tgz", + "integrity": "sha512-Yi8hcoqsrXGdt0yObxbebHXFOiUA+2v3n53epuOg1QUgOB6c4XzvisBNVXJSl8RYA5KrDuSL2yq9Qmqe5N0ryA==", "license": "MIT", "dependencies": { - "@octokit/request": "^9.1.4", - "@octokit/types": "^13.6.2", + "@octokit/request": "^9.2.3", + "@octokit/types": "^14.0.0", "universal-user-agent": "^7.0.0" }, "engines": { @@ -2487,30 +2548,30 @@ } }, "node_modules/@octokit/oauth-methods": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/@octokit/oauth-methods/-/oauth-methods-5.1.4.tgz", - "integrity": "sha512-Jc/ycnePClOvO1WL7tlC+TRxOFtyJBGuTDsL4dzXNiVZvzZdrPuNw7zHI3qJSUX2n6RLXE5L0SkFmYyNaVUFoQ==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@octokit/oauth-methods/-/oauth-methods-5.1.5.tgz", + "integrity": "sha512-Ev7K8bkYrYLhoOSZGVAGsLEscZQyq7XQONCBBAl2JdMg7IT3PQn/y8P0KjloPoYpI5UylqYrLeUcScaYWXwDvw==", "license": "MIT", "dependencies": { "@octokit/oauth-authorization-url": "^7.0.0", - "@octokit/request": "^9.2.1", - "@octokit/request-error": "^6.1.7", - "@octokit/types": "^13.6.2" + "@octokit/request": "^9.2.3", + "@octokit/request-error": "^6.1.8", + "@octokit/types": "^14.0.0" }, "engines": { "node": ">= 18" } }, "node_modules/@octokit/openapi-types": { - "version": "24.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", - "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "version": "25.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.0.0.tgz", + "integrity": "sha512-FZvktFu7HfOIJf2BScLKIEYjDsw6RKc7rBJCdvCTfKsVnx2GEB/Nbzjr29DUdb7vQhlzS/j8qDzdditP0OC6aw==", "license": "MIT" }, "node_modules/@octokit/openapi-webhooks-types": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-webhooks-types/-/openapi-webhooks-types-10.3.0.tgz", - "integrity": "sha512-Dog+FB4pvsfcGZ9CFyYwb7I6K4QkzCDuN0H3hh5Nr9mMQ4wbBceqUKyJNKN2A0SQ6j4UU3CYNuvfoX9mQlhLUQ==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-webhooks-types/-/openapi-webhooks-types-11.0.0.tgz", + "integrity": "sha512-ZBzCFj98v3SuRM7oBas6BHZMJRadlnDoeFfvm1olVxZnYeU6Vh97FhPxyS5aLh5pN51GYv2I51l/hVUAVkGBlA==", "license": "MIT" }, "node_modules/@octokit/plugin-paginate-graphql": { @@ -2526,12 +2587,12 @@ } }, "node_modules/@octokit/plugin-paginate-rest": { - "version": "11.6.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.6.0.tgz", - "integrity": "sha512-n5KPteiF7pWKgBIBJSk8qzoZWcUkza2O6A0za97pMGVrGfPdltxrfmfF5GucHYvHGZD8BdaZmmHGz5cX/3gdpw==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-12.0.0.tgz", + "integrity": "sha512-MPd6WK1VtZ52lFrgZ0R2FlaoiWllzgqFHaSZxvp72NmoDeZ0m8GeJdg4oB6ctqMTYyrnDYp592Xma21mrgiyDA==", "license": "MIT", "dependencies": { - "@octokit/types": "^13.10.0" + "@octokit/types": "^14.0.0" }, "engines": { "node": ">= 18" @@ -2541,12 +2602,12 @@ } }, "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "13.5.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.5.0.tgz", - "integrity": "sha512-9Pas60Iv9ejO3WlAX3maE1+38c5nqbJXV5GrncEfkndIpZrJ/WPMRd2xYDcPPEt5yzpxcjw9fWNoPhsSGzqKqw==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-14.0.0.tgz", + "integrity": "sha512-iQt6ovem4b7zZYZQtdv+PwgbL5VPq37th1m2x2TdkgimIDJpsi2A6Q/OI/23i/hR6z5mL0EgisNR4dcbmckSZQ==", "license": "MIT", "dependencies": { - "@octokit/types": "^13.10.0" + "@octokit/types": "^14.0.0" }, "engines": { "node": ">= 18" @@ -2556,13 +2617,13 @@ } }, "node_modules/@octokit/plugin-retry": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-7.2.0.tgz", - "integrity": "sha512-psMbEYb/Fh+V+ZaFo8J16QiFz4sVTv3GntCSU+hYqzHiMdc3P+hhHLVv+dJt0PGIPAGoIA5u+J2DCJdK6lEPsQ==", + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-7.2.1.tgz", + "integrity": "sha512-wUc3gv0D6vNHpGxSaR3FlqJpTXGWgqmk607N9L3LvPL4QjaxDgX/1nY2mGpT37Khn+nlIXdljczkRnNdTTV3/A==", "license": "MIT", "dependencies": { - "@octokit/request-error": "^6.1.7", - "@octokit/types": "^13.6.2", + "@octokit/request-error": "^6.1.8", + "@octokit/types": "^14.0.0", "bottleneck": "^2.15.3" }, "engines": { @@ -2573,12 +2634,12 @@ } }, "node_modules/@octokit/plugin-throttling": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-9.4.0.tgz", - "integrity": "sha512-IOlXxXhZA4Z3m0EEYtrrACkuHiArHLZ3CvqWwOez/pURNqRuwfoFlTPbN5Muf28pzFuztxPyiUiNwz8KctdZaQ==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-10.0.0.tgz", + "integrity": "sha512-Kuq5/qs0DVYTHZuBAzCZStCzo2nKvVRo/TDNhCcpC2TKiOGz/DisXMCvjt3/b5kr6SCI1Y8eeeJTHBxxpFvZEg==", "license": "MIT", "dependencies": { - "@octokit/types": "^13.7.0", + "@octokit/types": "^14.0.0", "bottleneck": "^2.15.3" }, "engines": { @@ -2589,14 +2650,14 @@ } }, "node_modules/@octokit/request": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.2.tgz", - "integrity": "sha512-dZl0ZHx6gOQGcffgm1/Sf6JfEpmh34v3Af2Uci02vzUYz6qEN6zepoRtmybWXIGXFIK8K9ylE3b+duCWqhArtg==", + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.3.tgz", + "integrity": "sha512-Ma+pZU8PXLOEYzsWf0cn/gY+ME57Wq8f49WTXA8FMHp2Ps9djKw//xYJ1je8Hm0pR2lU9FUGeJRWOtxq6olt4w==", "license": "MIT", "dependencies": { - "@octokit/endpoint": "^10.1.3", - "@octokit/request-error": "^6.1.7", - "@octokit/types": "^13.6.2", + "@octokit/endpoint": "^10.1.4", + "@octokit/request-error": "^6.1.8", + "@octokit/types": "^14.0.0", "fast-content-type-parse": "^2.0.0", "universal-user-agent": "^7.0.2" }, @@ -2605,33 +2666,33 @@ } }, "node_modules/@octokit/request-error": { - "version": "6.1.7", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.7.tgz", - "integrity": "sha512-69NIppAwaauwZv6aOzb+VVLwt+0havz9GT5YplkeJv7fG7a40qpLt/yZKyiDxAhgz0EtgNdNcb96Z0u+Zyuy2g==", + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.8.tgz", + "integrity": "sha512-WEi/R0Jmq+IJKydWlKDmryPcmdYSVjL3ekaiEL1L9eo1sUnqMJ+grqmC9cjk7CA7+b2/T397tO5d8YLOH3qYpQ==", "license": "MIT", "dependencies": { - "@octokit/types": "^13.6.2" + "@octokit/types": "^14.0.0" }, "engines": { "node": ">= 18" } }, "node_modules/@octokit/types": { - "version": "13.10.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", - "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.0.0.tgz", + "integrity": "sha512-VVmZP0lEhbo2O1pdq63gZFiGCKkm8PPp8AUOijlwPO6hojEVjspA0MWKP7E4hbvGxzFKNqKr6p0IYtOH/Wf/zA==", "license": "MIT", "dependencies": { - "@octokit/openapi-types": "^24.2.0" + "@octokit/openapi-types": "^25.0.0" } }, "node_modules/@octokit/webhooks": { - "version": "13.7.5", - "resolved": "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-13.7.5.tgz", - "integrity": "sha512-qmmu4cfKmm58RWyDPUDoI7ls9JWw88qbqPzEi+TDBaSirHQPsixxdPU4OjPDcnDnjee7JXv525yv4qNN3BRlyg==", + "version": "13.8.2", + "resolved": "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-13.8.2.tgz", + "integrity": "sha512-NgKpxIVp9MnEukvTF9s871v11bYTDZwpuyIYkU0ZIEM3d+DBOeiciIJPuCdjFMC1pQgv05MNKtdhbl8+Q+i3GA==", "license": "MIT", "dependencies": { - "@octokit/openapi-webhooks-types": "10.3.0", + "@octokit/openapi-webhooks-types": "11.0.0", "@octokit/request-error": "^6.1.7", "@octokit/webhooks-methods": "^5.1.1" }, @@ -2659,19 +2720,6 @@ "node": ">=14" } }, - "node_modules/@pkgr/core": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", - "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, "node_modules/@pnpm/config.env-replace": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", @@ -2718,9 +2766,9 @@ } }, "node_modules/@polka/url": { - "version": "1.0.0-next.28", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.28.tgz", - "integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==", + "version": "1.0.0-next.29", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", "dev": true, "license": "MIT" }, @@ -3466,9 +3514,9 @@ } }, "node_modules/@semantic-release/exec": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@semantic-release/exec/-/exec-7.0.3.tgz", - "integrity": "sha512-uNWwPNtWi3WTcTm3fWfFQEuj8otOvwoS5m9yo2jSVHuvqdZNsOWmuL0/FqcVyZnCI32fxyYV0G7PPb/TzCH6jw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@semantic-release/exec/-/exec-7.1.0.tgz", + "integrity": "sha512-4ycZ2atgEUutspPZ2hxO6z8JoQt4+y/kkHvfZ1cZxgl9WKJId1xPj+UadwInj+gMn2Gsv+fLnbrZ4s+6tK2TFQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3518,16 +3566,16 @@ } }, "node_modules/@semantic-release/github": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-11.0.1.tgz", - "integrity": "sha512-Z9cr0LgU/zgucbT9cksH0/pX9zmVda9hkDPcgIE0uvjMQ8w/mElDivGjx1w1pEQ+MuQJ5CBq3VCF16S6G4VH3A==", + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-11.0.2.tgz", + "integrity": "sha512-EhHimj3/eOSPu0OflgDzwgrawoGJIn8XLOkNS6WzwuTr8ebxyX976Y4mCqJ8MlkdQpV5+8T+49sy8xXlcm6uCg==", "dev": true, "license": "MIT", "dependencies": { "@octokit/core": "^6.0.0", - "@octokit/plugin-paginate-rest": "^11.0.0", + "@octokit/plugin-paginate-rest": "^12.0.0", "@octokit/plugin-retry": "^7.0.0", - "@octokit/plugin-throttling": "^9.0.0", + "@octokit/plugin-throttling": "^10.0.0", "@semantic-release/error": "^4.0.0", "aggregate-error": "^5.0.0", "debug": "^4.3.4", @@ -3950,9 +3998,9 @@ } }, "node_modules/@shikijs/vitepress-twoslash": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@shikijs/vitepress-twoslash/-/vitepress-twoslash-3.2.1.tgz", - "integrity": "sha512-lQNmw3v9gBFYdxfCW5upcDwfQu8BTJz4D4VPN72XElBA6gW82PKNmzZDoHhVcEmgm/cRQpPjpiY6CYChtv/AEw==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@shikijs/vitepress-twoslash/-/vitepress-twoslash-3.4.0.tgz", + "integrity": "sha512-3WPgEArF9sZamrB9WW6NGDj3r4+pvbWEvTjc+7jHkfoZRWJpIlyL6jqZ6MGScRHssgIq5ATG5WklflJs/nYoMw==", "dev": true, "license": "MIT", "dependencies": { @@ -3961,72 +4009,72 @@ "mdast-util-from-markdown": "^2.0.2", "mdast-util-gfm": "^3.1.0", "mdast-util-to-hast": "^13.2.0", - "shiki": "3.2.1", + "shiki": "3.4.0", "twoslash": "^0.3.1", "twoslash-vue": "^0.3.1", "vue": "^3.5.13" } }, "node_modules/@shikijs/vitepress-twoslash/node_modules/@shikijs/core": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.2.1.tgz", - "integrity": "sha512-FhsdxMWYu/C11sFisEp7FMGBtX/OSSbnXZDMBhGuUDBNTdsoZlMSgQv5f90rwvzWAdWIW6VobD+G3IrazxA6dQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.4.0.tgz", + "integrity": "sha512-0YOzTSRDn/IAfQWtK791gs1u8v87HNGToU6IwcA3K7nPoVOrS2Dh6X6A6YfXgPTSkTwR5y6myk0MnI0htjnwrA==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "3.2.1", + "@shikijs/types": "3.4.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "node_modules/@shikijs/vitepress-twoslash/node_modules/@shikijs/engine-javascript": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.2.1.tgz", - "integrity": "sha512-eMdcUzN3FMQYxOmRf2rmU8frikzoSHbQDFH2hIuXsrMO+IBOCI9BeeRkCiBkcLDHeRKbOCtYMJK3D6U32ooU9Q==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.4.0.tgz", + "integrity": "sha512-1ywDoe+z/TPQKj9Jw0eU61B003J9DqUFRfH+DVSzdwPUFhR7yOmfyLzUrFz0yw8JxFg/NgzXoQyyykXgO21n5Q==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "3.2.1", + "@shikijs/types": "3.4.0", "@shikijs/vscode-textmate": "^10.0.2", - "oniguruma-to-es": "^4.1.0" + "oniguruma-to-es": "^4.3.3" } }, "node_modules/@shikijs/vitepress-twoslash/node_modules/@shikijs/engine-oniguruma": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.2.1.tgz", - "integrity": "sha512-wZZAkayEn6qu2+YjenEoFqj0OyQI64EWsNR6/71d1EkG4sxEOFooowKivsWPpaWNBu3sxAG+zPz5kzBL/SsreQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.4.0.tgz", + "integrity": "sha512-zwcWlZ4OQuJ/+1t32ClTtyTU1AiDkK1lhtviRWoq/hFqPjCNyLj22bIg9rB7BfoZKOEOfrsGz7No33BPCf+WlQ==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "3.2.1", + "@shikijs/types": "3.4.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "node_modules/@shikijs/vitepress-twoslash/node_modules/@shikijs/langs": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.2.1.tgz", - "integrity": "sha512-If0iDHYRSGbihiA8+7uRsgb1er1Yj11pwpX1c6HLYnizDsKAw5iaT3JXj5ZpaimXSWky/IhxTm7C6nkiYVym+A==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.4.0.tgz", + "integrity": "sha512-bQkR+8LllaM2duU9BBRQU0GqFTx7TuF5kKlw/7uiGKoK140n1xlLAwCgXwSxAjJ7Htk9tXTFwnnsJTCU5nDPXQ==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "3.2.1" + "@shikijs/types": "3.4.0" } }, "node_modules/@shikijs/vitepress-twoslash/node_modules/@shikijs/themes": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.2.1.tgz", - "integrity": "sha512-k5DKJUT8IldBvAm8WcrDT5+7GA7se6lLksR+2E3SvyqGTyFMzU2F9Gb7rmD+t+Pga1MKrYFxDIeyWjMZWM6uBQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.4.0.tgz", + "integrity": "sha512-YPP4PKNFcFGLxItpbU0ZW1Osyuk8AyZ24YEFaq04CFsuCbcqydMvMUTi40V2dkc0qs1U2uZFrnU6s5zI6IH+uA==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "3.2.1" + "@shikijs/types": "3.4.0" } }, "node_modules/@shikijs/vitepress-twoslash/node_modules/@shikijs/types": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.2.1.tgz", - "integrity": "sha512-/NTWAk4KE2M8uac0RhOsIhYQf4pdU0OywQuYDGIGAJ6Mjunxl2cGiuLkvu4HLCMn+OTTLRWkjZITp+aYJv60yA==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.4.0.tgz", + "integrity": "sha512-EUT/0lGiE//7j5N/yTMNMT3eCWNcHJLrRKxT0NDXWIfdfSmFJKfPX7nMmRBrQnWboAzIsUziCThrYMMhjbMS1A==", "dev": true, "license": "MIT", "dependencies": { @@ -4035,14 +4083,13 @@ } }, "node_modules/@shikijs/vitepress-twoslash/node_modules/oniguruma-to-es": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.1.0.tgz", - "integrity": "sha512-SNwG909cSLo4vPyyPbU/VJkEc9WOXqu2ycBlfd1UCXLqk1IijcQktSBb2yRQ2UFPsDhpkaf+C1dtT3PkLK/yWA==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.3.tgz", + "integrity": "sha512-rPiZhzC3wXwE59YQMRDodUwwT9FZ9nNBwQQfsd1wfdtlKEyCdRV0avrTcSZ5xlIvGRVPd/cx6ZN45ECmS39xvg==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex-xs": "^1.0.0", - "oniguruma-parser": "^0.5.4", + "oniguruma-parser": "^0.12.1", "regex": "^6.0.1", "regex-recursion": "^6.0.2" } @@ -4068,18 +4115,18 @@ } }, "node_modules/@shikijs/vitepress-twoslash/node_modules/shiki": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.2.1.tgz", - "integrity": "sha512-VML/2o1/KGYkEf/stJJ+s9Ypn7jUKQPomGLGYso4JJFMFxVDyPNsjsI3MB3KLjlMOeH44gyaPdXC6rik2WXvUQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.4.0.tgz", + "integrity": "sha512-Ni80XHcqhOEXv5mmDAvf5p6PAJqbUc/RzFeaOqk+zP5DLvTPS3j0ckvA+MI87qoxTQ5RGJDVTbdl/ENLSyyAnQ==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/core": "3.2.1", - "@shikijs/engine-javascript": "3.2.1", - "@shikijs/engine-oniguruma": "3.2.1", - "@shikijs/langs": "3.2.1", - "@shikijs/themes": "3.2.1", - "@shikijs/types": "3.2.1", + "@shikijs/core": "3.4.0", + "@shikijs/engine-javascript": "3.4.0", + "@shikijs/engine-oniguruma": "3.4.0", + "@shikijs/langs": "3.4.0", + "@shikijs/themes": "3.4.0", + "@shikijs/types": "3.4.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } @@ -4206,9 +4253,9 @@ } }, "node_modules/@types/aws-lambda": { - "version": "8.10.147", - "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.147.tgz", - "integrity": "sha512-nD0Z9fNIZcxYX5Mai2CTmFD7wX7UldCkW2ezCF8D1T5hdiLsnTWDGRpfRYntU6VjTdLQjOvyszru7I1c1oCQew==", + "version": "8.10.149", + "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.149.tgz", + "integrity": "sha512-NXSZIhfJjnXqJgtS7IwutqIF/SOy1Wz5Px4gUY1RWITp3AYTyuJS4xaXr/bIJY1v15XMzrJ5soGnPM+7uigZjA==", "license": "MIT" }, "node_modules/@types/bytes": { @@ -4373,13 +4420,13 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.13.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.11.tgz", - "integrity": "sha512-iEUCUJoU0i3VnrCmgoWCXttklWcvoCIx4jzcP22fioIVSdTmjgoEvmAO/QPw6TcS9k5FrNgn4w7q5lGOd1CT5g==", + "version": "22.15.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.17.tgz", + "integrity": "sha512-wIX2aSZL5FE+MR0JlvF87BNVrtFWf6AE6rxSE9X7OwnVvoyCQjpzSRJ+M87se/4QCkCiebQAqrJ0y6fwIyi7nw==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.20.0" + "undici-types": "~6.21.0" } }, "node_modules/@types/normalize-package-data": { @@ -4417,9 +4464,9 @@ "license": "MIT" }, "node_modules/@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.0.tgz", + "integrity": "sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==", "dev": true, "license": "MIT" }, @@ -4480,21 +4527,21 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.27.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.27.0.tgz", - "integrity": "sha512-4henw4zkePi5p252c8ncBLzLce52SEUz2Ebj8faDnuUXz2UuHEONYcJ+G0oaCF+bYCWVZtrGzq3FD7YXetmnSA==", + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.0.tgz", + "integrity": "sha512-/jU9ettcntkBFmWUzzGgsClEi2ZFiikMX5eEQsmxIAWMOn4H3D4rvHssstmAHGVvrYnaMqdWWWg0b5M6IN/MTQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.27.0", - "@typescript-eslint/type-utils": "8.27.0", - "@typescript-eslint/utils": "8.27.0", - "@typescript-eslint/visitor-keys": "8.27.0", + "@typescript-eslint/scope-manager": "8.32.0", + "@typescript-eslint/type-utils": "8.32.0", + "@typescript-eslint/utils": "8.32.0", + "@typescript-eslint/visitor-keys": "8.32.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.0.1" + "ts-api-utils": "^2.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4520,16 +4567,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.27.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.27.0.tgz", - "integrity": "sha512-XGwIabPallYipmcOk45DpsBSgLC64A0yvdAkrwEzwZ2viqGqRUJ8eEYoPz0CWnutgAFbNMPdsGGvzjSmcWVlEA==", + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.32.0.tgz", + "integrity": "sha512-B2MdzyWxCE2+SqiZHAjPphft+/2x2FlO9YBx7eKE1BCb+rqBlQdhtAEhzIEdozHd55DXPmxBdpMygFJjfjjA9A==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.27.0", - "@typescript-eslint/types": "8.27.0", - "@typescript-eslint/typescript-estree": "8.27.0", - "@typescript-eslint/visitor-keys": "8.27.0", + "@typescript-eslint/scope-manager": "8.32.0", + "@typescript-eslint/types": "8.32.0", + "@typescript-eslint/typescript-estree": "8.32.0", + "@typescript-eslint/visitor-keys": "8.32.0", "debug": "^4.3.4" }, "engines": { @@ -4545,14 +4592,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.27.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.27.0.tgz", - "integrity": "sha512-8oI9GwPMQmBryaaxG1tOZdxXVeMDte6NyJA4i7/TWa4fBwgnAXYlIQP+uYOeqAaLJ2JRxlG9CAyL+C+YE9Xknw==", + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.0.tgz", + "integrity": "sha512-jc/4IxGNedXkmG4mx4nJTILb6TMjL66D41vyeaPWvDUmeYQzF3lKtN15WsAeTr65ce4mPxwopPSo1yUUAWw0hQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.27.0", - "@typescript-eslint/visitor-keys": "8.27.0" + "@typescript-eslint/types": "8.32.0", + "@typescript-eslint/visitor-keys": "8.32.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4563,16 +4610,16 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.27.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.27.0.tgz", - "integrity": "sha512-wVArTVcz1oJOIEJxui/nRhV0TXzD/zMSOYi/ggCfNq78EIszddXcJb7r4RCp/oBrjt8n9A0BSxRMKxHftpDxDA==", + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.32.0.tgz", + "integrity": "sha512-t2vouuYQKEKSLtJaa5bB4jHeha2HJczQ6E5IXPDPgIty9EqcJxpr1QHQ86YyIPwDwxvUmLfP2YADQ5ZY4qddZg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.27.0", - "@typescript-eslint/utils": "8.27.0", + "@typescript-eslint/typescript-estree": "8.32.0", + "@typescript-eslint/utils": "8.32.0", "debug": "^4.3.4", - "ts-api-utils": "^2.0.1" + "ts-api-utils": "^2.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4587,9 +4634,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.27.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.27.0.tgz", - "integrity": "sha512-/6cp9yL72yUHAYq9g6DsAU+vVfvQmd1a8KyA81uvfDE21O2DwQ/qxlM4AR8TSdAu+kJLBDrEHKC5/W2/nxsY0A==", + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.0.tgz", + "integrity": "sha512-O5Id6tGadAZEMThM6L9HmVf5hQUXNSxLVKeGJYWNhhVseps/0LddMkp7//VDkzwJ69lPL0UmZdcZwggj9akJaA==", "dev": true, "license": "MIT", "engines": { @@ -4601,20 +4648,20 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.27.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.27.0.tgz", - "integrity": "sha512-BnKq8cqPVoMw71O38a1tEb6iebEgGA80icSxW7g+kndx0o6ot6696HjG7NdgfuAVmVEtwXUr3L8R9ZuVjoQL6A==", + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.0.tgz", + "integrity": "sha512-pU9VD7anSCOIoBFnhTGfOzlVFQIA1XXiQpH/CezqOBaDppRwTglJzCC6fUQGpfwey4T183NKhF1/mfatYmjRqQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.27.0", - "@typescript-eslint/visitor-keys": "8.27.0", + "@typescript-eslint/types": "8.32.0", + "@typescript-eslint/visitor-keys": "8.32.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", - "ts-api-utils": "^2.0.1" + "ts-api-utils": "^2.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4628,16 +4675,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.27.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.27.0.tgz", - "integrity": "sha512-njkodcwH1yvmo31YWgRHNb/x1Xhhq4/m81PhtvmRngD8iHPehxffz1SNCO+kwaePhATC+kOa/ggmvPoPza5i0Q==", + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.0.tgz", + "integrity": "sha512-8S9hXau6nQ/sYVtC3D6ISIDoJzS1NsCK+gluVhLN2YkBPX+/1wkwyUiDKnxRh15579WoOIyVWnoyIf3yGI9REw==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.27.0", - "@typescript-eslint/types": "8.27.0", - "@typescript-eslint/typescript-estree": "8.27.0" + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.32.0", + "@typescript-eslint/types": "8.32.0", + "@typescript-eslint/typescript-estree": "8.32.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4652,13 +4699,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.27.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.27.0.tgz", - "integrity": "sha512-WsXQwMkILJvffP6z4U3FYJPlbf/j07HIxmDjZpbNvBJkMfvwXj5ACRkkHwBDvLBbDbtX5TdU64/rcvKJ/vuInQ==", + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.0.tgz", + "integrity": "sha512-1rYQTCLFFzOI5Nl0c8LUpJT8HxpwVRn9E4CkMsYfuN6ctmQqExjSTzzSk0Tz2apmXy7WU6/6fyaZVVA/thPN+w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.27.0", + "@typescript-eslint/types": "8.32.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -4689,10 +4736,10 @@ "dev": true, "license": "ISC" }, - "node_modules/@unrs/rspack-resolver-binding-darwin-arm64": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@unrs/rspack-resolver-binding-darwin-arm64/-/rspack-resolver-binding-darwin-arm64-1.2.2.tgz", - "integrity": "sha512-i7z0B+C0P8Q63O/5PXJAzeFtA1ttY3OR2VSJgGv18S+PFNwD98xHgAgPOT1H5HIV6jlQP8Avzbp09qxJUdpPNw==", + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.7.2.tgz", + "integrity": "sha512-vxtBno4xvowwNmO/ASL0Y45TpHqmNkAaDtz4Jqb+clmcVSSl8XCG/PNFFkGsXXXS6AMjP+ja/TtNCFFa1QwLRg==", "cpu": [ "arm64" ], @@ -4703,10 +4750,10 @@ "darwin" ] }, - "node_modules/@unrs/rspack-resolver-binding-darwin-x64": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@unrs/rspack-resolver-binding-darwin-x64/-/rspack-resolver-binding-darwin-x64-1.2.2.tgz", - "integrity": "sha512-YEdFzPjIbDUCfmehC6eS+AdJYtFWY35YYgWUnqqTM2oe/N58GhNy5yRllxYhxwJ9GcfHoNc6Ubze1yjkNv+9Qg==", + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.7.2.tgz", + "integrity": "sha512-qhVa8ozu92C23Hsmv0BF4+5Dyyd5STT1FolV4whNgbY6mj3kA0qsrGPe35zNR3wAN7eFict3s4Rc2dDTPBTuFQ==", "cpu": [ "x64" ], @@ -4717,10 +4764,10 @@ "darwin" ] }, - "node_modules/@unrs/rspack-resolver-binding-freebsd-x64": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@unrs/rspack-resolver-binding-freebsd-x64/-/rspack-resolver-binding-freebsd-x64-1.2.2.tgz", - "integrity": "sha512-TU4ntNXDgPN2giQyyzSnGWf/dVCem5lvwxg0XYvsvz35h5H19WrhTmHgbrULMuypCB3aHe1enYUC9rPLDw45mA==", + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.7.2.tgz", + "integrity": "sha512-zKKdm2uMXqLFX6Ac7K5ElnnG5VIXbDlFWzg4WJ8CGUedJryM5A3cTgHuGMw1+P5ziV8CRhnSEgOnurTI4vpHpg==", "cpu": [ "x64" ], @@ -4731,10 +4778,10 @@ "freebsd" ] }, - "node_modules/@unrs/rspack-resolver-binding-linux-arm-gnueabihf": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@unrs/rspack-resolver-binding-linux-arm-gnueabihf/-/rspack-resolver-binding-linux-arm-gnueabihf-1.2.2.tgz", - "integrity": "sha512-ik3w4/rU6RujBvNWiDnKdXi1smBhqxEDhccNi/j2rHaMjm0Fk49KkJ6XKsoUnD2kZ5xaMJf9JjailW/okfUPIw==", + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.7.2.tgz", + "integrity": "sha512-8N1z1TbPnHH+iDS/42GJ0bMPLiGK+cUqOhNbMKtWJ4oFGzqSJk/zoXFzcQkgtI63qMcUI7wW1tq2usZQSb2jxw==", "cpu": [ "arm" ], @@ -4745,10 +4792,24 @@ "linux" ] }, - "node_modules/@unrs/rspack-resolver-binding-linux-arm64-gnu": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@unrs/rspack-resolver-binding-linux-arm64-gnu/-/rspack-resolver-binding-linux-arm64-gnu-1.2.2.tgz", - "integrity": "sha512-fp4Azi8kHz6TX8SFmKfyScZrMLfp++uRm2srpqRjsRZIIBzH74NtSkdEUHImR4G7f7XJ+sVZjCc6KDDK04YEpQ==", + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.7.2.tgz", + "integrity": "sha512-tjYzI9LcAXR9MYd9rO45m1s0B/6bJNuZ6jeOxo1pq1K6OBuRMMmfyvJYval3s9FPPGmrldYA3mi4gWDlWuTFGA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.7.2.tgz", + "integrity": "sha512-jon9M7DKRLGZ9VYSkFMflvNqu9hDtOCEnO2QAryFWgT6o6AXU8du56V7YqnaLKr6rAbZBWYsYpikF226v423QA==", "cpu": [ "arm64" ], @@ -4759,10 +4820,10 @@ "linux" ] }, - "node_modules/@unrs/rspack-resolver-binding-linux-arm64-musl": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@unrs/rspack-resolver-binding-linux-arm64-musl/-/rspack-resolver-binding-linux-arm64-musl-1.2.2.tgz", - "integrity": "sha512-gMiG3DCFioJxdGBzhlL86KcFgt9HGz0iDhw0YVYPsShItpN5pqIkNrI+L/Q/0gfDiGrfcE0X3VANSYIPmqEAlQ==", + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.7.2.tgz", + "integrity": "sha512-c8Cg4/h+kQ63pL43wBNaVMmOjXI/X62wQmru51qjfTvI7kmCy5uHTJvK/9LrF0G8Jdx8r34d019P1DVJmhXQpA==", "cpu": [ "arm64" ], @@ -4773,10 +4834,66 @@ "linux" ] }, - "node_modules/@unrs/rspack-resolver-binding-linux-x64-gnu": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@unrs/rspack-resolver-binding-linux-x64-gnu/-/rspack-resolver-binding-linux-x64-gnu-1.2.2.tgz", - "integrity": "sha512-n/4n2CxaUF9tcaJxEaZm+lqvaw2gflfWQ1R9I7WQgYkKEKbRKbpG/R3hopYdUmLSRI4xaW1Cy0Bz40eS2Yi4Sw==", + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.7.2.tgz", + "integrity": "sha512-A+lcwRFyrjeJmv3JJvhz5NbcCkLQL6Mk16kHTNm6/aGNc4FwPHPE4DR9DwuCvCnVHvF5IAd9U4VIs/VvVir5lg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.7.2.tgz", + "integrity": "sha512-hQQ4TJQrSQW8JlPm7tRpXN8OCNP9ez7PajJNjRD1ZTHQAy685OYqPrKjfaMw/8LiHCt8AZ74rfUVHP9vn0N69Q==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.7.2.tgz", + "integrity": "sha512-NoAGbiqrxtY8kVooZ24i70CjLDlUFI7nDj3I9y54U94p+3kPxwd2L692YsdLa+cqQ0VoqMWoehDFp21PKRUoIQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.7.2.tgz", + "integrity": "sha512-KaZByo8xuQZbUhhreBTW+yUnOIHUsv04P8lKjQ5otiGoSJ17ISGYArc+4vKdLEpGaLbemGzr4ZeUbYQQsLWFjA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.7.2.tgz", + "integrity": "sha512-dEidzJDubxxhUCBJ/SHSMJD/9q7JkyfBMT77Px1npl4xpg9t0POLvnWywSk66BgZS/b2Hy9Y1yFaoMTFJUe9yg==", "cpu": [ "x64" ], @@ -4787,10 +4904,10 @@ "linux" ] }, - "node_modules/@unrs/rspack-resolver-binding-linux-x64-musl": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@unrs/rspack-resolver-binding-linux-x64-musl/-/rspack-resolver-binding-linux-x64-musl-1.2.2.tgz", - "integrity": "sha512-cHyhAr6rlYYbon1L2Ag449YCj3p6XMfcYTP0AQX+KkQo025d1y/VFtPWvjMhuEsE2lLvtHm7GdJozj6BOMtzVg==", + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.7.2.tgz", + "integrity": "sha512-RvP+Ux3wDjmnZDT4XWFfNBRVG0fMsc+yVzNFUqOflnDfZ9OYujv6nkh+GOr+watwrW4wdp6ASfG/e7bkDradsw==", "cpu": [ "x64" ], @@ -4801,10 +4918,10 @@ "linux" ] }, - "node_modules/@unrs/rspack-resolver-binding-wasm32-wasi": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@unrs/rspack-resolver-binding-wasm32-wasi/-/rspack-resolver-binding-wasm32-wasi-1.2.2.tgz", - "integrity": "sha512-eogDKuICghDLGc32FtP+WniG38IB1RcGOGz0G3z8406dUdjJvxfHGuGs/dSlM9YEp/v0lEqhJ4mBu6X2nL9pog==", + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.7.2.tgz", + "integrity": "sha512-y797JBmO9IsvXVRCKDXOxjyAE4+CcZpla2GSoBQ33TVb3ILXuFnMrbR/QQZoauBYeOFuu4w3ifWLw52sdHGz6g==", "cpu": [ "wasm32" ], @@ -4812,16 +4929,16 @@ "license": "MIT", "optional": true, "dependencies": { - "@napi-rs/wasm-runtime": "^0.2.7" + "@napi-rs/wasm-runtime": "^0.2.9" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/@unrs/rspack-resolver-binding-win32-arm64-msvc": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@unrs/rspack-resolver-binding-win32-arm64-msvc/-/rspack-resolver-binding-win32-arm64-msvc-1.2.2.tgz", - "integrity": "sha512-7sWRJumhpXSi2lccX8aQpfFXHsSVASdWndLv8AmD8nDRA/5PBi8IplQVZNx2mYRx6+Bp91Z00kuVqpXO9NfCTg==", + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.7.2.tgz", + "integrity": "sha512-gtYTh4/VREVSLA+gHrfbWxaMO/00y+34htY7XpioBTy56YN2eBjkPrY1ML1Zys89X3RJDKVaogzwxlM1qU7egg==", "cpu": [ "arm64" ], @@ -4832,10 +4949,24 @@ "win32" ] }, - "node_modules/@unrs/rspack-resolver-binding-win32-x64-msvc": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@unrs/rspack-resolver-binding-win32-x64-msvc/-/rspack-resolver-binding-win32-x64-msvc-1.2.2.tgz", - "integrity": "sha512-hewo/UMGP1a7O6FG/ThcPzSJdm/WwrYDNkdGgWl6M18H6K6MSitklomWpT9MUtT5KGj++QJb06va/14QBC4pvw==", + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.7.2.tgz", + "integrity": "sha512-Ywv20XHvHTDRQs12jd3MY8X5C8KLjDbg/jyaal/QLKx3fAShhJyD4blEANInsjxW3P7isHx1Blt56iUDDJO3jg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.7.2.tgz", + "integrity": "sha512-friS8NEQfHaDbkThxopGk+LuE5v3iY0StruifjQEt7SLbA46OnfgMO15sOTkbpJkol6RB+1l1TYPXh0sCddpvA==", "cpu": [ "x64" ], @@ -4861,9 +4992,9 @@ } }, "node_modules/@vitest/coverage-v8": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.9.tgz", - "integrity": "sha512-15OACZcBtQ34keIEn19JYTVuMFTlFrClclwWjHo/IRPg/8ELpkgNTl0o7WLP9WO9XGH6+tip9CPYtEOrIDJvBA==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.1.3.tgz", + "integrity": "sha512-cj76U5gXCl3g88KSnf80kof6+6w+K4BjOflCl7t6yRJPDuCrHtVu0SgNYOUARJOL5TI8RScDbm5x4s1/P9bvpw==", "dev": true, "license": "MIT", "dependencies": { @@ -4876,7 +5007,7 @@ "istanbul-reports": "^3.1.7", "magic-string": "^0.30.17", "magicast": "^0.3.5", - "std-env": "^3.8.0", + "std-env": "^3.9.0", "test-exclude": "^7.0.1", "tinyrainbow": "^2.0.0" }, @@ -4884,8 +5015,8 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "3.0.9", - "vitest": "3.0.9" + "@vitest/browser": "3.1.3", + "vitest": "3.1.3" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -4894,14 +5025,14 @@ } }, "node_modules/@vitest/expect": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.9.tgz", - "integrity": "sha512-5eCqRItYgIML7NNVgJj6TVCmdzE7ZVgJhruW0ziSQV4V7PvLkDL1bBkBdcTs/VuIz0IxPb5da1IDSqc1TR9eig==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.1.3.tgz", + "integrity": "sha512-7FTQQuuLKmN1Ig/h+h/GO+44Q1IlglPlR2es4ab7Yvfx+Uk5xsv+Ykk+MEt/M2Yn/xGmzaLKxGw2lgy2bwuYqg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.0.9", - "@vitest/utils": "3.0.9", + "@vitest/spy": "3.1.3", + "@vitest/utils": "3.1.3", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" }, @@ -4910,13 +5041,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.9.tgz", - "integrity": "sha512-ryERPIBOnvevAkTq+L1lD+DTFBRcjueL9lOUfXsLfwP92h4e+Heb+PjiqS3/OURWPtywfafK0kj++yDFjWUmrA==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.1.3.tgz", + "integrity": "sha512-PJbLjonJK82uCWHjzgBJZuR7zmAOrSvKk1QBxrennDIgtH4uK0TB1PvYmc0XBCigxxtiAVPfWtAdy4lpz8SQGQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.0.9", + "@vitest/spy": "3.1.3", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, @@ -4947,9 +5078,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.9.tgz", - "integrity": "sha512-OW9F8t2J3AwFEwENg3yMyKWweF7oRJlMyHOMIhO5F3n0+cgQAJZBjNgrF8dLwFTEXl5jUqBLXd9QyyKv8zEcmA==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.3.tgz", + "integrity": "sha512-i6FDiBeJUGLDKADw2Gb01UtUNb12yyXAqC/mmRWuYl+m/U9GS7s8us5ONmGkGpUUo7/iAYzI2ePVfOZTYvUifA==", "dev": true, "license": "MIT", "dependencies": { @@ -4960,13 +5091,13 @@ } }, "node_modules/@vitest/runner": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.9.tgz", - "integrity": "sha512-NX9oUXgF9HPfJSwl8tUZCMP1oGx2+Sf+ru6d05QjzQz4OwWg0psEzwY6VexP2tTHWdOkhKHUIZH+fS6nA7jfOw==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.1.3.tgz", + "integrity": "sha512-Tae+ogtlNfFei5DggOsSUvkIaSuVywujMj6HzR97AHK6XK8i3BuVyIifWAm/sE3a15lF5RH9yQIrbXYuo0IFyA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.0.9", + "@vitest/utils": "3.1.3", "pathe": "^2.0.3" }, "funding": { @@ -4974,13 +5105,13 @@ } }, "node_modules/@vitest/snapshot": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.9.tgz", - "integrity": "sha512-AiLUiuZ0FuA+/8i19mTYd+re5jqjEc2jZbgJ2up0VY0Ddyyxg/uUtBDpIFAy4uzKaQxOW8gMgBdAJJ2ydhu39A==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.1.3.tgz", + "integrity": "sha512-XVa5OPNTYUsyqG9skuUkFzAeFnEzDp8hQu7kZ0N25B1+6KjGm4hWLtURyBbsIAOekfWQ7Wuz/N/XXzgYO3deWQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.0.9", + "@vitest/pretty-format": "3.1.3", "magic-string": "^0.30.17", "pathe": "^2.0.3" }, @@ -4989,9 +5120,9 @@ } }, "node_modules/@vitest/spy": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.9.tgz", - "integrity": "sha512-/CcK2UDl0aQ2wtkp3YVWldrpLRNCfVcIOFGlVGKO4R5eajsH393Z1yiXLVQ7vWsj26JOEjeZI0x5sm5P4OGUNQ==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.1.3.tgz", + "integrity": "sha512-x6w+ctOEmEXdWaa6TO4ilb7l9DxPR5bwEb6hILKuxfU1NqWT2mpJD9NJN7t3OTfxmVlOMrvtoFJGdgyzZ605lQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5002,35 +5133,35 @@ } }, "node_modules/@vitest/ui": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-3.0.9.tgz", - "integrity": "sha512-FpZD4aIv/qNpwkV3XbLV6xldWFHMgoNWAJEgg5GmpObmAOLAErpYjew9dDwXdYdKOS3iZRKdwI+P3JOJcYeUBg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-3.1.3.tgz", + "integrity": "sha512-IipSzX+8DptUdXN/GWq3hq5z18MwnpphYdOMm0WndkRGYELzfq7NDP8dMpZT7JGW1uXFrIGxOW2D0Xi++ulByg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.0.9", + "@vitest/utils": "3.1.3", "fflate": "^0.8.2", "flatted": "^3.3.3", "pathe": "^2.0.3", "sirv": "^3.0.1", - "tinyglobby": "^0.2.12", + "tinyglobby": "^0.2.13", "tinyrainbow": "^2.0.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "vitest": "3.0.9" + "vitest": "3.1.3" } }, "node_modules/@vitest/utils": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.9.tgz", - "integrity": "sha512-ilHM5fHhZ89MCp5aAaM9uhfl1c2JdxVxl3McqsdVyVNN6JffnEen8UMCdRTzOhGXNQGo5GNL9QugHrz727Wnng==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.1.3.tgz", + "integrity": "sha512-2Ltrpht4OmHO9+c/nmHtF09HWiyWdworqnHIwjfvDyWjuwKbdkcS9AnhsDn+8E2RM4x++foD1/tNuLPVvWG1Rg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.0.9", + "@vitest/pretty-format": "3.1.3", "loupe": "^3.1.3", "tinyrainbow": "^2.0.0" }, @@ -5342,6 +5473,43 @@ "url": "https://github.com/sponsors/antfu" } }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/acorn": { "version": "8.14.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", @@ -5752,6 +5920,27 @@ "url": "https://github.com/sponsors/antfu" } }, + "node_modules/body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -6345,15 +6534,14 @@ } }, "node_modules/cmake-js": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/cmake-js/-/cmake-js-7.3.0.tgz", - "integrity": "sha512-dXs2zq9WxrV87bpJ+WbnGKv8WUBXDw8blNiwNHoRe/it+ptscxhQHKB1SJXa1w+kocLMeP28Tk4/eTCezg4o+w==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/cmake-js/-/cmake-js-7.3.1.tgz", + "integrity": "sha512-aJtHDrTFl8qovjSSqXT9aC2jdGfmP8JQsPtjdLAXFfH1BF4/ImZ27Jx0R61TFg8Apc3pl6e2yBKMveAeRXx2Rw==", "license": "MIT", "dependencies": { "axios": "^1.6.5", "debug": "^4", "fs-extra": "^11.2.0", - "lodash.isplainobject": "^4.0.6", "memory-stream": "^1.0.0", "node-api-headers": "^1.1.0", "npmlog": "^6.0.2", @@ -6541,6 +6729,29 @@ "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", "license": "ISC" }, + "node_modules/content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/conventional-changelog-angular": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", @@ -6642,6 +6853,26 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, "node_modules/copy-anything": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", @@ -6662,6 +6893,20 @@ "dev": true, "license": "MIT" }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/cosmiconfig": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", @@ -7052,6 +7297,16 @@ "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", "license": "MIT" }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -7219,10 +7474,17 @@ "dev": true, "license": "MIT" }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true, + "license": "MIT" + }, "node_modules/electron": { - "version": "35.0.3", - "resolved": "https://registry.npmjs.org/electron/-/electron-35.0.3.tgz", - "integrity": "sha512-kjQAYEWXSr2TyK19IZoF85dzFIBaYuX7Yp/C+34b5Y/jmI2z270CGie+RjmEGMMitsy0G8YJKftukhYMuWlK6g==", + "version": "36.2.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-36.2.0.tgz", + "integrity": "sha512-5yldoRjBKxPQfI0QMX+qq750o3Nl8N1SZnJqOPMq0gZ6rIJ+7y4ZLp808GrFwjfTm05TYgq3GSD8FGuKQZqwEw==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -7258,6 +7520,16 @@ "dev": true, "license": "MIT" }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -7583,9 +7855,9 @@ } }, "node_modules/es-module-lexer": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", - "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", "dev": true, "license": "MIT" }, @@ -7647,9 +7919,9 @@ } }, "node_modules/es-toolkit": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.33.0.tgz", - "integrity": "sha512-X13Q/ZSc+vsO1q600bvNK4bxgXMkHcf//RxCmYDaRY5DAcT+eoXjY5hoAPGMdRnWQjvyLEcyauG3b6hz76LNqg==", + "version": "1.37.2", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.37.2.tgz", + "integrity": "sha512-ADDfk+pPFF0ofMpRAIc6on01p8heiuwuuJsYLzTP4UOjxVK9QsE2+0D1Q4J/zX2XBo6ac+27H5++YBIwmGAX/g==", "dev": true, "license": "MIT", "workspaces": [ @@ -7713,6 +7985,13 @@ "node": ">=6" } }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true, + "license": "MIT" + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -7727,23 +8006,24 @@ } }, "node_modules/eslint": { - "version": "9.23.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.23.0.tgz", - "integrity": "sha512-jV7AbNoFPAY1EkFYpLq5bslU9NLNO8xnEeQXwErNibVryjk67wHVmddTBilc5srIttJDBrB0eMHKZBFbSIABCw==", + "version": "9.26.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.26.0.tgz", + "integrity": "sha512-Hx0MOjPh6uK9oq9nVsATZKE/Wlbai7KFjfCuw9UHaguDW3x+HF0O5nIi3ud39TWgrTjTO5nHxmL3R1eANinWHQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.19.2", - "@eslint/config-helpers": "^0.2.0", - "@eslint/core": "^0.12.0", + "@eslint/config-array": "^0.20.0", + "@eslint/config-helpers": "^0.2.1", + "@eslint/core": "^0.13.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.23.0", - "@eslint/plugin-kit": "^0.2.7", + "@eslint/js": "9.26.0", + "@eslint/plugin-kit": "^0.2.8", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", + "@modelcontextprotocol/sdk": "^1.8.0", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -7767,7 +8047,8 @@ "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3" + "optionator": "^0.9.3", + "zod": "^3.24.2" }, "bin": { "eslint": "bin/eslint.js" @@ -7826,29 +8107,29 @@ } }, "node_modules/eslint-import-resolver-typescript": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-4.2.2.tgz", - "integrity": "sha512-Rg1YEsb9UKLQ8BOv27cS3TZ6LhEAKQVgVOXArcE/sQrlnX8+FjmJRSC29ij1qrn+eurFuMsCFUcs7/+27T0vqQ==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-4.3.4.tgz", + "integrity": "sha512-buzw5z5VtiQMysYLH9iW9BV04YyZebsw+gPi+c4FCjfS9i6COYOrEWw9t3m3wA9PFBfqcBCqWf32qrXLbwafDw==", "dev": true, "license": "ISC", "dependencies": { "debug": "^4.4.0", "get-tsconfig": "^4.10.0", - "rspack-resolver": "^1.2.2", + "is-bun-module": "^2.0.0", "stable-hash": "^0.0.5", - "tinyglobby": "^0.2.12" + "tinyglobby": "^0.2.13", + "unrs-resolver": "^1.6.3" }, "engines": { "node": "^16.17.0 || >=18.6.0" }, "funding": { - "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + "url": "https://opencollective.com/eslint-import-resolver-typescript" }, "peerDependencies": { "eslint": "*", "eslint-plugin-import": "*", - "eslint-plugin-import-x": "*", - "is-bun-module": "*" + "eslint-plugin-import-x": "*" }, "peerDependenciesMeta": { "eslint-plugin-import": { @@ -7856,9 +8137,6 @@ }, "eslint-plugin-import-x": { "optional": true - }, - "is-bun-module": { - "optional": true } } }, @@ -7991,9 +8269,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "50.6.8", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.6.8.tgz", - "integrity": "sha512-PPZVqhoXaalMQwDGzcQrJtPSPIPOYsSMtvkjYAdsIazOW20yhYtVX4+jLL+XznD4zYTXyZbPWPRKkNev4D4lyw==", + "version": "50.6.14", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.6.14.tgz", + "integrity": "sha512-JUudvooQbUx3iB8n/MzXMOV/VtaXq7xL4CeXhYryinr8osck7nV6fE2/xUXTiH3epPXcvq6TE3HQfGQuRHErTQ==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -8004,10 +8282,9 @@ "escape-string-regexp": "^4.0.0", "espree": "^10.1.0", "esquery": "^1.6.0", - "parse-imports": "^2.1.1", + "parse-imports-exports": "^0.2.4", "semver": "^7.6.3", - "spdx-expression-parse": "^4.0.0", - "synckit": "^0.9.1" + "spdx-expression-parse": "^4.0.0" }, "engines": { "node": ">=18" @@ -8017,13 +8294,13 @@ } }, "node_modules/eslint-plugin-n": { - "version": "17.16.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.16.2.tgz", - "integrity": "sha512-iQM5Oj+9o0KaeLoObJC/uxNGpktZCkYiTTBo8PkRWq3HwNcRxwpvSDFjBhQ5+HLJzBTy+CLDC5+bw0Z5GyhlOQ==", + "version": "17.18.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.18.0.tgz", + "integrity": "sha512-hvZ/HusueqTJ7VDLoCpjN0hx4N4+jHIWTXD4TMLHy9F23XkDagR9v+xQWRWR57yY55GPF8NnD4ox9iGTxirY8A==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.1", + "@eslint-community/eslint-utils": "^4.5.0", "enhanced-resolve": "^5.17.1", "eslint-plugin-es-x": "^7.8.0", "get-tsconfig": "^4.8.1", @@ -8359,12 +8636,45 @@ "node": ">=0.10.0" } }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/eventemitter3": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", "license": "MIT" }, + "node_modules/eventsource": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", + "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eventsource-parser": "^3.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/eventsource-parser": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.1.tgz", + "integrity": "sha512-VARTJ9CYeuQYb0pZEPbzi740OWFgpHe7AYJ2WFZVnUDUQp5Dk2yJUgF36YsZ81cOyxT0QxmXD2EQpapAouzWVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/execa": { "version": "9.5.2", "resolved": "https://registry.npmjs.org/execa/-/execa-9.5.2.tgz", @@ -8393,15 +8703,97 @@ } }, "node_modules/expect-type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.0.tgz", - "integrity": "sha512-80F22aiJ3GLyVnS/B3HzgR6RelZVumzj9jkL0Rhz4h0xYbNW9PjlQz5h3J/SShErbXBc295vseR4/MIbVmUbeA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.1.tgz", + "integrity": "sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==", "dev": true, "license": "Apache-2.0", "engines": { "node": ">=12.0.0" } }, + "node_modules/express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express-rate-limit": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.0.tgz", + "integrity": "sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": "^4.11 || 5 || ^5.0.0-beta.1" + } + }, + "node_modules/express/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -8564,9 +8956,9 @@ } }, "node_modules/fdir": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz", - "integrity": "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==", + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", + "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", "dev": true, "license": "MIT", "peerDependencies": { @@ -8579,16 +8971,17 @@ } }, "node_modules/feed": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/feed/-/feed-4.2.2.tgz", - "integrity": "sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/feed/-/feed-5.0.0.tgz", + "integrity": "sha512-b+xl8kQ/bxInBKTe3GLCGDFU45kFiDSIEEdDUAUGGThN1Jqpx+7uFb95NEPjI1JAjXy2iEFPzxHsK2rIEyJibw==", "dev": true, "license": "MIT", "dependencies": { "xml-js": "^1.6.11" }, "engines": { - "node": ">=0.4.0" + "node": ">=20", + "pnpm": ">=10" } }, "node_modules/fflate": { @@ -8667,6 +9060,24 @@ "node": ">=8" } }, + "node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/find-up": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-7.0.0.tgz", @@ -8827,6 +9238,26 @@ "node": ">= 6" } }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/from2": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", @@ -9854,6 +10285,23 @@ "dev": true, "license": "BSD-2-Clause" }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/http-proxy-agent": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", @@ -9928,7 +10376,6 @@ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -9937,9 +10384,9 @@ } }, "node_modules/ignore": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.3.tgz", - "integrity": "sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.4.tgz", + "integrity": "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==", "license": "MIT", "engines": { "node": ">= 4" @@ -10092,6 +10539,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/ipull": { "version": "3.9.2", "resolved": "https://registry.npmjs.org/ipull/-/ipull-3.9.2.tgz", @@ -10243,15 +10700,13 @@ } }, "node_modules/is-bun-module": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.3.0.tgz", - "integrity": "sha512-DgXeu5UWI0IsMQundYb5UAOzm6G2eVnarJ0byP6Tm55iZNKceD59LNPA2L4VvsScTtHcw0yEkVwSf7PC+QoLSA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", "dev": true, "license": "MIT", - "optional": true, - "peer": true, "dependencies": { - "semver": "^7.6.3" + "semver": "^7.7.1" } }, "node_modules/is-callable": { @@ -10476,6 +10931,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "dev": true, + "license": "MIT" + }, "node_modules/is-regex": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", @@ -10935,9 +11397,9 @@ } }, "node_modules/less": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/less/-/less-4.2.2.tgz", - "integrity": "sha512-tkuLHQlvWUTeQ3doAqnHbNn8T6WX1KA8yvbKG9x4VtKtIjHsVKQZCH11zRgAfbDAXC2UNIg/K9BYAAcEzUIrNg==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/less/-/less-4.3.0.tgz", + "integrity": "sha512-X9RyH9fvemArzfdP8Pi3irr7lor2Ok4rOttDXBhlwDg+wKQsXOXgHWduAJE1EsF7JJx0w0bcO6BC6tCKKYnXKA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -10949,7 +11411,7 @@ "lessc": "bin/lessc" }, "engines": { - "node": ">=6" + "node": ">=14" }, "optionalDependencies": { "errno": "^0.1.1", @@ -11133,6 +11595,7 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true, "license": "MIT" }, "node_modules/lodash.isstring": { @@ -11646,6 +12109,16 @@ "dev": true, "license": "MIT" }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/memory-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/memory-stream/-/memory-stream-1.0.0.tgz", @@ -11668,6 +12141,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -12373,6 +12859,22 @@ "node": "^18 || >=20" } }, + "node_modules/napi-postinstall": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.2.3.tgz", + "integrity": "sha512-Mi7JISo/4Ij2tDZ2xBE2WH+/KvVlkhA6juEjpEeRAVPNCpN3nxJo/5FhDNKgBcdmcmhaH6JjgST4xY/23ZYK0w==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -12398,6 +12900,16 @@ "node": ">= 4.4.x" } }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -15412,26 +15924,39 @@ } }, "node_modules/octokit": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/octokit/-/octokit-4.1.2.tgz", - "integrity": "sha512-0kcTxJOK3yQrJsRb8wKa28hlTze4QOz4sLuUnfXXnhboDhFKgv8LxS86tFwbsafDW9JZ08ByuVAE8kQbYJIZkA==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/octokit/-/octokit-4.1.3.tgz", + "integrity": "sha512-PP+EL8h4xPCE9NBo6jXq6I2/EiTXsn1cg9F0IZehHBv/qhuQpyGMFElEB17miWKciuT6vRHiFFiG9+FoXOmg6A==", "license": "MIT", "dependencies": { - "@octokit/app": "^15.1.4", - "@octokit/core": "^6.1.4", + "@octokit/app": "^15.1.6", + "@octokit/core": "^6.1.5", "@octokit/oauth-app": "^7.1.6", "@octokit/plugin-paginate-graphql": "^5.2.4", - "@octokit/plugin-paginate-rest": "^11.4.2", - "@octokit/plugin-rest-endpoint-methods": "^13.3.1", - "@octokit/plugin-retry": "^7.1.4", - "@octokit/plugin-throttling": "^9.4.0", - "@octokit/request-error": "^6.1.7", - "@octokit/types": "^13.7.0" + "@octokit/plugin-paginate-rest": "^12.0.0", + "@octokit/plugin-rest-endpoint-methods": "^14.0.0", + "@octokit/plugin-retry": "^7.2.1", + "@octokit/plugin-throttling": "^10.0.0", + "@octokit/request-error": "^6.1.8", + "@octokit/types": "^14.0.0" }, "engines": { "node": ">= 18" } }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -15458,9 +15983,9 @@ } }, "node_modules/oniguruma-parser": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.5.4.tgz", - "integrity": "sha512-yNxcQ8sKvURiTwP0mV6bLQCYE7NKfKRRWunhbZnXgxSmB1OXa1lHrN3o4DZd+0Si0kU5blidK7BcROO8qv5TZA==", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.1.tgz", + "integrity": "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==", "dev": true, "license": "MIT" }, @@ -15717,18 +16242,14 @@ "node": ">=6" } }, - "node_modules/parse-imports": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/parse-imports/-/parse-imports-2.2.1.tgz", - "integrity": "sha512-OL/zLggRp8mFhKL0rNORUTR4yBYujK/uU+xZL+/0Rgm2QE4nLO9v8PzEweSJEbMGKmDRjJE4R3IMJlL2di4JeQ==", + "node_modules/parse-imports-exports": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/parse-imports-exports/-/parse-imports-exports-0.2.4.tgz", + "integrity": "sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ==", "dev": true, - "license": "Apache-2.0 AND MIT", + "license": "MIT", "dependencies": { - "es-module-lexer": "^1.5.3", - "slashes": "^3.0.12" - }, - "engines": { - "node": ">= 18" + "parse-statements": "1.0.11" } }, "node_modules/parse-json": { @@ -15772,6 +16293,13 @@ "node": ">= 0.10" } }, + "node_modules/parse-statements": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/parse-statements/-/parse-statements-1.0.11.tgz", + "integrity": "sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==", + "dev": true, + "license": "MIT" + }, "node_modules/parse5": { "version": "7.2.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", @@ -15802,6 +16330,16 @@ "dev": true, "license": "MIT" }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/path-browserify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", @@ -15862,6 +16400,16 @@ "node": "20 || >=22" } }, + "node_modules/path-to-regexp": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + } + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -15933,6 +16481,16 @@ "node": ">=4" } }, + "node_modules/pkce-challenge": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz", + "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16.20.0" + } + }, "node_modules/pkg-conf": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-2.1.0.tgz", @@ -16177,6 +16735,20 @@ "dev": true, "license": "ISC" }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -16222,6 +16794,22 @@ "node": ">=6" } }, + "node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -16256,6 +16844,32 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", + "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.6.3", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -16709,27 +17323,21 @@ "fsevents": "~2.3.2" } }, - "node_modules/rspack-resolver": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/rspack-resolver/-/rspack-resolver-1.2.2.tgz", - "integrity": "sha512-Fwc19jMBA3g+fxDJH2B4WxwZjE0VaaOL7OX/A4Wn5Zv7bOD/vyPZhzXfaO73Xc2GAlfi96g5fGUa378WbIGfFw==", + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", "dev": true, "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/JounQin" + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" }, - "optionalDependencies": { - "@unrs/rspack-resolver-binding-darwin-arm64": "1.2.2", - "@unrs/rspack-resolver-binding-darwin-x64": "1.2.2", - "@unrs/rspack-resolver-binding-freebsd-x64": "1.2.2", - "@unrs/rspack-resolver-binding-linux-arm-gnueabihf": "1.2.2", - "@unrs/rspack-resolver-binding-linux-arm64-gnu": "1.2.2", - "@unrs/rspack-resolver-binding-linux-arm64-musl": "1.2.2", - "@unrs/rspack-resolver-binding-linux-x64-gnu": "1.2.2", - "@unrs/rspack-resolver-binding-linux-x64-musl": "1.2.2", - "@unrs/rspack-resolver-binding-wasm32-wasi": "1.2.2", - "@unrs/rspack-resolver-binding-win32-arm64-msvc": "1.2.2", - "@unrs/rspack-resolver-binding-win32-x64-msvc": "1.2.2" + "engines": { + "node": ">= 18" } }, "node_modules/run-parallel": { @@ -16836,8 +17444,7 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, - "license": "MIT", - "optional": true + "license": "MIT" }, "node_modules/sax": { "version": "1.4.1", @@ -17046,6 +17653,52 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/send/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/send/node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/serialize-error": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", @@ -17077,6 +17730,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -17132,17 +17801,24 @@ "node": ">= 0.4" } }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true, + "license": "ISC" + }, "node_modules/sharp": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", - "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.1.tgz", + "integrity": "sha512-1j0w61+eVxu7DawFJtnfYcvSv6qPFvfTaqzTQ2BLknVhHTwGS8sc63ZBF4rzkWMBVKybo4S5OBtDdZahh2A1xg==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", - "semver": "^7.6.3" + "semver": "^7.7.1" }, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" @@ -17151,25 +17827,26 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.33.5", - "@img/sharp-darwin-x64": "0.33.5", - "@img/sharp-libvips-darwin-arm64": "1.0.4", - "@img/sharp-libvips-darwin-x64": "1.0.4", - "@img/sharp-libvips-linux-arm": "1.0.5", - "@img/sharp-libvips-linux-arm64": "1.0.4", - "@img/sharp-libvips-linux-s390x": "1.0.4", - "@img/sharp-libvips-linux-x64": "1.0.4", - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", - "@img/sharp-libvips-linuxmusl-x64": "1.0.4", - "@img/sharp-linux-arm": "0.33.5", - "@img/sharp-linux-arm64": "0.33.5", - "@img/sharp-linux-s390x": "0.33.5", - "@img/sharp-linux-x64": "0.33.5", - "@img/sharp-linuxmusl-arm64": "0.33.5", - "@img/sharp-linuxmusl-x64": "0.33.5", - "@img/sharp-wasm32": "0.33.5", - "@img/sharp-win32-ia32": "0.33.5", - "@img/sharp-win32-x64": "0.33.5" + "@img/sharp-darwin-arm64": "0.34.1", + "@img/sharp-darwin-x64": "0.34.1", + "@img/sharp-libvips-darwin-arm64": "1.1.0", + "@img/sharp-libvips-darwin-x64": "1.1.0", + "@img/sharp-libvips-linux-arm": "1.1.0", + "@img/sharp-libvips-linux-arm64": "1.1.0", + "@img/sharp-libvips-linux-ppc64": "1.1.0", + "@img/sharp-libvips-linux-s390x": "1.1.0", + "@img/sharp-libvips-linux-x64": "1.1.0", + "@img/sharp-libvips-linuxmusl-arm64": "1.1.0", + "@img/sharp-libvips-linuxmusl-x64": "1.1.0", + "@img/sharp-linux-arm": "0.34.1", + "@img/sharp-linux-arm64": "0.34.1", + "@img/sharp-linux-s390x": "0.34.1", + "@img/sharp-linux-x64": "0.34.1", + "@img/sharp-linuxmusl-arm64": "0.34.1", + "@img/sharp-linuxmusl-x64": "0.34.1", + "@img/sharp-wasm32": "0.34.1", + "@img/sharp-win32-ia32": "0.34.1", + "@img/sharp-win32-x64": "0.34.1" } }, "node_modules/shebang-command": { @@ -17545,13 +18222,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/slashes": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/slashes/-/slashes-3.0.12.tgz", - "integrity": "sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA==", - "dev": true, - "license": "ISC" - }, "node_modules/sleep-promise": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/sleep-promise/-/sleep-promise-9.1.0.tgz", @@ -17701,10 +18371,20 @@ "dev": true, "license": "MIT" }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/std-env": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.1.tgz", - "integrity": "sha512-vj5lIj3Mwf9D79hBkltk5qmkFI+biIKWS2IBxEyEU3AX1tUf7AoL8nSazCOiiqQsGKIq01SClsKEzweu34uwvA==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz", + "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==", "dev": true, "license": "MIT" }, @@ -18216,23 +18896,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/synckit": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", - "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@pkgr/core": "^0.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, "node_modules/tabbable": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", @@ -18518,20 +19181,20 @@ "license": "MIT" }, "node_modules/tinyexec": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", - "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz", + "integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==", "dev": true, "license": "MIT" }, "node_modules/tinyglobby": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz", - "integrity": "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==", + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", + "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", "dev": true, "license": "MIT", "dependencies": { - "fdir": "^6.4.3", + "fdir": "^6.4.4", "picomatch": "^4.0.2" }, "engines": { @@ -18593,6 +19256,16 @@ "node": ">=12" } }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, "node_modules/totalist": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", @@ -18757,6 +19430,44 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/type-is/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/type-is/node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/typed-array-buffer": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", @@ -18836,17 +19547,17 @@ } }, "node_modules/typedoc": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.28.1.tgz", - "integrity": "sha512-Mn2VPNMaxoe/hlBiLriG4U55oyAa3Xo+8HbtEwV7F5WEOPXqtxzGuMZhJYHaqFJpajeQ6ZDUC2c990NAtTbdgw==", + "version": "0.28.4", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.28.4.tgz", + "integrity": "sha512-xKvKpIywE1rnqqLgjkoq0F3wOqYaKO9nV6YkkSat6IxOWacUCc/7Es0hR3OPmkIqkPoEn7U3x+sYdG72rstZQA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@gerrit0/mini-shiki": "^3.2.1", + "@gerrit0/mini-shiki": "^3.2.2", "lunr": "^2.3.9", "markdown-it": "^14.1.0", "minimatch": "^9.0.5", - "yaml": "^2.7.0 " + "yaml": "^2.7.1" }, "bin": { "typedoc": "bin/typedoc" @@ -18860,9 +19571,9 @@ } }, "node_modules/typedoc-plugin-markdown": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.5.2.tgz", - "integrity": "sha512-n0wfkCQU4nts13v8RSWMzIGNMbDo4P+oumHW6JudriknJLJSzx7p19OKJP8rKXvBkA+SFFuT7mW8lkMZZROz4g==", + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.6.3.tgz", + "integrity": "sha512-86oODyM2zajXwLs4Wok2mwVEfCwCnp756QyhLGX2IfsdRYr1DXLCgJgnLndaMUjJD7FBhnLk2okbNE9PdLxYRw==", "dev": true, "license": "MIT", "engines": { @@ -18873,9 +19584,9 @@ } }, "node_modules/typedoc-plugin-mdn-links": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/typedoc-plugin-mdn-links/-/typedoc-plugin-mdn-links-5.0.1.tgz", - "integrity": "sha512-eofdcc2nZZpipz/ubjG+7UYMi6Xu95svUwnZ+ClJh6NJdrv7kAOerL9N3iDOpo5kwQeK86GqPWwnv6LUGo5Wrw==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/typedoc-plugin-mdn-links/-/typedoc-plugin-mdn-links-5.0.2.tgz", + "integrity": "sha512-Bd3lsVWPSpDkn6NGZyPHpcK088PUvH4SRq4RD97OjA6l8PQA3yOnJhGACtjmIDdcenRTgWUosH+55ANZhx/wkw==", "dev": true, "license": "MIT", "peerDependencies": { @@ -18893,9 +19604,9 @@ } }, "node_modules/typescript": { - "version": "5.8.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", - "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -18907,15 +19618,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.27.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.27.0.tgz", - "integrity": "sha512-ZZ/8+Y0rRUMuW1gJaPtLWe4ryHbsPLzzibk5Sq+IFa2aOH1Vo0gPr1fbA6pOnzBke7zC2Da4w8AyCgxKXo3lqA==", + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.32.0.tgz", + "integrity": "sha512-UMq2kxdXCzinFFPsXc9o2ozIpYCCOiEC46MG3yEh5Vipq6BO27otTtEBZA1fQ66DulEUgE97ucQ/3YY66CPg0A==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.27.0", - "@typescript-eslint/parser": "8.27.0", - "@typescript-eslint/utils": "8.27.0" + "@typescript-eslint/eslint-plugin": "8.32.0", + "@typescript-eslint/parser": "8.32.0", + "@typescript-eslint/utils": "8.32.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -18977,9 +19688,9 @@ "license": "MIT" }, "node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, @@ -19136,6 +19847,49 @@ "node": ">= 10.0.0" } }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unrs-resolver": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.7.2.tgz", + "integrity": "sha512-BBKpaylOW8KbHsu378Zky/dGh4ckT/4NW/0SHRABdqRLcQJ2dAOjDo9g97p04sWflm0kqPqpUatxReNV/dqI5A==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/JounQin" + }, + "optionalDependencies": { + "@unrs/resolver-binding-darwin-arm64": "1.7.2", + "@unrs/resolver-binding-darwin-x64": "1.7.2", + "@unrs/resolver-binding-freebsd-x64": "1.7.2", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.7.2", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.7.2", + "@unrs/resolver-binding-linux-arm64-gnu": "1.7.2", + "@unrs/resolver-binding-linux-arm64-musl": "1.7.2", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.7.2", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.7.2", + "@unrs/resolver-binding-linux-riscv64-musl": "1.7.2", + "@unrs/resolver-binding-linux-s390x-gnu": "1.7.2", + "@unrs/resolver-binding-linux-x64-gnu": "1.7.2", + "@unrs/resolver-binding-linux-x64-musl": "1.7.2", + "@unrs/resolver-binding-wasm32-wasi": "1.7.2", + "@unrs/resolver-binding-win32-arm64-msvc": "1.7.2", + "@unrs/resolver-binding-win32-ia32-msvc": "1.7.2", + "@unrs/resolver-binding-win32-x64-msvc": "1.7.2" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -19193,6 +19947,16 @@ "node": "^18.17.0 || >=20.5.0" } }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/vfile": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", @@ -19299,15 +20063,15 @@ } }, "node_modules/vite-node": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.9.tgz", - "integrity": "sha512-w3Gdx7jDcuT9cNn9jExXgOyKmf5UOTb6WMHz8LGAm54eS1Elf5OuBhCxl6zJxGhEeIkgsE1WbHuoL0mj/UXqXg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.1.3.tgz", + "integrity": "sha512-uHV4plJ2IxCl4u1up1FQRrqclylKAogbtBfOTwcuJ28xFi+89PZ57BRh+naIRvH70HPwxy5QHYzg1OrEaC7AbA==", "dev": true, "license": "MIT", "dependencies": { "cac": "^6.7.14", "debug": "^4.4.0", - "es-module-lexer": "^1.6.0", + "es-module-lexer": "^1.7.0", "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0" }, @@ -19425,31 +20189,32 @@ } }, "node_modules/vitest": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.9.tgz", - "integrity": "sha512-BbcFDqNyBlfSpATmTtXOAOj71RNKDDvjBM/uPfnxxVGrG+FSH2RQIwgeEngTaTkuU/h0ScFvf+tRcKfYXzBybQ==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.1.3.tgz", + "integrity": "sha512-188iM4hAHQ0km23TN/adso1q5hhwKqUpv+Sd6p5sOuh6FhQnRNW3IsiIpvxqahtBabsJ2SLZgmGSpcYK4wQYJw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "3.0.9", - "@vitest/mocker": "3.0.9", - "@vitest/pretty-format": "^3.0.9", - "@vitest/runner": "3.0.9", - "@vitest/snapshot": "3.0.9", - "@vitest/spy": "3.0.9", - "@vitest/utils": "3.0.9", + "@vitest/expect": "3.1.3", + "@vitest/mocker": "3.1.3", + "@vitest/pretty-format": "^3.1.3", + "@vitest/runner": "3.1.3", + "@vitest/snapshot": "3.1.3", + "@vitest/spy": "3.1.3", + "@vitest/utils": "3.1.3", "chai": "^5.2.0", "debug": "^4.4.0", - "expect-type": "^1.1.0", + "expect-type": "^1.2.1", "magic-string": "^0.30.17", "pathe": "^2.0.3", - "std-env": "^3.8.0", + "std-env": "^3.9.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.13", "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", - "vite-node": "3.0.9", + "vite-node": "3.1.3", "why-is-node-running": "^2.3.0" }, "bin": { @@ -19465,8 +20230,8 @@ "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.0.9", - "@vitest/ui": "3.0.9", + "@vitest/browser": "3.1.3", + "@vitest/ui": "3.1.3", "happy-dom": "*", "jsdom": "*" }, @@ -19494,6 +20259,13 @@ } } }, + "node_modules/vitest/node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, "node_modules/vue": { "version": "3.5.13", "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.13.tgz", @@ -19830,9 +20602,9 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", - "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz", + "integrity": "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==", "dev": true, "license": "ISC", "bin": { @@ -19905,6 +20677,26 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/zod": { + "version": "3.24.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.4.tgz", + "integrity": "sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-json-schema": { + "version": "3.24.5", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz", + "integrity": "sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==", + "dev": true, + "license": "ISC", + "peerDependencies": { + "zod": "^3.24.1" + } + }, "node_modules/zwitch": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", @@ -19917,9 +20709,9 @@ } }, "node_modules/zx": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/zx/-/zx-8.4.1.tgz", - "integrity": "sha512-1Cb+Tfwt/daKV6wckBeDbB6h3IMauqj9KWp+EcbYzi9doeJeIHCktxp/yWspXOXRdoUzBCQSKoUgm3g8r9fz5A==", + "version": "8.5.4", + "resolved": "https://registry.npmjs.org/zx/-/zx-8.5.4.tgz", + "integrity": "sha512-44oKea9Sa8ZnOkTnS6fRJpg3quzgnbB43nLrVfYnqE86J4sxgZMUDLezzKET/FdOAVkF4X+Alm9Bume+W+RW9Q==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/package.json b/package.json index 30afc487..79f9834f 100644 --- a/package.json +++ b/package.json @@ -133,74 +133,74 @@ }, "homepage": "https://node-llama-cpp.withcat.ai", "devDependencies": { - "@commitlint/cli": "^19.8.0", - "@commitlint/config-conventional": "^19.8.0", - "@eslint/compat": "^1.2.7", + "@commitlint/cli": "^19.8.1", + "@commitlint/config-conventional": "^19.8.1", + "@eslint/compat": "^1.2.9", "@fontsource/inter": "^5.2.5", - "@nolebase/vitepress-plugin-git-changelog": "^2.15.1", - "@nolebase/vitepress-plugin-og-image": "^2.15.1", + "@nolebase/vitepress-plugin-git-changelog": "^2.17.0", + "@nolebase/vitepress-plugin-og-image": "^2.17.0", "@resvg/resvg-js": "^2.6.2", - "@semantic-release/exec": "^7.0.3", - "@semantic-release/github": "11.0.1", + "@semantic-release/exec": "^7.1.0", + "@semantic-release/github": "11.0.2", "@semantic-release/npm": "12.0.1", - "@shikijs/vitepress-twoslash": "^3.2.1", + "@shikijs/vitepress-twoslash": "^3.4.0", "@stylistic/eslint-plugin": "^4.2.0", "@types/async-retry": "^1.4.9", "@types/bytes": "^3.1.5", "@types/cross-spawn": "^6.0.6", "@types/fs-extra": "^11.0.4", - "@types/node": "^22.13.11", + "@types/node": "^22.15.17", "@types/proper-lockfile": "^4.1.4", - "@types/semver": "^7.5.8", + "@types/semver": "^7.7.0", "@types/validate-npm-package-name": "^4.0.2", "@types/which": "^3.0.4", "@types/yargs": "^17.0.33", - "@vitest/coverage-v8": "^3.0.9", - "@vitest/ui": "^3.0.9", - "electron": "^35.0.3", - "eslint": "^9.23.0", - "eslint-import-resolver-typescript": "^4.2.2", + "@vitest/coverage-v8": "^3.1.3", + "@vitest/ui": "^3.1.3", + "electron": "^36.2.0", + "eslint": "^9.26.0", + "eslint-import-resolver-typescript": "^4.3.4", "eslint-plugin-import": "^2.31.0", - "eslint-plugin-jsdoc": "^50.6.8", - "eslint-plugin-n": "^17.16.2", - "feed": "^4.2.2", + "eslint-plugin-jsdoc": "^50.6.14", + "eslint-plugin-n": "^17.18.0", + "feed": "^5.0.0", "husky": "^9.1.7", "rehype": "^13.0.2", "rimraf": "^6.0.1", "semantic-release": "^24.2.3", - "sharp": "^0.33.5", + "sharp": "^0.34.1", "tslib": "^2.8.1", - "typedoc": "^0.28.1", - "typedoc-plugin-markdown": "^4.5.2", - "typedoc-plugin-mdn-links": "^5.0.1", + "typedoc": "^0.28.4", + "typedoc-plugin-markdown": "^4.6.3", + "typedoc-plugin-mdn-links": "^5.0.2", "typedoc-vitepress-theme": "^1.1.2", - "typescript": "^5.8.2", - "typescript-eslint": "^8.27.0", - "vite-node": "^3.0.9", + "typescript": "^5.8.3", + "typescript-eslint": "^8.32.0", + "vite-node": "^3.1.3", "vitepress": "^1.6.3", - "vitest": "^3.0.9", - "zx": "^8.4.1" + "vitest": "^3.1.3", + "zx": "^8.5.4" }, "dependencies": { - "@huggingface/jinja": "^0.3.3", + "@huggingface/jinja": "^0.5.0", "async-retry": "^1.3.3", "bytes": "^3.1.2", "chalk": "^5.4.1", "chmodrp": "^1.0.2", - "cmake-js": "^7.3.0", + "cmake-js": "^7.3.1", "cross-env": "^7.0.3", "cross-spawn": "^7.0.6", "env-var": "^7.5.0", "filenamify": "^6.0.0", "fs-extra": "^11.3.0", - "ignore": "^7.0.0", + "ignore": "^7.0.4", "ipull": "^3.9.2", "is-unicode-supported": "^2.1.0", "lifecycle-utils": "^2.0.0", "log-symbols": "^7.0.0", "nanoid": "^5.1.5", "node-addon-api": "^8.3.1", - "octokit": "^4.1.2", + "octokit": "^4.1.3", "ora": "^8.2.0", "pretty-ms": "^9.2.0", "proper-lockfile": "^4.1.2", diff --git a/src/bindings/AddonTypes.ts b/src/bindings/AddonTypes.ts index c6d8a6cd..b1f3ca0b 100644 --- a/src/bindings/AddonTypes.ts +++ b/src/bindings/AddonTypes.ts @@ -149,6 +149,8 @@ export type AddonContext = { setThreads(threads: number): void, printTimings(): void, ensureDraftContextIsCompatibleForSpeculative(draftContext: AddonContext): void, + saveSequenceStateToFile(filePath: string, sequenceId: number, tokens: Uint32Array): Promise, + loadSequenceStateFromFile(filePath: string, sequenceId: number, maxContextSize: number): Promise, setLora(lora: AddonModelLora, scale: number): void }; diff --git a/src/bindings/getLlama.ts b/src/bindings/getLlama.ts index 62e5d95e..faf626b4 100644 --- a/src/bindings/getLlama.ts +++ b/src/bindings/getLlama.ts @@ -46,6 +46,7 @@ export type LlamaOptions = { * - **`false`**: Disable any GPU support and only use the CPU. * * `"auto"` by default. + * @see Use the `getLlamaGpuTypes` function to get the available GPU types (from the above list) for the current machine at runtime. */ gpu?: "auto" | LlamaGpuType | { type: "auto", @@ -155,7 +156,22 @@ export type LlamaOptions = { * * The default can be set using the `NODE_LLAMA_CPP_DEBUG` environment variable. */ - debug?: boolean + debug?: boolean, + + /** + * Loads existing binaries without loading the `llama.cpp` backend, + * and then disposes the returned `Llama` instance right away before returning it. + * + * Useful for performing a fast and efficient test to check whether the given configuration can be loaded. + * Can be used for determining which GPU types the current machine supports before actually using them. + * + * Enabling this option implies that `build: "never"` and `skipDownload: true`. + * + * The returned `Llama` instance will be disposed and cannot be used. + * + * Defaults to `false`. + */ + dryRun?: boolean }; export type LastBuildOptions = { @@ -230,7 +246,22 @@ export type LastBuildOptions = { * * The default can be set using the `NODE_LLAMA_CPP_DEBUG` environment variable. */ - debug?: boolean + debug?: boolean, + + /** + * Loads existing binaries without loading the `llama.cpp` backend, + * and then disposes the returned `Llama` instance right away before returning it. + * + * Useful for performing a fast and efficient test to check whether the given configuration can be loaded. + * Can be used for determining which GPU types the current machine supports before actually using them. + * + * Enabling this option implies that `build: "never"` and `skipDownload: true`. + * + * The returned `Llama` instance will be disposed and cannot be used. + * + * Defaults to `false`. + */ + dryRun?: boolean }; export const getLlamaFunctionName = "getLlama"; @@ -277,6 +308,7 @@ export async function getLlama(type: "lastBuild", lastBuildOptions?: LastBuildOp export async function getLlama(options?: LlamaOptions | "lastBuild", lastBuildOptions?: LastBuildOptions) { if (options === "lastBuild") { const lastBuildInfo = await getLastBuildInfo(); + const dryRun = lastBuildOptions?.dryRun ?? false; const getLlamaOptions: LlamaOptions = { logLevel: lastBuildOptions?.logLevel ?? defaultLlamaCppLogLevel, logger: lastBuildOptions?.logger ?? Llama.defaultConsoleLogger, @@ -286,7 +318,8 @@ export async function getLlama(options?: LlamaOptions | "lastBuild", lastBuildOp maxThreads: lastBuildOptions?.maxThreads, vramPadding: lastBuildOptions?.vramPadding ?? defaultLlamaVramPadding, ramPadding: lastBuildOptions?.ramPadding ?? defaultLlamaRamPadding, - debug: lastBuildOptions?.debug ?? defaultLlamaCppDebugMode + debug: lastBuildOptions?.debug ?? defaultLlamaCppDebugMode, + dryRun }; if (lastBuildInfo == null) @@ -302,7 +335,7 @@ export async function getLlama(options?: LlamaOptions | "lastBuild", lastBuildOp const binding = loadBindingModule(resolvedBindingPath); const buildMetadata = await getLocalBuildBinaryBuildMetadata(lastBuildInfo.folderName); - return await Llama._create({ + const res = await Llama._create({ bindings: binding, bindingPath: resolvedBindingPath, buildType: "localBuild", @@ -312,8 +345,14 @@ export async function getLlama(options?: LlamaOptions | "lastBuild", lastBuildOp maxThreads: lastBuildOptions?.maxThreads, vramPadding: lastBuildOptions?.vramPadding ?? defaultLlamaVramPadding, ramPadding: lastBuildOptions?.ramPadding ?? defaultLlamaRamPadding, - debug: lastBuildOptions?.debug ?? defaultLlamaCppDebugMode + debug: lastBuildOptions?.debug ?? defaultLlamaCppDebugMode, + skipLlamaInit: dryRun }); + + if (dryRun) + await res.dispose(); + + return res; } catch (err) { console.error(getConsoleLogPrefix() + "Failed to load last build. Error:", err); console.info(getConsoleLogPrefix() + "Falling back to default binaries"); @@ -339,7 +378,8 @@ export async function getLlamaForOptions({ maxThreads, vramPadding = defaultLlamaVramPadding, ramPadding = defaultLlamaRamPadding, - debug = defaultLlamaCppDebugMode + debug = defaultLlamaCppDebugMode, + dryRun = false }: LlamaOptions, { updateLastBuildInfoOnCompile = false, skipLlamaInit = false, @@ -363,6 +403,13 @@ export async function getLlamaForOptions({ if (vramPadding == null) vramPadding = defaultLlamaVramPadding; if (ramPadding == null) ramPadding = defaultLlamaRamPadding; if (debug == null) debug = defaultLlamaCppDebugMode; + if (dryRun == null) dryRun = false; + + if (dryRun) { + build = "never"; + skipDownload = true; + skipLlamaInit = true; + } const clonedLlamaCppRepoReleaseInfo = await getClonedLlamaCppRepoReleaseInfo(); let canUsePrebuiltBinaries = (build === "forceRebuild" || !usePrebuiltBinaries) @@ -404,7 +451,8 @@ export async function getLlamaForOptions({ maxThreads, vramPadding, ramPadding, - debug + debug, + dryRun }); } catch (err) { return await getLlamaForOptions({ @@ -420,7 +468,8 @@ export async function getLlamaForOptions({ maxThreads, vramPadding, ramPadding, - debug + debug, + dryRun }); } } else @@ -469,8 +518,12 @@ export async function getLlamaForOptions({ pipeBinaryTestErrorLogs }); - if (llama != null) + if (llama != null) { + if (dryRun) + await llama.dispose(); + return llama; + } } } @@ -511,8 +564,9 @@ export async function getLlamaForOptions({ llamaCpp: llamaCppInfo }; + let llama: Llama | undefined = undefined; try { - return await buildAndLoadLlamaBinary({ + llama = await buildAndLoadLlamaBinary({ buildOptions, skipDownload, logLevel, @@ -540,6 +594,13 @@ export async function getLlamaForOptions({ if (isLastItem) throw err; } + + if (llama != null) { + if (dryRun) + await llama.dispose(); + + return llama; + } } throw new Error("Failed to build llama.cpp"); diff --git a/src/bindings/utils/compileLLamaCpp.ts b/src/bindings/utils/compileLLamaCpp.ts index 93010809..91b6b338 100644 --- a/src/bindings/utils/compileLLamaCpp.ts +++ b/src/bindings/utils/compileLLamaCpp.ts @@ -130,6 +130,9 @@ export async function compileLlamaCpp(buildOptions: BuildOptions, compileOptions if (!cmakeCustomOptions.has("GGML_CCACHE")) cmakeCustomOptions.set("GGML_CCACHE", "OFF"); + if (!cmakeCustomOptions.has("LLAMA_CURL")) + cmakeCustomOptions.set("LLAMA_CURL", "OFF"); + if (buildOptions.platform === "win" && buildOptions.arch === "arm64" && !cmakeCustomOptions.has("GGML_OPENMP")) cmakeCustomOptions.set("GGML_OPENMP", "OFF"); @@ -461,6 +464,15 @@ async function applyResultDirFixes(resultDirPath: string, tempDirPath: string) { await fs.remove(tempDirPath); } + + // the vulkan-shaders-gen binary is not needed at runtime + const vulkanShadersGenBinary = path.join( + resultDirPath, + getPlatform() === "win" + ? "vulkan-shaders-gen.exe" + : "vulkan-shaders-gen" + ); + await fs.remove(vulkanShadersGenBinary); } async function resolvePrebuiltBinaryPath(prebuiltBinaryDirectoryPath: string) { diff --git a/src/bindings/utils/getLlamaGpuTypes.ts b/src/bindings/utils/getLlamaGpuTypes.ts new file mode 100644 index 00000000..82430132 --- /dev/null +++ b/src/bindings/utils/getLlamaGpuTypes.ts @@ -0,0 +1,36 @@ +import process from "process"; +import {LlamaGpuType} from "../types.js"; +import {getGpuTypesToUseForOption} from "./getGpuTypesToUseForOption.js"; +import {getPlatform} from "./getPlatform.js"; + +/** + * Get the list of GPU types that can be used with `getLlama` on the current machine. + * + * When passing `"supported"`, only the GPU types that have the + * necessary libraries and drivers installed on the current machine will be returned. + * All of these GPU types have prebuilt binaries for the current platform and architecture. + * + * When passing `"allValid"`, all GPU types that are compatible with the current OS and architecture will be returned. + * Some of these GPU types may not have prebuilt binaries for the current platform and architecture, + * as some of them are inadvisable for the current machine (like CUDA on an x64 Mac machine). + */ +export async function getLlamaGpuTypes(include: "supported" | "allValid"): Promise { + if (include === "supported") + return await getGpuTypesToUseForOption("auto"); + + const platform = getPlatform(); + const arch = process.arch; + + const res: LlamaGpuType[] = []; + + // Metal is not properly supported by llama.cpp on x64 Mac machines + if (platform === "mac" && arch === "arm64") + res.push("metal"); + else + res.push("cuda"); + + res.push("vulkan"); + res.push(false); + + return res; +} diff --git a/src/bindings/utils/testBindingBinary.ts b/src/bindings/utils/testBindingBinary.ts index 7151c702..ef59d6ad 100644 --- a/src/bindings/utils/testBindingBinary.ts +++ b/src/bindings/utils/testBindingBinary.ts @@ -3,9 +3,11 @@ import {fileURLToPath} from "url"; import {createRequire} from "module"; import path from "path"; import {getConsoleLogPrefix} from "../../utils/getConsoleLogPrefix.js"; -import {runningInElectron} from "../../utils/runtime.js"; +import {runningInBun, runningInElectron} from "../../utils/runtime.js"; import {BuildGpu, LlamaLogLevel} from "../types.js"; import {LlamaLogLevelToAddonLogLevel} from "../Llama.js"; +import {newGithubIssueUrl} from "../../config.js"; +import {getPlatform} from "./getPlatform.js"; import type {BindingModule} from "../AddonTypes.js"; const require = createRequire(import.meta.url); @@ -33,6 +35,28 @@ export async function testBindingBinary( return true; } + try { + const runningInsideSnapOnLinux = getPlatform() === "linux" && process.env.SNAP != null; + if (runningInsideSnapOnLinux && !runningInBun && !runningInElectron) { + const nodeSea = await import("node:sea"); + if (nodeSea.isSea()) { + console.warn( + getConsoleLogPrefix() + + "node SEA is detected, so testing a binding binary with the current system prior to importing it cannot be done.\n" + + getConsoleLogPrefix() + + "Assuming the test passed with the risk that the process may crash due to an incompatible binary.\n" + + getConsoleLogPrefix() + + "If this is an issue in your case, " + + "please open an issue on GitHub with the details of the environment where this happens: " + newGithubIssueUrl + ); + + return true; + } + } + } catch (err) { + // do nothing + } + async function getForkFunction() { if (runningInElectron) { try { @@ -273,7 +297,14 @@ if (process.env.TEST_BINDING_CP === "true" && (process.parentPort != null || pro const gpuType = binding.getGpuType(); void (gpuType as BuildGpu satisfies typeof gpuType); if (gpuType !== message.gpu) - throw new Error(`Binary GPU type mismatch. Expected: ${message.gpu}, got: ${gpuType}`); + throw new Error( + "Binary GPU type mismatch. " + + `Expected: ${message.gpu}, got: ${gpuType}. ` + ( + message.gpu === "cuda" + ? "May be due to a linker issue, ensure you don't have multiple conflicting CUDA installations." + : "May be due to a linker issue, ensure the native dependencies are not broken." + ) + ); binding.ensureGpuDeviceIsSupported(); diff --git a/src/chatWrappers/QwenChatWrapper.ts b/src/chatWrappers/QwenChatWrapper.ts index 6ac44a97..4fc3d7dd 100644 --- a/src/chatWrappers/QwenChatWrapper.ts +++ b/src/chatWrappers/QwenChatWrapper.ts @@ -1,7 +1,8 @@ import {ChatWrapper, ChatWrapperJinjaMatchConfiguration} from "../ChatWrapper.js"; import { - ChatModelFunctions, ChatWrapperCheckModelCompatibilityParams, ChatWrapperGenerateContextStateOptions, ChatWrapperGeneratedContextState, - ChatWrapperSettings, isChatModelResponseSegment + ChatModelFunctions, ChatModelResponse, ChatModelSegment, ChatWrapperCheckModelCompatibilityParams, + ChatWrapperGenerateContextStateOptions, ChatWrapperGeneratedContextState, ChatWrapperSettings, isChatModelResponseFunctionCall, + isChatModelResponseSegment } from "../types.js"; import {LlamaText, SpecialToken, SpecialTokensText} from "../utils/LlamaText.js"; import {GgufArchitectureType} from "../gguf/types/GgufMetadataTypes.js"; @@ -12,40 +13,9 @@ export class QwenChatWrapper extends ChatWrapper { public readonly wrapperName: string = "Qwen"; public readonly keepOnlyLastThought: boolean; + public readonly thoughts: "auto" | "discourage"; - public override readonly settings: ChatWrapperSettings = { - supportsSystemMessages: true, - functions: { - call: { - optionalPrefixSpace: true, - prefix: LlamaText("\n", new SpecialTokensText(""), '\n{"name": "'), - paramsPrefix: '", "arguments": ', - suffix: LlamaText("}\n", new SpecialTokensText("")), - emptyCallParamsPlaceholder: {} - }, - result: { - prefix: LlamaText(new SpecialTokensText("\n\n")), - suffix: LlamaText(new SpecialTokensText("\n")) - }, - parallelism: { - call: { - sectionPrefix: "", - sectionSuffix: LlamaText(new SpecialTokensText("<|im_end|>\n")) - }, - result: { - sectionPrefix: LlamaText(new SpecialTokensText("<|im_start|>user")), - sectionSuffix: LlamaText(new SpecialTokensText("<|im_end|>\n<|im_start|>assistant\n")) - } - } - }, - segments: { - reiterateStackAfterFunctionCalls: true, - thought: { - prefix: LlamaText(new SpecialTokensText("")), - suffix: LlamaText(new SpecialTokensText("")) - } - } - }; + public override readonly settings: ChatWrapperSettings; public constructor(options: { /** @@ -55,15 +25,70 @@ export class QwenChatWrapper extends ChatWrapper { * * Defaults to `true`. */ - keepOnlyLastThought?: boolean + keepOnlyLastThought?: boolean, + + /** + * Control the usage of thoughts in the model responses. + * + * Defaults to `"auto"`. + */ + thoughts?: "auto" | "discourage", + + /** @internal */ + _lineBreakBeforeFunctionCallPrefix?: boolean } = {}) { super(); const { - keepOnlyLastThought = true + keepOnlyLastThought = true, + thoughts = "auto", + _lineBreakBeforeFunctionCallPrefix = false } = options; this.keepOnlyLastThought = keepOnlyLastThought; + this.thoughts = thoughts; + + this.settings = { + supportsSystemMessages: true, + functions: { + call: { + optionalPrefixSpace: true, + prefix: LlamaText([ + _lineBreakBeforeFunctionCallPrefix + ? "\n" + : "", + new SpecialTokensText(""), '\n{"name": "' + ]), + paramsPrefix: '", "arguments": ', + suffix: LlamaText("}\n", new SpecialTokensText("")), + emptyCallParamsPlaceholder: {} + }, + result: { + prefix: LlamaText(new SpecialTokensText("\n\n")), + suffix: LlamaText(new SpecialTokensText("\n")) + }, + parallelism: { + call: { + sectionPrefix: "", + betweenCalls: _lineBreakBeforeFunctionCallPrefix + ? "" + : "\n", + sectionSuffix: LlamaText(new SpecialTokensText("<|im_end|>\n")) + }, + result: { + sectionPrefix: LlamaText(new SpecialTokensText("<|im_start|>user")), + sectionSuffix: LlamaText(new SpecialTokensText("<|im_end|>\n<|im_start|>assistant\n")) + } + } + }, + segments: { + reiterateStackAfterFunctionCalls: true, + thought: { + prefix: LlamaText(new SpecialTokensText("")), + suffix: LlamaText(new SpecialTokensText("")) + } + } + }; } public override generateContextState({ @@ -115,14 +140,18 @@ export class QwenChatWrapper extends ChatWrapper { } else if (item.type === "model") { flush(); + const transformedModelResponse = (this.thoughts === "discourage" && isLastItem) + ? discourageThoughtsInModelResponse(item.response) + : item.response; + currentAggregateFocus = null; modelTexts.push( this.generateModelResponseText( (this.keepOnlyLastThought && !isLastItem) - ? item.response.filter((response) => ( + ? transformedModelResponse.filter((response) => ( !isChatModelResponseSegment(response) || response.segmentType !== "thought" )) - : item.response + : transformedModelResponse ) ); } else @@ -204,13 +233,44 @@ export class QwenChatWrapper extends ChatWrapper { /** @internal */ public static override _checkModelCompatibility(options: ChatWrapperCheckModelCompatibilityParams): boolean { const architecture = options.fileInfo?.metadata.general.architecture; - return architecture == null || architecture === GgufArchitectureType.qwen2; + return ( + architecture == null || + architecture === GgufArchitectureType.qwen2 || + architecture === GgufArchitectureType.qwen2moe || + architecture === GgufArchitectureType.qwen2vl || + architecture === GgufArchitectureType.qwen3 || + architecture === GgufArchitectureType.qwen3moe + ); } /** @internal */ public static override _getOptionConfigurationsToTestIfCanSupersedeJinjaTemplate(): ChatWrapperJinjaMatchConfiguration { return [ - [undefined, {}, {_requireFunctionCallSettingsExtraction: true}] + [{}, {}, {_requireFunctionCallSettingsExtraction: true}], + [{_lineBreakBeforeFunctionCallPrefix: true}, {}, {_requireFunctionCallSettingsExtraction: true}] ]; } } + +function discourageThoughtsInModelResponse(response: ChatModelResponse["response"]) { + const emptyThought: ChatModelSegment = { + type: "segment", + segmentType: "thought", + ended: true, + text: "\n\n", + raw: LlamaText(new SpecialTokensText("\n\n\n\n")).toJSON() + }; + const res: ChatModelResponse["response"] = [...response]; + + for (let i = res.length - 1; i >= 0; i--) { + const item = res[i]; + + if (isChatModelResponseFunctionCall(item)) { + res.splice(i + 1, 0, emptyThought); + return res; + } + } + + res.unshift(emptyThought); + return res; +} diff --git a/src/cli/commands/inspect/commands/InspectGpuCommand.ts b/src/cli/commands/inspect/commands/InspectGpuCommand.ts index 487a0fca..59502963 100644 --- a/src/cli/commands/inspect/commands/InspectGpuCommand.ts +++ b/src/cli/commands/inspect/commands/InspectGpuCommand.ts @@ -165,6 +165,7 @@ export const InspectGpuCommand: CommandModule = { async function getLlamaForGpu(gpu: BuildGpu) { try { + // if you're reading this line, then you're probably looking for the `dryRun` option on `getLlama` return await getLlamaForOptions({ gpu: gpu, build: "never", diff --git a/src/cli/recommendedModels.ts b/src/cli/recommendedModels.ts index c1a4329c..efba3526 100644 --- a/src/cli/recommendedModels.ts +++ b/src/cli/recommendedModels.ts @@ -227,10 +227,8 @@ export const recommendedModels: ModelRecommendation[] = [{ fileOptions: [ "hf:bartowski/gemma-2-9b-it-GGUF:Q6_K_L", "hf:bartowski/gemma-2-9b-it-GGUF:Q6_K", - "hf:bartowski/gemma-2-9b-it-GGUF:Q5_K_L", "hf:bartowski/gemma-2-9b-it-GGUF:Q5_K_M", "hf:bartowski/gemma-2-9b-it-GGUF:Q5_K_S", - "hf:bartowski/gemma-2-9b-it-GGUF:Q4_K_L", "hf:bartowski/gemma-2-9b-it-GGUF:Q4_K_M" ] }, { @@ -258,10 +256,8 @@ export const recommendedModels: ModelRecommendation[] = [{ fileOptions: [ "hf:bartowski/gemma-2-27b-it-GGUF:Q6_K_L", "hf:bartowski/gemma-2-27b-it-GGUF:Q6_K", - "hf:bartowski/gemma-2-27b-it-GGUF:Q5_K_L", "hf:bartowski/gemma-2-27b-it-GGUF:Q5_K_M", "hf:bartowski/gemma-2-27b-it-GGUF:Q5_K_S", - "hf:bartowski/gemma-2-27b-it-GGUF:Q4_K_L", "hf:bartowski/gemma-2-27b-it-GGUF:Q4_K_M" ] }, { diff --git a/src/config.ts b/src/config.ts index 433b3ca4..b68078ae 100644 --- a/src/config.ts +++ b/src/config.ts @@ -122,5 +122,6 @@ export const documentationPageUrls = { RosettaIllegalHardwareInstruction: documentationUrl + "/guide/troubleshooting#illegal-hardware-instruction" } } as const; +export const newGithubIssueUrl = "https://github.com/withcatai/node-llama-cpp/issues"; export const recommendedBaseDockerImage = "node:20"; export const minAllowedContextSizeInCalculations = 24; diff --git a/src/evaluator/LlamaChat/LlamaChat.ts b/src/evaluator/LlamaChat/LlamaChat.ts index d2843d2c..da15b1c0 100644 --- a/src/evaluator/LlamaChat/LlamaChat.ts +++ b/src/evaluator/LlamaChat/LlamaChat.ts @@ -105,6 +105,37 @@ export type LlamaChatResponseSegmentChunk = { segmentEndTime?: Date }; +export type LlamaChatResponseFunctionCallParamsChunk = { + /** + * Each different function call has a different `callIndex`. + * + * When the previous function call has finished being generated, the `callIndex` of the next one will increment. + * + * Use this value to distinguish between different function calls. + */ + callIndex: number, + + /** + * The name of the function being called + */ + functionName: string, + + /** + * A chunk of the generated text used for the function call parameters. + * + * Collect all the chunks together to construct the full function call parameters. + * + * After the function call is finished, the entire constructed params text can be parsed as a JSON object, + * according to the function parameters schema. + */ + paramsChunk: string, + + /** + * When this is `true`, the current chunk is the last chunk in the generation of the current function call parameters. + */ + done: boolean +}; + export type LLamaChatGenerateResponseOptions = { /** * Called as the model generates the main response with the generated text chunk. @@ -247,13 +278,30 @@ export type LLamaChatGenerateResponseOptions void } & ({ grammar?: LlamaGrammar, functions?: never, documentFunctionParams?: never, maxParallelFunctionCalls?: never, - onFunctionCall?: never + onFunctionCall?: never, + onFunctionCallParamsChunk?: never } | { grammar?: never, functions?: Functions | ChatModelFunctions, @@ -261,7 +309,8 @@ export type LLamaChatGenerateResponseOptions - ) => void + ) => void, + onFunctionCallParamsChunk?: (chunk: LlamaChatResponseFunctionCallParamsChunk) => void }); export type LLamaChatLoadAndCompleteUserMessageOptions = { @@ -465,6 +514,7 @@ export class LlamaChat { onTextChunk, onToken, onResponseChunk, + onFunctionCallParamsChunk, signal, stopOnAbortSignal = false, maxTokens, @@ -501,6 +551,7 @@ export class LlamaChat { onTextChunk, onToken, onResponseChunk, + onFunctionCallParamsChunk, signal, stopOnAbortSignal, maxTokens, @@ -1433,6 +1484,7 @@ class GenerateResponseState["onTextChunk"]; private readonly onToken: LLamaChatGenerateResponseOptions["onToken"]; private readonly onResponseChunk: LLamaChatGenerateResponseOptions["onResponseChunk"]; + private readonly onFunctionCallParamsChunk: LLamaChatGenerateResponseOptions["onFunctionCallParamsChunk"]; private readonly signal: LLamaChatGenerateResponseOptions["signal"]; private readonly stopOnAbortSignal: LLamaChatGenerateResponseOptions["stopOnAbortSignal"]; public readonly maxTokens: LLamaChatGenerateResponseOptions["maxTokens"]; @@ -1531,6 +1583,7 @@ class GenerateResponseState functionParamsGenerationDoneDetector.addStopTrigger(stopTrigger)); - for await (const tokens of this.evaluateWithContextShift(loadContextWindow)) { - pushAll(this.currentFunctionCallCurrentPartTokens, tokens); + if (this.currentFunctionCallCurrentPartTokens.length > 0) + this.onFunctionCallParamsChunk?.({ + callIndex: this.resFunctionCalls.length, + functionName: this.functionEvaluationFunctionName, + paramsChunk: this.llamaChat.model.detokenize(this.currentFunctionCallCurrentPartTokens, false, lastPartTokens), + done: false + }); + for await (const tokens of this.evaluateWithContextShift(loadContextWindow)) { functionParamsGenerationDoneDetector.recordGeneration({ text: this.currentText, tokens: this.currentTokens }); + this.onFunctionCallParamsChunk?.({ + callIndex: this.resFunctionCalls.length, + functionName: this.functionEvaluationFunctionName, + paramsChunk: this.llamaChat.model.detokenize( + tokens, + false, + resolveLastTokens([lastPartTokens, this.currentFunctionCallCurrentPartTokens]) + ), + done: functionParamsGenerationDoneDetector.hasTriggeredStops + }); + + pushAll(this.currentFunctionCallCurrentPartTokens, tokens); + if (functionParamsGenerationDoneDetector.hasTriggeredStops) break; } @@ -3073,7 +3146,7 @@ class SegmentHandler void } & ({ grammar?: LlamaGrammar, functions?: never, documentFunctionParams?: never, - maxParallelFunctionCalls?: never + maxParallelFunctionCalls?: never, + onFunctionCallParamsChunk?: never } | { grammar?: never, functions?: Functions | ChatSessionModelFunctions, documentFunctionParams?: boolean, - maxParallelFunctionCalls?: number + maxParallelFunctionCalls?: number, + onFunctionCallParamsChunk?: (chunk: LlamaChatResponseFunctionCallParamsChunk) => void }); export type LLamaChatCompletePromptOptions = { @@ -424,6 +443,7 @@ export class LlamaChatSession { onTextChunk, onToken, onResponseChunk, + onFunctionCallParamsChunk, signal, stopOnAbortSignal = false, maxTokens, @@ -443,10 +463,13 @@ export class LlamaChatSession { const {responseText} = await this.promptWithMeta(prompt, { // this is a workaround to allow passing both `functions` and `grammar` functions: functions as undefined, + grammar: grammar as undefined, documentFunctionParams: documentFunctionParams as undefined, maxParallelFunctionCalls: maxParallelFunctionCalls as undefined, + onFunctionCallParamsChunk: onFunctionCallParamsChunk as undefined, - onTextChunk, onToken, onResponseChunk, signal, stopOnAbortSignal, maxTokens, temperature, minP, topK, topP, seed, grammar, + onTextChunk, onToken, onResponseChunk, signal, stopOnAbortSignal, maxTokens, + temperature, minP, topK, topP, seed, trimWhitespaceSuffix, responsePrefix, repeatPenalty, tokenBias, customStopTriggers }); @@ -464,6 +487,7 @@ export class LlamaChatSession { onTextChunk, onToken, onResponseChunk, + onFunctionCallParamsChunk, signal, stopOnAbortSignal = false, maxTokens, @@ -500,6 +524,7 @@ export class LlamaChatSession { let newContextWindowChatHistory = lastEvaluation?.contextWindow == null ? undefined : appendUserMessageToChatHistory(lastEvaluation?.contextWindow, prompt); + let previousFunctionCalls: number = 0; const resolvedResponsePrefix = (responsePrefix != null && responsePrefix !== "") ? responsePrefix @@ -553,6 +578,14 @@ export class LlamaChatSession { onTextChunk: safeEventCallback(onTextChunk), onToken: safeEventCallback(onToken), onResponseChunk: safeEventCallback(onResponseChunk), + onFunctionCallParamsChunk: onFunctionCallParamsChunk == null + ? undefined + : safeEventCallback((chunk) => onFunctionCallParamsChunk?.({ + callIndex: previousFunctionCalls + chunk.callIndex, + functionName: chunk.functionName, + paramsChunk: chunk.paramsChunk, + done: chunk.done + })), signal: abortController.signal, stopOnAbortSignal, repeatPenalty, @@ -675,6 +708,7 @@ export class LlamaChatSession { }); startNewChunk = false; + previousFunctionCalls++; } lastEvaluation.cleanHistory = newChatHistory; diff --git a/src/evaluator/LlamaContext/LlamaContext.ts b/src/evaluator/LlamaContext/LlamaContext.ts index 803a1b97..e5797a4f 100644 --- a/src/evaluator/LlamaContext/LlamaContext.ts +++ b/src/evaluator/LlamaContext/LlamaContext.ts @@ -1,3 +1,4 @@ +import path from "path"; import {acquireLock, AsyncDisposeAggregator, DisposeAggregator, DisposedError, EventRelay, Lock, withLock} from "lifecycle-utils"; import {removeNullFields} from "../../utils/removeNullFields.js"; import {Token} from "../../types.js"; @@ -1145,7 +1146,6 @@ export class LlamaContextSequence { /** * Clear the history of the sequence. - * If `prependBos` was enabled, the BOS token will be prepended to the sequence again. */ public async clearHistory() { this._ensureNotDisposed(); @@ -1578,6 +1578,90 @@ export class LlamaContextSequence { } } + /** + * Save the current context sequence evaluation state to a file. + * @see [Saving and restoring a context sequence evaluation state + * ](https://node-llama-cpp.withcat.ai/guide/chat-session#save-and-restore-with-context-sequence-state) + */ + public async saveStateToFile(filePath: string) { + this._ensureNotDisposed(); + + const resolvedPath = path.resolve(process.cwd(), filePath); + + const evaluatorLock = await acquireLock(this._lock, "evaluate"); + const contextLock = await acquireLock(this._context, "context"); + + try { + this._ensureNotDisposed(); + + const fileSize = await this._context._ctx.saveSequenceStateToFile( + resolvedPath, + this._sequenceId, + Uint32Array.from(this.contextTokens) + ); + return {fileSize}; + } finally { + contextLock.dispose(); + evaluatorLock.dispose(); + } + } + + /** + * Load a context sequence evaluation state from a file. + * + * Trying to load a state file with a longer context size than the current sequence's context size will fail and throw an error. + * + * You must ensure that the file was created from the exact same model, otherwise, using this function may crash the process. + * @see [Saving and restoring a context sequence evaluation state + * ](https://node-llama-cpp.withcat.ai/guide/chat-session#save-and-restore-with-context-sequence-state) + */ + public async loadStateFromFile(filePath: string, acceptRisk: { + /** + * Loading a state file created using a different model may crash the process. + * + * You must accept this risk to use this feature. + */ + acceptRisk: true + }) { + if (!acceptRisk.acceptRisk) + throw new Error("The `acceptRisk` option must be set to `true` to use this feature"); + + this._ensureNotDisposed(); + + const resolvedPath = path.resolve(process.cwd(), filePath); + + const evaluatorLock = await acquireLock(this._lock, "evaluate"); + const contextLock = await acquireLock(this._context, "context"); + + try { + this._ensureNotDisposed(); + + this._tokenPredictorOwner = {}; + await this._abortTokenPredictor(true); + this._ensureNotDisposed(); + + this._loadedTokenPredictions.length = 0; + this._nextTokenIndex = 0; + this._contextTokens = []; + + const tokens = Array.from( + await this._context._ctx.loadSequenceStateFromFile(resolvedPath, this._sequenceId, this.contextSize) + ) as Token[]; + + if (tokens.length > this.contextSize) { + this._context._ctx.disposeSequence(this._sequenceId); + throw new Error("The given state file is too large for the current context size"); + } + + this._contextTokens = tokens; + this._nextTokenIndex = tokens.length; + this._loadedTokenPredictions.length = 0; + } finally { + contextLock.dispose(); + evaluatorLock.dispose(); + } + } + /** @internal */ private async *_evaluate(tokens: Token[], metadata: Metadata, { temperature, diff --git a/src/gguf/fileReaders/GgufNetworkFetchFileReader.ts b/src/gguf/fileReaders/GgufNetworkFetchFileReader.ts index 9b15b828..2fd2eb6f 100644 --- a/src/gguf/fileReaders/GgufNetworkFetchFileReader.ts +++ b/src/gguf/fileReaders/GgufNetworkFetchFileReader.ts @@ -2,7 +2,8 @@ import retry from "async-retry"; import {withLock} from "lifecycle-utils"; import {GgufReadOffset} from "../utils/GgufReadOffset.js"; import {defaultExtraAllocationSize, ggufDefaultFetchRetryOptions} from "../consts.js"; -import {ModelFileAccessTokens, resolveModelFileAccessTokensTryHeaders} from "../../utils/modelFileAccesTokens.js"; +import {ModelFileAccessTokens, resolveModelFileAccessTokensTryHeaders} from "../../utils/modelFileAccessTokens.js"; +import {ModelDownloadEndpoints} from "../../utils/modelDownloadEndpoints.js"; import {GgufFileReader} from "./GgufFileReader.js"; type GgufFetchFileReaderOptions = { @@ -10,7 +11,8 @@ type GgufFetchFileReaderOptions = { retryOptions?: retry.Options, headers?: Record, signal?: AbortSignal, - tokens?: ModelFileAccessTokens + tokens?: ModelFileAccessTokens, + endpoints?: ModelDownloadEndpoints }; export class GgufNetworkFetchFileReader extends GgufFileReader { @@ -18,15 +20,17 @@ export class GgufNetworkFetchFileReader extends GgufFileReader { public readonly retryOptions: retry.Options; public readonly headers: Record; public readonly tokens?: ModelFileAccessTokens; + public readonly endpoints?: ModelDownloadEndpoints; private readonly _signal?: AbortSignal; private _tryHeaders: Record[] | undefined = undefined; - public constructor({url, retryOptions = ggufDefaultFetchRetryOptions, headers, tokens, signal}: GgufFetchFileReaderOptions) { + public constructor({url, retryOptions = ggufDefaultFetchRetryOptions, headers, tokens, endpoints, signal}: GgufFetchFileReaderOptions) { super(); this.url = url; this.retryOptions = retryOptions; this.headers = headers ?? {}; this.tokens = tokens; + this.endpoints = endpoints; this._signal = signal; } @@ -88,7 +92,7 @@ export class GgufNetworkFetchFileReader extends GgufFileReader { private async _fetchByteRange(start: number, length: number): Promise { if (this._tryHeaders == null) - this._tryHeaders = await resolveModelFileAccessTokensTryHeaders(this.url, this.tokens, this.headers); + this._tryHeaders = await resolveModelFileAccessTokensTryHeaders(this.url, this.tokens, this.endpoints, this.headers); const headersToTry = [this.headers, ...this._tryHeaders]; diff --git a/src/gguf/insights/GgufInsights.ts b/src/gguf/insights/GgufInsights.ts index 04fd3687..8b0f85e9 100644 --- a/src/gguf/insights/GgufInsights.ts +++ b/src/gguf/insights/GgufInsights.ts @@ -454,21 +454,38 @@ export class GgufInsights { const nHead = this._ggufFileInfo.architectureMetadata.attention?.head_count ?? 0; const nEmbd = this._ggufFileInfo.architectureMetadata.embedding_length ?? 0; const nEmbdHeadK = this._ggufFileInfo.architectureMetadata.attention?.key_length ?? ((nHead == 0) ? 0 : (nEmbd / nHead)); - const nHeadKv = this._ggufFileInfo.architectureMetadata.attention?.head_count_kv ?? nHead; - const modelNEmbdKGqa = nEmbdHeadK * nHeadKv; + const nHeadKv: number | number[] = this._ggufFileInfo.architectureMetadata.attention?.head_count_kv ?? nHead; + const nEmbdHeadV = this._ggufFileInfo.architectureMetadata.attention?.value_length ?? ((nHead == 0) ? 0 : nEmbd / nHead); const ssmDConv = this._ggufFileInfo.architectureMetadata.ssm?.conv_kernel ?? 0; const ssmDInner = this._ggufFileInfo.architectureMetadata.ssm?.inner_size ?? 0; - const modelNEmbdKS = (ssmDConv > 0 ? (ssmDConv - 1) : 0) * ssmDInner; - - const nEmbdHeadV = this._ggufFileInfo.architectureMetadata.attention?.value_length ?? ((nHead == 0) ? 0 : nEmbd / nHead); - const modelNEmbdVGqa = nEmbdHeadV * nHeadKv; + const modelNEmbdKS = (this._ggufFileInfo.architectureMetadata.wkv?.head_size ?? 0) !== 0 + ? (this._ggufFileInfo.architectureMetadata.token_shift_count ?? 0) * nEmbd + : (ssmDConv > 0 ? (ssmDConv - 1) : 0) * ssmDInner; const ssmDState = this._ggufFileInfo.architectureMetadata.ssm?.state_size ?? 0; - const modelNEmbdVS = ssmDState * ssmDInner; - - const totalNEmbdKGqa = modelNEmbdKGqa + modelNEmbdKS; - const totalNEmbdVGqa = modelNEmbdVGqa + modelNEmbdVS; + const modelNEmbdVS = (this._ggufFileInfo.architectureMetadata.wkv?.head_size ?? 0) !== 0 + ? nEmbd * (this._ggufFileInfo.architectureMetadata.wkv?.head_size ?? 0) + : ssmDState * ssmDInner; + + let totalElementsK = 0; + let totalElementsV = 0; + for (let i = 0; i < layers; i++) { + const nHeadKvArrayItem: number = (typeof nHeadKv === "number") + ? nHeadKv + : nHeadKv[i] !== 0 + ? nHeadKv[i] + : nHead; + + const nEmbdKGqa = nEmbdHeadK * nHeadKvArrayItem; + const nEmbdVGqa = nEmbdHeadV * nHeadKvArrayItem; + + const totalNEmbdKGqa = nEmbdKGqa + modelNEmbdKS; + const totalNEmbdVGqa = nEmbdVGqa + modelNEmbdVS; + + totalElementsK += totalNEmbdKGqa * contextSize; + totalElementsV += totalNEmbdVGqa * contextSize; + } const keyTypeSize = this._ggufFileInfo.metadata.general?.architecture === GgufArchitectureType.mamba // if `type_k` of `llama_context_params` changes to be configurable in `LlamaContext`, @@ -481,10 +498,10 @@ export class GgufInsights { ? this._llama._consts.ggmlTypeF32Size : this._llama._consts.ggmlTypeF16Size; - const keyTensorsSize = layers * totalNEmbdKGqa * contextSize * keyTypeSize; - const valueTensorsSize = layers * totalNEmbdVGqa * contextSize * valueTypeSize; - - return keyTensorsSize + valueTensorsSize; + return ( + (totalElementsK * keyTypeSize) + + (totalElementsV * valueTypeSize) + ); } /** diff --git a/src/gguf/insights/utils/resolveModelGpuLayersOption.ts b/src/gguf/insights/utils/resolveModelGpuLayersOption.ts index c6065b7f..1edae352 100644 --- a/src/gguf/insights/utils/resolveModelGpuLayersOption.ts +++ b/src/gguf/insights/utils/resolveModelGpuLayersOption.ts @@ -239,22 +239,81 @@ function findMaxPossibleContextSizeForVram({gpuLayers, ggufInsights, vram, isEmb }) { const maxContextSize = getDefaultModelContextSize({trainContextSize: ggufInsights.trainContextSize}); - for (let contextSize = maxContextSize; contextSize >= minAllowedContextSizeInCalculations; contextSize--) { - const contextVram = ggufInsights.estimateContextResourceRequirements({ - contextSize, - batchSize: getDefaultContextBatchSize({contextSize, sequences: 1}), - modelGpuLayers: gpuLayers, - sequences: 1, - isEmbeddingContext, - flashAttention - }).gpuVram; - - if (contextVram <= vram) - return { + return findMaxValidValue({ + maxValue: maxContextSize, + minValue: minAllowedContextSizeInCalculations, + minStep: 1, + test(contextSize) { + const contextVram = ggufInsights.estimateContextResourceRequirements({ contextSize, - vram: contextVram - }; + batchSize: getDefaultContextBatchSize({contextSize, sequences: 1}), + modelGpuLayers: gpuLayers, + sequences: 1, + isEmbeddingContext, + flashAttention + }).gpuVram; + + if (contextVram <= vram) + return { + contextSize, + vram: contextVram + }; + + return null; + } + }); +} + +function findMaxValidValue({ + maxValue, + minValue, + minStep = 1, + test +}: { + maxValue: number, + minValue: number, + minStep?: number, + test(value: number): T | null +}): T | null { + let step = -Math.max(minStep, Math.floor((maxValue - minValue) / 4)); + let bestValue: null | {value: number, result: T} = null; + + for (let value = maxValue; value >= minValue;) { + const result: T | null = (bestValue != null && value === bestValue.value) + ? bestValue.result + : test(value); + + if (result != null) { + if (bestValue == null || value >= bestValue.value) { + bestValue = {value: value, result: result}; + + if (step === -minStep) + break; + else if (step < 0) + step = Math.max(minStep, Math.floor(-step / 2)); + } + } else if (bestValue != null && value < bestValue.value) { + value = bestValue.value; + step = Math.max(minStep, Math.floor(Math.abs(step) / 2)); + continue; + } else if (step > 0) + step = -Math.max(minStep, Math.floor(step / 2)); + + if (value === minValue && step === -minStep) + break; + + value += step; + if (value < minValue) { + value = minValue; + step = Math.max(minStep, Math.floor(Math.abs(step) / 2)); + } else if (value > maxValue) { + value = maxValue; + step = -Math.max(minStep, Math.floor(Math.abs(step) / 2)); + } } + if (bestValue != null) + return bestValue.result; + return null; } diff --git a/src/gguf/parser/GgufV2Parser.ts b/src/gguf/parser/GgufV2Parser.ts index 10a6f557..cdd66bc4 100644 --- a/src/gguf/parser/GgufV2Parser.ts +++ b/src/gguf/parser/GgufV2Parser.ts @@ -7,7 +7,7 @@ import { import {GgufMetadata} from "../types/GgufMetadataTypes.js"; import {GgmlType, GgufTensorInfo} from "../types/GgufTensorInfoTypes.js"; import {convertMetadataKeyValueRecordToNestedObject} from "../utils/convertMetadataKeyValueRecordToNestedObject.js"; -import {promisableLoop, Promisable, transformPromisable, transformPromisables} from "../../utils/transformPromisable.js"; +import {promisableLoop, Promisable, transformPromisable, transformPromisablesInOrder} from "../../utils/transformPromisable.js"; import {noDirectSubNestingGGufMetadataKeys} from "../consts.js"; import {Writable} from "../../utils/utilTypes.js"; @@ -85,10 +85,10 @@ export class GgufV2Parser { } if (type === GgufValueType.Array) { - const arrayTypePromisable = this._fileReader.readUint32(readOffset); - const arrayLengthPromisable = this._fileReader.readUint64(readOffset); - - return transformPromisables([arrayTypePromisable, arrayLengthPromisable], ([arrayType, arrayLength]) => { + return transformPromisablesInOrder([ + () => this._fileReader.readUint32(readOffset), + () => this._fileReader.readUint64(readOffset) + ], ([arrayType, arrayLength]) => { const arrayValues: MetadataValue[] = []; let i = 0; @@ -115,11 +115,14 @@ export class GgufV2Parser { protected async _readRawHeader(readOffset: GgufReadOffset) { const initialOffset = readOffset.offset; - const tensorCountPromisable = this._fileReader.readUint64(readOffset); - const metadataKVCountPromisable = transformPromisable(this._fileReader.readUint64(readOffset), Number); + const tensorCountAndMetadataKVCountPromisable = transformPromisablesInOrder([ + () => this._fileReader.readUint64(readOffset), + () => transformPromisable(this._fileReader.readUint64(readOffset), Number) + ]); - const tensorCount = tensorCountPromisable instanceof Promise ? await tensorCountPromisable : tensorCountPromisable; - const metadataKVCount = metadataKVCountPromisable instanceof Promise ? await metadataKVCountPromisable : metadataKVCountPromisable; + const [tensorCount, metadataKVCount] = tensorCountAndMetadataKVCountPromisable instanceof Promise + ? await tensorCountAndMetadataKVCountPromisable + : tensorCountAndMetadataKVCountPromisable; const metadata: MetadataKeyValueRecord = {}; @@ -127,10 +130,10 @@ export class GgufV2Parser { return promisableLoop({ condition: () => i < metadataKVCount, callback: () => { - const keyResultPromisable = this._readStringValue(readOffset); - const valueTypePromisable = this._fileReader.readUint32(readOffset); - - return transformPromisables([keyResultPromisable, valueTypePromisable], ([keyResult, valueType]) => { + return transformPromisablesInOrder([ + () => this._readStringValue(readOffset), + () => this._fileReader.readUint32(readOffset) + ], ([keyResult, valueType]) => { return transformPromisable(this._readGgufValue(valueType, readOffset), (value) => { metadata[keyResult] = value; }); @@ -153,11 +156,12 @@ export class GgufV2Parser { return promisableLoop({ condition: () => i < BigInt(tensorCount), callback: () => { - const namePromisable = this._readStringValue(readOffset); - const dimensionsNumberPromisable = this._fileReader.readUint32(readOffset); const dimensions: (number | bigint)[] = []; - return transformPromisables([namePromisable, dimensionsNumberPromisable], ([name, dimensionsNumber]) => { + return transformPromisablesInOrder([ + () => this._readStringValue(readOffset), + () => this._fileReader.readUint32(readOffset) + ], ([name, dimensionsNumber]) => { let d = 0; return promisableLoop({ condition: () => d < dimensionsNumber, @@ -168,10 +172,10 @@ export class GgufV2Parser { }, afterthought: () => void d++, returnValue: () => { - const ggmlTypePromisable = this._fileReader.readUint32(readOffset); - const offsetPromisable = this._fileReader.readUint64(readOffset); - - return transformPromisables([ggmlTypePromisable, offsetPromisable], ([ggmlType, offset]) => { + return transformPromisablesInOrder([ + () => this._fileReader.readUint32(readOffset), + () => this._fileReader.readUint64(readOffset) + ], ([ggmlType, offset]) => { tensorInfo.push({ name, dimensions, diff --git a/src/gguf/readGgufFileInfo.ts b/src/gguf/readGgufFileInfo.ts index 86e51a37..f57a0669 100644 --- a/src/gguf/readGgufFileInfo.ts +++ b/src/gguf/readGgufFileInfo.ts @@ -1,8 +1,9 @@ import retry from "async-retry"; import {isUrl} from "../utils/isUrl.js"; -import {ModelFileAccessTokens} from "../utils/modelFileAccesTokens.js"; +import {ModelFileAccessTokens} from "../utils/modelFileAccessTokens.js"; import {getAuthorizationHeader, isModelUri, parseModelUri, resolveParsedModelUri} from "../utils/parseModelUri.js"; import {Writable} from "../utils/utilTypes.js"; +import {ModelDownloadEndpoints} from "../utils/modelDownloadEndpoints.js"; import {parseGguf} from "./parser/parseGguf.js"; import {GgufNetworkFetchFileReader} from "./fileReaders/GgufNetworkFetchFileReader.js"; import {GgufFsFileReader} from "./fileReaders/GgufFsFileReader.js"; @@ -28,7 +29,8 @@ export async function readGgufFileInfo(pathOrUri: string, { fetchHeaders = {}, spliceSplitFiles = true, signal, - tokens + tokens, + endpoints }: { /** * Whether to read the tensor info from the file's header. @@ -71,22 +73,32 @@ export async function readGgufFileInfo(pathOrUri: string, { signal?: AbortSignal, - tokens?: ModelFileAccessTokens + /** + * Tokens to use to access the remote model file. + */ + tokens?: ModelFileAccessTokens, + + /** + * Configure the URLs used for resolving model URIs. + * @see [Model URIs](https://node-llama-cpp.withcat.ai/guide/downloading-models#model-uris) + */ + endpoints?: ModelDownloadEndpoints } = {}) { const useNetworkReader = sourceType === "network" || (sourceType == null && (isUrl(pathOrUri) || isModelUri(pathOrUri))); async function createFileReader(pathOrUri: string) { if (useNetworkReader) { - const parsedModelUri = await resolveParsedModelUri(parseModelUri(pathOrUri), { - tokens, signal, + const parsedModelUri = await resolveParsedModelUri(parseModelUri(pathOrUri, undefined, endpoints), { + tokens, endpoints, signal, authorizationHeader: getAuthorizationHeader(fetchHeaders) }); return new GgufNetworkFetchFileReader({ - url: parsedModelUri?.resolvedUrl ?? normalizeGgufDownloadUrl(pathOrUri), + url: parsedModelUri?.resolvedUrl ?? normalizeGgufDownloadUrl(pathOrUri, endpoints), retryOptions: fetchRetryOptions, headers: fetchHeaders, signal, - tokens + tokens, + endpoints }); } else if (sourceType === "filesystem" || sourceType == null) { return new GgufFsFileReader({ diff --git a/src/gguf/types/GgufMetadataTypes.ts b/src/gguf/types/GgufMetadataTypes.ts index 40388ca5..827493fc 100644 --- a/src/gguf/types/GgufMetadataTypes.ts +++ b/src/gguf/types/GgufMetadataTypes.ts @@ -1,5 +1,7 @@ export const enum GgufArchitectureType { llama = "llama", + llama4 = "llama4", + deci = "deci", falcon = "falcon", grok = "grok", gpt2 = "gpt2", @@ -11,14 +13,19 @@ export const enum GgufArchitectureType { refact = "refact", bert = "bert", nomicBert = "nomic-bert", + nomicBertMoe = "nomic-bert-moe", jinaBertV2 = "jina-bert-v2", bloom = "bloom", stablelm = "stablelm", qwen = "qwen", qwen2 = "qwen2", qwen2moe = "qwen2moe", + qwen2vl = "qwen2vl", + qwen3 = "qwen3", + qwen3moe = "qwen3moe", phi2 = "phi2", phi3 = "phi3", + phimoe = "phimoe", plamo = "plamo", codeshell = "codeshell", orion = "orion", @@ -27,18 +34,22 @@ export const enum GgufArchitectureType { minicpm3 = "minicpm3", gemma = "gemma", gemma2 = "gemma2", + gemma3 = "gemma3", starcoder2 = "starcoder2", mamba = "mamba", xverse = "xverse", commandR = "command-r", + cohere2 = "cohere2", dbrx = "dbrx", olmo = "olmo", olmo2 = "olmo2", olmoe = "olmoe", openelm = "openelm", arctic = "arctic", + deepseek = "deepseek", deepseek2 = "deepseek2", chatglm = "chatglm", + glm4 = "glm4", bitnet = "bitnet", t5 = "t5", t5encoder = "t5encoder", @@ -46,9 +57,15 @@ export const enum GgufArchitectureType { nemotron = "nemotron", exaone = "exaone", rwkv6 = "rwkv6", + rwkv6qwen2 = "rwkv6qwen2", + rwkv7 = "rwkv7", + arwkv7 = "arwkv7", granite = "granite", granitemoe = "granitemoe", chameleon = "chameleon", + wavtokenizerDec = "wavtokenizer-dec", + plm = "plm", + bailingmoe = "bailingmoe", unknown = "(unknown)" } @@ -224,11 +241,11 @@ export const enum GgufMetadataTokenizerTokenType { export type GgufMetadataTokenizer = { readonly ggml: { readonly model: "no_vocab" | "llama" | "gpt2" | "bert" | string, - readonly pre?: "default" | "llama3" | "llama-v3" | "llama-bpe" | "deepseek-llm" | "deepseek-coder" | "falcon" | "falcon3" | "mpt" | - "starcoder" | "gpt-2" | "phi-2" | "jina-es" | "jina-de" | "jina-v1-en" | "jina-v2-es" | "jina-v2-de" | "jina-v2-code" | - "refact" | "command-r" | "qwen2" | "stablelm2" | "olmo" | "dbrx" | "smaug-bpe" | "poro-chat" | "chatglm-bpe" | "viking" | - "jais" | "tekken" | "smollm" | "codeshell" | "bloom" | "gpt3-finnish" | "exaone" | "chameleon" | "minerva-7b" | "megrez" | - "gpt-4o" | string, + readonly pre?: "default" | "llama3" | "llama-v3" | "llama-bpe" | "deepseek-llm" | "deepseek-coder" | "falcon" | "falcon3" | + "pixtral" | "mpt" | "starcoder" | "gpt-2" | "phi-2" | "jina-es" | "jina-de" | "jina-v1-en" | "jina-v2-es" | "jina-v2-de" | + "jina-v2-code" | "refact" | "command-r" | "qwen2" | "stablelm2" | "olmo" | "dbrx" | "smaug-bpe" | "poro-chat" | "chatglm-bpe" | + "viking" | "jais" | "tekken" | "smollm" | "codeshell" | "bloom" | "gpt3-finnish" | "exaone" | "chameleon" | "minerva-7b" | + "megrez" | "gpt-4o" | "superbpe" | "trillion" | "bailingmoe" | string, readonly tokens: readonly string[], readonly token_type: GgufMetadataTokenizerTokenType[], readonly token_type_count?: number, @@ -288,10 +305,11 @@ export type GgufMetadataDefaultArchitectureType = { readonly expert_used_count?: number, readonly pooling_type?: GgufMetadataArchitecturePoolingType, readonly logit_scale?: number, + readonly token_shift_count?: number, readonly attention?: { readonly head_count?: number, - readonly head_count_kv?: number, + readonly head_count_kv?: number | number[], readonly max_alibi_bias?: number, readonly clamp_kqv?: number, readonly layer_norm_epsilon?: number, @@ -318,6 +336,10 @@ export type GgufMetadataDefaultArchitectureType = { readonly inner_size?: number, readonly state_size?: number, readonly time_step_rank?: number + }, + + readonly wkv?: { + readonly head_size?: number } }; diff --git a/src/gguf/utils/normalizeGgufDownloadUrl.ts b/src/gguf/utils/normalizeGgufDownloadUrl.ts index 28994397..53dd9a38 100644 --- a/src/gguf/utils/normalizeGgufDownloadUrl.ts +++ b/src/gguf/utils/normalizeGgufDownloadUrl.ts @@ -1,7 +1,11 @@ -export function normalizeGgufDownloadUrl(url: string) { +import {ModelDownloadEndpoints, resolveHuggingFaceEndpoint} from "../../utils/modelDownloadEndpoints.js"; + +export function normalizeGgufDownloadUrl(url: string, endpoints?: ModelDownloadEndpoints) { const parsedUrl = new URL(url); - if (parsedUrl.hostname === "huggingface.co" || parsedUrl.hostname === "hf.co") { + if (parsedUrl.hostname === "huggingface.co" || parsedUrl.hostname === "hf.co" || + parsedUrl.hostname === (new URL(resolveHuggingFaceEndpoint(endpoints))).hostname + ) { const pathnameParts = parsedUrl.pathname.split("/"); if (pathnameParts.length > 3 && pathnameParts[3] === "blob") { diff --git a/src/index.ts b/src/index.ts index 8bc97681..6605c331 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,7 @@ import {DisposedError} from "lifecycle-utils"; import {Llama} from "./bindings/Llama.js"; import {getLlama, type LlamaOptions, type LastBuildOptions} from "./bindings/getLlama.js"; +import {getLlamaGpuTypes} from "./bindings/utils/getLlamaGpuTypes.js"; import {NoBinaryFoundError} from "./bindings/utils/NoBinaryFoundError.js"; import { type LlamaGpuType, LlamaLogLevel, LlamaLogLevelGreaterThan, LlamaLogLevelGreaterThanOrEqual, LlamaVocabularyType @@ -32,7 +33,7 @@ import { LlamaChat, type LlamaChatOptions, type LLamaChatGenerateResponseOptions, type LLamaChatLoadAndCompleteUserMessageOptions, type LLamaChatContextShiftOptions, type LlamaChatResponse, type LlamaChatResponseFunctionCall, type LlamaChatLoadAndCompleteUserResponse, type LlamaChatResponseChunk, type LlamaChatResponseTextChunk, - type LlamaChatResponseSegmentChunk, type LlamaChatResponseSegment + type LlamaChatResponseSegmentChunk, type LlamaChatResponseFunctionCallParamsChunk, type LlamaChatResponseSegment } from "./evaluator/LlamaChat/LlamaChat.js"; import { LlamaChatSessionPromptCompletionEngine, type LLamaChatPromptCompletionEngineOptions @@ -109,7 +110,7 @@ import { type GgufMetadataBloom, type GgufMetadataFalcon, type GgufMetadataMamba, isGgufMetadataOfArchitectureType } from "./gguf/types/GgufMetadataTypes.js"; import {GgmlType, type GgufTensorInfo} from "./gguf/types/GgufTensorInfoTypes.js"; -import {type ModelFileAccessTokens} from "./utils/modelFileAccesTokens.js"; +import {type ModelFileAccessTokens} from "./utils/modelFileAccessTokens.js"; import {type OverridesObject} from "./utils/OverridesObject.js"; import type {LlamaClasses} from "./utils/getLlamaClasses.js"; import type {ChatHistoryFunctionCallMessageTemplate} from "./chatWrappers/generic/utils/chatHistoryFunctionCallMessageTemplate.js"; @@ -119,6 +120,7 @@ import type {TemplateChatWrapperSegmentsOptions} from "./chatWrappers/generic/ut export { Llama, getLlama, + getLlamaGpuTypes, type LlamaOptions, type LastBuildOptions, type LlamaGpuType, @@ -183,6 +185,7 @@ export { type LlamaChatResponseChunk, type LlamaChatResponseTextChunk, type LlamaChatResponseSegmentChunk, + type LlamaChatResponseFunctionCallParamsChunk, type LlamaChatResponseSegment, LlamaChatSessionPromptCompletionEngine, type LLamaChatPromptCompletionEngineOptions, diff --git a/src/utils/createModelDownloader.ts b/src/utils/createModelDownloader.ts index 4927888b..4acc0b23 100644 --- a/src/utils/createModelDownloader.ts +++ b/src/utils/createModelDownloader.ts @@ -7,7 +7,8 @@ import {createSplitPartFilename, resolveSplitGgufParts} from "../gguf/utils/reso import {getFilenameForBinarySplitGgufPartUrls, resolveBinarySplitGgufPartUrls} from "../gguf/utils/resolveBinarySplitGgufPartUrls.js"; import {cliModelsDirectory, isCI} from "../config.js"; import {safeEventCallback} from "./safeEventCallback.js"; -import {ModelFileAccessTokens, resolveModelFileAccessTokensTryHeaders} from "./modelFileAccesTokens.js"; +import {ModelFileAccessTokens, resolveModelFileAccessTokensTryHeaders} from "./modelFileAccessTokens.js"; +import {ModelDownloadEndpoints} from "./modelDownloadEndpoints.js"; import {pushAll} from "./pushAll.js"; import {resolveModelDestination} from "./resolveModelDestination.js"; import {getAuthorizationHeader, resolveParsedModelUri} from "./parseModelUri.js"; @@ -19,7 +20,7 @@ export type ModelDownloaderOptions = ({ * * The supported URI schemes are: * - **HTTP:** `https://`, `http://` - * - **Hugging Face:** `hf:/:` (`#` is optional, but recommended) + * - **Hugging Face:** `hf:/:` (`:` is optional, but recommended) * - **Hugging Face:** `hf://#` (`#` is optional) */ modelUri: string @@ -67,8 +68,17 @@ export type ModelDownloaderOptions = ({ */ parallelDownloads?: number, + /** + * Tokens to use to access the remote model file when downloading. + */ tokens?: ModelFileAccessTokens, + /** + * Configure the URLs used for resolving model URIs. + * @see [Model URIs](https://node-llama-cpp.withcat.ai/guide/downloading-models#model-uris) + */ + endpoints?: ModelDownloadEndpoints, + /** @internal */ _showUriResolvingProgress?: boolean }; @@ -89,7 +99,7 @@ export type ModelDownloaderOptions = ({ * * The supported URI schemes are: * - **HTTP:** `https://`, `http://` - * - **Hugging Face:** `hf:/:` (`#` is optional, but recommended) + * - **Hugging Face:** `hf:/:` (`:` is optional, but recommended) * - **Hugging Face:** `hf://#` (`#` is optional) * @example * ```typescript @@ -206,6 +216,7 @@ export class ModelDownloader { /** @internal */ private readonly _showCliProgress: boolean; /** @internal */ private readonly _onProgress?: ModelDownloaderOptions["onProgress"]; /** @internal */ private readonly _tokens?: ModelFileAccessTokens; + /** @internal */ private readonly _endpoints?: ModelDownloadEndpoints; /** @internal */ public readonly _deleteTempFileOnCancel: boolean; /** @internal */ private readonly _skipExisting: boolean; /** @internal */ private readonly _parallelDownloads: number; @@ -223,7 +234,7 @@ export class ModelDownloader { }) { const { dirPath = cliModelsDirectory, headers, showCliProgress = false, onProgress, deleteTempFileOnCancel = true, - skipExisting = true, parallelDownloads = 4, tokens + skipExisting = true, parallelDownloads = 4, tokens, endpoints } = options; this._modelUrl = resolvedModelUrl; @@ -236,6 +247,7 @@ export class ModelDownloader { this._skipExisting = skipExisting; this._parallelDownloads = parallelDownloads; this._tokens = tokens; + this._endpoints = endpoints; this._onDownloadProgress = this._onDownloadProgress.bind(this); } @@ -352,7 +364,10 @@ export class ModelDownloader { if (this._tokens == null) return; - pushAll(this._tryHeaders, await resolveModelFileAccessTokensTryHeaders(this._modelUrl, this._tokens, this._headers)); + pushAll( + this._tryHeaders, + await resolveModelFileAccessTokensTryHeaders(this._modelUrl, this._tokens, this._endpoints, this._headers) + ); } /** @internal */ @@ -455,7 +470,7 @@ export class ModelDownloader { resolvedModelUrl: string, resolvedFileName?: string }> { - const resolvedModelDestination = resolveModelDestination(resolvedModelUri!); + const resolvedModelDestination = resolveModelDestination(resolvedModelUri!, undefined, options.endpoints); if (resolvedModelDestination.type == "file") return { @@ -482,11 +497,13 @@ export class ModelDownloader { }, () => { return resolveParsedModelUri(resolvedModelDestination.parsedUri, { tokens: options.tokens, + endpoints: options.endpoints, authorizationHeader: getAuthorizationHeader(options.headers) }); }) : await resolveParsedModelUri(resolvedModelDestination.parsedUri, { tokens: options.tokens, + endpoints: options.endpoints, authorizationHeader: getAuthorizationHeader(options.headers) }); diff --git a/src/utils/modelDownloadEndpoints.ts b/src/utils/modelDownloadEndpoints.ts new file mode 100644 index 00000000..a6a7d1f0 --- /dev/null +++ b/src/utils/modelDownloadEndpoints.ts @@ -0,0 +1,50 @@ +import {isUrl} from "./isUrl.js"; + +export type ModelDownloadEndpoints = { + /** + * Endpoint to use for resolving Hugging Face model URIs (`hf:`). + * + * Can also be set by using the environment variable `HF_ENDPOINT` or `MODEL_ENDPOINT`. + * + * Defaults to `"https://huggingface.co/"`. + * @see [Model URIs](https://node-llama-cpp.withcat.ai/guide/downloading-models#model-uris) + */ + huggingFace?: string +}; + +export function resolveHuggingFaceEndpoint(endpoints?: ModelDownloadEndpoints) { + const ensureLastSlash = (url: string) => ( + url.endsWith("/") + ? url + : url + "/" + ); + + if (endpoints?.huggingFace != null && isUrl(endpoints?.huggingFace, false)) + return ensureLastSlash(endpoints?.huggingFace); + + // https://github.com/ggml-org/llama.cpp/pull/12664/files#diff-201cbc8fd17750764ed4a0862232e81503550c201995e16dc2e2766754eaa57a + const modelEndpoint = process.env.MODEL_ENDPOINT; + if (modelEndpoint != null && isUrl(modelEndpoint, false)) + return ensureLastSlash(modelEndpoint); + + // https://github.com/ggml-org/llama.cpp/pull/12664/files#diff-201cbc8fd17750764ed4a0862232e81503550c201995e16dc2e2766754eaa57a + const hfEndpoint = process.env.HF_ENDPOINT; + if (hfEndpoint != null && isUrl(hfEndpoint, false)) + return ensureLastSlash(hfEndpoint); + + return "https://huggingface.co/"; +} + +export function isHuggingFaceUrl(url: string, endpoints?: ModelDownloadEndpoints) { + const parsedUrl = new URL(url); + const hfEndpoint = resolveHuggingFaceEndpoint(endpoints); + const hfEndpointDomain = (new URL(hfEndpoint)).hostname; + + if (parsedUrl.hostname === hfEndpointDomain) + return true; + + return ( + (hfEndpoint === "https://huggingface.co/" || hfEndpoint === "https://hf.co/") && + (parsedUrl.hostname === "huggingface.co" || parsedUrl.hostname === "hf.co") + ); +} diff --git a/src/utils/modelFileAccesTokens.ts b/src/utils/modelFileAccessTokens.ts similarity index 89% rename from src/utils/modelFileAccesTokens.ts rename to src/utils/modelFileAccessTokens.ts index 7291c8f9..acb1bde7 100644 --- a/src/utils/modelFileAccesTokens.ts +++ b/src/utils/modelFileAccessTokens.ts @@ -3,6 +3,7 @@ import path from "path"; import os from "os"; import fs from "fs-extra"; import {isUrl} from "./isUrl.js"; +import {isHuggingFaceUrl, ModelDownloadEndpoints} from "./modelDownloadEndpoints.js"; export type ModelFileAccessTokens = { huggingFace?: string @@ -11,6 +12,7 @@ export type ModelFileAccessTokens = { export async function resolveModelFileAccessTokensTryHeaders( modelUrl: string, tokens?: ModelFileAccessTokens, + endpoints?: ModelDownloadEndpoints, baseHeaders?: Record ) { const res: Record[] = []; @@ -18,10 +20,9 @@ export async function resolveModelFileAccessTokensTryHeaders( if (tokens == null || !isUrl(modelUrl)) return res; - const parsedUrl = new URL(modelUrl); const {huggingFace} = tokens; - if (parsedUrl.hostname === "huggingface.co" || parsedUrl.hostname === "hf.co") { + if (isHuggingFaceUrl(modelUrl, endpoints)) { const hfToken = resolveHfToken(huggingFace); res.push({ diff --git a/src/utils/parseModelUri.ts b/src/utils/parseModelUri.ts index 504218ee..babea2b6 100644 --- a/src/utils/parseModelUri.ts +++ b/src/utils/parseModelUri.ts @@ -4,7 +4,8 @@ import {getFilenameForBinarySplitGgufPartUrls, resolveBinarySplitGgufPartUrls} f import {createSplitPartFilename, getGgufSplitPartsInfo} from "../gguf/utils/resolveSplitGgufParts.js"; import {ggufQuantNames} from "../gguf/utils/ggufQuantNames.js"; import {isUrl} from "./isUrl.js"; -import {ModelFileAccessTokens, resolveModelFileAccessTokensTryHeaders} from "./modelFileAccesTokens.js"; +import {ModelFileAccessTokens, resolveModelFileAccessTokensTryHeaders} from "./modelFileAccessTokens.js"; +import {isHuggingFaceUrl, ModelDownloadEndpoints, resolveHuggingFaceEndpoint} from "./modelDownloadEndpoints.js"; import {parseModelFileName} from "./parseModelFileName.js"; const defaultHuggingFaceBranch = "main"; @@ -36,23 +37,26 @@ export type ResolvedParsedModelUri = { fullFilename: string }; -export function parseModelUri(urlOrUri: string, convertUrlToSupportedUri: boolean = false): ParsedModelUri | null { +export function parseModelUri( + urlOrUri: string, convertUrlToSupportedUri: boolean = false, endpoints?: ModelDownloadEndpoints +): ParsedModelUri | null { if (urlOrUri.startsWith("hf://")) - return parseHuggingFaceUriContent(urlOrUri.slice("hf://".length), urlOrUri); + return parseHuggingFaceUriContent(urlOrUri.slice("hf://".length), urlOrUri, endpoints); else if (urlOrUri.startsWith("huggingface://")) - return parseHuggingFaceUriContent(urlOrUri.slice("huggingface://".length), urlOrUri); + return parseHuggingFaceUriContent(urlOrUri.slice("huggingface://".length), urlOrUri, endpoints); else if (urlOrUri.startsWith("hf:")) - return parseHuggingFaceUriContent(urlOrUri.slice("hf:".length), urlOrUri); + return parseHuggingFaceUriContent(urlOrUri.slice("hf:".length), urlOrUri, endpoints); else if (urlOrUri.startsWith("huggingface:")) - return parseHuggingFaceUriContent(urlOrUri.slice("huggingface:".length), urlOrUri); + return parseHuggingFaceUriContent(urlOrUri.slice("huggingface:".length), urlOrUri, endpoints); else if (urlOrUri.startsWith("hf.co/")) - return parseHuggingFaceUriContent(urlOrUri.slice("hf.co/".length), urlOrUri); + return parseHuggingFaceUriContent(urlOrUri.slice("hf.co/".length), urlOrUri, endpoints); else if (urlOrUri.startsWith("huggingface.co/")) - return parseHuggingFaceUriContent(urlOrUri.slice("huggingface.co/".length), urlOrUri); + return parseHuggingFaceUriContent(urlOrUri.slice("huggingface.co/".length), urlOrUri, endpoints); if (isUrl(urlOrUri)) { const parsedUrl = new URL(urlOrUri); - if (parsedUrl.hostname === "huggingface.co" || parsedUrl.hostname === "hf.co") { + + if (isHuggingFaceUrl(parsedUrl.href, endpoints)) { const pathnameParts = parsedUrl.pathname.split("/"); const slashes = pathnameParts.length - 1; const [, user, model] = pathnameParts; @@ -60,14 +64,15 @@ export function parseModelUri(urlOrUri: string, convertUrlToSupportedUri: boolea if (slashes === 2 && user != null && model != null) { return parseHuggingFaceUriContent([ decodeURIComponent(user), "/", decodeURIComponent(model) - ].join(""), urlOrUri); + ].join(""), urlOrUri, endpoints); } } } if (convertUrlToSupportedUri && isUrl(urlOrUri)) { - const parsedUrl = new URL(normalizeGgufDownloadUrl(urlOrUri)); - if (parsedUrl.hostname === "huggingface.co" || parsedUrl.hostname === "hf.co") { + const parsedUrl = new URL(normalizeGgufDownloadUrl(urlOrUri, endpoints)); + + if (isHuggingFaceUrl(parsedUrl.href, endpoints)) { const pathnameParts = parsedUrl.pathname.split("/"); const [, user, model, resolve, branch, ...pathParts] = pathnameParts; const filePath = pathParts.join("/"); @@ -83,7 +88,7 @@ export function parseModelUri(urlOrUri: string, convertUrlToSupportedUri: boolea branch !== defaultHuggingFaceBranch ? `#${decodeURIComponent(branch)}` : "" - ].join(""), urlOrUri); + ].join(""), urlOrUri, endpoints); } } } @@ -101,16 +106,17 @@ export function isModelUri(modelUri: string) { export async function resolveParsedModelUri( modelUri: ParsedModelUri, - options?: {tokens?: ModelFileAccessTokens, signal?: AbortSignal, authorizationHeader?: string} + options?: {tokens?: ModelFileAccessTokens, endpoints?: ModelDownloadEndpoints, signal?: AbortSignal, authorizationHeader?: string} ): Promise; export async function resolveParsedModelUri( modelUri: ParsedModelUri | undefined | null, - options?: {tokens?: ModelFileAccessTokens, signal?: AbortSignal, authorizationHeader?: string} + options?: {tokens?: ModelFileAccessTokens, endpoints?: ModelDownloadEndpoints, signal?: AbortSignal, authorizationHeader?: string} ): Promise; export async function resolveParsedModelUri( modelUri: ParsedModelUri | undefined | null, - {tokens, signal, authorizationHeader}: { + {tokens, endpoints, signal, authorizationHeader}: { tokens?: ModelFileAccessTokens, + endpoints?: ModelDownloadEndpoints, signal?: AbortSignal, authorizationHeader?: string } = {} @@ -131,6 +137,7 @@ export async function resolveParsedModelUri( modelTag, fullUri: modelUri.uri, tokens, + endpoints, signal, authorizationHeader }); @@ -159,7 +166,7 @@ export async function resolveParsedModelUri( : resolvedBaseFilename; const resolvedUrl = normalizeGgufDownloadUrl([ - "https://huggingface.co/", encodeURIComponent(modelUri.resolveDetails.user), + resolveHuggingFaceEndpoint(endpoints), encodeURIComponent(modelUri.resolveDetails.user), "/", encodeURIComponent(modelUri.resolveDetails.model), "/resolve/", encodeURIComponent(defaultHuggingFaceBranch), "/", filename @@ -167,7 +174,7 @@ export async function resolveParsedModelUri( .map((item) => encodeURIComponent(item)) .join("/"), "?download=true" - ].join("")); + ].join(""), endpoints); return { type: "resolved", @@ -184,22 +191,22 @@ export function getAuthorizationHeader(headers?: Record): string } async function fetchHuggingFaceModelManifest({ - user, model, modelTag, fullUri, tokens, signal, authorizationHeader + user, model, modelTag, fullUri, tokens, endpoints, signal, authorizationHeader }: { user: string, model: string, modelTag: string, - fullUri: string, tokens?: ModelFileAccessTokens, signal?: AbortSignal, authorizationHeader?: string + fullUri: string, tokens?: ModelFileAccessTokens, endpoints?: ModelDownloadEndpoints, signal?: AbortSignal, authorizationHeader?: string }): Promise<{ rfilename: string, size: number }> { const manifestUrl = [ - "https://huggingface.co/v2/", encodeURIComponent(user), + resolveHuggingFaceEndpoint(endpoints), "v2/", encodeURIComponent(user), "/", encodeURIComponent(model), "/manifests/", encodeURIComponent(modelTag) ].join(""); const headersToTry = [ {}, - await resolveModelFileAccessTokensTryHeaders(manifestUrl, tokens) + await resolveModelFileAccessTokensTryHeaders(manifestUrl, tokens, endpoints) ]; while (headersToTry.length > 0) { @@ -254,7 +261,7 @@ async function fetchHuggingFaceModelManifest({ throw new Error(`Failed to fetch manifest for ${JSON.stringify(fullUri)}: no more headers to try`); } -function parseHuggingFaceUriContent(uri: string, fullUri: string): ParsedModelUri { +function parseHuggingFaceUriContent(uri: string, fullUri: string, endpoints: ModelDownloadEndpoints | undefined): ParsedModelUri { const [user, model, ...pathParts] = uri.split("/"); let rest = pathParts.join("/"); @@ -329,11 +336,11 @@ function parseHuggingFaceUriContent(uri: string, fullUri: string): ParsedModelUr throw new Error(`Invalid Hugging Face URI: ${fullUri}`); const resolvedUrl = normalizeGgufDownloadUrl([ - "https://huggingface.co/", encodeURIComponent(user), + resolveHuggingFaceEndpoint(endpoints), encodeURIComponent(user), "/", encodeURIComponent(model), "/resolve/", encodeURIComponent(branch), "/", filePath, "?download=true" - ].join("")); + ].join(""), endpoints); const filename = resolveModelFilenameFromUrl(resolvedUrl)!; const filePrefix = buildHuggingFaceFilePrefix(user, model, branch, filePathParts.slice(0, -1), filename); diff --git a/src/utils/resolveModelDestination.ts b/src/utils/resolveModelDestination.ts index a5418de2..032027f3 100644 --- a/src/utils/resolveModelDestination.ts +++ b/src/utils/resolveModelDestination.ts @@ -2,6 +2,7 @@ import path from "path"; import {normalizeGgufDownloadUrl} from "../gguf/utils/normalizeGgufDownloadUrl.js"; import {parseModelUri, ParsedModelUri, resolveParsedModelUri, getAuthorizationHeader} from "./parseModelUri.js"; import {isUrl} from "./isUrl.js"; +import {ModelDownloadEndpoints} from "./modelDownloadEndpoints.js"; export type ResolveModelDestination = { type: "url", @@ -16,8 +17,10 @@ export type ResolveModelDestination = { path: string }; -export function resolveModelDestination(modelDestination: string, convertUrlToUri: boolean = false): ResolveModelDestination { - const parsedUri = parseModelUri(modelDestination, convertUrlToUri); +export function resolveModelDestination( + modelDestination: string, convertUrlToUri: boolean = false, endpoints?: ModelDownloadEndpoints +): ResolveModelDestination { + const parsedUri = parseModelUri(modelDestination, convertUrlToUri, endpoints); if (parsedUri != null) { return { @@ -31,7 +34,7 @@ export function resolveModelDestination(modelDestination: string, convertUrlToUr } else if (isUrl(modelDestination)) { return { type: "url", - url: normalizeGgufDownloadUrl(modelDestination) + url: normalizeGgufDownloadUrl(modelDestination, endpoints) }; } diff --git a/src/utils/resolveModelFile.ts b/src/utils/resolveModelFile.ts index 4d6d9398..f3f9519d 100644 --- a/src/utils/resolveModelFile.ts +++ b/src/utils/resolveModelFile.ts @@ -5,7 +5,8 @@ import {cliModelsDirectory} from "../config.js"; import {getReadablePath} from "../cli/utils/getReadablePath.js"; import {resolveSplitGgufParts} from "../gguf/utils/resolveSplitGgufParts.js"; import {resolveModelDestination} from "./resolveModelDestination.js"; -import {ModelFileAccessTokens} from "./modelFileAccesTokens.js"; +import {ModelFileAccessTokens} from "./modelFileAccessTokens.js"; +import {ModelDownloadEndpoints} from "./modelDownloadEndpoints.js"; import {createModelDownloader} from "./createModelDownloader.js"; import {genericFilePartNumber} from "./parseModelUri.js"; import {isFilePartText} from "./parseModelFileName.js"; @@ -83,6 +84,12 @@ export type ResolveModelFileOptions = { */ tokens?: ModelFileAccessTokens, + /** + * Configure the URLs used for resolving model URIs. + * @see [Model URIs](https://node-llama-cpp.withcat.ai/guide/downloading-models#model-uris) + */ + endpoints?: ModelDownloadEndpoints, + /** * The signal to use to cancel a download. */ @@ -169,6 +176,7 @@ export async function resolveModelFile( deleteTempFileOnCancel = true, parallel = 4, tokens, + endpoints, signal } = typeof optionsOrDirectory === "string" ? {directory: optionsOrDirectory} @@ -181,7 +189,7 @@ export async function resolveModelFile( if (download === false) resolvedVerify = false; - const resolvedModelDestination = resolveModelDestination(uriOrPath); + const resolvedModelDestination = resolveModelDestination(uriOrPath, undefined, endpoints); if (resolvedModelDestination.type === "file") { const resolvedFilePath = path.resolve(resolvedDirectory, uriOrPath); @@ -202,7 +210,7 @@ export async function resolveModelFile( else pushAll(expectedFileNames, resolvedModelDestination.parsedUri.possibleFullFilenames); } else if (expectedFileNames.length === 0 && resolvedModelDestination.type === "url") { - const enforcedParsedUrl = resolveModelDestination(uriOrPath, true); + const enforcedParsedUrl = resolveModelDestination(uriOrPath, true, endpoints); if (enforcedParsedUrl != null && enforcedParsedUrl.type === "uri") { if (enforcedParsedUrl.parsedUri.type === "resolved") expectedFileNames.push(enforcedParsedUrl.parsedUri.fullFilename); @@ -249,7 +257,8 @@ export async function resolveModelFile( fileName: fileName || undefined, parallelDownloads: parallel, onProgress, - tokens + tokens, + endpoints }); if (foundExpectedFilePath != null && downloader.totalFiles === 1 && await fs.pathExists(downloader.entrypointFilePath)) { diff --git a/src/utils/transformPromisable.ts b/src/utils/transformPromisable.ts index 0f4e1f17..0ce742d0 100644 --- a/src/utils/transformPromisable.ts +++ b/src/utils/transformPromisable.ts @@ -93,4 +93,52 @@ export function promisableLoop({ return iterate(); } +/** + * Calls the given getters in order, and when a promise is encountered, waits for it to resolve before continuing. + * The result is transformed using the transformer function. + * + * This is used as a performance optimization to avoid adding many microtasks to the event loop, + * which makes reading from buffers significantly faster. + * @param getters - An array of functions that return values or promises + * @param transformer - The transformer function that takes the promisable values and transforms them into the result of this function + */ +export function transformPromisablesInOrder< + const T extends (() => Promisable)[], + const R = {readonly [Index in keyof T]: Awaited>;} +>( + getters: T, + transformer: ( + values: {readonly [Index in keyof T]: Awaited>;} + ) => Promisable = ((values) => values as R) +): Promisable { + let i = 0; + const res: any[] = []; + let skipPushingValue = true; + + function iterate(currentValue: any): Promisable { + if (skipPushingValue) + skipPushingValue = false; + else + res.push(currentValue); + + while (i < getters.length) { + const getter = getters[i]; + if (getter == null) + break; + + i++; + + const value = getter(); + if (value instanceof Promise) + return value.then(iterate); + + res.push(value); + } + + return transformer(res as {[Index in keyof T]: Awaited>;}); + } + + return iterate(undefined); +} + export type Promisable = T | Promise; diff --git a/templates/electron-typescript-react/package.json b/templates/electron-typescript-react/package.json index 0c8d5317..df1afcf1 100644 --- a/templates/electron-typescript-react/package.json +++ b/templates/electron-typescript-react/package.json @@ -23,39 +23,39 @@ }, "dependencies": { "@fontsource-variable/inter": "^5.2.5", - "birpc": "^2.2.0", + "birpc": "^2.3.0", "classnames": "^2.5.1", "highlight.js": "^11.11.1", "lifecycle-utils": "^2.0.0", "markdown-it": "^14.1.0", "node-llama-cpp": "file:../..", "pretty-ms": "^9.2.0", - "react": "^19.0.0", - "react-dom": "^19.0.0", + "react": "^19.1.0", + "react-dom": "^19.1.0", "semver": "^7.7.1" }, "devDependencies": { "@stylistic/eslint-plugin": "^4.2.0", "@types/markdown-it": "^14.1.2", - "@types/react": "^19.0.12", - "@types/react-dom": "^19.0.4", - "@types/semver": "^7.5.8", - "@vitejs/plugin-react": "^4.3.4", - "electron": "^35.0.3", - "electron-builder": "^25.1.8", - "eslint": "^9.23.0", - "eslint-import-resolver-typescript": "^4.2.2", + "@types/react": "^19.1.3", + "@types/react-dom": "^19.1.3", + "@types/semver": "^7.7.0", + "@vitejs/plugin-react": "^4.4.1", + "electron": "^36.2.0", + "electron-builder": "^26.0.12", + "eslint": "^9.26.0", + "eslint-import-resolver-typescript": "^4.3.4", "eslint-plugin-import": "^2.31.0", - "eslint-plugin-jsdoc": "^50.6.8", + "eslint-plugin-jsdoc": "^50.6.11", "eslint-plugin-react-hooks": "^5.2.0", - "eslint-plugin-react-refresh": "^0.4.19", + "eslint-plugin-react-refresh": "^0.4.20", "rimraf": "^6.0.1", - "typescript": "^5.8.2", - "typescript-eslint": "^8.27.0", - "vite": "^6.2.2", + "typescript": "^5.8.3", + "typescript-eslint": "^8.32.0", + "vite": "^6.3.5", "vite-plugin-electron": "^0.29.0", "vite-plugin-electron-renderer": "^0.14.6", - "zx": "^8.4.1" + "zx": "^8.5.3" }, "overrides": { "electron-builder": { diff --git a/templates/node-typescript/package.json b/templates/node-typescript/package.json index 9f77a046..f90101e8 100644 --- a/templates/node-typescript/package.json +++ b/templates/node-typescript/package.json @@ -39,16 +39,16 @@ }, "devDependencies": { "@stylistic/eslint-plugin": "^4.2.0", - "@types/node": "^22.13.11", - "eslint": "^9.23.0", - "eslint-import-resolver-typescript": "^4.2.2", + "@types/node": "^22.15.17", + "eslint": "^9.26.0", + "eslint-import-resolver-typescript": "^4.3.4", "eslint-plugin-import": "^2.31.0", - "eslint-plugin-jsdoc": "^50.6.8", - "eslint-plugin-n": "^17.16.2", + "eslint-plugin-jsdoc": "^50.6.11", + "eslint-plugin-n": "^17.17.0", "rimraf": "^6.0.1", "tslib": "^2.8.1", - "typescript": "^5.8.2", - "typescript-eslint": "^8.27.0", - "vite-node": "^3.0.9" + "typescript": "^5.8.3", + "typescript-eslint": "^8.32.0", + "vite-node": "^3.1.3" } } diff --git a/test/modelDependent/bgeReranker/rank.test.ts b/test/modelDependent/bgeReranker/rank.test.ts index 5d3dee3b..bfc90c33 100644 --- a/test/modelDependent/bgeReranker/rank.test.ts +++ b/test/modelDependent/bgeReranker/rank.test.ts @@ -43,16 +43,16 @@ describe("bgeReranker", () => { expect(simplifyRanks([highestRank])[0]).toMatchInlineSnapshot("0.01798620996209156"); expect(simplifyRanks(ranks)).toMatchInlineSnapshot(` [ - 0.00001670142184809518, - 0.00001670142184809518, - 0.00001670142184809518, + 0.000013674009084599736, + 0.000013674009084599736, + 0.000013674009084599736, 0.003684239899435989, - 0.00001670142184809518, + 0.000013674009084599736, 0.01798620996209156, - 0.00001670142184809518, - 0.00001670142184809518, - 0.00001670142184809518, - 0.00001670142184809518, + 0.000013674009084599736, + 0.000013674009084599736, + 0.00002039908727992137, + 0.000013674009084599736, ] `); }); @@ -94,16 +94,16 @@ describe("bgeReranker", () => { expect(simplifyRanks([highestRank])[0]).toMatchInlineSnapshot("0.01798620996209156"); expect(simplifyRanks(ranks)).toMatchInlineSnapshot(` [ - 0.00001670142184809518, - 0.00001670142184809518, - 0.00001670142184809518, + 0.000013674009084599736, + 0.000013674009084599736, + 0.000013674009084599736, 0.003684239899435989, - 0.00001670142184809518, + 0.000013674009084599736, 0.01798620996209156, - 0.00001670142184809518, - 0.00001670142184809518, - 0.00001670142184809518, - 0.00001670142184809518, + 0.000013674009084599736, + 0.000013674009084599736, + 0.00002039908727992137, + 0.000013674009084599736, ] `); }); @@ -156,27 +156,27 @@ describe("bgeReranker", () => { }, { "document": "Not all the things that shine are made of gold", - "score": 0.00001670142184809518, + "score": 0.00002039908727992137, }, { "document": "I love eating pizza with extra cheese", - "score": 0.00001670142184809518, + "score": 0.000013674009084599736, }, { "document": "Dogs love to play fetch with their owners", - "score": 0.00001670142184809518, + "score": 0.000013674009084599736, }, { "document": "The sky is clear and blue today", - "score": 0.00001670142184809518, + "score": 0.000013674009084599736, }, { "document": "Cleaning the house is a good way to keep it tidy", - "score": 0.00001670142184809518, + "score": 0.000013674009084599736, }, { "document": "A warm cup of tea is perfect for a cold winter day", - "score": 0.00001670142184809518, + "score": 0.000013674009084599736, }, ] `); @@ -196,7 +196,7 @@ function simplifySortedRanks { [ { "probabilities": Map { - 578 => 0.4307296, - 1115 => 0.1304376, + 578 => 0.4307292, + 1115 => 0.1304377, 1102 => 0.0516853, 763 => 0.042889, 1283 => 0.029397, @@ -113,28 +113,28 @@ describe("llama 3.1", () => { }, { "probabilities": Map { - 16053 => 0.4223004, - 4062 => 0.303636, - 39935 => 0.0603957, - 2944 => 0.0373029, - 5679 => 0.0238112, - 11914 => 0.0162982, - 2144 => 0.0146834, - 1121 => 0.0069844, - 17571 => 0.0057943, - 3446 => 0.0049344, + 16053 => 0.4222992, + 4062 => 0.3036339, + 39935 => 0.0603973, + 2944 => 0.0373043, + 5679 => 0.0238118, + 11914 => 0.0162981, + 2144 => 0.0146835, + 1121 => 0.0069849, + 17571 => 0.0057944, + 3446 => 0.0049346, }, "token": 16053, }, { "probabilities": Map { - 5679 => 0.9981183, + 5679 => 0.9981185, 12875 => 0.0001592, 18964 => 0.0001154, 39935 => 0.000115, 13 => 0.0001049, 627 => 0.0000928, - 656 => 0.0000626, + 656 => 0.0000625, 893 => 0.0000563, 198 => 0.0000522, 374 => 0.0000519, @@ -143,57 +143,57 @@ describe("llama 3.1", () => { }, { "probabilities": Map { - 374 => 0.8126624, - 1587 => 0.0481527, - 596 => 0.0247333, - 1120 => 0.022303, - 3250 => 0.0215451, - 706 => 0.0161837, - 15849 => 0.0086941, - 1053 => 0.0059118, - 55064 => 0.0037806, - 11 => 0.0036656, + 374 => 0.8126541, + 1587 => 0.0481526, + 596 => 0.0247368, + 1120 => 0.0223041, + 3250 => 0.0215465, + 706 => 0.0161833, + 15849 => 0.0086943, + 1053 => 0.0059125, + 55064 => 0.0037811, + 11 => 0.0036657, }, "token": 374, }, { "probabilities": Map { - 2288 => 0.275759, - 1120 => 0.1666484, - 539 => 0.1577515, - 779 => 0.1334379, - 264 => 0.055854, - 1101 => 0.0292162, - 16053 => 0.0176804, - 5042 => 0.0158628, - 1193 => 0.014583, - 2744 => 0.0140902, + 2288 => 0.2757553, + 1120 => 0.1666547, + 539 => 0.1577473, + 779 => 0.133445, + 264 => 0.0558533, + 1101 => 0.0292142, + 16053 => 0.0176781, + 5042 => 0.015864, + 1193 => 0.014582, + 2744 => 0.0140904, }, "token": 2288, }, { "probabilities": Map { - 16053 => 0.9066131, - 13326 => 0.0636239, - 19781 => 0.0071587, + 16053 => 0.9065909, + 13326 => 0.0636439, + 19781 => 0.007158, 17551 => 0.0020244, - 10968 => 0.0012676, - 11920 => 0.0011004, + 10968 => 0.0012683, + 11920 => 0.0011008, 6435 => 0.0010087, - 34386 => 0.0007757, + 34386 => 0.0007758, 1208 => 0.0006099, - 25366 => 0.0005671, + 25366 => 0.0005672, }, "token": 16053, }, { "probabilities": Map { - 311 => 0.9882798, - 1524 => 0.0061862, - 11 => 0.0025764, - 323 => 0.0005241, + 311 => 0.988279, + 1524 => 0.0061858, + 11 => 0.0025774, + 323 => 0.0005243, 13 => 0.0003535, - 627 => 0.000321, + 627 => 0.0003211, 1606 => 0.0002642, 2288 => 0.0002583, 369 => 0.0001247, @@ -203,46 +203,46 @@ describe("llama 3.1", () => { }, { "probabilities": Map { - 2512 => 0.7492305, - 1524 => 0.0989488, - 656 => 0.0324057, - 636 => 0.0240605, - 7940 => 0.014415, - 33586 => 0.0108681, - 387 => 0.0086816, - 1781 => 0.0058569, - 1629 => 0.0054877, - 3351 => 0.0051116, + 2512 => 0.7492248, + 1524 => 0.0989405, + 656 => 0.032411, + 636 => 0.0240648, + 7940 => 0.0144123, + 33586 => 0.0108691, + 387 => 0.0086826, + 1781 => 0.0058571, + 1629 => 0.005489, + 3351 => 0.0051125, }, "token": 2512, }, { "probabilities": Map { - 922 => 0.9521903, - 1606 => 0.0150086, - 11 => 0.0140083, + 922 => 0.9521815, + 1606 => 0.015013, + 11 => 0.014011, 430 => 0.0029686, - 627 => 0.0023146, - 13 => 0.0018861, - 1524 => 0.0018015, - 369 => 0.001769, - 323 => 0.0009245, - 382 => 0.0008478, + 627 => 0.002315, + 13 => 0.0018864, + 1524 => 0.0018013, + 369 => 0.0017693, + 323 => 0.0009247, + 382 => 0.0008479, }, "token": 922, }, { "probabilities": Map { - 279 => 0.6508099, - 4205 => 0.3128838, - 1148 => 0.0113662, - 1690 => 0.0044249, - 904 => 0.0030378, - 1202 => 0.0026805, + 279 => 0.6508148, + 4205 => 0.3128796, + 1148 => 0.0113661, + 1690 => 0.004425, + 904 => 0.0030377, + 1202 => 0.0026803, 264 => 0.0011171, 1790 => 0.001086, 813 => 0.0010579, - 1524 => 0.00077, + 1524 => 0.0007699, }, "token": 279, }, @@ -280,43 +280,43 @@ describe("llama 3.1", () => { expect(res).toMatchInlineSnapshot(` [ { - "confidence": 0.4307296, + "confidence": 0.4307292, "token": 578, }, { - "confidence": 0.4223004, + "confidence": 0.4222992, "token": 16053, }, { - "confidence": 0.9981183, + "confidence": 0.9981185, "token": 5679, }, { - "confidence": 0.8126624, + "confidence": 0.8126541, "token": 374, }, { - "confidence": 0.275759, + "confidence": 0.2757553, "token": 2288, }, { - "confidence": 0.9066131, + "confidence": 0.9065909, "token": 16053, }, { - "confidence": 0.9882798, + "confidence": 0.988279, "token": 311, }, { - "confidence": 0.7492305, + "confidence": 0.7492248, "token": 2512, }, { - "confidence": 0.9521903, + "confidence": 0.9521815, "token": 922, }, { - "confidence": 0.6508099, + "confidence": 0.6508148, "token": 279, }, ] @@ -353,10 +353,10 @@ describe("llama 3.1", () => { expect(res).toMatchInlineSnapshot(` [ { - "confidence": 0.4307296, + "confidence": 0.4307292, "probabilities": Map { - 578 => 0.4307296, - 1115 => 0.1304376, + 578 => 0.4307292, + 1115 => 0.1304377, 1102 => 0.0516853, 763 => 0.042889, 1283 => 0.029397, @@ -369,31 +369,31 @@ describe("llama 3.1", () => { "token": 578, }, { - "confidence": 0.4223004, + "confidence": 0.4222992, "probabilities": Map { - 16053 => 0.4223004, - 4062 => 0.303636, - 39935 => 0.0603957, - 2944 => 0.0373029, - 5679 => 0.0238112, - 11914 => 0.0162982, - 2144 => 0.0146834, - 1121 => 0.0069844, - 17571 => 0.0057943, - 3446 => 0.0049344, + 16053 => 0.4222992, + 4062 => 0.3036339, + 39935 => 0.0603973, + 2944 => 0.0373043, + 5679 => 0.0238118, + 11914 => 0.0162981, + 2144 => 0.0146835, + 1121 => 0.0069849, + 17571 => 0.0057944, + 3446 => 0.0049346, }, "token": 16053, }, { - "confidence": 0.9981183, + "confidence": 0.9981185, "probabilities": Map { - 5679 => 0.9981183, + 5679 => 0.9981185, 12875 => 0.0001592, 18964 => 0.0001154, 39935 => 0.000115, 13 => 0.0001049, 627 => 0.0000928, - 656 => 0.0000626, + 656 => 0.0000625, 893 => 0.0000563, 198 => 0.0000522, 374 => 0.0000519, @@ -401,62 +401,62 @@ describe("llama 3.1", () => { "token": 5679, }, { - "confidence": 0.8126624, + "confidence": 0.8126541, "probabilities": Map { - 374 => 0.8126624, - 1587 => 0.0481527, - 596 => 0.0247333, - 1120 => 0.022303, - 3250 => 0.0215451, - 706 => 0.0161837, - 15849 => 0.0086941, - 1053 => 0.0059118, - 55064 => 0.0037806, - 11 => 0.0036656, + 374 => 0.8126541, + 1587 => 0.0481526, + 596 => 0.0247368, + 1120 => 0.0223041, + 3250 => 0.0215465, + 706 => 0.0161833, + 15849 => 0.0086943, + 1053 => 0.0059125, + 55064 => 0.0037811, + 11 => 0.0036657, }, "token": 374, }, { - "confidence": 0.275759, + "confidence": 0.2757553, "probabilities": Map { - 2288 => 0.275759, - 1120 => 0.1666484, - 539 => 0.1577515, - 779 => 0.1334379, - 264 => 0.055854, - 1101 => 0.0292162, - 16053 => 0.0176804, - 5042 => 0.0158628, - 1193 => 0.014583, - 2744 => 0.0140902, + 2288 => 0.2757553, + 1120 => 0.1666547, + 539 => 0.1577473, + 779 => 0.133445, + 264 => 0.0558533, + 1101 => 0.0292142, + 16053 => 0.0176781, + 5042 => 0.015864, + 1193 => 0.014582, + 2744 => 0.0140904, }, "token": 2288, }, { - "confidence": 0.9066131, + "confidence": 0.9065909, "probabilities": Map { - 16053 => 0.9066131, - 13326 => 0.0636239, - 19781 => 0.0071587, + 16053 => 0.9065909, + 13326 => 0.0636439, + 19781 => 0.007158, 17551 => 0.0020244, - 10968 => 0.0012676, - 11920 => 0.0011004, + 10968 => 0.0012683, + 11920 => 0.0011008, 6435 => 0.0010087, - 34386 => 0.0007757, + 34386 => 0.0007758, 1208 => 0.0006099, - 25366 => 0.0005671, + 25366 => 0.0005672, }, "token": 16053, }, { - "confidence": 0.9882798, + "confidence": 0.988279, "probabilities": Map { - 311 => 0.9882798, - 1524 => 0.0061862, - 11 => 0.0025764, - 323 => 0.0005241, + 311 => 0.988279, + 1524 => 0.0061858, + 11 => 0.0025774, + 323 => 0.0005243, 13 => 0.0003535, - 627 => 0.000321, + 627 => 0.0003211, 1606 => 0.0002642, 2288 => 0.0002583, 369 => 0.0001247, @@ -465,50 +465,50 @@ describe("llama 3.1", () => { "token": 311, }, { - "confidence": 0.7492305, + "confidence": 0.7492248, "probabilities": Map { - 2512 => 0.7492305, - 1524 => 0.0989488, - 656 => 0.0324057, - 636 => 0.0240605, - 7940 => 0.014415, - 33586 => 0.0108681, - 387 => 0.0086816, - 1781 => 0.0058569, - 1629 => 0.0054877, - 3351 => 0.0051116, + 2512 => 0.7492248, + 1524 => 0.0989405, + 656 => 0.032411, + 636 => 0.0240648, + 7940 => 0.0144123, + 33586 => 0.0108691, + 387 => 0.0086826, + 1781 => 0.0058571, + 1629 => 0.005489, + 3351 => 0.0051125, }, "token": 2512, }, { - "confidence": 0.9521903, + "confidence": 0.9521815, "probabilities": Map { - 922 => 0.9521903, - 1606 => 0.0150086, - 11 => 0.0140083, + 922 => 0.9521815, + 1606 => 0.015013, + 11 => 0.014011, 430 => 0.0029686, - 627 => 0.0023146, - 13 => 0.0018861, - 1524 => 0.0018015, - 369 => 0.001769, - 323 => 0.0009245, - 382 => 0.0008478, + 627 => 0.002315, + 13 => 0.0018864, + 1524 => 0.0018013, + 369 => 0.0017693, + 323 => 0.0009247, + 382 => 0.0008479, }, "token": 922, }, { - "confidence": 0.6508099, + "confidence": 0.6508148, "probabilities": Map { - 279 => 0.6508099, - 4205 => 0.3128838, - 1148 => 0.0113662, - 1690 => 0.0044249, - 904 => 0.0030378, - 1202 => 0.0026805, + 279 => 0.6508148, + 4205 => 0.3128796, + 1148 => 0.0113661, + 1690 => 0.004425, + 904 => 0.0030377, + 1202 => 0.0026803, 264 => 0.0011171, 1790 => 0.001086, 813 => 0.0010579, - 1524 => 0.00077, + 1524 => 0.0007699, }, "token": 279, }, diff --git a/test/modelDependent/llama3.2/sequenceState.test.ts b/test/modelDependent/llama3.2/sequenceState.test.ts new file mode 100644 index 00000000..151fc4f3 --- /dev/null +++ b/test/modelDependent/llama3.2/sequenceState.test.ts @@ -0,0 +1,299 @@ +import {describe, expect, test} from "vitest"; +import fs from "fs-extra"; +import {LlamaChatSession, TokenMeter} from "../../../src/index.js"; +import {getModelFile} from "../../utils/modelFiles.js"; +import {getTestLlama} from "../../utils/getTestLlama.js"; +import {getTempTestFilePath} from "../../utils/helpers/getTempTestDir.js"; +import {toBytes} from "../../../src/cli/utils/toBytes.js"; + +describe("llama 3.2", () => { + describe("chatSession", () => { + describe("sequence state", () => { + test("save and load a state works properly", {timeout: 1000 * 60 * 60 * 2}, async (test) => { + const modelPath = await getModelFile("Llama-3.2-3B-Instruct.Q4_K_M.gguf"); + const llama = await getTestLlama(); + + const model = await llama.loadModel({ + modelPath + }); + const context = await model.createContext({ + contextSize: 1024, + sequences: 2 + }); + const contextSequence1 = context.getSequence(); + const contextSequence2 = context.getSequence(); + + const chatSession1 = new LlamaChatSession({ + contextSequence: contextSequence1 + }); + const chatSession2 = new LlamaChatSession({ + contextSequence: contextSequence2 + }); + + const [ + res1, + res2 + ] = await Promise.all([ + chatSession1.prompt("Remember: locks are not doors", {maxTokens: 6}), + chatSession2.prompt("Remember: giraffes are not elephants", {maxTokens: 5}) + ]); + expect(res1).to.toMatchInlineSnapshot("\"That's a clever phrase.\""); + expect(res2).to.toMatchInlineSnapshot('"I appreciate the reminder."'); + + + const stateFile1Path = await getTempTestFilePath("state1"); + const state1Tokens = contextSequence1.contextTokens.slice(); + await contextSequence1.saveStateToFile(stateFile1Path); + test.onTestFinished(() => fs.remove(stateFile1Path)); + + expect(contextSequence1.contextTokens).to.eql(state1Tokens); + expect(contextSequence1.contextTokens.length).toMatchInlineSnapshot("105"); + expect(toBytes((await fs.stat(stateFile1Path)).size)).to.toMatchInlineSnapshot('"11.49MB"'); + + + const stateFile2Path = await getTempTestFilePath("state2"); + const state2Tokens = contextSequence2.contextTokens.slice(); + await contextSequence2.saveStateToFile(stateFile2Path); + test.onTestFinished(() => fs.remove(stateFile2Path)); + + expect(contextSequence2.contextTokens).to.eql(state2Tokens); + expect(contextSequence2.contextTokens.length).toMatchInlineSnapshot("106"); + expect(toBytes((await fs.stat(stateFile2Path)).size)).to.toMatchInlineSnapshot('"11.6MB"'); + + + await contextSequence1.clearHistory(); + const contextSequence1TokensState1 = contextSequence1.tokenMeter.getState(); + + expect(contextSequence1.contextTokens).to.eql([]); + expect(contextSequence1TokensState1).toMatchInlineSnapshot(` + { + "usedInputTokens": 99, + "usedOutputTokens": 6, + } + `); + + const chatSession1_1 = new LlamaChatSession({ + contextSequence: contextSequence1 + }); + const res1_1 = await chatSession1_1.prompt("What did I tell you to remember?", {maxTokens: 12}); + expect(res1_1).to.toMatchInlineSnapshot("\"You didn't tell me to remember anything. This is the\""); + + await contextSequence1.clearHistory(); + const contextSequence1TokensState2 = contextSequence1.tokenMeter.getState(); + + expect(contextSequence1.contextTokens).to.eql([]); + expect(TokenMeter.diff(contextSequence1TokensState2, contextSequence1TokensState1)).toMatchInlineSnapshot(` + { + "usedInputTokens": 101, + "usedOutputTokens": 12, + } + `); + + await contextSequence1.loadStateFromFile(stateFile1Path, {acceptRisk: true}); + expect(contextSequence1.contextTokens).to.eql(state1Tokens); + expect(contextSequence1.contextTokens.length).toMatchInlineSnapshot("105"); + + const contextSequence1TokensState3 = contextSequence1.tokenMeter.getState(); + expect(TokenMeter.diff(contextSequence1TokensState3, contextSequence1TokensState2)).toMatchInlineSnapshot(` + { + "usedInputTokens": 0, + "usedOutputTokens": 0, + } + `); + + const chatSession1_2 = new LlamaChatSession({ + contextSequence: contextSequence1 + }); + chatSession1_2.setChatHistory(chatSession1.getChatHistory()); + const res1_2 = await chatSession1_2.prompt("What did I tell you to remember?", {maxTokens: 12}); + const contextSequence1TokensState4 = contextSequence1.tokenMeter.getState(); + + expect(res1_2).to.toMatchInlineSnapshot('"You told me to remember that "locks are not doors"."'); + const contextSequence1TokensState4Diff = TokenMeter.diff(contextSequence1TokensState4, contextSequence1TokensState3); + expect(contextSequence1TokensState4Diff.usedInputTokens).to.be.lessThan(contextSequence1TokensState1.usedInputTokens); + expect(contextSequence1TokensState4Diff).toMatchInlineSnapshot(` + { + "usedInputTokens": 18, + "usedOutputTokens": 12, + } + `); + }); + + test("save and load a state works across different contexts", {timeout: 1000 * 60 * 60 * 2}, async (test) => { + const modelPath = await getModelFile("Llama-3.2-3B-Instruct.Q4_K_M.gguf"); + const llama = await getTestLlama(); + + const model = await llama.loadModel({ + modelPath + }); + const context1 = await model.createContext({ + contextSize: 1024 + }); + const context2 = await model.createContext({ + contextSize: 1024 + }); + const contextSequence1 = context1.getSequence(); + const contextSequence2 = context2.getSequence(); + + const chatSession1 = new LlamaChatSession({ + contextSequence: contextSequence1 + }); + + const res1 = await chatSession1.prompt("Remember: locks are not doors", {maxTokens: 6}); + expect(res1).to.toMatchInlineSnapshot("\"That's a clever phrase.\""); + + + const stateFile1Path = await getTempTestFilePath("state1"); + const state1Tokens = contextSequence1.contextTokens.slice(); + await contextSequence1.saveStateToFile(stateFile1Path); + test.onTestFinished(() => fs.remove(stateFile1Path)); + const contextSequence1TokensState = contextSequence1.tokenMeter.getState(); + + expect(contextSequence1.contextTokens).to.eql(state1Tokens); + expect(contextSequence1.contextTokens.length).toMatchInlineSnapshot("105"); + expect(toBytes((await fs.stat(stateFile1Path)).size)).to.toMatchInlineSnapshot('"11.49MB"'); + expect(contextSequence1TokensState).to.toMatchInlineSnapshot(` + { + "usedInputTokens": 99, + "usedOutputTokens": 6, + } + `); + + contextSequence1.dispose(); + + + const chatSession2 = new LlamaChatSession({ + contextSequence: contextSequence2 + }); + chatSession2.setChatHistory(chatSession1.getChatHistory()); + await contextSequence2.loadStateFromFile(stateFile1Path, {acceptRisk: true}); + + const res2 = await chatSession2.prompt("What did I tell you to remember?", {maxTokens: 12}); + expect(res2).to.toMatchInlineSnapshot('"You told me to remember that "locks are not doors"."'); + const contextSequence2TokensState = contextSequence2.tokenMeter.getState(); + expect(contextSequence2TokensState.usedInputTokens).to.be.lessThan(contextSequence1TokensState.usedInputTokens); + expect(contextSequence2TokensState).toMatchInlineSnapshot(` + { + "usedInputTokens": 18, + "usedOutputTokens": 12, + } + `); + }); + + test("restoring to a smaller context sequence fails", {timeout: 1000 * 60 * 60 * 2}, async (test) => { + const modelPath = await getModelFile("Llama-3.2-3B-Instruct.Q4_K_M.gguf"); + const llama = await getTestLlama(); + + const model = await llama.loadModel({ + modelPath + }); + const context1 = await model.createContext({ + contextSize: 1024 + }); + const context2 = await model.createContext({ + contextSize: 100 + }); + const contextSequence1 = context1.getSequence(); + const contextSequence2 = context2.getSequence(); + + const chatSession1 = new LlamaChatSession({ + contextSequence: contextSequence1 + }); + + const res1 = await chatSession1.prompt("Remember: locks are not doors", {maxTokens: 6}); + expect(res1).to.toMatchInlineSnapshot("\"That's a clever phrase.\""); + + + const stateFile1Path = await getTempTestFilePath("state1"); + const state1Tokens = contextSequence1.contextTokens.slice(); + await contextSequence1.saveStateToFile(stateFile1Path); + test.onTestFinished(() => fs.remove(stateFile1Path)); + const contextSequence1TokensState = contextSequence1.tokenMeter.getState(); + + expect(contextSequence1.contextTokens).to.eql(state1Tokens); + expect(contextSequence1.contextTokens.length).toMatchInlineSnapshot("105"); + expect(toBytes((await fs.stat(stateFile1Path)).size)).to.toMatchInlineSnapshot('"11.49MB"'); + expect(contextSequence1TokensState).to.toMatchInlineSnapshot(` + { + "usedInputTokens": 99, + "usedOutputTokens": 6, + } + `); + + contextSequence1.dispose(); + + + const chatSession2 = new LlamaChatSession({ + contextSequence: contextSequence2 + }); + chatSession2.setChatHistory(chatSession1.getChatHistory()); + try { + await contextSequence2.loadStateFromFile(stateFile1Path, {acceptRisk: true}); + expect.unreachable("Should have thrown an error"); + } catch (err) { + expect(err).toMatchInlineSnapshot("[Error: Failed to load state from file. Current context sequence size may be smaller that the state of the file]"); + } + + expect(contextSequence2.contextTokens).to.eql([]); + }); + + test("restoring to a smaller context sequence fails - 2 sequences", {timeout: 1000 * 60 * 60 * 2}, async (test) => { + const modelPath = await getModelFile("Llama-3.2-3B-Instruct.Q4_K_M.gguf"); + const llama = await getTestLlama(); + + const model = await llama.loadModel({ + modelPath + }); + const context1 = await model.createContext({ + contextSize: 1024 + }); + const context2 = await model.createContext({ + contextSize: 100, + sequences: 2 + }); + const contextSequence1 = context1.getSequence(); + const contextSequence2 = context2.getSequence(); + + const chatSession1 = new LlamaChatSession({ + contextSequence: contextSequence1 + }); + + const res1 = await chatSession1.prompt("Remember: locks are not doors", {maxTokens: 6}); + expect(res1).to.toMatchInlineSnapshot("\"That's a clever phrase.\""); + + + const stateFile1Path = await getTempTestFilePath("state1"); + const state1Tokens = contextSequence1.contextTokens.slice(); + await contextSequence1.saveStateToFile(stateFile1Path); + test.onTestFinished(() => fs.remove(stateFile1Path)); + const contextSequence1TokensState = contextSequence1.tokenMeter.getState(); + + expect(contextSequence1.contextTokens).to.eql(state1Tokens); + expect(contextSequence1.contextTokens.length).toMatchInlineSnapshot("105"); + expect(toBytes((await fs.stat(stateFile1Path)).size)).to.toMatchInlineSnapshot('"11.49MB"'); + expect(contextSequence1TokensState).to.toMatchInlineSnapshot(` + { + "usedInputTokens": 99, + "usedOutputTokens": 6, + } + `); + + contextSequence1.dispose(); + + + const chatSession2 = new LlamaChatSession({ + contextSequence: contextSequence2 + }); + chatSession2.setChatHistory(chatSession1.getChatHistory()); + try { + await contextSequence2.loadStateFromFile(stateFile1Path, {acceptRisk: true}); + expect.unreachable("Should have thrown an error"); + } catch (err) { + expect(err).toMatchInlineSnapshot("[Error: Failed to load state from file. Current context sequence size may be smaller that the state of the file]"); + } + + expect(contextSequence2.contextTokens).to.eql([]); + }); + }); + }); +}); diff --git a/test/standalone/chatWrappers/DeepSeekChatWrapper.test.ts b/test/standalone/chatWrappers/DeepSeekChatWrapper.test.ts index 413dcd74..9f848c47 100644 --- a/test/standalone/chatWrappers/DeepSeekChatWrapper.test.ts +++ b/test/standalone/chatWrappers/DeepSeekChatWrapper.test.ts @@ -66,7 +66,7 @@ describe("DeepSeekChatWrapper", () => { text: "What is the time?" }, { type: "model", - response: ["I'll fet some information for you", { + response: ["I'll fetch some information for you", { type: "functionCall", name: "getTime", description: "Retrieve the current time", @@ -270,7 +270,7 @@ describe("DeepSeekChatWrapper", () => { new SpecialTokensText("<|end▁of▁sentence|><|User|>"), "What is the time?", new SpecialTokensText("<|Assistant|>"), - "I'll fet some information for you", + "I'll fetch some information for you", new SpecialTokensText(""), diff --git a/test/standalone/chatWrappers/QwenChatWrapper.test.ts b/test/standalone/chatWrappers/QwenChatWrapper.test.ts index 577bfa14..030f4fd6 100644 --- a/test/standalone/chatWrappers/QwenChatWrapper.test.ts +++ b/test/standalone/chatWrappers/QwenChatWrapper.test.ts @@ -66,7 +66,7 @@ describe("QwenChatWrapper", () => { text: "What is the time?" }, { type: "model", - response: ["I'll fet some information for you", { + response: ["I'll fetch some information for you", { type: "functionCall", name: "getTime", description: "Retrieve the current time", @@ -187,10 +187,7 @@ describe("QwenChatWrapper", () => { "What is the time?", new SpecialTokensText("<|im_end|> <|im_start|>assistant - "), - " - ", - new SpecialTokensText(""), + "), " {"name": "getTime", "arguments": {"hours": "24", "seconds": true}} ", @@ -310,8 +307,7 @@ describe("QwenChatWrapper", () => { new SpecialTokensText("<|im_end|> <|im_start|>assistant "), - "I'll fet some information for you - ", + "I'll fetch some information for you", new SpecialTokensText(""), " {"name": "getTime", "arguments": {"hours": "24", "seconds": true}} diff --git a/test/standalone/chatWrappers/utils/resolveChatWrapper.test.ts b/test/standalone/chatWrappers/utils/resolveChatWrapper.test.ts index d0a671b1..ddea8365 100644 --- a/test/standalone/chatWrappers/utils/resolveChatWrapper.test.ts +++ b/test/standalone/chatWrappers/utils/resolveChatWrapper.test.ts @@ -445,6 +445,94 @@ const qwqJinjaTemplate = ` {%- endif %} `.slice(1, -1); +const qwen3Template = ` +{%- if tools %} + {{- '<|im_start|>system\\n' }} + {%- if messages[0].role == 'system' %} + {{- messages[0].content + '\\n\\n' }} + {%- endif %} + {{- "# Tools\\n\\nYou may call one or more functions to assist with the user query.\\n\\nYou are provided with function signatures within XML tags:\\n" }} + {%- for tool in tools %} + {{- "\\n" }} + {{- tool | tojson }} + {%- endfor %} + {{- "\\n\\n\\nFor each function call, return a json object with function name and arguments within XML tags:\\n\\n{\\"name\\": , \\"arguments\\": }\\n<|im_end|>\\n" }} +{%- else %} + {%- if messages[0].role == 'system' %} + {{- '<|im_start|>system\\n' + messages[0].content + '<|im_end|>\\n' }} + {%- endif %} +{%- endif %} +{%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %} +{%- for index in range(ns.last_query_index, -1, -1) %} + {%- set message = messages[index] %} + {%- if ns.multi_step_tool and message.role == "user" and not('' in message.content and '' in message.content) %} + {%- set ns.multi_step_tool = false %} + {%- set ns.last_query_index = index %} + {%- endif %} +{%- endfor %} +{%- for message in messages %} + {%- if (message.role == "user") or (message.role == "system" and not loop.first) %} + {{- '<|im_start|>' + message.role + '\\n' + message.content + '<|im_end|>' + '\\n' }} + {%- elif message.role == "assistant" %} + {%- set content = message.content %} + {%- set reasoning_content = '' %} + {%- if message.reasoning_content is defined and message.reasoning_content is not none %} + {%- set reasoning_content = message.reasoning_content %} + {%- else %} + {%- if '' in message.content %} + {%- set content = message.content.split('')[-1].lstrip('\\n') %} + {%- set reasoning_content = message.content.split('')[0].rstrip('\\n').split('')[-1].lstrip('\\n') %} + {%- endif %} + {%- endif %} + {%- if loop.index0 > ns.last_query_index %} + {%- if loop.last or (not loop.last and reasoning_content) %} + {{- '<|im_start|>' + message.role + '\\n\\n' + reasoning_content.strip('\\n') + '\\n\\n\\n' + content.lstrip('\\n') }} + {%- else %} + {{- '<|im_start|>' + message.role + '\\n' + content }} + {%- endif %} + {%- else %} + {{- '<|im_start|>' + message.role + '\\n' + content }} + {%- endif %} + {%- if message.tool_calls %} + {%- for tool_call in message.tool_calls %} + {%- if (loop.first and content) or (not loop.first) %} + {{- '\\n' }} + {%- endif %} + {%- if tool_call.function %} + {%- set tool_call = tool_call.function %} + {%- endif %} + {{- '\\n{"name": "' }} + {{- tool_call.name }} + {{- '", "arguments": ' }} + {%- if tool_call.arguments is string %} + {{- tool_call.arguments }} + {%- else %} + {{- tool_call.arguments | tojson }} + {%- endif %} + {{- '}\\n' }} + {%- endfor %} + {%- endif %} + {{- '<|im_end|>\\n' }} + {%- elif message.role == "tool" %} + {%- if loop.first or (messages[loop.index0 - 1].role != "tool") %} + {{- '<|im_start|>user' }} + {%- endif %} + {{- '\\n\\n' }} + {{- message.content }} + {{- '\\n' }} + {%- if loop.last or (messages[loop.index0 + 1].role != "tool") %} + {{- '<|im_end|>\\n' }} + {%- endif %} + {%- endif %} +{%- endfor %} +{%- if add_generation_prompt %} + {{- '<|im_start|>assistant\\n' }} + {%- if enable_thinking is defined and enable_thinking is false %} + {{- '\\n\\n\\n\\n' }} + {%- endif %} +{%- endif %} +`.slice(1, -1); + describe("resolveChatWrapper", () => { test("should resolve to specialized AlpacaChatWrapper", () => { @@ -618,4 +706,16 @@ describe("resolveChatWrapper", () => { }); expect(chatWrapper).to.be.instanceof(QwenChatWrapper); }); + + test("should resolve to specialized QwenChatWrapper 2", {timeout: 1000 * 60 * 60 * 2}, async () => { + const chatWrapper = resolveChatWrapper({ + customWrapperSettings: { + jinjaTemplate: { + template: qwen3Template + } + }, + fallbackToOtherWrappersOnJinjaError: false + }); + expect(chatWrapper).to.be.instanceof(QwenChatWrapper); + }); }); diff --git a/test/standalone/cli/recommendedModels.test.ts b/test/standalone/cli/recommendedModels.test.ts new file mode 100644 index 00000000..6ccf727a --- /dev/null +++ b/test/standalone/cli/recommendedModels.test.ts @@ -0,0 +1,35 @@ +import {describe, expect, test} from "vitest"; +import {parseModelUri, resolveParsedModelUri} from "../../../src/utils/parseModelUri.js"; +import {recommendedModels} from "../../../src/cli/recommendedModels.js"; + +describe("cli", () => { + describe("recommended models", () => { + test("all URIs resolve correctly", async () => { + const unresolvedUris = ( + await Promise.all( + recommendedModels + .flatMap((modelOption) => ( + modelOption.fileOptions.map(((uri) => [modelOption.name, uri])) + )) + .map(async ([modelName, uri]) => { + if (uri == null) + return null; + + try { + await resolveParsedModelUri(parseModelUri(uri)); + return null; + } catch (err) { + return { + modelName, + uri + }; + } + }) + ) + ) + .filter((unresolvedUri) => unresolvedUri != null); + + expect(unresolvedUris).to.eql([]); + }); + }); +}); diff --git a/test/standalone/utils/parseModelUri.test.ts b/test/standalone/utils/parseModelUri.test.ts index 35aeca63..ead2f2d3 100644 --- a/test/standalone/utils/parseModelUri.test.ts +++ b/test/standalone/utils/parseModelUri.test.ts @@ -6,13 +6,13 @@ const __filename = fileURLToPath(import.meta.url); describe("utils", () => { describe("parseModelUri", () => { - test("File path is not resolved", async () => { + test("File path is not resolved", () => { const parsedModelUri = parseModelUri(__filename); expect(parsedModelUri).to.eql(null); }); - test("URL is not resolved by default", async () => { + test("URL is not resolved by default", () => { const parsedModelUri = parseModelUri( "https://huggingface.co/mradermacher/Meta-Llama-3.1-8B-Instruct-GGUF/resolve/main/Meta-Llama-3.1-8B-Instruct.Q4_K_M.gguf" ); @@ -20,7 +20,7 @@ describe("utils", () => { expect(parsedModelUri).to.eql(null); }); - test("Hugging Face URL is resolved", async () => { + test("Hugging Face URL is resolved", () => { const parsedModelUri = parseModelUri( "https://huggingface.co/mradermacher/Meta-Llama-3.1-8B-Instruct-GGUF/resolve/main/Meta-Llama-3.1-8B-Instruct.Q4_K_M.gguf", true @@ -38,7 +38,7 @@ describe("utils", () => { `); }); - test("Hugging Face URL is resolved 2", async () => { + test("Hugging Face URL is resolved 2", () => { const parsedModelUri = parseModelUri( "https://huggingface.co/mradermacher/Meta-Llama-3.1-8B-Instruct-GGUF/resolve/main/Meta-Llama-3.1-8B-Instruct.Q4_K_M.gguf?download=true", true @@ -56,7 +56,7 @@ describe("utils", () => { `); }); - test("Hugging Face URL is resolved 3", async () => { + test("Hugging Face URL is resolved 3", () => { const parsedModelUri = parseModelUri( "https://huggingface.co/bartowski/Meta-Llama-3.1-70B-Instruct-GGUF/blob/main/Meta-Llama-3.1-70B-Instruct-Q5_K_L/Meta-Llama-3.1-70B-Instruct-Q5_K_L-00001-of-00002.gguf", true @@ -74,7 +74,7 @@ describe("utils", () => { `); }); - test("Hugging Face URL is resolved 4", async () => { + test("Hugging Face URL is resolved 4", () => { const parsedModelUri = parseModelUri( "https://huggingface.co/bartowski/Meta-Llama-3.1-70B-Instruct-GGUF/resolve/main/Meta-Llama-3.1-70B-Instruct-Q5_K_L/Meta-Llama-3.1-70B-Instruct-Q5_K_L-00001-of-00002.gguf?download=true", true @@ -92,7 +92,7 @@ describe("utils", () => { `); }); - test("Hugging Face URL is resolved 5", async () => { + test("Hugging Face URL is resolved 5", () => { const parsedModelUri = parseModelUri( "https://huggingface.co/mradermacher/Meta-Llama-3.1-70B-Instruct-GGUF/blob/main/Meta-Llama-3.1-70B-Instruct.Q8_0.gguf.part1of2", true @@ -110,7 +110,7 @@ describe("utils", () => { `); }); - test("Hugging Face URI is resolved", async () => { + test("Hugging Face URI is resolved", () => { const parsedModelUri = parseModelUri("hf:mradermacher/Meta-Llama-3.1-8B-Instruct-GGUF/Meta-Llama-3.1-8B-Instruct.Q4_K_M.gguf"); expect(parsedModelUri).toMatchInlineSnapshot(` @@ -125,7 +125,7 @@ describe("utils", () => { `); }); - test("Hugging Face URI is resolved 2", async () => { + test("Hugging Face URI is resolved 2", () => { const parsedModelUri = parseModelUri("hf:bartowski/Meta-Llama-3.1-70B-Instruct-GGUF/Meta-Llama-3.1-70B-Instruct-Q5_K_L/Meta-Llama-3.1-70B-Instruct-Q5_K_L-00001-of-00002.gguf"); expect(parsedModelUri).toMatchInlineSnapshot(` @@ -140,7 +140,7 @@ describe("utils", () => { `); }); - test("Hugging Face URI is resolved 3", async () => { + test("Hugging Face URI is resolved 3", () => { const parsedModelUri = parseModelUri("hf:mradermacher/Meta-Llama-3.1-70B-Instruct-GGUF/Meta-Llama-3.1-70B-Instruct.Q8_0.gguf.part1of2"); expect(parsedModelUri).toMatchInlineSnapshot(` @@ -155,7 +155,7 @@ describe("utils", () => { `); }); - test("Hugging Face simple URI is resolved", async () => { + test("Hugging Face simple URI is resolved", {timeout: 1000 * 10}, async () => { const parsedModelUri = parseModelUri("hf:mradermacher/Meta-Llama-3.1-8B-Instruct-GGUF:Q4_K_M"); expect(parsedModelUri).toMatchInlineSnapshot(` @@ -192,7 +192,7 @@ describe("utils", () => { `); }); - test("Hugging Face simple URI is resolved - lowercase quant", async () => { + test("Hugging Face simple URI is resolved - lowercase quant", {timeout: 1000 * 10}, async () => { const parsedModelUri = parseModelUri("hf:mradermacher/Meta-Llama-3.1-8B-Instruct-GGUF:q4_k_m"); expect(parsedModelUri).toMatchInlineSnapshot(` @@ -229,27 +229,27 @@ describe("utils", () => { `); }); - test("Hugging Face simple URI is resolved 2", async () => { - const parsedModelUri = parseModelUri("hf:bartowski/Meta-Llama-3.1-70B-Instruct-GGUF:Q5_K_L"); + test("Hugging Face simple URI is resolved 2", {timeout: 1000 * 10}, async () => { + const parsedModelUri = parseModelUri("hf:bartowski/Meta-Llama-3.1-70B-Instruct-GGUF:Q5_K_M"); expect(parsedModelUri).toMatchInlineSnapshot(` { "baseFilename": "Meta-Llama-3.1-70B-Instruct", "filePrefix": "hf_bartowski_", "possibleFullFilenames": [ - "hf_bartowski_Meta-Llama-3.1-70B-Instruct.Q5_K_L.gguf", - "hf_bartowski_Meta-Llama-3.1-70B-Instruct.Q5_K_L-00001-of-{: + "hf_bartowski_Meta-Llama-3.1-70B-Instruct.Q5_K_M.gguf", + "hf_bartowski_Meta-Llama-3.1-70B-Instruct.Q5_K_M-00001-of-{: {number} :}.gguf", ], "resolveDetails": { "model": "Meta-Llama-3.1-70B-Instruct-GGUF", - "tag": "Q5_K_L", + "tag": "Q5_K_M", "type": "hf", "user": "bartowski", }, "type": "unresolved", - "uri": "hf:bartowski/Meta-Llama-3.1-70B-Instruct-GGUF:Q5_K_L", + "uri": "hf:bartowski/Meta-Llama-3.1-70B-Instruct-GGUF:Q5_K_M", } `); @@ -257,16 +257,16 @@ describe("utils", () => { expect(resolvedUri).toMatchInlineSnapshot(` { "filePrefix": "hf_bartowski_", - "filename": "Meta-Llama-3.1-70B-Instruct.Q5_K_L-00001-of-00002.gguf", - "fullFilename": "hf_bartowski_Meta-Llama-3.1-70B-Instruct.Q5_K_L-00001-of-00002.gguf", - "resolvedUrl": "https://huggingface.co/bartowski/Meta-Llama-3.1-70B-Instruct-GGUF/resolve/main/Meta-Llama-3.1-70B-Instruct-Q5_K_L/Meta-Llama-3.1-70B-Instruct-Q5_K_L-00001-of-00002.gguf?download=true", + "filename": "Meta-Llama-3.1-70B-Instruct.Q5_K_M-00001-of-00002.gguf", + "fullFilename": "hf_bartowski_Meta-Llama-3.1-70B-Instruct.Q5_K_M-00001-of-00002.gguf", + "resolvedUrl": "https://huggingface.co/bartowski/Meta-Llama-3.1-70B-Instruct-GGUF/resolve/main/Meta-Llama-3.1-70B-Instruct-Q5_K_M/Meta-Llama-3.1-70B-Instruct-Q5_K_M-00001-of-00002.gguf?download=true", "type": "resolved", - "uri": "hf:bartowski/Meta-Llama-3.1-70B-Instruct-GGUF:Q5_K_L", + "uri": "hf:bartowski/Meta-Llama-3.1-70B-Instruct-GGUF:Q5_K_M", } `); }); - test("Hugging Face simple URI is resolved 3", async () => { + test("Hugging Face simple URI is resolved 3", {timeout: 1000 * 10}, async () => { const parsedModelUri = parseModelUri("hf:mradermacher/Meta-Llama-3.1-8B-Instruct-GGUF"); expect(parsedModelUri).toMatchInlineSnapshot(` @@ -307,7 +307,7 @@ describe("utils", () => { `); }); - test("Hugging Face simple URI is resolved 4", async () => { + test("Hugging Face simple URI is resolved 4", {timeout: 1000 * 10}, async () => { const parsedModelUri = parseModelUri("hf:mradermacher/Meta-Llama-3.1-70B-Instruct-GGUF:Q8_0"); expect(parsedModelUri).toMatchInlineSnapshot(` @@ -339,7 +339,7 @@ describe("utils", () => { } }); - test("Hugging Face simple URI is resolved 5", async () => { + test("Hugging Face simple URI is resolved 5", {timeout: 1000 * 10}, async () => { const parsedModelUri = parseModelUri("https://huggingface.co/mradermacher/Meta-Llama-3.1-8B-Instruct-GGUF"); expect(parsedModelUri).toMatchInlineSnapshot(` @@ -380,7 +380,7 @@ describe("utils", () => { `); }); - test("Hugging Face simple URI is resolved 6", async () => { + test("Hugging Face simple URI is resolved 6", {timeout: 1000 * 10}, async () => { const parsedModelUri = parseModelUri("hf:mradermacher/Meta-Llama-3.1-70B-Instruct-GGUF:invalid"); expect(parsedModelUri).toMatchInlineSnapshot(` diff --git a/test/utils/helpers/getTempTestDir.ts b/test/utils/helpers/getTempTestDir.ts new file mode 100644 index 00000000..c76a7244 --- /dev/null +++ b/test/utils/helpers/getTempTestDir.ts @@ -0,0 +1,32 @@ +import path from "path"; +import {fileURLToPath} from "url"; +import fs from "fs-extra"; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const tempDir = path.join(__dirname, "..", "..", ".temp"); + +export async function getTempTestDir() { + await fs.ensureDir(tempDir); + return tempDir; +} + +export async function getTempTestFilePath(fileName: string) { + const tempDir = await getTempTestDir(); + const currentDate = new Date(); + const fileDateString = [ + String(currentDate.getFullYear()), + String(currentDate.getMonth() + 1).padStart(2, "0"), + String(currentDate.getDate()).padStart(2, "0"), + String(currentDate.getHours()).padStart(2, "0"), + String(currentDate.getMinutes()).padStart(2, "0"), + String(currentDate.getSeconds()).padStart(2, "0"), + String(currentDate.getMilliseconds()).padStart(3, "0") + ].join(""); + const randomText = Math.random() + .toString(36) + .slice(2, 10 + 2); + + const resolvedFilename = fileDateString + "_" + randomText + "_" + fileName; + + return path.join(tempDir, resolvedFilename); +} diff --git a/test/utils/setupAndTestOnPaperspace.sh b/test/utils/setupAndTestOnPaperspace.sh index 051d9654..ae52410b 100644 --- a/test/utils/setupAndTestOnPaperspace.sh +++ b/test/utils/setupAndTestOnPaperspace.sh @@ -11,7 +11,7 @@ installationCommand='bash -c "$(curl -fsSL https://raw.githubusercontent.com/wit defaultRepo="withcatai/node-llama-cpp" targetFolder="$HOME/workspace/test-node-llama-cpp" -nodejsVersion="21" +nodejsVersion="20" colorYellow=$'\e[33m' diff --git a/vitest.config.ts b/vitest.config.ts index ebcdbf4c..f7c45fb3 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -11,6 +11,14 @@ export default defineConfig({ minForks: 1, maxForks: 1, singleFork: true + + // uncomment for profiling + // execArgv: [ + // "--cpu-prof", + // "--cpu-prof-dir=test-runner-profile", + // "--heap-prof", + // "--heap-prof-dir=test-runner-profile" + // ] } }, snapshotSerializers: [