diff --git a/.gitignore b/.gitignore index 990de72..fbbb803 100644 --- a/.gitignore +++ b/.gitignore @@ -109,4 +109,8 @@ external-resources/dlc/**/*.mp4 external-resources/dlc/**/*.tar external-resources/dlc/**/*.zip external-resources/dlc/**/*.sql -external-resources/dlc/**/*.torrent \ No newline at end of file +external-resources/dlc/**/*.torrent + +# 忽略启动器更新临时目录 +update-temp/ +update.bat diff --git a/external-resources/dlc/dlc-index.json b/external-resources/dlc/dlc-index.json index 8edbf75..c2b0e35 100644 --- a/external-resources/dlc/dlc-index.json +++ b/external-resources/dlc/dlc-index.json @@ -6,12 +6,12 @@ "2.0.0": { "magnet": "magnet:?xt=urn:btih:a7f8c85dcef68ae7958f0f3548603ea9016897df&dn=ala-training-v2.0.0.tar&tr=wss%3A%2F%2Flearning.panchuantech.cn%2Fannounce", "comment": "第一个版本", - "riquire":{} + "require": {} }, "2.0.2": { "magnet": "magnet:?xt=urn:btih:98995512a1cf581a1baea19132b1a6550ec424fc&dn=ala-training-v2.0.2.tar&tr=wss%3A%2F%2Flearning.panchuantech.cn%2Fannounce", "comment": "相比上一个版本修复了一些问题", - "riquire":{} + "require": {} } } }, @@ -22,10 +22,43 @@ "2.0.2": { "magnet": "magnet:?xt=urn:btih:cff0fb96747c5fc4696af4c9fa8cd30330050250&dn=ai_learning_assistant.sql&tr=wss%3A%2F%2Flearning.panchuantech.cn%2Fannounce&tr=wss%3A%2F%2F114.66.58.95%3A17853%2Fannounce", "comment": "第一个版本", - "riquire":{ + "require": { "TRAINING_TAR": "^2.0.0" } } } + }, + { + "id": "AI_LEARNING_ASSISTANT_LAUNCHER", + "name": "AI学习助手启动器", + "versions": { + "2.0.2": { + "magnet": "magnet:?xt=urn:btih:30469d14ed0eaf65f88d6a2c51cea9888c4a2ff7&dn=AI-Learning-Assistant-Launcher-win32-x64-2.0.2-p2p.zip&tr=wss%3A%2F%2Flearning.panchuantech.cn%2Fannounce&tr=wss%3A%2F%2F114.66.58.95%3A17853%2Fannounce", + "comment": "测试更新使用版本", + "require": {} + } + } + }, + { + "id": "OBSIDIAN_SETUP_EXE", + "name": "obsidian 安装程序", + "versions": { + "1.8.10": { + "magnet": "magnet:?xt=urn:btih:c05567b4ca6b53f73b0902824a3098713673f907&dn=install_obsidian.exe&tr=wss%3A%2F%2Flearning.panchuantech.cn%2Fannounce&tr=wss%3A%2F%2F114.66.58.95%3A17853%2Fannounce", + "comment": "第一个版本", + "require": {} + } + } + }, + { + "id": "LM_STUDIO_SETUP_EXE", + "name": "lm studio 安装程序", + "versions": { + "0.3.23": { + "magnet": "magnet:?xt=urn:btih:c368d43704e39686c8904d19816f20c08803d5c3&dn=install_lm_studio.exe&tr=wss%3A%2F%2Flearning.panchuantech.cn%2Fannounce&tr=wss%3A%2F%2F114.66.58.95%3A17853%2Fannounce", + "comment": "第一个版本", + "require": {} + } + } } ] diff --git a/icons/joint_build.png b/icons/joint_build.png new file mode 100644 index 0000000..967f3a0 Binary files /dev/null and b/icons/joint_build.png differ diff --git a/package-lock.json b/package-lock.json index 2f2c1f3..b483edd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,11 +15,13 @@ "@langchain/ollama": "^0.2.4", "@langchain/openai": "^0.6.14", "@types/webtorrent": "^0.110.1", + "adm-zip": "^0.5.16", "electron-squirrel-startup": "^1.0.1", "langchain": "^0.3.35", "pdf-lib": "^1.17.1", "react": "^19.1.0", - "react-dom": "^19.1.0" + "react-dom": "^19.1.0", + "semver": "^7.7.3" }, "devDependencies": { "@ant-design/v5-patch-for-react-19": "^1.0.3", @@ -34,6 +36,7 @@ "@electron/fuses": "^1.8.0", "@stdlib/utils-convert-path": "^0.2.2", "@svgr/webpack": "^8.1.0", + "@types/adm-zip": "^0.5.7", "@types/cross-spawn": "^6.0.6", "@types/dockerode": "^3.3.40", "@types/form-data": "^2.2.1", @@ -224,13 +227,13 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.28.6.tgz", + "integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" }, @@ -239,9 +242,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.28.5", - "resolved": "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.28.5.tgz", - "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.28.6.tgz", + "integrity": "sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==", "dev": true, "license": "MIT", "engines": { @@ -249,21 +252,22 @@ } }, "node_modules/@babel/core": { - "version": "7.28.5", - "resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.28.5.tgz", - "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.28.6.tgz", + "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.5", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.28.3", - "@babel/helpers": "^7.28.4", - "@babel/parser": "^7.28.5", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.5", - "@babel/types": "^7.28.5", + "@babel/code-frame": "^7.28.6", + "@babel/generator": "^7.28.6", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", @@ -290,14 +294,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.28.5", - "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.28.5.tgz", - "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.28.6.tgz", + "integrity": "sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.5", - "@babel/types": "^7.28.5", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -320,13 +324,13 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmmirror.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.27.2", + "@babel/compat-data": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", @@ -347,18 +351,18 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.28.5", - "resolved": "https://registry.npmmirror.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.5.tgz", - "integrity": "sha512-q3WC4JfdODypvxArsJQROfupPBq9+lMwjKq7C33GhbFYJsufD0yd/ziwD+hJucLeWsnFPWZjsU2DNFqBPE7jwQ==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz", + "integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-member-expression-to-functions": "^7.28.5", "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/helper-replace-supers": "^7.27.1", + "@babel/helper-replace-supers": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/traverse": "^7.28.5", + "@babel/traverse": "^7.28.6", "semver": "^6.3.1" }, "engines": { @@ -407,17 +411,17 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.5", - "resolved": "https://registry.npmmirror.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.5.tgz", - "integrity": "sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==", + "version": "0.6.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.6.tgz", + "integrity": "sha512-mOAsxeeKkUKayvZR3HeTYD/fICpCPLJrU5ZjelT/PA6WHtNDBOE436YiaEUvHN454bRM3CebhDsIpieCc4texA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-plugin-utils": "^7.27.1", - "debug": "^4.4.1", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "debug": "^4.4.3", "lodash.debounce": "^4.0.8", - "resolve": "^1.22.10" + "resolve": "^1.22.11" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -448,29 +452,29 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.28.3", - "resolved": "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", - "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.28.3" + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -493,9 +497,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", - "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", "dev": true, "license": "MIT", "engines": { @@ -521,15 +525,15 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz", - "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz", + "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-member-expression-to-functions": "^7.28.5", "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/traverse": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -583,42 +587,42 @@ } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.28.3", - "resolved": "https://registry.npmmirror.com/@babel/helper-wrap-function/-/helper-wrap-function-7.28.3.tgz", - "integrity": "sha512-zdf983tNfLZFletc0RRXYrHrucBEg95NIFMkn6K9dbeMYnsgHaSBGcQqdsCSStG2PYwRre0Qc2NNSCXbG+xc6g==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-wrap-function/-/helper-wrap-function-7.28.6.tgz", + "integrity": "sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.3", - "@babel/types": "^7.28.2" + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.28.4", - "resolved": "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.28.4.tgz", - "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.28.6.tgz", + "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4" + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.28.5", - "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.28.5.tgz", - "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.28.6.tgz", + "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.28.5" + "@babel/types": "^7.28.6" }, "bin": { "parser": "bin/babel-parser.js" @@ -695,14 +699,14 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.28.3", - "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.3.tgz", - "integrity": "sha512-b6YTX108evsvE4YgWyQ921ZAFFQm3Bn+CA3+ZXlNVnPhx+UfsVURoPjfGAPCjBgrqo30yX/C2nZGX96DxvR9Iw==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.6.tgz", + "integrity": "sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.28.3" + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/traverse": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -725,13 +729,13 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.27.1.tgz", - "integrity": "sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.28.6.tgz", + "integrity": "sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -741,13 +745,13 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", - "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", + "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -757,13 +761,13 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", - "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz", + "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -773,13 +777,13 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", - "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz", + "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -822,15 +826,15 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.28.0", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.28.0.tgz", - "integrity": "sha512-BEOdvX4+M765icNPZeidyADIvQ1m1gmunXufXxvRESy/jNNyfovIqUyE7MVgGBjWktCoJlzvFA1To2O4ymIO3Q==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.28.6.tgz", + "integrity": "sha512-9knsChgsMzBV5Yh3kkhrZNxH3oCYAfMBkNNaVN4cP2RVlFPe8wYdwwcnOsAbkdDoV9UjFtOXWrWB52M8W4jNeA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-remap-async-to-generator": "^7.27.1", - "@babel/traverse": "^7.28.0" + "@babel/traverse": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -840,14 +844,14 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.27.1.tgz", - "integrity": "sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.28.6.tgz", + "integrity": "sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-remap-async-to-generator": "^7.27.1" }, "engines": { @@ -874,13 +878,13 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.28.5", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.5.tgz", - "integrity": "sha512-45DmULpySVvmq9Pj3X9B+62Xe+DJGov27QravQJU1LLcapR6/10i+gYVAucGGJpHBp5mYxIMK4nDAT/QDLr47g==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.6.tgz", + "integrity": "sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -890,14 +894,14 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.27.1.tgz", - "integrity": "sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.28.6.tgz", + "integrity": "sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -907,14 +911,14 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.28.3", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.3.tgz", - "integrity": "sha512-LtPXlBbRoc4Njl/oh1CeD/3jC+atytbnf/UqLoqTDcEYGUPj022+rvfkbDYieUrSj3CaV4yHDByPE+T2HwfsJg==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.6.tgz", + "integrity": "sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.28.3", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -924,18 +928,18 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.28.4", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.4.tgz", - "integrity": "sha512-cFOlhIYPBv/iBoc+KS3M6et2XPtbT2HiCRfBXWtfpc9OAyostldxIf9YAYB6ypURBBbx+Qv6nyrLzASfJe+hBA==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.6.tgz", + "integrity": "sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-globals": "^7.28.0", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-replace-supers": "^7.27.1", - "@babel/traverse": "^7.28.4" + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-replace-supers": "^7.28.6", + "@babel/traverse": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -945,14 +949,14 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.27.1.tgz", - "integrity": "sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.28.6.tgz", + "integrity": "sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/template": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/template": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -979,14 +983,14 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.27.1.tgz", - "integrity": "sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.28.6.tgz", + "integrity": "sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1012,14 +1016,14 @@ } }, "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.27.1.tgz", - "integrity": "sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.28.6.tgz", + "integrity": "sha512-5suVoXjC14lUN6ZL9OLKIHCNVWCrqGqlmEp/ixdXjvgnEl/kauLvvMO/Xw9NyMc95Joj1AeLVPVMvibBgSoFlA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1045,14 +1049,14 @@ } }, "node_modules/@babel/plugin-transform-explicit-resource-management": { - "version": "7.28.0", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.0.tgz", - "integrity": "sha512-K8nhUcn3f6iB+P3gwCv/no7OdzOZQcKchW6N389V6PD8NUWKZHzndOd9sPDVbMoBsbmjMqlB4L9fm+fEFNVlwQ==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.6.tgz", + "integrity": "sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-transform-destructuring": "^7.28.0" + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/plugin-transform-destructuring": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -1062,13 +1066,13 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.28.5", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.5.tgz", - "integrity": "sha512-D4WIMaFtwa2NizOp+dnoFjRez/ClKiC2BqqImwKd1X28nqBtZEyCYJ2ozQrrzlxAFrcrjxo39S6khe9RNDlGzw==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.6.tgz", + "integrity": "sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1129,13 +1133,13 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.27.1.tgz", - "integrity": "sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.28.6.tgz", + "integrity": "sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1161,13 +1165,13 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.28.5", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.5.tgz", - "integrity": "sha512-axUuqnUTBuXyHGcJEVVh9pORaN6wC5bYfE7FGzPiaWa3syib9m7g+/IT/4VgCOe2Upef43PHzeAvcrVek6QuuA==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.6.tgz", + "integrity": "sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1210,14 +1214,14 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.27.1.tgz", - "integrity": "sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.28.6.tgz", + "integrity": "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1296,13 +1300,13 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.27.1.tgz", - "integrity": "sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.28.6.tgz", + "integrity": "sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1312,13 +1316,13 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.27.1.tgz", - "integrity": "sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.28.6.tgz", + "integrity": "sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1328,17 +1332,17 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.28.4", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.4.tgz", - "integrity": "sha512-373KA2HQzKhQCYiRVIRr+3MjpCObqzDlyrM6u4I201wL8Mp2wHf7uB8GhDwis03k2ti8Zr65Zyyqs1xOxUF/Ew==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.6.tgz", + "integrity": "sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-transform-destructuring": "^7.28.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/plugin-transform-destructuring": "^7.28.5", "@babel/plugin-transform-parameters": "^7.27.7", - "@babel/traverse": "^7.28.4" + "@babel/traverse": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1365,13 +1369,13 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.27.1.tgz", - "integrity": "sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.28.6.tgz", + "integrity": "sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1381,13 +1385,13 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.28.5", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.5.tgz", - "integrity": "sha512-N6fut9IZlPnjPwgiQkXNhb+cT8wQKFlJNqcZkWlcTqkcqx6/kU4ynGmLFoa4LViBSirn05YAwk+sQBbPfxtYzQ==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.6.tgz", + "integrity": "sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, "engines": { @@ -1414,14 +1418,14 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.27.1.tgz", - "integrity": "sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.28.6.tgz", + "integrity": "sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1431,15 +1435,15 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.27.1.tgz", - "integrity": "sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.28.6.tgz", + "integrity": "sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-create-class-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1497,17 +1501,17 @@ } }, "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.27.1.tgz", - "integrity": "sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.28.6.tgz", + "integrity": "sha512-61bxqhiRfAACulXSLd/GxqmAedUSrRZIu/cbaT18T1CetkTmtDN15it7i80ru4DVqRK1WMxQhXs+Lf9kajm5Ow==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-syntax-jsx": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/plugin-syntax-jsx": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1550,13 +1554,13 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.28.4", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.4.tgz", - "integrity": "sha512-+ZEdQlBoRg9m2NnzvEeLgtvBMO4tkFBw5SQIUgLICgTrumLoU7lr+Oghi6km2PFj+dbUt2u1oby2w3BDO9YQnA==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.6.tgz", + "integrity": "sha512-eZhoEZHYQLL5uc1gS5e9/oTknS0sSSAtd5TkKMUp3J+S/CaUjagc0kOUPsEbDmMeva0nC3WWl4SxVY6+OBuxfw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1566,14 +1570,14 @@ } }, "node_modules/@babel/plugin-transform-regexp-modifiers": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.27.1.tgz", - "integrity": "sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.28.6.tgz", + "integrity": "sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1615,13 +1619,13 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.27.1.tgz", - "integrity": "sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.28.6.tgz", + "integrity": "sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, "engines": { @@ -1680,17 +1684,17 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.28.5", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.5.tgz", - "integrity": "sha512-x2Qa+v/CuEoX7Dr31iAfr0IhInrVOWZU/2vJMJ00FOR/2nM0BcBEclpaf9sWCDc+v5e9dMrhSH8/atq/kX7+bA==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.6.tgz", + "integrity": "sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-create-class-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/plugin-syntax-typescript": "^7.27.1" + "@babel/plugin-syntax-typescript": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1716,14 +1720,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.27.1.tgz", - "integrity": "sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.28.6.tgz", + "integrity": "sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1750,14 +1754,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.27.1.tgz", - "integrity": "sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.28.6.tgz", + "integrity": "sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1767,76 +1771,76 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.28.5", - "resolved": "https://registry.npmmirror.com/@babel/preset-env/-/preset-env-7.28.5.tgz", - "integrity": "sha512-S36mOoi1Sb6Fz98fBfE+UZSpYw5mJm0NUHtIKrOuNcqeFauy1J6dIvXm2KRVKobOSaGq4t/hBXdN4HGU3wL9Wg==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/preset-env/-/preset-env-7.28.6.tgz", + "integrity": "sha512-GaTI4nXDrs7l0qaJ6Rg06dtOXTBCG6TMDB44zbqofCIC4PqC7SEvmFFtpxzCDw9W5aJ7RKVshgXTLvLdBFV/qw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.28.5", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-plugin-utils": "^7.27.1", + "@babel/compat-data": "^7.28.6", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5", "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.3", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.6", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-import-assertions": "^7.27.1", - "@babel/plugin-syntax-import-attributes": "^7.27.1", + "@babel/plugin-syntax-import-assertions": "^7.28.6", + "@babel/plugin-syntax-import-attributes": "^7.28.6", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", "@babel/plugin-transform-arrow-functions": "^7.27.1", - "@babel/plugin-transform-async-generator-functions": "^7.28.0", - "@babel/plugin-transform-async-to-generator": "^7.27.1", + "@babel/plugin-transform-async-generator-functions": "^7.28.6", + "@babel/plugin-transform-async-to-generator": "^7.28.6", "@babel/plugin-transform-block-scoped-functions": "^7.27.1", - "@babel/plugin-transform-block-scoping": "^7.28.5", - "@babel/plugin-transform-class-properties": "^7.27.1", - "@babel/plugin-transform-class-static-block": "^7.28.3", - "@babel/plugin-transform-classes": "^7.28.4", - "@babel/plugin-transform-computed-properties": "^7.27.1", + "@babel/plugin-transform-block-scoping": "^7.28.6", + "@babel/plugin-transform-class-properties": "^7.28.6", + "@babel/plugin-transform-class-static-block": "^7.28.6", + "@babel/plugin-transform-classes": "^7.28.6", + "@babel/plugin-transform-computed-properties": "^7.28.6", "@babel/plugin-transform-destructuring": "^7.28.5", - "@babel/plugin-transform-dotall-regex": "^7.27.1", + "@babel/plugin-transform-dotall-regex": "^7.28.6", "@babel/plugin-transform-duplicate-keys": "^7.27.1", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.27.1", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.28.6", "@babel/plugin-transform-dynamic-import": "^7.27.1", - "@babel/plugin-transform-explicit-resource-management": "^7.28.0", - "@babel/plugin-transform-exponentiation-operator": "^7.28.5", + "@babel/plugin-transform-explicit-resource-management": "^7.28.6", + "@babel/plugin-transform-exponentiation-operator": "^7.28.6", "@babel/plugin-transform-export-namespace-from": "^7.27.1", "@babel/plugin-transform-for-of": "^7.27.1", "@babel/plugin-transform-function-name": "^7.27.1", - "@babel/plugin-transform-json-strings": "^7.27.1", + "@babel/plugin-transform-json-strings": "^7.28.6", "@babel/plugin-transform-literals": "^7.27.1", - "@babel/plugin-transform-logical-assignment-operators": "^7.28.5", + "@babel/plugin-transform-logical-assignment-operators": "^7.28.6", "@babel/plugin-transform-member-expression-literals": "^7.27.1", "@babel/plugin-transform-modules-amd": "^7.27.1", - "@babel/plugin-transform-modules-commonjs": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.28.6", "@babel/plugin-transform-modules-systemjs": "^7.28.5", "@babel/plugin-transform-modules-umd": "^7.27.1", "@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1", "@babel/plugin-transform-new-target": "^7.27.1", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1", - "@babel/plugin-transform-numeric-separator": "^7.27.1", - "@babel/plugin-transform-object-rest-spread": "^7.28.4", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.28.6", + "@babel/plugin-transform-numeric-separator": "^7.28.6", + "@babel/plugin-transform-object-rest-spread": "^7.28.6", "@babel/plugin-transform-object-super": "^7.27.1", - "@babel/plugin-transform-optional-catch-binding": "^7.27.1", - "@babel/plugin-transform-optional-chaining": "^7.28.5", + "@babel/plugin-transform-optional-catch-binding": "^7.28.6", + "@babel/plugin-transform-optional-chaining": "^7.28.6", "@babel/plugin-transform-parameters": "^7.27.7", - "@babel/plugin-transform-private-methods": "^7.27.1", - "@babel/plugin-transform-private-property-in-object": "^7.27.1", + "@babel/plugin-transform-private-methods": "^7.28.6", + "@babel/plugin-transform-private-property-in-object": "^7.28.6", "@babel/plugin-transform-property-literals": "^7.27.1", - "@babel/plugin-transform-regenerator": "^7.28.4", - "@babel/plugin-transform-regexp-modifiers": "^7.27.1", + "@babel/plugin-transform-regenerator": "^7.28.6", + "@babel/plugin-transform-regexp-modifiers": "^7.28.6", "@babel/plugin-transform-reserved-words": "^7.27.1", "@babel/plugin-transform-shorthand-properties": "^7.27.1", - "@babel/plugin-transform-spread": "^7.27.1", + "@babel/plugin-transform-spread": "^7.28.6", "@babel/plugin-transform-sticky-regex": "^7.27.1", "@babel/plugin-transform-template-literals": "^7.27.1", "@babel/plugin-transform-typeof-symbol": "^7.27.1", "@babel/plugin-transform-unicode-escapes": "^7.27.1", - "@babel/plugin-transform-unicode-property-regex": "^7.27.1", + "@babel/plugin-transform-unicode-property-regex": "^7.28.6", "@babel/plugin-transform-unicode-regex": "^7.27.1", - "@babel/plugin-transform-unicode-sets-regex": "^7.27.1", + "@babel/plugin-transform-unicode-sets-regex": "^7.28.6", "@babel/preset-modules": "0.1.6-no-external-plugins", "babel-plugin-polyfill-corejs2": "^0.4.14", "babel-plugin-polyfill-corejs3": "^0.13.0", @@ -1918,42 +1922,42 @@ } }, "node_modules/@babel/runtime": { - "version": "7.28.4", - "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.28.4.tgz", - "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.28.6.tgz", + "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmmirror.com/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.28.5", - "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.28.5.tgz", - "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.28.6.tgz", + "integrity": "sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.5", + "@babel/code-frame": "^7.28.6", + "@babel/generator": "^7.28.6", "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.5", - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.5", + "@babel/parser": "^7.28.6", + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6", "debug": "^4.3.1" }, "engines": { @@ -1961,9 +1965,9 @@ } }, "node_modules/@babel/types": { - "version": "7.28.5", - "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.28.5.tgz", - "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.28.6.tgz", + "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==", "dev": true, "license": "MIT", "dependencies": { @@ -1985,8 +1989,7 @@ "version": "4.1.1", "resolved": "https://registry.npmmirror.com/@cfworker/json-schema/-/json-schema-4.1.1.tgz", "integrity": "sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", @@ -2013,9 +2016,9 @@ } }, "node_modules/@electron-forge/cli": { - "version": "7.10.2", - "resolved": "https://registry.npmmirror.com/@electron-forge/cli/-/cli-7.10.2.tgz", - "integrity": "sha512-X1RtS5IqNgzGDS2rr1q0Y74wU/m3DbU4vSgllNun1ZQv1BfMpDcKLhnKi3aeetoA0huLTpMVU9eWJ7bziI9fxA==", + "version": "7.11.1", + "resolved": "https://registry.npmmirror.com/@electron-forge/cli/-/cli-7.11.1.tgz", + "integrity": "sha512-pk8AoLsr7t7LBAt0cFD06XFA6uxtPdvtLx06xeal7O9o7GHGCbj29WGwFoJ8Br/ENM0Ho868S3PrAn1PtBXt5g==", "dev": true, "funding": [ { @@ -2029,9 +2032,9 @@ ], "license": "MIT", "dependencies": { - "@electron-forge/core": "7.10.2", - "@electron-forge/core-utils": "7.10.2", - "@electron-forge/shared-types": "7.10.2", + "@electron-forge/core": "7.11.1", + "@electron-forge/core-utils": "7.11.1", + "@electron-forge/shared-types": "7.11.1", "@electron/get": "^3.0.0", "@inquirer/prompts": "^6.0.1", "@listr2/prompt-adapter-inquirer": "^2.0.22", @@ -2053,9 +2056,9 @@ } }, "node_modules/@electron-forge/core": { - "version": "7.10.2", - "resolved": "https://registry.npmmirror.com/@electron-forge/core/-/core-7.10.2.tgz", - "integrity": "sha512-HAIuOtpOfGjA0cd55tbEV2gAv+A7tSZg9bonmVDYFEe6dBgbLk8a3+/1fJUdWW8fyFkg1wa8zK7pjP751bAXsA==", + "version": "7.11.1", + "resolved": "https://registry.npmmirror.com/@electron-forge/core/-/core-7.11.1.tgz", + "integrity": "sha512-YtuPLzggPKPabFAD2rOZFE0s7f4KaUTpGRduhSMbZUqpqD1TIPyfoDBpYiZvao3Ht8pyZeOJjbzcC0LpFs9gIQ==", "dev": true, "funding": [ { @@ -2069,17 +2072,17 @@ ], "license": "MIT", "dependencies": { - "@electron-forge/core-utils": "7.10.2", - "@electron-forge/maker-base": "7.10.2", - "@electron-forge/plugin-base": "7.10.2", - "@electron-forge/publisher-base": "7.10.2", - "@electron-forge/shared-types": "7.10.2", - "@electron-forge/template-base": "7.10.2", - "@electron-forge/template-vite": "7.10.2", - "@electron-forge/template-vite-typescript": "7.10.2", - "@electron-forge/template-webpack": "7.10.2", - "@electron-forge/template-webpack-typescript": "7.10.2", - "@electron-forge/tracer": "7.10.2", + "@electron-forge/core-utils": "7.11.1", + "@electron-forge/maker-base": "7.11.1", + "@electron-forge/plugin-base": "7.11.1", + "@electron-forge/publisher-base": "7.11.1", + "@electron-forge/shared-types": "7.11.1", + "@electron-forge/template-base": "7.11.1", + "@electron-forge/template-vite": "7.11.1", + "@electron-forge/template-vite-typescript": "7.11.1", + "@electron-forge/template-webpack": "7.11.1", + "@electron-forge/template-webpack-typescript": "7.11.1", + "@electron-forge/tracer": "7.11.1", "@electron/get": "^3.0.0", "@electron/packager": "^18.3.5", "@electron/rebuild": "^3.7.0", @@ -2109,13 +2112,13 @@ } }, "node_modules/@electron-forge/core-utils": { - "version": "7.10.2", - "resolved": "https://registry.npmmirror.com/@electron-forge/core-utils/-/core-utils-7.10.2.tgz", - "integrity": "sha512-JXrk2hWR4q8KgZFABpojjuqql3tYeVIH6qmtbkNEkZEQq7YIxajJBCct7J7bWfNQTmHotsQ3k5KLknhyhTaBMw==", + "version": "7.11.1", + "resolved": "https://registry.npmmirror.com/@electron-forge/core-utils/-/core-utils-7.11.1.tgz", + "integrity": "sha512-9UxRWVsfcziBsbAA2MS0Oz4yYovQCO2BhnGIfsbKNTBtMc/RcVSxAS0NMyymce44i43p1ZC/FqWhnt1XqYw3bQ==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/shared-types": "7.10.2", + "@electron-forge/shared-types": "7.11.1", "@electron/rebuild": "^3.7.0", "@malept/cross-spawn-promise": "^2.0.0", "chalk": "^4.0.0", @@ -2131,13 +2134,13 @@ } }, "node_modules/@electron-forge/maker-base": { - "version": "7.10.2", - "resolved": "https://registry.npmmirror.com/@electron-forge/maker-base/-/maker-base-7.10.2.tgz", - "integrity": "sha512-1QN4qnPVTjo+qWYG+s0kYv7XcuIowsPVvbl718FgJUcvkxyRjUA6kWHjFxRvdV6g7Sa2PzZBF+/Mrjpws1lehQ==", + "version": "7.11.1", + "resolved": "https://registry.npmmirror.com/@electron-forge/maker-base/-/maker-base-7.11.1.tgz", + "integrity": "sha512-yhZrCGoN6bDeiB5DHFaueZ1h84AReElEj+f0hl2Ph4UbZnO0cnLpbx+Bs+XfMLAiA+beC8muB5UDK5ysfuT9BQ==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/shared-types": "7.10.2", + "@electron-forge/shared-types": "7.11.1", "fs-extra": "^10.0.0", "which": "^2.0.2" }, @@ -2146,14 +2149,14 @@ } }, "node_modules/@electron-forge/maker-deb": { - "version": "7.10.2", - "resolved": "https://registry.npmmirror.com/@electron-forge/maker-deb/-/maker-deb-7.10.2.tgz", - "integrity": "sha512-4MPr9NW5UbEUbf9geZn5R/0O/QVIiy2EgUXOYOeKkA7oR8U6I1I3+BytYFHYcxbY6+PGhi1H1VTLJLITbHGVWw==", + "version": "7.11.1", + "resolved": "https://registry.npmmirror.com/@electron-forge/maker-deb/-/maker-deb-7.11.1.tgz", + "integrity": "sha512-QTYiryQLYPDkq6pIfBmx0GQ6D8QatUkowH7rTlW5MnCUa0uumX0Xu7yGIjesuwW37fxT3Lv4xi+FSXMCm2eC1w==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/maker-base": "7.10.2", - "@electron-forge/shared-types": "7.10.2" + "@electron-forge/maker-base": "7.11.1", + "@electron-forge/shared-types": "7.11.1" }, "engines": { "node": ">= 16.4.0" @@ -2163,14 +2166,14 @@ } }, "node_modules/@electron-forge/maker-rpm": { - "version": "7.10.2", - "resolved": "https://registry.npmmirror.com/@electron-forge/maker-rpm/-/maker-rpm-7.10.2.tgz", - "integrity": "sha512-LQoeYzbY/z1yuBBA+bNutCJmhCA4NcXUbFO4OTqsIX8B6y1zNTYZT4JEuhoK7eBsP4/Rz6u/JnNp0XOyjftOUQ==", + "version": "7.11.1", + "resolved": "https://registry.npmmirror.com/@electron-forge/maker-rpm/-/maker-rpm-7.11.1.tgz", + "integrity": "sha512-iEfJPRQQyaTqk2EbUfZgulChNWvxGXeYUH0xBX/r5cj1pL4vcJXt3jLMQBVn3mk/0Ytv9UWRs8R/XuNWX6sf2w==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/maker-base": "7.10.2", - "@electron-forge/shared-types": "7.10.2" + "@electron-forge/maker-base": "7.11.1", + "@electron-forge/shared-types": "7.11.1" }, "engines": { "node": ">= 16.4.0" @@ -2180,14 +2183,14 @@ } }, "node_modules/@electron-forge/maker-squirrel": { - "version": "7.10.2", - "resolved": "https://registry.npmmirror.com/@electron-forge/maker-squirrel/-/maker-squirrel-7.10.2.tgz", - "integrity": "sha512-Y5EhNSBXf4a7qcq+BK/x5qVDlQ1Gez5V+arUpDvVxf1zwvsB1aSyAjmoBrOKGYD9A5pJzjkMWMDw95MStl1W4A==", + "version": "7.11.1", + "resolved": "https://registry.npmmirror.com/@electron-forge/maker-squirrel/-/maker-squirrel-7.11.1.tgz", + "integrity": "sha512-oSg7fgad6l+X0DjtRkSpMzB0AjzyDO4mb2gzM4kTodkP1ADeiMi08bxy0ZeCESqLm5+fG72cAPmEr3BAPvI1yw==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/maker-base": "7.10.2", - "@electron-forge/shared-types": "7.10.2", + "@electron-forge/maker-base": "7.11.1", + "@electron-forge/shared-types": "7.11.1", "fs-extra": "^10.0.0" }, "engines": { @@ -2198,14 +2201,14 @@ } }, "node_modules/@electron-forge/maker-zip": { - "version": "7.10.2", - "resolved": "https://registry.npmmirror.com/@electron-forge/maker-zip/-/maker-zip-7.10.2.tgz", - "integrity": "sha512-APRqVPM+O1rj4O7sk5f8tqJpS5UgxcUJEsCnXN4JRpdRvsOlMopzYZdazlCLH9l7S+r4ZKirjtMluIGeYq8YOg==", + "version": "7.11.1", + "resolved": "https://registry.npmmirror.com/@electron-forge/maker-zip/-/maker-zip-7.11.1.tgz", + "integrity": "sha512-30rcp0AbJLfkFBX2hmO14LKXx7z9V61LffTVbTCFMh5vUB2kZvcA5xAhsBk2oUJWfGVxe1DuSEU0rDR9bUMHUg==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/maker-base": "7.10.2", - "@electron-forge/shared-types": "7.10.2", + "@electron-forge/maker-base": "7.11.1", + "@electron-forge/shared-types": "7.11.1", "cross-zip": "^4.0.0", "fs-extra": "^10.0.0", "got": "^11.8.5" @@ -2215,41 +2218,41 @@ } }, "node_modules/@electron-forge/plugin-auto-unpack-natives": { - "version": "7.10.2", - "resolved": "https://registry.npmmirror.com/@electron-forge/plugin-auto-unpack-natives/-/plugin-auto-unpack-natives-7.10.2.tgz", - "integrity": "sha512-uQnahm1DECwqI8hBC7PKccyfovY/YqHNz8de3OxyjQDmwsqQfCA8Ucyh1E9n4NMEpw6Co8KLn+qF2BuIOsftLA==", + "version": "7.11.1", + "resolved": "https://registry.npmmirror.com/@electron-forge/plugin-auto-unpack-natives/-/plugin-auto-unpack-natives-7.11.1.tgz", + "integrity": "sha512-5uRM3WNv7jIeDt8pLP3V4U2puWHPGJ/3qRuSE47RKgTp5qxpZidWHSYcEJJxjoqOL/7KFwSqKSQ/a36GoZV4Fg==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/plugin-base": "7.10.2", - "@electron-forge/shared-types": "7.10.2" + "@electron-forge/plugin-base": "7.11.1", + "@electron-forge/shared-types": "7.11.1" }, "engines": { "node": ">= 16.4.0" } }, "node_modules/@electron-forge/plugin-base": { - "version": "7.10.2", - "resolved": "https://registry.npmmirror.com/@electron-forge/plugin-base/-/plugin-base-7.10.2.tgz", - "integrity": "sha512-+4YLmkLZxvS6JFXYNI4dHt8Il8iIvwk2o6lCJGwNysOUq2KOZ3Wu1He4Ko8HhKcO1VWbFvslbh57oQn963Aryw==", + "version": "7.11.1", + "resolved": "https://registry.npmmirror.com/@electron-forge/plugin-base/-/plugin-base-7.11.1.tgz", + "integrity": "sha512-lKpSOV1GA3FoYiD9k05i6v4KaQVmojnRgCr7d6VL1bFp13QOtXSaAWhFI9mtSY7rGElOacX6Zt7P7rPoB8T9eQ==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/shared-types": "7.10.2" + "@electron-forge/shared-types": "7.11.1" }, "engines": { "node": ">= 16.4.0" } }, "node_modules/@electron-forge/plugin-fuses": { - "version": "7.10.2", - "resolved": "https://registry.npmmirror.com/@electron-forge/plugin-fuses/-/plugin-fuses-7.10.2.tgz", - "integrity": "sha512-X8FaBL5pVvKCTBNaa9EjbH6vuaeIU7UcPSmP9501XF4zcKPCfTbQKz49LTMl7gd5YzUm82IlqRjte12LLpcSDQ==", + "version": "7.11.1", + "resolved": "https://registry.npmmirror.com/@electron-forge/plugin-fuses/-/plugin-fuses-7.11.1.tgz", + "integrity": "sha512-Td517mHf+RjQAayFDM2kKb7NaGdRXrZfPbc7KOHlGbXthp5YTkFu2cCZGWokiqt1y1wsFaAodULhqBIg7vbbbw==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/plugin-base": "7.10.2", - "@electron-forge/shared-types": "7.10.2" + "@electron-forge/plugin-base": "7.11.1", + "@electron-forge/shared-types": "7.11.1" }, "engines": { "node": ">= 16.4.0" @@ -2259,16 +2262,16 @@ } }, "node_modules/@electron-forge/plugin-webpack": { - "version": "7.10.2", - "resolved": "https://registry.npmmirror.com/@electron-forge/plugin-webpack/-/plugin-webpack-7.10.2.tgz", - "integrity": "sha512-DUv82kOWsZQ8DQmwZ7SlM2BdDQDwAzTYcplEu2dMuk/kEjEyykzvULS+LPHW5pR8qeq3usJlZdPGwf5/oJ4y4w==", + "version": "7.11.1", + "resolved": "https://registry.npmmirror.com/@electron-forge/plugin-webpack/-/plugin-webpack-7.11.1.tgz", + "integrity": "sha512-WeP65H68/81FLiEENjq7XIwCc+ZUTlj1+Xz8Ue/uqKZeBnH3B4bjE6SaMWFgkbl/BgIGs2m61huKfl84z0w6fA==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/core-utils": "7.10.2", - "@electron-forge/plugin-base": "7.10.2", - "@electron-forge/shared-types": "7.10.2", - "@electron-forge/web-multi-logger": "7.10.2", + "@electron-forge/core-utils": "7.11.1", + "@electron-forge/plugin-base": "7.11.1", + "@electron-forge/shared-types": "7.11.1", + "@electron-forge/web-multi-logger": "7.11.1", "chalk": "^4.0.0", "debug": "^4.3.1", "fast-glob": "^3.2.7", @@ -2284,26 +2287,26 @@ } }, "node_modules/@electron-forge/publisher-base": { - "version": "7.10.2", - "resolved": "https://registry.npmmirror.com/@electron-forge/publisher-base/-/publisher-base-7.10.2.tgz", - "integrity": "sha512-2k2VOY0wOoAgQoQXn/u3EJ2Ka2v363+wC/+zUMTWGeRHW8pRwX84WX2SpsTttRzbsqAEMJYw5FAzgMBEQUTfpg==", + "version": "7.11.1", + "resolved": "https://registry.npmmirror.com/@electron-forge/publisher-base/-/publisher-base-7.11.1.tgz", + "integrity": "sha512-rXE9oMFGMtdQrixnumWYH5TTGsp99iPHZb3jI74YWq518ctCh6DlIgWlhf6ok2X0+lhWovcIb45KJucUFAQ13w==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/shared-types": "7.10.2" + "@electron-forge/shared-types": "7.11.1" }, "engines": { "node": ">= 16.4.0" } }, "node_modules/@electron-forge/shared-types": { - "version": "7.10.2", - "resolved": "https://registry.npmmirror.com/@electron-forge/shared-types/-/shared-types-7.10.2.tgz", - "integrity": "sha512-e2pd9RsdbKwsNf6UtKoolmJGy92Nc0/XO4SI91doV8cM954hM2XSYz3VHoqXebMFAF1JDfXoEUt6UCRbEDgMgw==", + "version": "7.11.1", + "resolved": "https://registry.npmmirror.com/@electron-forge/shared-types/-/shared-types-7.11.1.tgz", + "integrity": "sha512-vvBWdAEh53UJlDGUevpaJk1+sqDMQibfrbHR+0IPA4MPyQex7/Uhv3vYH9oGHujBVAChQahjAuJt0fG6IJBLZg==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/tracer": "7.10.2", + "@electron-forge/tracer": "7.11.1", "@electron/packager": "^18.3.5", "@electron/rebuild": "^3.7.0", "listr2": "^7.0.2" @@ -2313,14 +2316,14 @@ } }, "node_modules/@electron-forge/template-base": { - "version": "7.10.2", - "resolved": "https://registry.npmmirror.com/@electron-forge/template-base/-/template-base-7.10.2.tgz", - "integrity": "sha512-D9DbEx3rtikIhUyn4tcz2pJqHNU/+FXKNnzSvmrJoJ9LusR3C42OU9GtbU8oT3nawpnCGgPFIOGXrzexFPp6DA==", + "version": "7.11.1", + "resolved": "https://registry.npmmirror.com/@electron-forge/template-base/-/template-base-7.11.1.tgz", + "integrity": "sha512-XpTaEf+EfQw+0BlSAtSpZKYIKYvKu4raNzSGHZZoSYHp+HDC7R+MlpFQmSJiGdYQzQ14C+uxO42tVjgM0DMbpw==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/core-utils": "7.10.2", - "@electron-forge/shared-types": "7.10.2", + "@electron-forge/core-utils": "7.11.1", + "@electron-forge/shared-types": "7.11.1", "@malept/cross-spawn-promise": "^2.0.0", "debug": "^4.3.1", "fs-extra": "^10.0.0", @@ -2332,14 +2335,14 @@ } }, "node_modules/@electron-forge/template-vite": { - "version": "7.10.2", - "resolved": "https://registry.npmmirror.com/@electron-forge/template-vite/-/template-vite-7.10.2.tgz", - "integrity": "sha512-hR9HBOM902yq7zhFl8bO3w5ufMgitdd5ZwDzAdKITFh2ttZemHy9ha5S0K+R+4GoXHz8t7hUTHk8+iPy09qrpA==", + "version": "7.11.1", + "resolved": "https://registry.npmmirror.com/@electron-forge/template-vite/-/template-vite-7.11.1.tgz", + "integrity": "sha512-Or8Lxf4awoeUZoMTKJEw5KQDIhqOFs24WhVka3yZXxc6VgVWN79KmYKYM6uM/YMQttmafhsBhY2t1Lxo1WR/ug==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/shared-types": "7.10.2", - "@electron-forge/template-base": "7.10.2", + "@electron-forge/shared-types": "7.11.1", + "@electron-forge/template-base": "7.11.1", "fs-extra": "^10.0.0" }, "engines": { @@ -2347,14 +2350,14 @@ } }, "node_modules/@electron-forge/template-vite-typescript": { - "version": "7.10.2", - "resolved": "https://registry.npmmirror.com/@electron-forge/template-vite-typescript/-/template-vite-typescript-7.10.2.tgz", - "integrity": "sha512-df7rpxxIOIyZn0RfQ1GIlLW7dXhxkerc9uZ3ozO4C7zfvip3z0Mg+wS1synktPfr4WISaPktIdnj3mVu6Uu7Mw==", + "version": "7.11.1", + "resolved": "https://registry.npmmirror.com/@electron-forge/template-vite-typescript/-/template-vite-typescript-7.11.1.tgz", + "integrity": "sha512-Us4AHXFb+4z+gXgZImSqMBS63oKnsQWLOhqRg321xiDzu2UcQPlwgWNb4rAEKNVC1e7LXrUNDHuBiTrQkvWXbg==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/shared-types": "7.10.2", - "@electron-forge/template-base": "7.10.2", + "@electron-forge/shared-types": "7.11.1", + "@electron-forge/template-base": "7.11.1", "fs-extra": "^10.0.0" }, "engines": { @@ -2362,14 +2365,14 @@ } }, "node_modules/@electron-forge/template-webpack": { - "version": "7.10.2", - "resolved": "https://registry.npmmirror.com/@electron-forge/template-webpack/-/template-webpack-7.10.2.tgz", - "integrity": "sha512-VIUXA+XHM5SLjg7fIpOOmBsgi0LstkjrEz4gUzVL0AaITM7e+BCziIHld1ceXLbQ1FnKtrUGnQ9X/cHYxYvhHg==", + "version": "7.11.1", + "resolved": "https://registry.npmmirror.com/@electron-forge/template-webpack/-/template-webpack-7.11.1.tgz", + "integrity": "sha512-15lbXxi+er461MPk6sbwAOyjofAHwmQjTvxNCiNpaU2naEwbj3t0SlLq/BMr5HxnVOaMmA7+lKV9afkIom+d4Q==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/shared-types": "7.10.2", - "@electron-forge/template-base": "7.10.2", + "@electron-forge/shared-types": "7.11.1", + "@electron-forge/template-base": "7.11.1", "fs-extra": "^10.0.0" }, "engines": { @@ -2377,14 +2380,14 @@ } }, "node_modules/@electron-forge/template-webpack-typescript": { - "version": "7.10.2", - "resolved": "https://registry.npmmirror.com/@electron-forge/template-webpack-typescript/-/template-webpack-typescript-7.10.2.tgz", - "integrity": "sha512-JtrLUAFbxxWJ1kU7b8MNyL5SO9/rY5UeNz1b9hvMvilW8GxyMWUen58dafgdnx3OpKLNZnhOOhgRagNppEzJOA==", + "version": "7.11.1", + "resolved": "https://registry.npmmirror.com/@electron-forge/template-webpack-typescript/-/template-webpack-typescript-7.11.1.tgz", + "integrity": "sha512-6ExfFnFkHBz8rvRFTFg5HVGTC12uJpbVk4q8DVg0R8rhhxhqiVNh8lF2UPtZ2yT2UtGWjXNVlyP3Y3T6q6E3GQ==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/shared-types": "7.10.2", - "@electron-forge/template-base": "7.10.2", + "@electron-forge/shared-types": "7.11.1", + "@electron-forge/template-base": "7.11.1", "fs-extra": "^10.0.0", "typescript": "~5.4.5", "webpack": "^5.69.1" @@ -2408,9 +2411,9 @@ } }, "node_modules/@electron-forge/tracer": { - "version": "7.10.2", - "resolved": "https://registry.npmmirror.com/@electron-forge/tracer/-/tracer-7.10.2.tgz", - "integrity": "sha512-jhLLQbttfZViSOYn/3SJc8HML+jNZAytPVJwgGGd3coUiFysWJ2Xald99iqOiouPAhIigBfNPxQb/q/EbcDu4g==", + "version": "7.11.1", + "resolved": "https://registry.npmmirror.com/@electron-forge/tracer/-/tracer-7.11.1.tgz", + "integrity": "sha512-tiB6cglVQFcSw9N8GRwVwZUeB9u0DOx2Mj7aFXBUsFLUYQapvVGv51tUSy/UAW5lvmubGscYIILuVko+II3+NA==", "dev": true, "license": "MIT", "dependencies": { @@ -2421,9 +2424,9 @@ } }, "node_modules/@electron-forge/web-multi-logger": { - "version": "7.10.2", - "resolved": "https://registry.npmmirror.com/@electron-forge/web-multi-logger/-/web-multi-logger-7.10.2.tgz", - "integrity": "sha512-6ltVtkpGSleEGOPd4C+Z+GUKoMsKjTGD1YwcedZM1L07dlpQAgvRU2e/6lRQuOxVPmylpzbotow/h1mRgDBVWQ==", + "version": "7.11.1", + "resolved": "https://registry.npmmirror.com/@electron-forge/web-multi-logger/-/web-multi-logger-7.11.1.tgz", + "integrity": "sha512-NZQyAxaDPHK/9G24sMKB3RknYxz79C+qO+SkIKoGjN0vT44kxAYc0u4rpem9FYPNN3hpSLFVOgn1EWoaKXnl7A==", "dev": true, "license": "MIT", "dependencies": { @@ -2471,6 +2474,7 @@ "integrity": "sha512-zx0EIq78WlY/lBb1uXlziZmDZI4ubcCXIMJ4uGjXzZW0nS19TjSPeXPAjzzTmKQlJUZm0SbmZhPKP7tuQ1SsEw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "chalk": "^4.1.1", "fs-extra": "^9.0.1", @@ -2878,9 +2882,9 @@ "license": "MIT" }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.0", - "resolved": "https://registry.npmmirror.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", - "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "version": "4.9.1", + "resolved": "https://registry.npmmirror.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3102,9 +3106,9 @@ } }, "node_modules/@inquirer/core/node_modules/@types/node": { - "version": "22.19.3", - "resolved": "https://registry.npmmirror.com/@types/node/-/node-22.19.3.tgz", - "integrity": "sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA==", + "version": "22.19.7", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-22.19.7.tgz", + "integrity": "sha512-MciR4AKGHWl7xwxkBa6xUGxQJ4VBOmPTF7sL+iGzuahOFaO0jHCsuEfS80pan1ef4gWId1oWOweIhrDEYLuaOw==", "dev": true, "license": "MIT", "dependencies": { @@ -3207,6 +3211,7 @@ "integrity": "sha512-yl43JD/86CIj3Mz5mvvLJqAOfIup7ncxfJ0Btnl0/v5TouVUyeEdcpknfgc+yMevS/48oH9WAkkw93m7otLb/A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@inquirer/checkbox": "^3.0.1", "@inquirer/confirm": "^4.0.1", @@ -3361,6 +3366,7 @@ "resolved": "https://registry.npmmirror.com/@langchain/anthropic/-/anthropic-0.3.34.tgz", "integrity": "sha512-8bOW1A2VHRCjbzdYElrjxutKNs9NSIxYRGtR+OJWVzluMqoKKh2NmmFrpPizEyqCUEG2tTq5xt6XA1lwfqMJRA==", "license": "MIT", + "peer": true, "dependencies": { "@anthropic-ai/sdk": "^0.65.0", "fast-xml-parser": "^4.4.1" @@ -3405,7 +3411,6 @@ "https://github.com/sponsors/ctavan" ], "license": "MIT", - "peer": true, "bin": { "uuid": "dist/bin/uuid" } @@ -3415,6 +3420,7 @@ "resolved": "https://registry.npmmirror.com/@langchain/deepseek/-/deepseek-0.1.0.tgz", "integrity": "sha512-5VzaG/oi2oSfBt+JUdXWjavZcmOzjk14+N5sCFnbrY6xeAjHrtBq7VeBcBJcHqkrjafxADK1aVGV0hpbhiFyJg==", "license": "MIT", + "peer": true, "dependencies": { "@langchain/openai": "^0.6.0" }, @@ -3430,6 +3436,7 @@ "resolved": "https://registry.npmmirror.com/@langchain/google-genai/-/google-genai-0.2.18.tgz", "integrity": "sha512-m9EiN3VKC01A7/625YQ6Q1Lqq8zueewADX4W5Tcme4RImN75zkg2Z7FYbD1Fo6Zwolc4wBNO6LUtbg3no4rv1Q==", "license": "MIT", + "peer": true, "dependencies": { "@google/generative-ai": "^0.24.0", "uuid": "^11.1.0" @@ -3629,18 +3636,18 @@ } }, "node_modules/@parcel/watcher": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher/-/watcher-2.5.1.tgz", - "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==", + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher/-/watcher-2.5.6.tgz", + "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==", "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, "dependencies": { - "detect-libc": "^1.0.3", + "detect-libc": "^2.0.3", "is-glob": "^4.0.3", - "micromatch": "^4.0.5", - "node-addon-api": "^7.0.0" + "node-addon-api": "^7.0.0", + "picomatch": "^4.0.3" }, "engines": { "node": ">= 10.0.0" @@ -3650,25 +3657,25 @@ "url": "https://opencollective.com/parcel" }, "optionalDependencies": { - "@parcel/watcher-android-arm64": "2.5.1", - "@parcel/watcher-darwin-arm64": "2.5.1", - "@parcel/watcher-darwin-x64": "2.5.1", - "@parcel/watcher-freebsd-x64": "2.5.1", - "@parcel/watcher-linux-arm-glibc": "2.5.1", - "@parcel/watcher-linux-arm-musl": "2.5.1", - "@parcel/watcher-linux-arm64-glibc": "2.5.1", - "@parcel/watcher-linux-arm64-musl": "2.5.1", - "@parcel/watcher-linux-x64-glibc": "2.5.1", - "@parcel/watcher-linux-x64-musl": "2.5.1", - "@parcel/watcher-win32-arm64": "2.5.1", - "@parcel/watcher-win32-ia32": "2.5.1", - "@parcel/watcher-win32-x64": "2.5.1" + "@parcel/watcher-android-arm64": "2.5.6", + "@parcel/watcher-darwin-arm64": "2.5.6", + "@parcel/watcher-darwin-x64": "2.5.6", + "@parcel/watcher-freebsd-x64": "2.5.6", + "@parcel/watcher-linux-arm-glibc": "2.5.6", + "@parcel/watcher-linux-arm-musl": "2.5.6", + "@parcel/watcher-linux-arm64-glibc": "2.5.6", + "@parcel/watcher-linux-arm64-musl": "2.5.6", + "@parcel/watcher-linux-x64-glibc": "2.5.6", + "@parcel/watcher-linux-x64-musl": "2.5.6", + "@parcel/watcher-win32-arm64": "2.5.6", + "@parcel/watcher-win32-ia32": "2.5.6", + "@parcel/watcher-win32-x64": "2.5.6" } }, "node_modules/@parcel/watcher-android-arm64": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz", - "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==", + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz", + "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==", "cpu": [ "arm64" ], @@ -3687,9 +3694,9 @@ } }, "node_modules/@parcel/watcher-darwin-arm64": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz", - "integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==", + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz", + "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==", "cpu": [ "arm64" ], @@ -3708,9 +3715,9 @@ } }, "node_modules/@parcel/watcher-darwin-x64": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz", - "integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==", + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz", + "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==", "cpu": [ "x64" ], @@ -3729,9 +3736,9 @@ } }, "node_modules/@parcel/watcher-freebsd-x64": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz", - "integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==", + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz", + "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==", "cpu": [ "x64" ], @@ -3750,9 +3757,9 @@ } }, "node_modules/@parcel/watcher-linux-arm-glibc": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz", - "integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==", + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz", + "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==", "cpu": [ "arm" ], @@ -3771,9 +3778,9 @@ } }, "node_modules/@parcel/watcher-linux-arm-musl": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz", - "integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==", + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz", + "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==", "cpu": [ "arm" ], @@ -3792,9 +3799,9 @@ } }, "node_modules/@parcel/watcher-linux-arm64-glibc": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz", - "integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==", + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz", + "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==", "cpu": [ "arm64" ], @@ -3813,9 +3820,9 @@ } }, "node_modules/@parcel/watcher-linux-arm64-musl": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz", - "integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==", + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz", + "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==", "cpu": [ "arm64" ], @@ -3834,9 +3841,9 @@ } }, "node_modules/@parcel/watcher-linux-x64-glibc": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz", - "integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==", + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", + "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==", "cpu": [ "x64" ], @@ -3855,9 +3862,9 @@ } }, "node_modules/@parcel/watcher-linux-x64-musl": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz", - "integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==", + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz", + "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==", "cpu": [ "x64" ], @@ -3876,9 +3883,9 @@ } }, "node_modules/@parcel/watcher-win32-arm64": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz", - "integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==", + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz", + "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==", "cpu": [ "arm64" ], @@ -3897,9 +3904,9 @@ } }, "node_modules/@parcel/watcher-win32-ia32": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz", - "integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==", + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz", + "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==", "cpu": [ "ia32" ], @@ -3918,9 +3925,9 @@ } }, "node_modules/@parcel/watcher-win32-x64": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz", - "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==", + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz", + "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==", "cpu": [ "x64" ], @@ -3938,18 +3945,18 @@ "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/watcher/node_modules/detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "node_modules/@parcel/watcher/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, - "bin": { - "detect-libc": "bin/detect-libc.js" - }, "engines": { - "node": ">=0.10" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/@pdf-lib/standard-fonts": { @@ -4058,9 +4065,9 @@ "license": "BSD-3-Clause" }, "node_modules/@rc-component/async-validator": { - "version": "5.0.4", - "resolved": "https://registry.npmmirror.com/@rc-component/async-validator/-/async-validator-5.0.4.tgz", - "integrity": "sha512-qgGdcVIF604M9EqjNF0hbUTz42bz/RDtxWdWuU5EQe3hi7M8ob54B6B35rOsvX5eSvIHIzT9iH1R3n+hk3CGfg==", + "version": "5.1.0", + "resolved": "https://registry.npmmirror.com/@rc-component/async-validator/-/async-validator-5.1.0.tgz", + "integrity": "sha512-n4HcR5siNUXRX23nDizbZBQPO0ZM/5oTtmKZ6/eqL0L2bo747cklFdZGRN2f+c9qWGICwDzrhW0H7tE9PptdcA==", "dev": true, "license": "MIT", "dependencies": { @@ -4192,9 +4199,9 @@ } }, "node_modules/@rc-component/trigger": { - "version": "2.3.0", - "resolved": "https://registry.npmmirror.com/@rc-component/trigger/-/trigger-2.3.0.tgz", - "integrity": "sha512-iwaxZyzOuK0D7lS+0AQEtW52zUWxoGqTGkke3dRyb8pYiShmRpCjB/8TzPI4R6YySCH7Vm9BZj/31VPiiQTLBg==", + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/@rc-component/trigger/-/trigger-2.3.1.tgz", + "integrity": "sha512-ORENF39PeXTzM+gQEshuk460Z8N4+6DkjpxlpE7Q3gYy1iBpLrx0FOJz3h62ryrJZ/3zCAUIkT1Pb/8hHWpb3A==", "dev": true, "license": "MIT", "dependencies": { @@ -4288,16 +4295,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@silentbot1/nat-api/node_modules/human-signals": { - "version": "4.3.1", - "resolved": "https://registry.npmmirror.com/human-signals/-/human-signals-4.3.1.tgz", - "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=14.18.0" - } - }, "node_modules/@silentbot1/nat-api/node_modules/is-stream": { "version": "3.0.0", "resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-3.0.0.tgz", @@ -4376,19 +4373,6 @@ "dev": true, "license": "ISC" }, - "node_modules/@silentbot1/nat-api/node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@sindresorhus/is": { "version": "4.6.0", "resolved": "https://registry.npmmirror.com/@sindresorhus/is/-/is-4.6.0.tgz", @@ -4848,9 +4832,9 @@ } }, "node_modules/@stdlib/string-base-format-interpolate": { - "version": "0.2.2", - "resolved": "https://registry.npmmirror.com/@stdlib/string-base-format-interpolate/-/string-base-format-interpolate-0.2.2.tgz", - "integrity": "sha512-i9nU9rAB2+o/RR66TS9iQ8x+YzeUDL1SGiAo6GY3hP6Umz5Dx9Qp/v8T69gWVsb4a1YSclz5+YeCWaFgwvPjKA==", + "version": "0.2.3", + "resolved": "https://registry.npmmirror.com/@stdlib/string-base-format-interpolate/-/string-base-format-interpolate-0.2.3.tgz", + "integrity": "sha512-6r8SxRqSuzFaU1Qhvz5XORtYSo/BZ0E0/V0RS1qAX6Z3/Dn+g/qlfYEwQXpSwsch1yIURuNfBc77ychnP7d8XA==", "dev": true, "license": "Apache-2.0", "os": [ @@ -4874,9 +4858,9 @@ } }, "node_modules/@stdlib/string-base-format-tokenize": { - "version": "0.2.2", - "resolved": "https://registry.npmmirror.com/@stdlib/string-base-format-tokenize/-/string-base-format-tokenize-0.2.2.tgz", - "integrity": "sha512-kXq2015i+LJjqth5dN+hYnvJXBSzRm8w0ABWB5tYAsIuQTpQK+mSo2muM8JBEFEnqUHAwpUsu2qNTK/9o8lsJg==", + "version": "0.2.3", + "resolved": "https://registry.npmmirror.com/@stdlib/string-base-format-tokenize/-/string-base-format-tokenize-0.2.3.tgz", + "integrity": "sha512-Ha8ADT8sRlRClu3NSKbmKZY9V9I8TK80pU/pwTbr1F8j+KiIZx2Fs7M5SMk8n1rm1hwxC3Af5qU5t2EZ0fJISg==", "dev": true, "license": "Apache-2.0", "os": [ @@ -5458,6 +5442,7 @@ "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.1.0", @@ -5500,22 +5485,6 @@ } } }, - "node_modules/@svgr/core/node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, "node_modules/@svgr/hast-util-to-babel-ast": { "version": "8.0.0", "resolved": "https://registry.npmmirror.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", @@ -5606,22 +5575,6 @@ } } }, - "node_modules/@svgr/plugin-svgo/node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, "node_modules/@svgr/webpack": { "version": "8.1.0", "resolved": "https://registry.npmmirror.com/@svgr/webpack/-/webpack-8.1.0.tgz", @@ -5660,17 +5613,17 @@ } }, "node_modules/@thaunknown/simple-peer": { - "version": "10.0.12", - "resolved": "https://registry.npmmirror.com/@thaunknown/simple-peer/-/simple-peer-10.0.12.tgz", - "integrity": "sha512-sDrkkOdzlJL8+FXQqYcBb2THHQU+Yrar92SjfW4ZLs877/4QA2kFejuA6DVepsoMpoIbXShc7OCXCwYt4AtGdQ==", + "version": "10.1.0", + "resolved": "https://registry.npmmirror.com/@thaunknown/simple-peer/-/simple-peer-10.1.0.tgz", + "integrity": "sha512-xNM49v0rBbjIKrS9XNwXW3FFuGvsPGadFRWbBdLAY87pEJeo7V0dxyX6GBHP8UVlefffRedCLsjYXb6i8W9Ofg==", "dev": true, "license": "MIT", "dependencies": { - "debug": "^4.3.7", + "debug": "^4.4.3", "err-code": "^3.0.1", - "streamx": "^2.20.1", - "uint8-util": "^2.2.5", - "webrtc-polyfill": "^1.1.10" + "streamx": "^2.23.0", + "uint8-util": "^2.2.6", + "webrtc-polyfill": "^1.2.0" } }, "node_modules/@thaunknown/simple-peer/node_modules/err-code": { @@ -5680,6 +5633,18 @@ "dev": true, "license": "MIT" }, + "node_modules/@thaunknown/simple-peer/node_modules/streamx": { + "version": "2.23.0", + "resolved": "https://registry.npmmirror.com/streamx/-/streamx-2.23.0.tgz", + "integrity": "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "events-universal": "^1.0.0", + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" + } + }, "node_modules/@thaunknown/simple-websocket": { "version": "9.1.3", "resolved": "https://registry.npmmirror.com/@thaunknown/simple-websocket/-/simple-websocket-9.1.3.tgz", @@ -5755,6 +5720,16 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/adm-zip": { + "version": "0.5.7", + "resolved": "https://registry.npmmirror.com/@types/adm-zip/-/adm-zip-0.5.7.tgz", + "integrity": "sha512-DNEs/QvmyRLurdQPChqq0Md4zGvPwHerAJYWk9l2jCbD1VPpnzRJorOdiq4zsw09NFbYnhfsoEhWtxIzXpn2yw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/bittorrent-protocol": { "version": "3.1.7", "resolved": "https://registry.npmmirror.com/@types/bittorrent-protocol/-/bittorrent-protocol-3.1.7.tgz", @@ -5858,6 +5833,7 @@ "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -5895,9 +5871,22 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.19.7", - "resolved": "https://registry.npmmirror.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.7.tgz", - "integrity": "sha512-FvPtiIf1LfhzsaIXhv/PHan/2FeQBbtBDtfX2QfvPxdUelMDEckK08SM6nqo1MIZY3RUlfA+HV8+hFUSio78qg==", + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/@types/express-serve-static-core/-/express-serve-static-core-5.1.1.tgz", + "integrity": "sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/express/node_modules/@types/express-serve-static-core": { + "version": "4.19.8", + "resolved": "https://registry.npmmirror.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz", + "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==", "dev": true, "license": "MIT", "dependencies": { @@ -5936,9 +5925,9 @@ "license": "MIT" }, "node_modules/@types/http-cache-semantics": { - "version": "4.0.4", - "resolved": "https://registry.npmmirror.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", - "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==", "dev": true, "license": "MIT" }, @@ -5984,9 +5973,9 @@ } }, "node_modules/@types/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-FOvQ0YPD5NOfPgMzJihoT+Za5pdkDJWcbpuj1DjaKZIr/gxodQjY/uWEFlTNqW2ugXHUiL8lRQgw63dzKHZdeQ==", + "version": "4.17.23", + "resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-RDvF6wTulMPjrNdCoYRC8gNR880JNGT8uB+REUpC2Ns4pRqQJhGz90wh7rgdXDPpCczF3VGktDuFGVnz8zP7HA==", "dev": true, "license": "MIT" }, @@ -6017,10 +6006,11 @@ } }, "node_modules/@types/node": { - "version": "24.10.4", - "resolved": "https://registry.npmmirror.com/@types/node/-/node-24.10.4.tgz", - "integrity": "sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg==", + "version": "24.10.9", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-24.10.9.tgz", + "integrity": "sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw==", "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -6077,11 +6067,12 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "19.2.7", - "resolved": "https://registry.npmmirror.com/@types/react/-/react-19.2.7.tgz", - "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", + "version": "19.2.10", + "resolved": "https://registry.npmmirror.com/@types/react/-/react-19.2.10.tgz", + "integrity": "sha512-WPigyYuGhgZ/cTPRXB2EwUw+XvsRA3GqHlsP4qteqrnnjDrApbS7MxcGr/hke5iUoeB7E/gQtrs9I37zAJ0Vjw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -6120,13 +6111,12 @@ "license": "MIT" }, "node_modules/@types/send": { - "version": "0.17.6", - "resolved": "https://registry.npmmirror.com/@types/send/-/send-0.17.6.tgz", - "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==", + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/@types/send/-/send-1.2.1.tgz", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/mime": "^1", "@types/node": "*" } }, @@ -6152,6 +6142,17 @@ "@types/send": "<1" } }, + "node_modules/@types/serve-static/node_modules/@types/send": { + "version": "0.17.6", + "resolved": "https://registry.npmmirror.com/@types/send/-/send-0.17.6.tgz", + "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, "node_modules/@types/simple-peer": { "version": "9.11.9", "resolved": "https://registry.npmmirror.com/@types/simple-peer/-/simple-peer-9.11.9.tgz", @@ -6285,6 +6286,7 @@ "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "5.62.0", "@typescript-eslint/types": "5.62.0", @@ -6458,9 +6460,9 @@ } }, "node_modules/@vscode/sudo-prompt": { - "version": "9.3.1", - "resolved": "https://registry.npmmirror.com/@vscode/sudo-prompt/-/sudo-prompt-9.3.1.tgz", - "integrity": "sha512-9ORTwwS74VaTn38tNbQhsA5U44zkJfcb0BdTSyyG6frP4e8KMtHuTXYmwefe5dpL8XB1aGSIVTaLjD3BbWb5iA==", + "version": "9.3.2", + "resolved": "https://registry.npmmirror.com/@vscode/sudo-prompt/-/sudo-prompt-9.3.2.tgz", + "integrity": "sha512-gcXoCN00METUNFeQOFJ+C9xUI0DKB+0EGMVg7wbVYRHBw2Eq3fKisDZOkRdOz3kqXRKOENMfShPOmypw1/8nOw==", "dev": true, "license": "MIT" }, @@ -6714,6 +6716,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -6767,6 +6770,15 @@ "node": ">=12.20.0" } }, + "node_modules/adm-zip": { + "version": "0.5.16", + "resolved": "https://registry.npmmirror.com/adm-zip/-/adm-zip-0.5.16.tgz", + "integrity": "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==", + "license": "MIT", + "engines": { + "node": ">=12.0" + } + }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-6.0.2.tgz", @@ -6813,6 +6825,7 @@ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -6920,7 +6933,6 @@ "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, @@ -6934,6 +6946,7 @@ "integrity": "sha512-3DdbGCa9tWAJGcCJ6rzR8EJFsv2CtyEbkVabZE14pfgUHfCicWCj0/QzQVLDYg8CPfQk9BH7fHCoTXHTy7MP/A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@ant-design/colors": "^7.2.1", "@ant-design/cssinjs": "^1.23.0", @@ -7317,14 +7330,14 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.14", - "resolved": "https://registry.npmmirror.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz", - "integrity": "sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==", + "version": "0.4.15", + "resolved": "https://registry.npmmirror.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.15.tgz", + "integrity": "sha512-hR3GwrRwHUfYwGfrisXPIDP3JcYfBrW7wKE7+Au6wDYl7fm/ka1NEII6kORzxNU556JjfidZeBsO10kYvtV1aw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.27.7", - "@babel/helper-define-polyfill-provider": "^0.6.5", + "@babel/compat-data": "^7.28.6", + "@babel/helper-define-polyfill-provider": "^0.6.6", "semver": "^6.3.1" }, "peerDependencies": { @@ -7356,13 +7369,13 @@ } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.5", - "resolved": "https://registry.npmmirror.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz", - "integrity": "sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==", + "version": "0.6.6", + "resolved": "https://registry.npmmirror.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.6.tgz", + "integrity": "sha512-hYm+XLYRMvupxiQzrvXUj7YyvFFVfv5gI0R71AJzudg1g2AI2vyCPPIFEBjk162/wFzti3inBHo7isWFuEVS/A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.5" + "@babel/helper-define-polyfill-provider": "^0.6.6" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -7411,9 +7424,9 @@ } }, "node_modules/bare-fs": { - "version": "4.5.2", - "resolved": "https://registry.npmmirror.com/bare-fs/-/bare-fs-4.5.2.tgz", - "integrity": "sha512-veTnRzkb6aPHOvSKIOy60KzURfBdUflr5VReI+NSaPL6xf+XLdONQgZgpYvUuZLVQ8dCqxpBAudaOM1+KpAUxw==", + "version": "4.5.3", + "resolved": "https://registry.npmmirror.com/bare-fs/-/bare-fs-4.5.3.tgz", + "integrity": "sha512-9+kwVx8QYvt3hPWnmb19tPnh38c6Nihz8Lx3t0g9+4GoIf3/fTgYwM4Z6NxgI+B9elLQA7mLE9PpqcWtOMRDiQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -7436,9 +7449,9 @@ } }, "node_modules/bare-module-resolve": { - "version": "1.12.0", - "resolved": "https://registry.npmmirror.com/bare-module-resolve/-/bare-module-resolve-1.12.0.tgz", - "integrity": "sha512-JrzrqlC3Tds0iKRwQs8xIIJ+FRieKA9ll0jaqpotDLZtjJPVevzRoeuUYZ5GIo1t1z7/pIRdk85Q3i/2xQLfEQ==", + "version": "1.12.1", + "resolved": "https://registry.npmmirror.com/bare-module-resolve/-/bare-module-resolve-1.12.1.tgz", + "integrity": "sha512-hbmAPyFpEq8FoZMd5sFO3u6MC5feluWoGE8YKlA8fCrl6mNtx68Wjg4DTiDJcqRJaovTvOYKfYngoBUnbaT7eg==", "dev": true, "license": "Apache-2.0", "optional": true, @@ -7545,9 +7558,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.9.11", - "resolved": "https://registry.npmmirror.com/baseline-browser-mapping/-/baseline-browser-mapping-2.9.11.tgz", - "integrity": "sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==", + "version": "2.9.19", + "resolved": "https://registry.npmmirror.com/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz", + "integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==", "dev": true, "license": "Apache-2.0", "bin": { @@ -7814,9 +7827,9 @@ } }, "node_modules/block-iterator": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/block-iterator/-/block-iterator-1.1.1.tgz", - "integrity": "sha512-DrjdVWZemVO4iBf4tiOXjUrY5cNesjzy0t7sIiu2rdl8cOCHRxAgKjSJFc3vBZYYMMmshUAxajl8QQh/uxXTKQ==", + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/block-iterator/-/block-iterator-1.1.2.tgz", + "integrity": "sha512-yAHUP44v2K25xLPdrgVTgwtuQctlullzjczu9CoUZom5AP3g4p1R1+aWHjS1GHG9JtcSUVUnbEPiuXiW5YZ24w==", "dev": true, "license": "MIT" }, @@ -8110,6 +8123,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -8453,9 +8467,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001761", - "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001761.tgz", - "integrity": "sha512-JF9ptu1vP2coz98+5051jZ4PwQgd2ni8A+gYSN7EA7dPKIMf0pDlSUxhdmVOaV3/fYK5uWBkgSXJaRLr4+3A6g==", + "version": "1.0.30001766", + "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001766.tgz", + "integrity": "sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA==", "dev": true, "funding": [ { @@ -9136,71 +9150,14 @@ "webpack": "^5.1.0" } }, - "node_modules/copy-webpack-plugin/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "node_modules/core-js-compat": { + "version": "3.48.0", + "resolved": "https://registry.npmmirror.com/core-js-compat/-/core-js-compat-3.48.0.tgz", + "integrity": "sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q==", "dev": true, "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/copy-webpack-plugin/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/copy-webpack-plugin/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "license": "MIT" - }, - "node_modules/copy-webpack-plugin/node_modules/schema-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-4.3.3.tgz", - "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/core-js-compat": { - "version": "3.47.0", - "resolved": "https://registry.npmmirror.com/core-js-compat/-/core-js-compat-3.47.0.tgz", - "integrity": "sha512-IGfuznZ/n7Kp9+nypamBhvwdwLsW6KC8IOaURw2doAK5e98AG3acVLdh0woOnEqCfUtS+Vu882JE4k/DAm3ItQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "browserslist": "^4.28.0" + "browserslist": "^4.28.1" }, "funding": { "type": "opencollective", @@ -9806,7 +9763,8 @@ "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.19.tgz", "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/debug": { "version": "4.4.3", @@ -9831,7 +9789,6 @@ "resolved": "https://registry.npmmirror.com/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -9942,6 +9899,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/default-gateway/node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, "node_modules/default-gateway/node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-2.0.1.tgz", @@ -9975,6 +9942,16 @@ "dev": true, "license": "ISC" }, + "node_modules/default-gateway/node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/defaults": { "version": "1.0.4", "resolved": "https://registry.npmmirror.com/defaults/-/defaults-1.0.4.tgz", @@ -10104,9 +10081,9 @@ "license": "MIT" }, "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmmirror.com/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "version": "4.0.4", + "resolved": "https://registry.npmmirror.com/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -10860,9 +10837,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.267", - "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", - "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==", + "version": "1.5.283", + "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.283.tgz", + "integrity": "sha512-3vifjt1HgrGW/h76UEeny+adYApveS9dH2h3p57JYzBSXJIKUJAvtmIytDKjcSCt9xHfrNCFJ7gts6vkhuq++w==", "dev": true, "license": "ISC" }, @@ -10949,9 +10926,9 @@ } }, "node_modules/electron/node_modules/@types/node": { - "version": "22.19.3", - "resolved": "https://registry.npmmirror.com/@types/node/-/node-22.19.3.tgz", - "integrity": "sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA==", + "version": "22.19.7", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-22.19.7.tgz", + "integrity": "sha512-MciR4AKGHWl7xwxkBa6xUGxQJ4VBOmPTF7sL+iGzuahOFaO0jHCsuEfS80pan1ef4gWId1oWOweIhrDEYLuaOw==", "dev": true, "license": "MIT", "dependencies": { @@ -11060,17 +11037,6 @@ "node": ">= 0.8" } }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmmirror.com/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, "node_modules/end-of-stream": { "version": "1.4.5", "resolved": "https://registry.npmmirror.com/end-of-stream/-/end-of-stream-1.4.5.tgz", @@ -11364,6 +11330,7 @@ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -11420,6 +11387,7 @@ "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, "license": "MIT", + "peer": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -11548,14 +11516,14 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.5.4", - "resolved": "https://registry.npmmirror.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.4.tgz", - "integrity": "sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg==", + "version": "5.5.5", + "resolved": "https://registry.npmmirror.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.5.tgz", + "integrity": "sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw==", "dev": true, "license": "MIT", "dependencies": { - "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.11.7" + "prettier-linter-helpers": "^1.0.1", + "synckit": "^0.11.12" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -11725,9 +11693,9 @@ } }, "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmmirror.com/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "version": "1.7.0", + "resolved": "https://registry.npmmirror.com/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -11791,9 +11759,9 @@ } }, "node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "version": "5.0.4", + "resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", "dev": true, "license": "MIT" }, @@ -11807,6 +11775,16 @@ "node": ">=0.8.x" } }, + "node_modules/events-universal": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/events-universal/-/events-universal-1.0.1.tgz", + "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.7.0" + } + }, "node_modules/evp_bytestokey": { "version": "1.0.3", "resolved": "https://registry.npmmirror.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", @@ -11953,6 +11931,7 @@ "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", @@ -12312,6 +12291,25 @@ "webpack": "^4.0.0 || ^5.0.0" } }, + "node_modules/file-loader/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, "node_modules/filename-reserved-regex": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", @@ -12524,6 +12522,25 @@ } } }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, "node_modules/form-data": { "version": "4.0.5", "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.5.tgz", @@ -13415,9 +13432,9 @@ } }, "node_modules/html-webpack-plugin": { - "version": "5.6.5", - "resolved": "https://registry.npmmirror.com/html-webpack-plugin/-/html-webpack-plugin-5.6.5.tgz", - "integrity": "sha512-4xynFbKNNk+WlzXeQQ+6YYsH2g7mpfPszQZUi3ovKlj+pDmngQ7vRXjrrmGROabmKwyQkcgcX5hqfOwHbFmK5g==", + "version": "5.6.6", + "resolved": "https://registry.npmmirror.com/html-webpack-plugin/-/html-webpack-plugin-5.6.6.tgz", + "integrity": "sha512-bLjW01UTrvoWTJQL5LsMRo1SypHW80FTm12OJRSnr3v6YHNhfe+1r0MYUZJMACxnCHURVnBWRwAsWs2yPU9Ezw==", "dev": true, "license": "MIT", "dependencies": { @@ -13617,13 +13634,13 @@ } }, "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "version": "4.3.1", + "resolved": "https://registry.npmmirror.com/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", "dev": true, "license": "Apache-2.0", "engines": { - "node": ">=10.17.0" + "node": ">=14.18.0" } }, "node_modules/humanize-ms": { @@ -14468,9 +14485,9 @@ } }, "node_modules/isomorphic-git": { - "version": "1.36.1", - "resolved": "https://registry.npmmirror.com/isomorphic-git/-/isomorphic-git-1.36.1.tgz", - "integrity": "sha512-fC8SRT8MwoaXDK8G4z5biPEbqf2WyEJUb2MJ2ftSd39/UIlsnoZxLGux+lae0poLZO4AEcx6aUVOh5bV+P8zFA==", + "version": "1.36.3", + "resolved": "https://registry.npmmirror.com/isomorphic-git/-/isomorphic-git-1.36.3.tgz", + "integrity": "sha512-bHF1nQTjL0IfSo13BHDO8oQ6SvYNQduTAdPJdSmrJ5JwZY2fsyjLujEXav5hqPCegSCAnc75ZsBUHqT/NqR7QA==", "dev": true, "license": "MIT", "dependencies": { @@ -15244,9 +15261,9 @@ } }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "version": "4.17.23", + "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", "dev": true, "license": "MIT" }, @@ -16006,7 +16023,6 @@ "resolved": "https://registry.npmmirror.com/mustache/-/mustache-4.2.0.tgz", "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", "license": "MIT", - "peer": true, "bin": { "mustache": "bin/mustache" } @@ -16022,9 +16038,9 @@ } }, "node_modules/nan": { - "version": "2.24.0", - "resolved": "https://registry.npmmirror.com/nan/-/nan-2.24.0.tgz", - "integrity": "sha512-Vpf9qnVW1RaDkoNKFUvfxqAbtI8ncb8OJlqZ9wwpXzWPEsvsB1nvdUi6oYrHIkQ1Y/tMDnr1h4nczS0VB9Xykg==", + "version": "2.25.0", + "resolved": "https://registry.npmmirror.com/nan/-/nan-2.25.0.tgz", + "integrity": "sha512-0M90Ag7Xn5KMLLZ7zliPWP3rT90P6PN+IzVFS0VqmnPktBk3700xUVv8Ikm9EUaUE5SDWdp/BIxdENzVznpm1g==", "dev": true, "license": "MIT", "optional": true @@ -16123,9 +16139,9 @@ } }, "node_modules/node-abi": { - "version": "3.85.0", - "resolved": "https://registry.npmmirror.com/node-abi/-/node-abi-3.85.0.tgz", - "integrity": "sha512-zsFhmbkAzwhTft6nd3VxcG0cvJsT70rL+BIGHWVq5fi6MwGrHwzqKaxXE+Hl2GmnGItnDKPPkO5/LQqjVkIdFg==", + "version": "3.87.0", + "resolved": "https://registry.npmmirror.com/node-abi/-/node-abi-3.87.0.tgz", + "integrity": "sha512-+CGM1L1CgmtheLcBuleyYOn7NWPVu0s0EJH2C4puxgEZb9h8QpR9G2dBfZJOAUhi7VQxuBPMd0hiISWcTyiYyQ==", "dev": true, "license": "MIT", "dependencies": { @@ -16161,39 +16177,17 @@ } }, "node_modules/node-datachannel": { - "version": "0.12.0", - "resolved": "https://registry.npmmirror.com/node-datachannel/-/node-datachannel-0.12.0.tgz", - "integrity": "sha512-pZ9FsVZpHdUKqyWynuCc9IBLkZPJMpDzpNk4YNPCizbIXHYifpYeWqSF35REHGIWi9JMCf11QzapsyQGo/Y4Ig==", + "version": "0.32.0", + "resolved": "https://registry.npmmirror.com/node-datachannel/-/node-datachannel-0.32.0.tgz", + "integrity": "sha512-kohrPL3rOWfiD+oJgc9R7Ibx10U3/yJ+oQ/uB2W2d2B+y4B1bkAMPoONRVS3PTz7AHFqdvoEe5VoRDZ+I6xFEw==", "dev": true, "hasInstallScript": true, "license": "MPL 2.0", "dependencies": { - "node-domexception": "^2.0.1", - "prebuild-install": "^7.0.1" + "prebuild-install": "^7.1.3" }, "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/node-datachannel/node_modules/node-domexception": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/node-domexception/-/node-domexception-2.0.2.tgz", - "integrity": "sha512-Qf9vHK9c5MGgUXj8SnucCIS4oEPuUstjRaMplLGeZpbWMfNV1rvEcXuwoXfN51dUfD1b4muPHPQtCx/5Dj/QAA==", - "deprecated": "Use your platform's native DOMException instead", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "license": "MIT", - "engines": { - "node": ">=16" + "node": ">=18.20.0" } }, "node_modules/node-domexception": { @@ -16357,13 +16351,6 @@ "node": ">=10" } }, - "node_modules/node-stdlib-browser/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmmirror.com/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", - "dev": true, - "license": "MIT" - }, "node_modules/nopt": { "version": "6.0.0", "resolved": "https://registry.npmmirror.com/nopt/-/nopt-6.0.0.tgz", @@ -17358,6 +17345,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -17520,6 +17508,7 @@ "integrity": "sha512-5xGWRa90Sp2+x1dQtNpIpeOQpTDBs9cZDmA/qs2vDNN2i18PdapqY7CmBeyLlMuGqXJRIOPaCaVZTLNQRWUH/A==", "dev": true, "license": "MIT", + "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -17531,9 +17520,9 @@ } }, "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz", + "integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==", "dev": true, "license": "MIT", "dependencies": { @@ -17707,19 +17696,16 @@ } }, "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "version": "1.4.1", + "resolved": "https://registry.npmmirror.com/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } + "license": "MIT" }, "node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmmirror.com/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "version": "6.14.1", + "resolved": "https://registry.npmmirror.com/qs/-/qs-6.14.1.tgz", + "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -18566,24 +18552,26 @@ } }, "node_modules/react": { - "version": "19.2.3", - "resolved": "https://registry.npmmirror.com/react/-/react-19.2.3.tgz", - "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==", + "version": "19.2.4", + "resolved": "https://registry.npmmirror.com/react/-/react-19.2.4.tgz", + "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } }, "node_modules/react-dom": { - "version": "19.2.3", - "resolved": "https://registry.npmmirror.com/react-dom/-/react-dom-19.2.3.tgz", - "integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==", + "version": "19.2.4", + "resolved": "https://registry.npmmirror.com/react-dom/-/react-dom-19.2.4.tgz", + "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { - "react": "^19.2.3" + "react": "^19.2.4" } }, "node_modules/react-is": { @@ -18594,9 +18582,9 @@ "license": "MIT" }, "node_modules/react-router": { - "version": "7.11.0", - "resolved": "https://registry.npmmirror.com/react-router/-/react-router-7.11.0.tgz", - "integrity": "sha512-uI4JkMmjbWCZc01WVP2cH7ZfSzH91JAZUDd7/nIprDgWxBV1TkkmLToFh7EbMTcMak8URFRa2YoBL/W8GWnCTQ==", + "version": "7.13.0", + "resolved": "https://registry.npmmirror.com/react-router/-/react-router-7.13.0.tgz", + "integrity": "sha512-PZgus8ETambRT17BUm/LL8lX3Of+oiLaPuVTRH3l1eLvSPpKO3AvhAEb5N7ihAFZQrYDqkvvWfFh9p0z9VsjLw==", "dev": true, "license": "MIT", "dependencies": { @@ -18617,13 +18605,13 @@ } }, "node_modules/react-router-dom": { - "version": "7.11.0", - "resolved": "https://registry.npmmirror.com/react-router-dom/-/react-router-dom-7.11.0.tgz", - "integrity": "sha512-e49Ir/kMGRzFOOrYQBdoitq3ULigw4lKbAyKusnvtDu2t4dBX4AGYPrzNvorXmVuOyeakai6FUPW5MmibvVG8g==", + "version": "7.13.0", + "resolved": "https://registry.npmmirror.com/react-router-dom/-/react-router-dom-7.13.0.tgz", + "integrity": "sha512-5CO/l5Yahi2SKC6rGZ+HDEjpjkGaG/ncEP7eWFTvFxbHP8yeeI0PxTDjimtpXYlR3b3i9/WIL4VJttPrESIf2g==", "dev": true, "license": "MIT", "dependencies": { - "react-router": "7.11.0" + "react-router": "7.13.0" }, "engines": { "node": ">=20.0.0" @@ -19386,9 +19374,9 @@ "license": "MIT" }, "node_modules/sass": { - "version": "1.97.1", - "resolved": "https://registry.npmmirror.com/sass/-/sass-1.97.1.tgz", - "integrity": "sha512-uf6HoO8fy6ClsrShvMgaKUn14f2EHQLQRtpsZZLeU/Mv0Q1K5P0+x2uvH6Cub39TVVbWNSrraUhDAoFph6vh0A==", + "version": "1.97.3", + "resolved": "https://registry.npmmirror.com/sass/-/sass-1.97.3.tgz", + "integrity": "sha512-fDz1zJpd5GycprAbu4Q2PV/RprsRtKC/0z82z0JLgdytmcq0+ujJbJ/09bPGDxCLkKY3Np5cRAOcWiVkLXJURg==", "dev": true, "license": "MIT", "dependencies": { @@ -19478,11 +19466,14 @@ } }, "node_modules/sax": { - "version": "1.4.3", - "resolved": "https://registry.npmmirror.com/sax/-/sax-1.4.3.tgz", - "integrity": "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==", + "version": "1.4.4", + "resolved": "https://registry.npmmirror.com/sax/-/sax-1.4.4.tgz", + "integrity": "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==", "dev": true, - "license": "BlueOak-1.0.0" + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } }, "node_modules/scheduler": { "version": "0.27.0", @@ -19491,15 +19482,16 @@ "license": "MIT" }, "node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "version": "4.3.3", + "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-4.3.3.tgz", + "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", "dev": true, "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" }, "engines": { "node": ">= 10.13.0" @@ -19509,6 +19501,43 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/schema-utils/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/schema-utils/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/schema-utils/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, "node_modules/scroll-into-view-if-needed": { "version": "3.1.0", "resolved": "https://registry.npmmirror.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz", @@ -19644,22 +19673,26 @@ } }, "node_modules/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmmirror.com/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "version": "1.9.2", + "resolved": "https://registry.npmmirror.com/serve-index/-/serve-index-1.9.2.tgz", + "integrity": "sha512-KDj11HScOaLmrPxl70KYNW1PksP4Nb/CLL2yvC+Qd2kHMPEEpfc4Re2e4FOay+bC/+XQl/7zAcWON3JVo5v3KQ==", "dev": true, "license": "MIT", "dependencies": { - "accepts": "~1.3.4", + "accepts": "~1.3.8", "batch": "0.6.1", "debug": "2.6.9", "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" + "http-errors": "~1.8.0", + "mime-types": "~2.1.35", + "parseurl": "~1.3.3" }, "engines": { "node": ">= 0.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/serve-index/node_modules/debug": { @@ -19683,28 +19716,22 @@ } }, "node_modules/serve-index/node_modules/http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "version": "1.8.1", + "resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", "dev": true, "license": "MIT", "dependencies": { "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" }, "engines": { "node": ">= 0.6" } }, - "node_modules/serve-index/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "dev": true, - "license": "ISC" - }, "node_modules/serve-index/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", @@ -19712,13 +19739,6 @@ "dev": true, "license": "MIT" }, - "node_modules/serve-index/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true, - "license": "ISC" - }, "node_modules/serve-index/node_modules/statuses": { "version": "1.5.0", "resolved": "https://registry.npmmirror.com/statuses/-/statuses-1.5.0.tgz", @@ -20592,13 +20612,16 @@ } }, "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/strip-json-comments": { @@ -20826,9 +20849,9 @@ } }, "node_modules/synckit": { - "version": "0.11.11", - "resolved": "https://registry.npmmirror.com/synckit/-/synckit-0.11.11.tgz", - "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", + "version": "0.11.12", + "resolved": "https://registry.npmmirror.com/synckit/-/synckit-0.11.12.tgz", + "integrity": "sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==", "dev": true, "license": "MIT", "dependencies": { @@ -20972,9 +20995,9 @@ } }, "node_modules/terser": { - "version": "5.44.1", - "resolved": "https://registry.npmmirror.com/terser/-/terser-5.44.1.tgz", - "integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==", + "version": "5.46.0", + "resolved": "https://registry.npmmirror.com/terser/-/terser-5.46.0.tgz", + "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -21025,63 +21048,6 @@ } } }, - "node_modules/terser-webpack-plugin/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "license": "MIT" - }, - "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-4.3.3.tgz", - "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/terser/node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz", @@ -21670,6 +21636,7 @@ "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -21679,9 +21646,9 @@ } }, "node_modules/uint8-util": { - "version": "2.2.5", - "resolved": "https://registry.npmmirror.com/uint8-util/-/uint8-util-2.2.5.tgz", - "integrity": "sha512-/QxVQD7CttWpVUKVPz9znO+3Dd4BdTSnFQ7pv/4drVhC9m4BaL2LFHTkJn6EsYoxT79VDq/2Gg8L0H22PrzyMw==", + "version": "2.2.6", + "resolved": "https://registry.npmmirror.com/uint8-util/-/uint8-util-2.2.6.tgz", + "integrity": "sha512-r+ZjS8CzPhtPF771ROOadUoqC40OVdiMKBI8lTfJQWb4W7+73sMBwMYmai/uvNcmZ7tBJJyZSad03yMWIt3RQg==", "dev": true, "license": "MIT", "dependencies": { @@ -21872,6 +21839,16 @@ "punycode": "^2.1.0" } }, + "node_modules/uri-js/node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/url": { "version": "0.11.4", "resolved": "https://registry.npmmirror.com/url/-/url-0.11.4.tgz", @@ -21886,13 +21863,6 @@ "node": ">= 0.4" } }, - "node_modules/url/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmmirror.com/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", - "dev": true, - "license": "MIT" - }, "node_modules/username": { "version": "5.1.0", "resolved": "https://registry.npmmirror.com/username/-/username-5.1.0.tgz", @@ -22090,9 +22060,9 @@ "license": "MIT" }, "node_modules/watchpack": { - "version": "2.5.0", - "resolved": "https://registry.npmmirror.com/watchpack/-/watchpack-2.5.0.tgz", - "integrity": "sha512-e6vZvY6xboSwLz2GD36c16+O/2Z6fKvIf4pOXptw2rY9MVwE/TXc6RGqxD3I3x0a28lwBY7DE+76uTPSsBrrCA==", + "version": "2.5.1", + "resolved": "https://registry.npmmirror.com/watchpack/-/watchpack-2.5.1.tgz", + "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", "dev": true, "license": "MIT", "dependencies": { @@ -22146,6 +22116,7 @@ "integrity": "sha512-Qphch25abbMNtekmEGJmeRUhLDbe+QfiWTiqpKYkpCOWY64v9eyl+KRRLmqOFA2AvKPpc9DC6+u2n76tQLBoaA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", @@ -22213,63 +22184,6 @@ "webpack": "^4.0.0 || ^5.0.0" } }, - "node_modules/webpack-dev-middleware/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/webpack-dev-middleware/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "license": "MIT" - }, - "node_modules/webpack-dev-middleware/node_modules/schema-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-4.3.3.tgz", - "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/webpack-dev-server": { "version": "4.15.2", "resolved": "https://registry.npmmirror.com/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz", @@ -22330,36 +22244,6 @@ } } }, - "node_modules/webpack-dev-server/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/webpack-dev-server/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, "node_modules/webpack-dev-server/node_modules/ipaddr.js": { "version": "2.3.0", "resolved": "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-2.3.0.tgz", @@ -22370,33 +22254,6 @@ "node": ">= 10" } }, - "node_modules/webpack-dev-server/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "license": "MIT" - }, - "node_modules/webpack-dev-server/node_modules/schema-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-4.3.3.tgz", - "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/webpack-merge": { "version": "5.10.0", "resolved": "https://registry.npmmirror.com/webpack-merge/-/webpack-merge-5.10.0.tgz", @@ -22422,72 +22279,14 @@ "node": ">=10.13.0" } }, - "node_modules/webpack/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/webpack/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/webpack/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "license": "MIT" - }, - "node_modules/webpack/node_modules/schema-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-4.3.3.tgz", - "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/webrtc-polyfill": { - "version": "1.1.10", - "resolved": "https://registry.npmmirror.com/webrtc-polyfill/-/webrtc-polyfill-1.1.10.tgz", - "integrity": "sha512-sOn0bj3/noUdzQX7rvk0jFbBurqWDGGo2ipl+WfgoOe/x3cxbGLk/ZUY+WHCISSlLaIeBumi1X3wxQZnUESExQ==", + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/webrtc-polyfill/-/webrtc-polyfill-1.2.0.tgz", + "integrity": "sha512-epaVJbKzWOY5Wf3k7DoZLNgHP/5IoALBvjvlZQgX+9vFnf9UfCHv+rc+r/vJ7jxQUwH3cIYx9blHfyWWxGbw1g==", "dev": true, "license": "MIT", "dependencies": { - "node-datachannel": "^v0.12.0", - "node-domexception": "^1.0.0" + "node-datachannel": "^0.32.0" }, "engines": { "node": ">=16.0.0" @@ -22708,9 +22507,9 @@ "optional": true }, "node_modules/which-typed-array": { - "version": "1.1.19", - "resolved": "https://registry.npmmirror.com/which-typed-array/-/which-typed-array-1.1.19.tgz", - "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "version": "1.1.20", + "resolved": "https://registry.npmmirror.com/which-typed-array/-/which-typed-array-1.1.20.tgz", + "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", "dev": true, "license": "MIT", "dependencies": { @@ -22817,11 +22616,12 @@ "license": "ISC" }, "node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmmirror.com/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "version": "8.19.0", + "resolved": "https://registry.npmmirror.com/ws/-/ws-8.19.0.tgz", + "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", "devOptional": true, "license": "MIT", + "peer": true, "engines": { "node": ">=10.0.0" }, @@ -22888,7 +22688,8 @@ "integrity": "sha512-c3Cp4eOVsYY5Q839dR5IejghRPpxciGmLWWaP9g+ppfMeBChMeLa1DCA+pmX/jyDZ+zxFOmlJL/82qVdayVoGQ==", "deprecated": "This package is now deprecated. Move to @xterm/xterm instead.", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/xterm-addon-fit": { "version": "0.5.0", @@ -23059,6 +22860,7 @@ "resolved": "https://registry.npmmirror.com/zod/-/zod-3.25.76.tgz", "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } @@ -23068,7 +22870,6 @@ "resolved": "https://registry.npmmirror.com/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz", "integrity": "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==", "license": "ISC", - "peer": true, "peerDependencies": { "zod": "^3.25 || ^4" } diff --git a/package.json b/package.json index b325b13..07041ae 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "@electron/fuses": "^1.8.0", "@stdlib/utils-convert-path": "^0.2.2", "@svgr/webpack": "^8.1.0", + "@types/adm-zip": "^0.5.7", "@types/cross-spawn": "^6.0.6", "@types/dockerode": "^3.3.40", "@types/form-data": "^2.2.1", @@ -88,6 +89,7 @@ "@langchain/ollama": "^0.2.4", "@langchain/openai": "^0.6.14", "@types/webtorrent": "^0.110.1", + "adm-zip": "^0.5.16", "electron-squirrel-startup": "^1.0.1", "langchain": "^0.3.35", "pdf-lib": "^1.17.1", diff --git a/src/main/cmd/index.ts b/src/main/cmd/index.ts index dbe8798..629e8cb 100644 --- a/src/main/cmd/index.ts +++ b/src/main/cmd/index.ts @@ -23,6 +23,194 @@ import { RunResult } from '@podman-desktop/api'; import { podMachineName } from '../podman-desktop/type-info'; import { isVTReady, isWSLInstall, wslVersion } from './is-wsl-install'; import { loggerFactory } from '../terminal-log'; +import { WEBTORRENT_CONFIG } from '../webtorrent-config'; + +/** + * 判断错误是否为 EBUSY 错误(文件被占用) + */ +function isEBUSYError(error: unknown): boolean { + if (error instanceof Error) { + return error.message.includes('EBUSY'); + } + if (typeof error === 'object' && error !== null && 'message' in error) { + return String((error as { message: unknown }).message).includes('EBUSY'); + } + return false; +} + +/** + * 获取错误信息 + */ +function getErrorMessage(error: unknown): string { + if (error instanceof Error) { + return error.message; + } + if (typeof error === 'string') { + return error; + } + return String(error); +} + +interface RetryExecuteOptions { + /** 执行的程序路径 */ + exePath: string; + /** 执行参数 */ + args: string[]; + /** 日志前缀,用于区分不同的安装程序 */ + logPrefix: string; +} + +/** + * 带重试机制执行安装程序 + * 处理 EBUSY 错误(文件被占用)的情况 + */ +async function executeWithRetry( + options: RetryExecuteOptions, +): Promise { + const { exePath, args, logPrefix } = options; + const maxRetries = WEBTORRENT_CONFIG.MAX_RETRIES; + + for (let retry = 0; retry < maxRetries; retry++) { + try { + // 每次重试前等待更长时间,让文件句柄有充足时间释放 + const waitTime = + retry === 0 + ? WEBTORRENT_CONFIG.RETRY_BASE_WAIT + : WEBTORRENT_CONFIG.RETRY_BASE_WAIT + + retry * WEBTORRENT_CONFIG.RETRY_INCREMENT; + await new Promise((resolve) => setTimeout(resolve, waitTime)); + + console.debug( + `[${logPrefix}] 尝试执行安装程序 (${retry + 1}/${maxRetries}),等待了 ${waitTime}ms`, + ); + const result = await commandLine.exec(exePath, args); + console.debug(`[${logPrefix}] 安装程序执行成功:`, result); + return true; + } catch (e) { + if (isEBUSYError(e) && retry < maxRetries - 1) { + console.warn( + `[${logPrefix}] 执行安装程序失败 (EBUSY),重试 ${retry + 1}/${maxRetries}...`, + ); + } else if (isEBUSYError(e)) { + // 所有重试都失败了,尝试最后一次长等待 + console.warn(`[${logPrefix}] 所有重试都失败,尝试最后一次长等待...`); + await new Promise((resolve) => + setTimeout(resolve, WEBTORRENT_CONFIG.FINAL_RETRY_WAIT), + ); + try { + const result = await commandLine.exec(exePath, args); + console.debug(`[${logPrefix}] 最后一次尝试成功:`, result); + return true; + } catch (finalError) { + console.error(`[${logPrefix}] 最后一次尝试也失败了:`, finalError); + throw finalError; + } + } else { + throw e; + } + } + } + return false; +} + +interface P2PInstallOptions { + /** DLC 索引中的 key */ + dlcKey: + | 'OBSIDIAN_SETUP_EXE' + | 'LM_STUDIO_SETUP_EXE' + | 'PDF_TAR' + | 'VOICE_TAR' + | 'TRAINING_TAR' + | 'TRAINING_VOICE_TAR' + | 'TRAINING_COURSE' + | 'LMSTUDIO_WINDOWS' + | 'AI_LEARNING_ASSISTANT_LAUNCHER' + | 'TEST_FILE'; + /** 安装程序参数 */ + installerArgs: string[]; + /** 日志前缀 */ + logPrefix: string; + /** 降级时使用的本地安装包相对路径 */ + fallbackInstallerPath: string; +} + +/** + * 通用的 P2P 下载安装逻辑 + * 优先使用 P2P 下载的安装包,失败时降级到本地安装包 + */ +async function installFromP2POrFallback( + options: P2PInstallOptions, +): Promise { + const { dlcKey, installerArgs, logPrefix, fallbackInstallerPath } = options; + + try { + // 首先检查是否有P2P下载的文件 + const { getDLCFromDLCIndex, destroyWebtorrentForInstall } = await import( + '../dlc' + ); + const dlcInfo = getDLCFromDLCIndex(dlcKey); + + if (dlcInfo) { + const latestVersion = Object.keys(dlcInfo.versions).sort().pop(); + if (latestVersion) { + const versionInfo = dlcInfo.versions[latestVersion]; + + // 完全销毁 torrent 以释放文件句柄,避免 EBUSY 错误 + if (versionInfo.magnet) { + try { + console.debug(`[${logPrefix}] 开始销毁种子以释放文件句柄...`); + await destroyWebtorrentForInstall(versionInfo.magnet); + // 等待额外的时间确保文件句柄完全释放 + await new Promise((resolve) => + setTimeout(resolve, WEBTORRENT_CONFIG.TORRENT_DESTROY_WAIT), + ); + console.debug(`[${logPrefix}] 种子已销毁,等待完成`); + } catch (e) { + console.warn(`[${logPrefix}] 销毁torrent失败:`, e); + } + } + + const downloadPath = path.join( + appPath, + 'external-resources', + 'dlc', + dlcKey, + latestVersion, + ); + + const fs = await import('fs'); + if (fs.existsSync(downloadPath)) { + const files = fs.readdirSync(downloadPath); + const exeFile = files.find((f: string) => f.endsWith('.exe')); + + if (exeFile) { + const exePath = path.join(downloadPath, exeFile); + return await executeWithRetry({ + exePath, + args: installerArgs, + logPrefix, + }); + } + } + } + } + } catch (error) { + console.error(`[${logPrefix}] 尝试使用P2P下载包失败,使用默认方式:`, error); + } + + // 降级到原有的本地安装包方式 + const result = await commandLine.exec( + path.join( + appPath, + 'external-resources', + 'ai-assistant-backend', + fallbackInstallerPath, + ), + installerArgs, + ); + console.debug(`[${logPrefix}] 本地安装包执行结果:`, result); + return true; +} const commandLine = new Exec(); @@ -488,17 +676,12 @@ async function checkWSLComponent() { } export async function installObsidian() { - const result = await commandLine.exec( - path.join( - appPath, - 'external-resources', - 'ai-assistant-backend', - 'install_obsidian.exe', - ), - ['/s'], - ); - console.debug(result); - return true; + return installFromP2POrFallback({ + dlcKey: 'OBSIDIAN_SETUP_EXE', + installerArgs: ['/s'], + logPrefix: 'Obsidian', + fallbackInstallerPath: 'install_obsidian.exe', + }); } export async function isObsidianInstall() { @@ -520,26 +703,24 @@ export async function isObsidianInstall() { } export async function installLMStudio() { - const result = await commandLine.exec( - path.join( - appPath, - 'external-resources', - 'ai-assistant-backend', - 'install_lm_studio.exe', - ), - ['/s'], - ); - console.debug(result); - return true; + return installFromP2POrFallback({ + dlcKey: 'LM_STUDIO_SETUP_EXE', + installerArgs: [], + logPrefix: 'LM Studio', + fallbackInstallerPath: 'install_lm_studio.exe', + }); } export async function isLMStudioInstall() { try { const result = await Promise.race([ new Promise((resolve, reject) => - setTimeout(() => reject('isLMStudioInstall命令超时'), 15000), + setTimeout( + () => reject('isLMStudioInstall命令超时'), + WEBTORRENT_CONFIG.LM_STUDIO_CHECK_TIMEOUT, + ), ), - // 如果用户安装lmstudio然后又卸载了lmstudio,那么这个命令会一直卡着,也不报错,所以要用一个10000ms的报错promise与它竞赛 + // 如果用户安装lmstudio然后又卸载了lmstudio,那么这个命令会一直卡着,也不报错,所以要用一个超时promise与它竞赛 commandLine.exec('lms', ['ls']), ]); console.debug('isLMStudioInstall', result); diff --git a/src/main/dlc/index.ts b/src/main/dlc/index.ts index 869cebe..511c865 100644 --- a/src/main/dlc/index.ts +++ b/src/main/dlc/index.ts @@ -8,6 +8,9 @@ import { DLCIndex, DLCId, OneDLCInfo, + setUploadEnabledHandle, + getUploadEnabledHandle, + getUploadStatsHandle, } from './type-info'; import { ipcHandle } from '../ipc-util'; import WebTorrent, * as allExports from 'webtorrent'; @@ -15,8 +18,48 @@ import path from 'path'; import { appPath } from '../exec'; import fs, { existsSync, mkdirSync, readFileSync, unlinkSync } from 'fs'; import { compare } from 'semver'; +import { WEBTORRENT_CONFIG } from '../webtorrent-config'; let client: WebTorrent.Instance | null = null; +let uploadEnabled = true; // 默认开启上传 + +// 上传配置文件路径 +const uploadConfigPath = path.join( + appPath, + 'external-resources', + 'dlc', + 'upload-config.json', +); + +// 读取上传配置 +function loadUploadConfig(): boolean { + try { + if (existsSync(uploadConfigPath)) { + const config = JSON.parse(readFileSync(uploadConfigPath, 'utf8')); + return config.uploadEnabled ?? true; + } + } catch (error) { + console.error('读取上传配置失败:', error); + } + return true; +} + +// 保存上传配置 +function saveUploadConfig(enabled: boolean): void { + try { + const dir = path.dirname(uploadConfigPath); + if (!existsSync(dir)) { + mkdirSync(dir, { recursive: true }); + } + fs.writeFileSync( + uploadConfigPath, + JSON.stringify({ uploadEnabled: enabled }, null, 2), + ); + } catch (error) { + console.error('保存上传配置失败:', error); + } +} + const getWebTorrent = async () => { const WebTorrentClass: WebTorrent.WebTorrent = // @ts-ignore @@ -59,7 +102,14 @@ const getWebTorrent = async () => { // }; export default async function init(ipcMain: IpcMain) { + // 加载上传配置 + uploadEnabled = loadUploadConfig(); + client = await getWebTorrent(); + + // 根据配置应用上传限制 + applyUploadThrottle(); + ipcHandle(ipcMain, startWebtorrentHandle, async (_event, magnet: string) => startWebtorrent(magnet), ); @@ -75,6 +125,13 @@ export default async function init(ipcMain: IpcMain) { ipcHandle(ipcMain, logsWebtorrentHandle, async (_event, magnet: string) => logsWebtorrent(magnet), ); + ipcHandle(ipcMain, setUploadEnabledHandle, async (_event, enabled: boolean) => + setUploadEnabled(enabled), + ); + ipcHandle(ipcMain, getUploadEnabledHandle, async (_event) => + getUploadEnabled(), + ); + ipcHandle(ipcMain, getUploadStatsHandle, async (_event) => getUploadStats()); // 检查种子文件和对应的实际文件,如果有文件,就添加到webtorrent中 await restoreTorrentsFromFiles(); } @@ -99,9 +156,9 @@ export async function startWebtorrent(magnet: string) { }); console.debug('种子文件已经存在,继续下载'); torrent.resume(); - return torrent; + return { success: true, infoHash: torrent.infoHash }; } else { - return client.add( + const newTorrent = client.add( magnet, { path: filePath, @@ -114,9 +171,11 @@ export async function startWebtorrent(magnet: string) { saveTorrentFile(filePath, torrent); }, ); + return { success: true, infoHash: newTorrent.infoHash }; } } else { console.warn('没找到链接对应的索引信息', magnet); + return { success: false, error: '没找到链接对应的索引信息' }; } } @@ -152,6 +211,35 @@ export async function pauseWebtorrent(magnet: string) { } } +/** + * 完全销毁种子并释放文件句柄 + * 注意:这会关闭所有文件句柄,但不会删除已下载的文件 + */ +export async function destroyWebtorrentForInstall( + magnet: string, +): Promise { + const torrent = await client.get(magnet); + if (torrent) { + return new Promise((resolve) => { + let resolved = false; + const safeResolve = () => { + if (!resolved) { + resolved = true; + resolve(); + } + }; + + torrent.pause(); + torrent.destroy({ destroyStore: false }, safeResolve); + + setTimeout( + safeResolve, + WEBTORRENT_CONFIG.TORRENT_DESTROY_CALLBACK_TIMEOUT, + ); + }); + } +} + export async function removeWebtorrent(magnet: string) { const torrent = await client.get(magnet); if (torrent) { @@ -387,8 +475,8 @@ export async function waitTorrentDone(id: DLCId, version: string) { // 轮询检查种子是否完成 return new Promise((resolve, reject) => { - const checkInterval = 1000; // 1秒检查一次 - const maxAttempts = 3600; // 最多检查1小时(3600秒) + const checkInterval = WEBTORRENT_CONFIG.DOWNLOAD_CHECK_INTERVAL; + const maxAttempts = WEBTORRENT_CONFIG.DOWNLOAD_MAX_ATTEMPTS; let attempts = 0; const intervalId = setInterval(() => { @@ -419,8 +507,8 @@ export async function waitTorrentDone(id: DLCId, version: string) { return; } - // 输出进度信息(可选,每10秒输出一次) - if (attempts % 10 === 0) { + // 输出进度信息(可选,每N秒输出一次) + if (attempts % WEBTORRENT_CONFIG.DOWNLOAD_PROGRESS_LOG_INTERVAL === 0) { console.debug( `种子 ${currentTorrent.name} 下载进度: ${(currentTorrent.progress * 100).toFixed(2)}%`, ); @@ -550,3 +638,71 @@ async function restoreTorrentsFromFiles() { console.error('恢复种子过程中发生错误:', error); } } + +/** 应用上传限速设置 */ +function applyUploadThrottle(): void { + if (!client) return; + + if (uploadEnabled) { + // 不限制上传速度 (-1 表示无限制) + client.throttleUpload(-1); + console.debug('上传已启用,不限速'); + } else { + // 限制上传速度为 0(禁用上传) + client.throttleUpload(0); + console.debug('上传已禁用,限速为 0'); + } +} + +/** 设置上传开关 */ +export function setUploadEnabled(enabled: boolean): { + success: boolean; + enabled: boolean; +} { + uploadEnabled = enabled; + saveUploadConfig(enabled); + applyUploadThrottle(); + console.debug(`上传设置已更新: ${enabled ? '启用' : '禁用'}`); + return { success: true, enabled }; +} + +/** 获取上传开关状态 */ +export function getUploadEnabled(): { enabled: boolean } { + return { enabled: uploadEnabled }; +} + +/** 获取上传统计信息 */ +export function getUploadStats(): { + enabled: boolean; + totalUploaded: number; + uploadSpeed: number; + activeTorrents: number; +} { + if (!client) { + return { + enabled: uploadEnabled, + totalUploaded: 0, + uploadSpeed: 0, + activeTorrents: 0, + }; + } + + let totalUploaded = 0; + let uploadSpeed = 0; + let activeTorrents = 0; + + for (const torrent of client.torrents) { + totalUploaded += torrent.uploaded || 0; + uploadSpeed += torrent.uploadSpeed || 0; + if (torrent.progress === 1 && !torrent.paused) { + activeTorrents++; + } + } + + return { + enabled: uploadEnabled, + totalUploaded, + uploadSpeed, + activeTorrents, + }; +} diff --git a/src/main/dlc/type-info.ts b/src/main/dlc/type-info.ts index 37d0a5d..7770c7f 100644 --- a/src/main/dlc/type-info.ts +++ b/src/main/dlc/type-info.ts @@ -13,6 +13,12 @@ export const queryWebtorrentHandle = `${channel}query`; export const logsWebtorrentHandle = `${channel}logs`; +export const setUploadEnabledHandle = `${channel}setUploadEnabled`; + +export const getUploadEnabledHandle = `${channel}getUploadEnabled`; + +export const getUploadStatsHandle = `${channel}getUploadStats`; + export const dLCIds = [ 'PDF_TAR', 'VOICE_TAR', @@ -20,6 +26,9 @@ export const dLCIds = [ 'TRAINING_VOICE_TAR', 'TRAINING_COURSE', 'LMSTUDIO_WINDOWS', + 'AI_LEARNING_ASSISTANT_LAUNCHER', + 'OBSIDIAN_SETUP_EXE', + 'LM_STUDIO_SETUP_EXE', 'TEST_FILE', ] as const; diff --git a/src/main/index.ts b/src/main/index.ts index 3b8f105..15149b2 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -13,7 +13,9 @@ import initPdfConvert from './pdf-convert'; import initTrainingService from './training-service'; import initLogService from './backup'; import initExternalUrl from './external-url'; +import { setupJointBuildHandlers, setupWindowCloseHandler, isTrayEnabled } from './joint-build'; import initDLC from './dlc'; +import initLauncherUpdate from './launcher-update'; import path from 'node:path'; import { appPath, autoAdaptEncodingForWindows } from './exec'; import { logDeviceInfo } from './logger/log-device-info'; @@ -80,7 +82,9 @@ initExampleMain(ipcMain); initPdfConvert(ipcMain); initTrainingService(ipcMain); initExternalUrl(ipcMain); +setupJointBuildHandlers(ipcMain); initDLC(ipcMain); +initLauncherUpdate(ipcMain); updateTemplate(); const createWindow = async () => { @@ -95,6 +99,9 @@ const createWindow = async () => { autoHideMenuBar: true, }); + // 设置窗口关闭行为(托盘最小化) + setupWindowCloseHandler(mainWindow); + // 最大化窗口 mainWindow.maximize(); @@ -121,6 +128,10 @@ app.on('ready', createWindow); // for applications and their menu bar to stay active until the user quits // explicitly with Cmd + Q. app.on('window-all-closed', () => { + // 如果托盘启用,不退出应用 + if (isTrayEnabled()) { + return; + } if (process.platform !== 'darwin') { app.quit(); } diff --git a/src/main/ipc-data-type.ts b/src/main/ipc-data-type.ts index acd7b57..5e606a6 100644 --- a/src/main/ipc-data-type.ts +++ b/src/main/ipc-data-type.ts @@ -16,7 +16,8 @@ export type Channels = | 'training-service' | 'backup' | 'open-external-url' - | 'webtorrent'; + | 'webtorrent' + | 'launcher-update'; export enum MESSAGE_TYPE { /** 阻断性错误,会把转圈中的按钮变成不转圈 */ @@ -69,12 +70,11 @@ import { ActionName as LogActionName, ServiceName as LogServiceName, } from './backup/type-info'; -import { +import { ActionName as ActionNameUrl, ServiceName as ServiceNameUrl, } from './external-url/type-info'; - export type AllAction = | ActionNamePodman | ActionNameCmd diff --git a/src/main/joint-build/index.ts b/src/main/joint-build/index.ts new file mode 100644 index 0000000..cf606e0 --- /dev/null +++ b/src/main/joint-build/index.ts @@ -0,0 +1,232 @@ +import { dialog, IpcMain, Tray, Menu, BrowserWindow, app, nativeImage } from 'electron'; +import { selectFolderHandle, getDiskInfoHandle, DiskInfo, setTrayEnabledHandle } from './type-info'; +import { exec } from 'child_process'; +import { promisify } from 'util'; +import path from 'path'; +import { ipcHandle } from '../ipc-util'; + +const execPromise = promisify(exec); + +// 托盘实例 +let tray: Tray | null = null; +// 是否启用托盘(共建开关状态) +let trayEnabled = false; +// 是否正在强制退出 +let forceQuit = false; + +// 获取Windows磁盘信息 +async function getWindowsDiskInfo(diskPath: string): Promise { + try { + // 获取盘符,例如 "C:" 或 "D:" + const driveLetter = path.parse(diskPath).root.replace('\\', ''); + + // 使用 wmic 命令获取磁盘信息 + const { stdout } = await execPromise( + `wmic logicaldisk where "DeviceID='${driveLetter}'" get Size,FreeSpace /format:csv`, + { encoding: 'utf8' } + ); + + const lines = stdout.trim().split('\n').filter(line => line.trim()); + if (lines.length < 2) { + throw new Error('无法获取磁盘信息'); + } + + // CSV格式: Node,FreeSpace,Size + const values = lines[1].split(','); + const freeSpace = parseInt(values[1], 10) || 0; + const totalSize = parseInt(values[2], 10) || 0; + + return { + total: totalSize, + free: freeSpace, + used: totalSize - freeSpace, + }; + } catch (error) { + console.error('获取磁盘信息失败:', error); + // 返回默认值 + return { + total: 500 * 1024 * 1024 * 1024, // 500GB + free: 200 * 1024 * 1024 * 1024, // 200GB + used: 300 * 1024 * 1024 * 1024, // 300GB + }; + } +} + +export function setupJointBuildHandlers(ipcMain: IpcMain): void { + // 处理选择文件夹 + ipcHandle(ipcMain, selectFolderHandle, async () => { + const result = await dialog.showOpenDialog({ + properties: ['openDirectory'], + defaultPath: 'C:\\', // Windows默认从C盘开始 + title: '选择共建计划存储路径', + }); + + if (result.canceled || !result.filePaths || result.filePaths.length === 0) { + return null; + } + + return result.filePaths[0]; + }); + + // 处理获取磁盘信息 + ipcHandle(ipcMain, getDiskInfoHandle, async (_event, diskPath: string) => { + return getWindowsDiskInfo(diskPath); + }); + + // 处理设置托盘启用状态(只更新状态,不销毁托盘) + ipcHandle(ipcMain, setTrayEnabledHandle, async (_event, enabled: boolean) => { + trayEnabled = enabled; + // 确保托盘始终存在 + createTray(); + // 更新托盘提示信息 + updateTrayTooltip(); + return true; + }); +} + +// 获取图标路径 +function getIconPath(): string { + // 开发环境和生产环境的路径不同 + if (app.isPackaged) { + return path.join(process.resourcesPath, 'icons', 'icon.png'); + } else { + return path.join(__dirname, '..', '..', 'icons', 'icon.png'); + } +} + +// 创建托盘 +function createTray(): void { + if (tray) return; + + try { + const iconPath = getIconPath(); + const icon = nativeImage.createFromPath(iconPath); + tray = new Tray(icon.resize({ width: 16, height: 16 })); + + updateTrayMenu(); + updateTrayTooltip(); + + // 双击托盘图标显示窗口 + tray.on('double-click', () => { + const windows = BrowserWindow.getAllWindows(); + if (windows.length > 0) { + const mainWindow = windows[0]; + mainWindow.show(); + mainWindow.focus(); + } + }); + } catch (error) { + console.error('创建托盘失败:', error); + } +} + +// 更新托盘菜单 +function updateTrayMenu(): void { + if (!tray) return; + + const contextMenu = Menu.buildFromTemplate([ + { + label: '打开AI学习助手', + click: () => { + const windows = BrowserWindow.getAllWindows(); + if (windows.length > 0) { + const mainWindow = windows[0]; + mainWindow.show(); + mainWindow.focus(); + // 发送路由事件到渲染进程,导航到主界面 + mainWindow.webContents.send('navigate-to', '/hello'); + } + }, + }, + { + label: '打开共建设置', + click: () => { + const windows = BrowserWindow.getAllWindows(); + if (windows.length > 0) { + const mainWindow = windows[0]; + mainWindow.show(); + mainWindow.focus(); + // 发送路由事件到渲染进程,导航到共建设置界面 + mainWindow.webContents.send('navigate-to', '/joint-build'); + } + }, + }, + { + label: trayEnabled ? '停止共建计划' : '运行共建计划', + click: () => { + trayEnabled = !trayEnabled; + // 更新菜单显示 + updateTrayMenu(); + updateTrayTooltip(); + // 通知渲染进程更新状态 + const windows = BrowserWindow.getAllWindows(); + if (windows.length > 0) { + windows[0].webContents.send('joint-build-status-changed', trayEnabled); + } + }, + }, + { type: 'separator' }, + { + label: '退出AI学习助手', + click: () => { + forceQuit = true; + app.quit(); + }, + }, + ]); + + tray.setContextMenu(contextMenu); +} + +// 更新托盘提示信息 +function updateTrayTooltip(): void { + if (!tray) return; + + const version = app.getVersion(); + const isJointBuilding = trayEnabled ? '正在共建中(ON)' : '共建已关闭(OFF)'; + if (!trayEnabled) { + tray.setToolTip(`AI学习助手 ${version}\n共建已关闭(OFF)`); + return; + } + // todo:获取动态数据 + const currentUploadSpeed = '0KB/s'; + const linkedTo = 0; + tray.setToolTip(`AI学习助手 ${version}\n${isJointBuilding}\n当前上传速度: ${currentUploadSpeed}\n已连接伙伴${linkedTo}人`); +} + +// 销毁托盘 +function destroyTray(): void { + if (tray) { + tray.destroy(); + tray = null; + } +} + +// 设置窗口关闭行为 +export function setupWindowCloseHandler(mainWindow: BrowserWindow): void { + // 确保托盘已创建 + createTray(); + + mainWindow.on('close', (event) => { + // 始终最小化到托盘,除非是强制退出 + if (!forceQuit) { + event.preventDefault(); + mainWindow.hide(); + } + }); +} + +// 检查是否强制退出 +export function isForceQuit(): boolean { + return forceQuit; +} + +// 设置强制退出标志 +export function setForceQuit(value: boolean): void { + forceQuit = value; +} + +// 获取托盘启用状态(始终启用托盘最小化) +export function isTrayEnabled(): boolean { + return true; +} diff --git a/src/main/joint-build/type-info.ts b/src/main/joint-build/type-info.ts new file mode 100644 index 0000000..ac7f09c --- /dev/null +++ b/src/main/joint-build/type-info.ts @@ -0,0 +1,12 @@ +export type ActionName = 'select-folder' | 'get-disk-info' | 'set-tray-enabled'; +export type ServiceName = 'joint-build'; + +export const selectFolderHandle = 'joint-build:select-folder'; +export const getDiskInfoHandle = 'joint-build:get-disk-info'; +export const setTrayEnabledHandle = 'joint-build:set-tray-enabled'; + +export interface DiskInfo { + total: number; // bytes + free: number; // bytes + used: number; // bytes +} diff --git a/src/main/launcher-update/index.ts b/src/main/launcher-update/index.ts new file mode 100644 index 0000000..3423050 --- /dev/null +++ b/src/main/launcher-update/index.ts @@ -0,0 +1,734 @@ +import { IpcMain, app, dialog } from 'electron'; +import { ipcHandle } from '../ipc-util'; +import { + checkLauncherUpdateHandle, + downloadLauncherUpdateHandle, + installLauncherUpdateHandle, +} from './type-info'; +import { + getLatestVersion, + startWebtorrent, + waitTorrentDone, + destroyWebtorrentForInstall, +} from '../dlc'; +import semver from 'semver'; +import path from 'path'; +import { appPath } from '../exec'; +import { existsSync, mkdirSync, rmSync } from 'fs'; +import { + readdir, + writeFile, + appendFile, + access, + rename, + stat, + unlink, + constants, +} from 'fs/promises'; +import { spawn } from 'child_process'; + +import packageJson from '../../../package.json'; +const currentVersion = packageJson.version; + +// 更新日志文件路径 +const updateLogPath = path.join(appPath, 'launcher-update.log'); +const updateLogBackupPath = path.join(appPath, 'launcher-update.log.old'); + +// 日志滚动配置 +const LOG_ROTATION_CONFIG = { + MAX_SIZE_BYTES: 1 * 1024 * 1024, // 1MB +}; + +/** + * 写入更新日志到文件 + * @param level 日志级别 + * @param message 日志消息 + * @param data 附加数据 + */ +async function writeUpdateLog( + level: 'DEBUG' | 'INFO' | 'WARN' | 'ERROR', + message: string, + data?: unknown, +) { + const timestamp = new Date().toISOString(); + let logLine = `[${timestamp}] [${level}] ${message}`; + if (data !== undefined) { + try { + logLine += ` ${JSON.stringify(data)}`; + } catch { + logLine += ` [无法序列化的数据]`; + } + } + logLine += '\n'; + + try { + await appendFile(updateLogPath, logLine, { encoding: 'utf8' }); + } catch (err) { + console.error('写入更新日志失败:', err); + } + + // 同时输出到控制台 + switch (level) { + case 'DEBUG': + console.debug(message, data ?? ''); + break; + case 'INFO': + console.log(message, data ?? ''); + break; + case 'WARN': + console.warn(message, data ?? ''); + break; + case 'ERROR': + console.error(message, data ?? ''); + break; + } +} + +/** + * 初始化日志文件(检查大小并执行滚动) + * 当日志文件超过 MAX_SIZE_BYTES 时,将旧日志重命名为 .old 文件 + */ +async function initUpdateLog() { + try { + // 检查日志文件是否存在及其大小 + if (existsSync(updateLogPath)) { + const stats = await stat(updateLogPath); + + if (stats.size >= LOG_ROTATION_CONFIG.MAX_SIZE_BYTES) { + // 删除旧的备份文件(如果存在) + try { + await unlink(updateLogBackupPath); + } catch { + // 备份文件不存在,忽略 + } + + // 将当前日志重命名为备份 + await rename(updateLogPath, updateLogBackupPath); + + console.log( + `[initUpdateLog] 日志文件已滚动,旧日志大小: ${(stats.size / 1024).toFixed(2)} KB`, + ); + } + } + } catch (err) { + console.error('[initUpdateLog] 日志滚动检查失败:', err); + } + + // 添加分隔符 + const separator = ` +${'='.repeat(60)} +[${new Date().toISOString()}] 启动器更新日志开始 +${'='.repeat(60)} +`; + try { + await appendFile(updateLogPath, separator, { encoding: 'utf8' }); + } catch { + // 忽略错误 + } +} + +export default async function init(ipcMain: IpcMain) { + ipcHandle(ipcMain, checkLauncherUpdateHandle, async (_event) => + checkLauncherUpdate(), + ); + ipcHandle(ipcMain, downloadLauncherUpdateHandle, async (_event) => + downloadLauncherUpdate(), + ); + ipcHandle(ipcMain, installLauncherUpdateHandle, async (_event) => + installLauncherUpdate(), + ); +} + +/** + * 清理更新临时目录 + * 当已是最新版本时调用,清理之前更新留下的临时文件 + */ +async function cleanupUpdateTempDir() { + const tempDir = path.join(app.getPath('temp'), 'launcher-update'); + + try { + if (existsSync(tempDir)) { + rmSync(tempDir, { recursive: true, force: true }); + await writeUpdateLog( + 'INFO', + '[cleanupUpdateTempDir] 已清理更新临时目录', + { tempDir }, + ); + } + } catch (err) { + await writeUpdateLog( + 'WARN', + '[cleanupUpdateTempDir] 清理更新临时目录失败', + err instanceof Error ? { message: err.message } : err, + ); + } +} + +export async function checkLauncherUpdate() { + await initUpdateLog(); + await writeUpdateLog('INFO', '[checkLauncherUpdate] 开始检查启动器更新'); + + try { + const latestVersionInfo = getLatestVersion( + 'AI_LEARNING_ASSISTANT_LAUNCHER', + ); + const latestVersion = latestVersionInfo.version; + + // 版本号规范校验 + if (!semver.valid(currentVersion)) { + await writeUpdateLog( + 'ERROR', + '[checkLauncherUpdate] 当前版本号格式无效', + { currentVersion }, + ); + throw new Error(`当前版本号格式无效: ${currentVersion}`); + } + + if (!semver.valid(latestVersion)) { + await writeUpdateLog( + 'ERROR', + '[checkLauncherUpdate] 最新版本号格式无效', + { latestVersion }, + ); + throw new Error(`最新版本号格式无效: ${latestVersion}`); + } + + const haveNew = semver.lt(currentVersion, latestVersion); + + await writeUpdateLog('INFO', '[checkLauncherUpdate] 检查启动器更新完成', { + currentVersion, + latestVersion, + haveNew, + }); + + // 如果已是最新版本,清理更新临时目录 + if (!haveNew) { + await cleanupUpdateTempDir(); + } + + return { + currentVersion, + latestVersion, + haveNew, + }; + } catch (error) { + await writeUpdateLog( + 'ERROR', + '[checkLauncherUpdate] 检查启动器更新失败', + error instanceof Error + ? { message: error.message, stack: error.stack } + : error, + ); + return { + currentVersion, + latestVersion: currentVersion, + haveNew: false, + }; + } +} + +export async function downloadLauncherUpdate() { + await writeUpdateLog('INFO', '[downloadLauncherUpdate] 开始下载启动器更新'); + + try { + const latestVersionInfo = getLatestVersion( + 'AI_LEARNING_ASSISTANT_LAUNCHER', + ); + + // 空值检查:确保 dlcInfo 和 magnet 存在 + if (!latestVersionInfo.dlcInfo?.magnet) { + throw new Error('未找到有效的更新包信息(dlcInfo 或 magnet 缺失)'); + } + + const { magnet } = latestVersionInfo.dlcInfo; + + await writeUpdateLog( + 'DEBUG', + '[downloadLauncherUpdate] 获取到最新版本信息', + { + version: latestVersionInfo.version, + magnet: magnet.substring(0, 50) + '...', + }, + ); + + await startWebtorrent(magnet); + await writeUpdateLog('DEBUG', '[downloadLauncherUpdate] WebTorrent 已启动'); + + const torrent = await waitTorrentDone( + 'AI_LEARNING_ASSISTANT_LAUNCHER', + latestVersionInfo.version, + ); + + const filePath = path.join(torrent.path, torrent.files[0].name); + await writeUpdateLog( + 'INFO', + '[downloadLauncherUpdate] 启动器更新下载完成', + { + path: torrent.path, + fileName: torrent.files[0].name, + }, + ); + + // 检查是否为本地开发环境,请打包后测试 + const isDev = !app.isPackaged; + if (isDev) { + await writeUpdateLog( + 'WARN', + '[downloadLauncherUpdate] 当前为本地开发环境,启动器更新功能可能无法正常工作', + ); + } + + return { + success: true, + version: latestVersionInfo.version, + filePath, + isDev, + }; + } catch (error) { + await writeUpdateLog( + 'ERROR', + '[downloadLauncherUpdate] 下载启动器更新失败', + error instanceof Error + ? { message: error.message, stack: error.stack } + : error, + ); + throw error; + } +} + +/** + * 生成自定义更新批处理脚本 + * 脚本功能:等待应用退出、解压更新包、校验完整性、备份旧版本、替换文件、恢复数据、启动新版本 + * + * 安全策略:采用"解压 -> 校验 -> 备份 -> 替换"模式 + * 1. 先在临时目录完整解压并校验 + * 2. 校验失败则直接启动旧版本,不做任何修改 + * 3. 校验成功后备份整个旧版本目录 + * 4. 替换失败时可从备份恢复 + */ +async function generateUpdateScript( + zipPath: string, + appDir: string, + tempDir: string, + newVersion: string, +): Promise { + const scriptContent = `@echo off +chcp 65001 >nul +setlocal enabledelayedexpansion + +set "ZIP_PATH=${zipPath.replace(/\//g, '\\')}" +set "APP_DIR=${appDir.replace(/\//g, '\\')}" +set "TEMP_DIR=${tempDir.replace(/\//g, '\\')}" +set "BACKUP_DIR=${tempDir.replace(/\//g, '\\')}\\external-resources-backup" +set "APP_BACKUP_DIR=${tempDir.replace(/\//g, '\\')}\\app-backup" +set "EXTRACT_DIR=${tempDir.replace(/\//g, '\\')}\\extracted" +set "UPDATE_LOG=${tempDir.replace(/\//g, '\\')}\\update-script.log" + +:: 日志函数 +call :log "========== 更新脚本开始 ==========" + +call :log "等待应用退出..." +:waitloop +tasklist /FI "IMAGENAME eq AI Learning Assistant Launcher.exe" 2>NUL | find /I "AI Learning Assistant Launcher.exe" >NUL +if not errorlevel 1 ( + timeout /t 1 /nobreak >nul + goto waitloop +) + +call :log "应用已退出,开始更新..." + +:: ========== 阶段1: 准备和解压 ========== +call :log "[阶段1] 准备临时目录..." +if exist "%TEMP_DIR%" rd /s /q "%TEMP_DIR%" 2>nul +mkdir "%TEMP_DIR%" +mkdir "%EXTRACT_DIR%" + +call :log "[阶段1] 解压更新包到临时目录..." +powershell -Command "try { Expand-Archive -Path '%ZIP_PATH%' -DestinationPath '%EXTRACT_DIR%' -Force -ErrorAction Stop; exit 0 } catch { Write-Host $_.Exception.Message; exit 1 }" +if errorlevel 1 ( + call :log "[错误] 解压失败!启动旧版本..." + goto :launch_old_version +) + +:: 查找解压后的目录(ZIP 内可能有一层目录) +set "SOURCE_DIR=" +for /d %%D in ("%EXTRACT_DIR%\\*") do set "SOURCE_DIR=%%D" +if not defined SOURCE_DIR set "SOURCE_DIR=%EXTRACT_DIR%" + +call :log "[阶段1] 解压完成,源目录: %SOURCE_DIR%" + +:: ========== 阶段2: 校验解压完整性 ========== +call :log "[阶段2] 校验更新包完整性..." + +:: 检查关键文件是否存在 +if not exist "%SOURCE_DIR%\\AI Learning Assistant Launcher.exe" ( + call :log "[错误] 校验失败:主程序文件不存在!启动旧版本..." + goto :launch_old_version +) + +if not exist "%SOURCE_DIR%\\resources" ( + call :log "[错误] 校验失败:resources 目录不存在!启动旧版本..." + goto :launch_old_version +) + +call :log "[阶段2] 校验通过,更新包完整" + +:: ========== 阶段3: 备份用户数据和旧版本 ========== +call :log "[阶段3] 备份用户数据 external-resources..." +if exist "%APP_DIR%\\external-resources" ( + xcopy "%APP_DIR%\\external-resources" "%BACKUP_DIR%\\" /E /I /H /Y /Q >nul 2>&1 + if errorlevel 1 ( + call :log "[警告] 用户数据备份可能不完整" + ) else ( + call :log "[阶段3] 用户数据备份完成" + ) +) + +call :log "[阶段3] 备份旧版本应用..." +mkdir "%APP_BACKUP_DIR%" 2>nul +xcopy "%APP_DIR%\\*" "%APP_BACKUP_DIR%\\" /E /I /H /Y /Q >nul 2>&1 +if errorlevel 1 ( + call :log "[警告] 旧版本备份可能不完整,但继续更新" +) else ( + call :log "[阶段3] 旧版本备份完成" +) + +:: ========== 阶段4: 替换文件 ========== +call :log "[阶段4] 清理旧版本文件(保留 external-resources)..." +for /d %%D in ("%APP_DIR%\\*") do ( + if /I not "%%~nxD"=="external-resources" ( + rd /s /q "%%D" 2>nul + ) +) +for %%F in ("%APP_DIR%\\*") do ( + del /f /q "%%F" 2>nul +) + +call :log "[阶段4] 安装新版本..." +xcopy "%SOURCE_DIR%\\*" "%APP_DIR%\\" /E /I /H /Y /Q >nul 2>&1 +if errorlevel 1 ( + call :log "[错误] 复制新文件失败!尝试从备份恢复..." + goto :restore_from_backup +) + +:: 验证安装结果 +if not exist "%APP_DIR%\\AI Learning Assistant Launcher.exe" ( + call :log "[错误] 安装验证失败:主程序不存在!尝试从备份恢复..." + goto :restore_from_backup +) + +call :log "[阶段4] 新版本安装完成" + +:: ========== 阶段5: 恢复用户数据 ========== +call :log "[阶段5] 恢复用户数据..." +if exist "%BACKUP_DIR%" ( + xcopy "%BACKUP_DIR%\\*" "%APP_DIR%\\external-resources\\" /E /I /H /Y /Q >nul 2>&1 + call :log "[阶段5] 用户数据恢复完成" +) + +:: ========== 阶段6: 清理和启动 ========== +call :log "[阶段6] 更新成功!清理临时文件..." +:: 延迟删除临时目录,避免影响日志 +start /b cmd /c "timeout /t 5 /nobreak >nul & rd /s /q "%TEMP_DIR%" 2>nul" + +call :log "[阶段6] 启动新版本..." +call :log "========== 更新脚本结束 ==========" +start "" "%APP_DIR%\\AI Learning Assistant Launcher.exe" +exit + +:: ========== 错误处理: 从备份恢复 ========== +:restore_from_backup +call :log "[恢复] 开始从备份恢复旧版本..." +if exist "%APP_BACKUP_DIR%\\AI Learning Assistant Launcher.exe" ( + :: 清理可能的残留 + for /d %%D in ("%APP_DIR%\\*") do rd /s /q "%%D" 2>nul + for %%F in ("%APP_DIR%\\*") do del /f /q "%%F" 2>nul + + :: 恢复备份 + xcopy "%APP_BACKUP_DIR%\\*" "%APP_DIR%\\" /E /I /H /Y /Q >nul 2>&1 + if exist "%APP_DIR%\\AI Learning Assistant Launcher.exe" ( + call :log "[恢复] 旧版本恢复成功" + goto :launch_old_version + ) +) +call :log "[恢复] 恢复失败,请手动重新安装应用" +pause +exit + +:: ========== 错误处理: 启动旧版本 ========== +:launch_old_version +call :log "[回退] 启动旧版本..." +if exist "%APP_DIR%\\AI Learning Assistant Launcher.exe" ( + start "" "%APP_DIR%\\AI Learning Assistant Launcher.exe" +) else ( + call :log "[错误] 旧版本也不存在,请手动重新安装" + pause +) +exit + +:: ========== 日志函数 ========== +:log +echo [%date% %time%] %~1 +echo [%date% %time%] %~1 >> "%UPDATE_LOG%" 2>nul +exit /b 0 +`; + + // 确保临时目录存在 + if (!existsSync(tempDir)) { + mkdirSync(tempDir, { recursive: true }); + } + + const scriptPath = path.join(tempDir, 'update.bat'); + await writeFile(scriptPath, scriptContent, { encoding: 'utf8' }); + + await writeUpdateLog('INFO', '[generateUpdateScript] 更新脚本已生成', { + scriptPath, + zipPath, + appDir, + tempDir, + newVersion, + }); + + return scriptPath; +} + +/** + * 等待文件句柄释放的重试配置 + */ +const FILE_RELEASE_CONFIG = { + MAX_RETRIES: 10, + INITIAL_DELAY_MS: 200, + MAX_DELAY_MS: 2000, +}; + +/** + * 检测文件是否可访问(句柄已释放) + * 通过尝试 rename 操作来验证文件是否被占用 + * @param filePath 文件路径 + * @returns 是否可访问 + */ +async function isFileAccessible(filePath: string): Promise { + try { + // 检查文件是否可读 + await access(filePath, constants.R_OK); + + // 尝试 rename 到自身(Windows 下被占用的文件无法 rename) + // 这是检测文件句柄是否释放的可靠方法 + const tempPath = filePath + '.tmp_check'; + await rename(filePath, tempPath); + await rename(tempPath, filePath); + + return true; + } catch { + return false; + } +} + +/** + * 等待文件句柄释放,使用指数退避重试机制 + * @param filePath 文件路径 + * @returns 文件是否可访问 + */ +async function waitForFileRelease(filePath: string): Promise { + let delay = FILE_RELEASE_CONFIG.INITIAL_DELAY_MS; + + for (let attempt = 1; attempt <= FILE_RELEASE_CONFIG.MAX_RETRIES; attempt++) { + const accessible = await isFileAccessible(filePath); + + if (accessible) { + await writeUpdateLog('DEBUG', '[waitForFileRelease] 文件句柄已释放', { + filePath, + attempt, + }); + return; + } + + await writeUpdateLog( + 'DEBUG', + '[waitForFileRelease] 文件仍被占用,等待重试', + { + filePath, + attempt, + nextDelayMs: delay, + }, + ); + + await new Promise((resolve) => setTimeout(resolve, delay)); + + // 指数退避,但不超过最大延迟 + delay = Math.min(delay * 2, FILE_RELEASE_CONFIG.MAX_DELAY_MS); + } + + throw new Error( + `文件句柄释放超时: ${filePath},已重试 ${FILE_RELEASE_CONFIG.MAX_RETRIES} 次`, + ); +} + +export async function installLauncherUpdate() { + await writeUpdateLog('INFO', '[installLauncherUpdate] 开始执行自定义更新'); + + // 如果是开发模式,不执行更新 + const isPackaged = app.isPackaged; + if (!isPackaged) { + await writeUpdateLog( + 'WARN', + '[installLauncherUpdate] 开发模式下不支持自动更新', + ); + return { + success: false, + message: '开发模式下不支持自动更新', + }; + } + + try { + // 获取最新版本信息 + await writeUpdateLog( + 'DEBUG', + '[installLauncherUpdate] 获取最新版本信息...', + ); + const latestVersionInfo = getLatestVersion( + 'AI_LEARNING_ASSISTANT_LAUNCHER', + ); + + // 空值检查:确保 dlcInfo 和 magnet 存在 + if (!latestVersionInfo.dlcInfo?.magnet) { + throw new Error('未找到有效的更新包信息(dlcInfo 或 magnet 缺失)'); + } + + const { magnet } = latestVersionInfo.dlcInfo; + const version = latestVersionInfo.version; + await writeUpdateLog('DEBUG', '[installLauncherUpdate] 最新版本:', version); + + // 下载目录 + const downloadPath = path.join( + appPath, + 'external-resources', + 'dlc', + 'AI_LEARNING_ASSISTANT_LAUNCHER', + version, + ); + await writeUpdateLog( + 'DEBUG', + '[installLauncherUpdate] 下载路径:', + downloadPath, + ); + + if (!existsSync(downloadPath)) { + await writeUpdateLog('ERROR', '[installLauncherUpdate] 下载目录不存在'); + throw new Error('更新包未下载,请先下载更新包'); + } + + // 查找 ZIP 文件 + const files = await readdir(downloadPath); + await writeUpdateLog( + 'DEBUG', + '[installLauncherUpdate] 下载目录文件列表:', + files, + ); + + const zipFile = files.find((f) => f.endsWith('.zip')); + if (!zipFile) { + await writeUpdateLog( + 'ERROR', + '[installLauncherUpdate] 未找到 .zip 更新包', + ); + throw new Error('未找到 .zip 更新包'); + } + + const zipPath = path.join(downloadPath, zipFile); + await writeUpdateLog( + 'DEBUG', + '[installLauncherUpdate] ZIP 文件路径:', + zipPath, + ); + + // 销毁 WebTorrent 以释放文件句柄 + await writeUpdateLog( + 'DEBUG', + '[installLauncherUpdate] 销毁 WebTorrent 释放文件句柄...', + ); + await destroyWebtorrentForInstall(magnet); + + // 使用重试机制等待文件句柄释放 + await waitForFileRelease(zipPath); + await writeUpdateLog('DEBUG', '[installLauncherUpdate] 文件句柄已释放'); + + // 获取应用目录和临时目录 + const exePath = app.getPath('exe'); + const appDir = path.dirname(exePath); + const tempDir = path.join(app.getPath('temp'), 'launcher-update'); + + await writeUpdateLog('DEBUG', '[installLauncherUpdate] 应用目录:', appDir); + await writeUpdateLog('DEBUG', '[installLauncherUpdate] 临时目录:', tempDir); + + // 显示更新确认对话框 + const result = await dialog.showMessageBox({ + type: 'info', + title: '准备更新', + message: '启动器将在关闭后自动更新', + detail: `当前版本: ${currentVersion}\n新版本: ${version}\n\n点击"确定"后程序将关闭并自动更新,更新完成后会自动重启。`, + buttons: ['确定', '取消'], + defaultId: 0, + cancelId: 1, + }); + + if (result.response !== 0) { + await writeUpdateLog('INFO', '[installLauncherUpdate] 用户取消更新'); + return { + success: false, + message: '用户取消更新', + }; + } + + await writeUpdateLog( + 'INFO', + '[installLauncherUpdate] 用户确认更新,准备执行自定义更新', + ); + + // 生成更新脚本 + const scriptPath = await generateUpdateScript( + zipPath, + appDir, + tempDir, + version, + ); + + await writeUpdateLog( + 'INFO', + '[installLauncherUpdate] 启动更新脚本:', + scriptPath, + ); + + // 启动更新脚本 + const updateProcess = spawn('cmd.exe', ['/c', scriptPath], { + detached: true, + stdio: 'ignore', + windowsHide: true, + }); + updateProcess.unref(); + + await writeUpdateLog( + 'INFO', + '[installLauncherUpdate] 更新脚本已启动,准备退出应用', + ); + + // 延迟退出应用 + setTimeout(() => { + app.quit(); + }, 1000); + + return { + success: true, + message: '正在更新启动器...', + }; + } catch (error) { + await writeUpdateLog( + 'ERROR', + '[installLauncherUpdate] 自定义更新失败', + error instanceof Error + ? { message: error.message, stack: error.stack } + : error, + ); + throw error; + } +} diff --git a/src/main/launcher-update/type-info.ts b/src/main/launcher-update/type-info.ts new file mode 100644 index 0000000..d43ca0e --- /dev/null +++ b/src/main/launcher-update/type-info.ts @@ -0,0 +1,9 @@ +import type { Channels } from '../ipc-data-type'; + +export const channel: Channels = 'launcher-update'; + +export const checkLauncherUpdateHandle = `${channel}checkUpdate`; + +export const downloadLauncherUpdateHandle = `${channel}downloadUpdate`; + +export const installLauncherUpdateHandle = `${channel}installUpdate`; diff --git a/src/main/preload.ts b/src/main/preload.ts index 7dc73b2..75cbaa9 100644 --- a/src/main/preload.ts +++ b/src/main/preload.ts @@ -21,6 +21,12 @@ import { startTrainingServiceHandle, courseHaveNewVersionTrainingServiceHandle, } from './training-service/type-info'; +import { + selectFolderHandle, + getDiskInfoHandle, + setTrayEnabledHandle, + DiskInfo, +} from './joint-build/type-info'; import { DLCIndex, logsWebtorrentHandle, @@ -29,7 +35,15 @@ import { removeWebtorrentHandle, startWebtorrentHandle, DLCId, + setUploadEnabledHandle, + getUploadEnabledHandle, + getUploadStatsHandle, } from './dlc/type-info'; +import { + checkLauncherUpdateHandle, + downloadLauncherUpdateHandle, + installLauncherUpdateHandle, +} from './launcher-update/type-info'; const electronHandler = { ipcRenderer: { @@ -129,8 +143,31 @@ const mainHandle = { logsTrainingServiceHandle, ); }, + // 共建计划相关 + selectJointBuildFolder: async (): Promise => { + return ipcInvoke(selectFolderHandle); + }, + getJointBuildDiskInfo: async (diskPath: string): Promise => { + return ipcInvoke(getDiskInfoHandle, diskPath); + }, + setTrayEnabled: async (enabled: boolean): Promise => { + return ipcInvoke(setTrayEnabledHandle, enabled); + }, + // 托盘菜单事件监听 + onNavigateTo: (callback: (route: string) => void) => { + const handler = (_event: IpcRendererEvent, route: string) => callback(route); + ipcRenderer.on('navigate-to', handler); + return () => ipcRenderer.removeListener('navigate-to', handler); + }, + onJointBuildStatusChanged: (callback: (enabled: boolean) => void) => { + const handler = (_event: IpcRendererEvent, enabled: boolean) => callback(enabled); + ipcRenderer.on('joint-build-status-changed', handler); + return () => ipcRenderer.removeListener('joint-build-status-changed', handler); + }, startWebtorrentHandle: async (url: string) => { - return ipcInvoke(startWebtorrentHandle, url); + return ipcInvoke< + { success: true; infoHash: string } | { success: false; error: string } + >(startWebtorrentHandle, url); }, queryWebtorrentHandle: async () => { return ipcInvoke(queryWebtorrentHandle); @@ -144,6 +181,44 @@ const mainHandle = { logsWebtorrentHandle: async (url: string) => { return ipcInvoke(logsWebtorrentHandle, url); }, + checkLauncherUpdateHandle: async () => { + return ipcInvoke<{ + currentVersion: string; + latestVersion: string; + haveNew: boolean; + }>(checkLauncherUpdateHandle); + }, + downloadLauncherUpdateHandle: async () => { + return ipcInvoke<{ + success: boolean; + version: string; + filePath: string; + isDev: boolean; + }>(downloadLauncherUpdateHandle); + }, + installLauncherUpdateHandle: async () => { + return ipcInvoke<{ + success: boolean; + message: string; + }>(installLauncherUpdateHandle); + }, + setUploadEnabledHandle: async (enabled: boolean) => { + return ipcInvoke<{ success: boolean; enabled: boolean }>( + setUploadEnabledHandle, + enabled, + ); + }, + getUploadEnabledHandle: async () => { + return ipcInvoke<{ enabled: boolean }>(getUploadEnabledHandle); + }, + getUploadStatsHandle: async () => { + return ipcInvoke<{ + enabled: boolean; + totalUploaded: number; + uploadSpeed: number; + activeTorrents: number; + }>(getUploadStatsHandle); + }, }; export type MainHandle = typeof mainHandle; diff --git a/src/main/training-service/index.ts b/src/main/training-service/index.ts index 562e30c..8f7aace 100644 --- a/src/main/training-service/index.ts +++ b/src/main/training-service/index.ts @@ -79,8 +79,8 @@ const createWindow = (): void => { export async function installTrainingService() { const latestVersion = getLatestVersion('TRAINING_TAR'); - const torrent = await startWebtorrent(latestVersion.dlcInfo.magnet); - await waitTorrentDone('TRAINING_TAR', latestVersion.version); + await startWebtorrent(latestVersion.dlcInfo.magnet); + const torrent = await waitTorrentDone('TRAINING_TAR', latestVersion.version); const tarPath = path.join(torrent.path, torrent.files[0].name); return installService('TRAINING', null, tarPath); } @@ -117,8 +117,11 @@ export async function updateCourseTrainingService() { } if ((await courseHaveNewVersionTrainingService()).haveNew) { const latestVersion = getLatestVersion('TRAINING_TAR'); - const torrent = await startWebtorrent(latestVersion.dlcInfo.magnet); - await waitTorrentDone('TRAINING_TAR', latestVersion.version); + await startWebtorrent(latestVersion.dlcInfo.magnet); + const torrent = await waitTorrentDone( + 'TRAINING_TAR', + latestVersion.version, + ); try { await stopService('TRAINING'); await removeService('TRAINING'); diff --git a/src/main/webtorrent-config.ts b/src/main/webtorrent-config.ts new file mode 100644 index 0000000..473deda --- /dev/null +++ b/src/main/webtorrent-config.ts @@ -0,0 +1,32 @@ +/** + * WebTorrent 相关的统一配置(单位:毫秒,除非另有说明) + */ +export const WEBTORRENT_CONFIG = { + // ============ 种子销毁与安装相关 ============ + /** 销毁种子后等待文件句柄释放的时间 */ + TORRENT_DESTROY_WAIT: 2000, + /** 销毁种子回调的超时时间 */ + TORRENT_DESTROY_CALLBACK_TIMEOUT: 3000, + + // ============ 重试机制相关 ============ + /** 重试的基础等待时间 */ + RETRY_BASE_WAIT: 1000, + /** 每次重试增加的等待时间 */ + RETRY_INCREMENT: 1000, + /** 所有重试失败后的最终等待时间 */ + FINAL_RETRY_WAIT: 10000, + /** 最大重试次数 */ + MAX_RETRIES: 8, + + // ============ 种子下载轮询相关 ============ + /** 检查种子完成状态的轮询间隔 */ + DOWNLOAD_CHECK_INTERVAL: 1000, + /** 最大轮询次数(3600 = 1小时) */ + DOWNLOAD_MAX_ATTEMPTS: 3600, + /** 输出进度信息的间隔次数(每 N 次输出一次) */ + DOWNLOAD_PROGRESS_LOG_INTERVAL: 10, + + // ============ 其他超时配置 ============ + /** LM Studio 安装检测命令超时时间 */ + LM_STUDIO_CHECK_TIMEOUT: 15000, +} as const; diff --git a/src/renderer/app.tsx b/src/renderer/app.tsx index 98a572e..78bb014 100644 --- a/src/renderer/app.tsx +++ b/src/renderer/app.tsx @@ -1,4 +1,4 @@ -import { MemoryRouter as Router, Routes, Route } from 'react-router-dom'; +import { MemoryRouter as Router, Routes, Route, useNavigate } from 'react-router-dom'; import '@ant-design/v5-patch-for-react-19'; import Hello from './pages/hello'; import './app.css'; @@ -15,13 +15,46 @@ import PdfConvert from './pages/pdf-convert'; import PdfConfig from './pages/pdf-config'; import LLMConfig from './pages/llm-api-config'; import VoiceRTCConfig from './pages/voice-rtc-config'; +import WelcomeModal from './pages/welcome/WelcomeModal'; +import JointBuild from './pages/joint-build'; +import { useEffect } from 'react'; + +// 托盘菜单导航监听组件 +function TrayNavigationHandler() { + const navigate = useNavigate(); + + useEffect(() => { + // 监听托盘菜单的导航事件 + const unsubscribeNavigate = window.mainHandle.onNavigateTo((route: string) => { + navigate(route); + }); + + // 监听共建计划状态变化事件 + const unsubscribeStatus = window.mainHandle.onJointBuildStatusChanged((enabled: boolean) => { + // 更新 localStorage + localStorage.setItem('joint_build_master_switch', String(enabled)); + // 触发页面刷新或状态更新 + window.dispatchEvent(new CustomEvent('joint-build-status-changed', { detail: enabled })); + }); + + return () => { + unsubscribeNavigate(); + unsubscribeStatus(); + }; + }, [navigate]); + + return null; +} import P2PTest from './pages/p2p-test'; export default function App() { return ( + + + } /> } /> } /> } /> diff --git a/src/renderer/containers/use-cmd/index.tsx b/src/renderer/containers/use-cmd/index.tsx index 433cc44..f205415 100644 --- a/src/renderer/containers/use-cmd/index.tsx +++ b/src/renderer/containers/use-cmd/index.tsx @@ -8,7 +8,7 @@ export default function useCmd() { const [wslVersion, setWSLVersion] = useState(''); const [checkingWsl, setCheckingWsl] = useState(true); const [isInstallObsidian, setIsInstallObsidian] = useState(true); - const [isInstallLMStudio, setIsInstallLMStudio] = useState(true); + const [isInstallLMStudio, setIsInstallLMStudio] = useState(false); const [loading, setLoading] = useState(false); function action( actionName: ActionName, diff --git a/src/renderer/pages/hello/index.scss b/src/renderer/pages/hello/index.scss index e3bc9f6..1495124 100644 --- a/src/renderer/pages/hello/index.scss +++ b/src/renderer/pages/hello/index.scss @@ -596,11 +596,27 @@ body{ padding: 8px 0; gap: 10px; width: auto; - max-width: 300px; + max-width: 400px; min-height: 53px; flex: none; order: 1; + .launcher-update-wrapper { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 4px 8px; + background: linear-gradient(135deg, rgba(22, 119, 255, 0.1) 0%, rgba(22, 119, 255, 0.05) 100%); + border-radius: 8px; + box-shadow: 0 2px 6px rgba(22, 119, 255, 0.15); + + .ant-progress { + .ant-progress-inner { + background-color: rgba(22, 119, 255, 0.15); + } + } + } + .status-indicator { box-sizing: border-box; display: flex; @@ -621,6 +637,24 @@ body{ transform: translateY(-2px); } + // 更新按钮使用蓝色 + &.update-button { + background: #1677ff; + + &:hover { + background: #4096ff; + } + + &.download-complete { + background: linear-gradient(135deg, #52c41a 0%, #73d13d 100%); + animation: pulse-green 2s infinite; + + &:hover { + background: linear-gradient(135deg, #73d13d 0%, #95de64 100%); + } + } + } + .log-text { display: flex; flex-direction: row; @@ -667,6 +701,44 @@ body{ transform: translateY(-2px); } } + + .joint-build-link { + text-decoration: none; + } + + .joint-build-button { + box-sizing: border-box; + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + padding: 2px 8px; + gap: 4px; + width: auto; + min-width: 90px; + min-height: 22px; + background: #52c41a; + border: 1px solid #52c41a; + border-radius: 6px; + color: #fff; + font-family: 'Inter', sans-serif; + font-style: normal; + font-weight: 500; + font-size: clamp(10px, 2vw, 12px); + line-height: 16px; + cursor: pointer; + + .joint-build-icon { + width: 16px; + height: 16px; + } + + &:hover { + background: #73d13d; + border-color: #73d13d; + transform: translateY(-2px); + } + } .dev-example-link-inline { text-decoration: none; @@ -1109,6 +1181,18 @@ body{ } } +@keyframes pulse-green { + 0% { + box-shadow: 0 0 0 0 rgba(82, 196, 26, 0.4); + } + 70% { + box-shadow: 0 0 0 8px rgba(82, 196, 26, 0); + } + 100% { + box-shadow: 0 0 0 0 rgba(82, 196, 26, 0); + } +} + @media screen and (max-width: 1200px) { .hello-root .hello-container .hello-content .features-section .features-container { flex-wrap: wrap; diff --git a/src/renderer/pages/hello/index.tsx b/src/renderer/pages/hello/index.tsx index 1497ae8..c593bc9 100644 --- a/src/renderer/pages/hello/index.tsx +++ b/src/renderer/pages/hello/index.tsx @@ -1,4 +1,12 @@ -import { Button, message, Space, Modal, notification, Popconfirm } from 'antd'; +import { + Button, + message, + Space, + Modal, + notification, + Popconfirm, + Progress, +} from 'antd'; import { NavLink } from 'react-router-dom'; import { useEffect, useState, useRef } from 'react'; // 添加 useRef 导入 import obsidianLogo from './2023_Obsidian_logo.png'; @@ -12,6 +20,7 @@ import wslLogo from './wslLogo.png'; // 新增导入Frame 3和Frame 8图片 import frame3 from './Frame 3.png'; import frame8 from './Frame 8.png'; +import jointBuildIcon from '../../../../icons/joint_build.png'; import './index.scss'; import { LeftOutlined, RightOutlined } from '@ant-design/icons'; import { useTrainingServiceShortcut } from '../../containers/use-training-service-shortcut'; @@ -49,6 +58,29 @@ export default function Hello() { }; }, [setupBackupListener]); + // 初始化托盘状态(根据共建开关) + useEffect(() => { + const initTrayStatus = async () => { + const masterSwitch = localStorage.getItem('joint_build_master_switch'); + const welcomeChoice = localStorage.getItem('ai_learning_assistant_welcome_shown'); + + let trayEnabled = false; + if (masterSwitch !== null) { + trayEnabled = masterSwitch === 'true'; + } else if (welcomeChoice === 'true') { + trayEnabled = true; + } + + try { + await window.mainHandle.setTrayEnabled(trayEnabled); + } catch (error) { + console.error('初始化托盘状态失败:', error); + } + }; + + initTrayStatus(); + }, []); + const [currentSlide, setCurrentSlide] = useState(0); const slides = [ @@ -152,6 +184,7 @@ export default function Hello() { useEffect(() => { startAutoSlide(); + checkLauncherUpdate(); return () => { clearSlideInterval(); @@ -189,6 +222,50 @@ export default function Hello() { }; const [trainingServiceRemoving, setTrainingServiceRemoving] = useState(false); + const [launcherUpdateInfo, setLauncherUpdateInfo] = useState<{ + currentVersion: string; + latestVersion: string; + haveNew: boolean; + } | null>(null); + const [launcherUpdating, setLauncherUpdating] = useState(false); + const [launcherDownloadProgress, setLauncherDownloadProgress] = useState(0); + const [launcherDownloadComplete, setLauncherDownloadComplete] = + useState(false); + const [launcherMagnet, setLauncherMagnet] = useState(null); + + // 轮询下载进度 + useEffect(() => { + if (!launcherUpdating || !launcherUpdateInfo?.haveNew) return; + + let mounted = true; + const fetchProgress = async () => { + try { + const dlcIndex = await window.mainHandle.queryWebtorrentHandle(); + const dlc = dlcIndex.find( + (item) => item.id === 'AI_LEARNING_ASSISTANT_LAUNCHER', + ); + if (!dlc || !mounted) return; + + const versionInfo = dlc.versions[launcherUpdateInfo.latestVersion]; + if (versionInfo?.progress) { + const progress = (versionInfo.progress.progress || 0) * 100; + if (mounted) { + setLauncherDownloadProgress(progress); + } + } + } catch (error) { + console.error('获取下载进度失败:', error); + } + }; + + fetchProgress(); + const intervalId = setInterval(fetchProgress, 1000); + + return () => { + mounted = false; + clearInterval(intervalId); + }; + }, [launcherUpdating, launcherUpdateInfo]); const removeTrainingService = async () => { setTrainingServiceRemoving(true); @@ -205,6 +282,124 @@ export default function Hello() { setTrainingServiceRemoving(false); }; + const checkLauncherUpdate = async () => { + try { + const info = await window.mainHandle.checkLauncherUpdateHandle(); + setLauncherUpdateInfo(info); + + // 检查是否已有下载完成的更新包,或正在下载中(用于恢复后台下载状态) + if (info?.haveNew) { + const dlcIndex = await window.mainHandle.queryWebtorrentHandle(); + const dlc = dlcIndex.find( + (item) => item.id === 'AI_LEARNING_ASSISTANT_LAUNCHER', + ); + if (dlc) { + const versionInfo = dlc.versions[info.latestVersion]; + if (versionInfo?.progress) { + const progress = versionInfo.progress.progress || 0; + if (progress >= 1) { + // 下载已完成 + setLauncherDownloadComplete(true); + setLauncherDownloadProgress(100); + setLauncherUpdating(false); + } else if (progress > 0) { + // 正在下载中,恢复下载状态 + setLauncherUpdating(true); + setLauncherDownloadProgress(progress * 100); + setLauncherMagnet(versionInfo.magnet); + setLauncherDownloadComplete(false); + } + } + } + } + } catch (error) { + console.error('检查启动器更新失败:', error); + } + }; + + const handleLauncherUpdate = async () => { + if (!launcherUpdateInfo || !launcherUpdateInfo.haveNew) { + message.info('已是最新版本'); + return; + } + + // 如果下载已完成,直接执行安装 + if (launcherDownloadComplete) { + setLauncherUpdating(true); + try { + const result = await window.mainHandle.installLauncherUpdateHandle(); + if (result.success) { + message.success(result.message); + } else { + message.warning(result.message); + } + } catch (error) { + console.error('安装启动器更新失败:', error); + message.error('安装失败:' + error.message); + } finally { + setLauncherUpdating(false); + } + return; + } + + setLauncherUpdating(true); + setLauncherDownloadProgress(0); + setLauncherDownloadComplete(false); + + try { + // 获取 DLC 信息并保存 magnet + const dlcIndex = await window.mainHandle.queryWebtorrentHandle(); + const dlc = dlcIndex.find( + (item) => item.id === 'AI_LEARNING_ASSISTANT_LAUNCHER', + ); + if (dlc && launcherUpdateInfo) { + const versionInfo = dlc.versions[launcherUpdateInfo.latestVersion]; + if (versionInfo?.magnet) { + setLauncherMagnet(versionInfo.magnet); + } + } + + const downloadResult = + await window.mainHandle.downloadLauncherUpdateHandle(); + + // 开发模式下不执行安装,直接提示 + if (downloadResult.isDev) { + message.warning('开发模式下不支持自动更新,请手动解压'); + setLauncherUpdating(false); + return; + } + + setLauncherDownloadProgress(100); + setLauncherDownloadComplete(true); + setLauncherUpdating(false); + setLauncherMagnet(null); + message.success('下载完成,点击按钮重启并更新'); + } catch (error) { + console.error('更新启动器失败:', error); + message.error('更新失败:' + error.message); + setLauncherUpdating(false); + setLauncherDownloadProgress(0); + setLauncherMagnet(null); + } + }; + + const handleCancelLauncherUpdate = async () => { + if (!launcherMagnet) { + message.warning('没有正在进行的下载'); + return; + } + try { + await window.mainHandle.pauseWebtorrentHandle(launcherMagnet); + setLauncherUpdating(false); + setLauncherDownloadProgress(0); + setLauncherMagnet(null); + message.info('已取消下载'); + } catch (error) { + console.error('取消下载失败:', error); + message.error('取消下载失败'); + } + }; + const wslStatusText = () => { if (!vTReady) { return '请在BIOS开启虚拟化'; @@ -623,9 +818,51 @@ export default function Hello() { 版本号:{__NPM_PACKAGE_VERSION__} 源码版本:{__COMMIT_HASH__}
- - + + + {/* + + */} + {launcherUpdateInfo?.haveNew && ( +
+ {launcherUpdating && !launcherDownloadComplete && ( + + )} + {launcherUpdating && !launcherDownloadComplete ? ( + + ) : ( + + )} +
+ )} +
+ + + +
+

共建参与模块设置

+

管理参与哪些模块的共建计划,请根据您电脑的磁盘空余选择开启

+
+ {modules.map((mod) => ( +
+
+
+ {mod.name} + + 推荐指数 {renderRecommendLevel(mod.recommendLevel)} + +
+ 磁盘占用 {mod.diskUsage} +
+ handleModuleToggle(mod.id, checked)} + disabled={!masterSwitch} + /> +
+ ))} +
+
+ + ); +} diff --git a/src/renderer/pages/lm-service/index.scss b/src/renderer/pages/lm-service/index.scss index f380793..c900132 100644 --- a/src/renderer/pages/lm-service/index.scss +++ b/src/renderer/pages/lm-service/index.scss @@ -15,10 +15,59 @@ display: flex; justify-content: space-between; } + + .download-wrapper { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 4px 8px; + background: linear-gradient(135deg, rgba(22, 119, 255, 0.1) 0%, rgba(22, 119, 255, 0.05) 100%); + border-radius: 8px; + box-shadow: 0 2px 6px rgba(22, 119, 255, 0.15); + transition: all 0.3s ease; + + .ant-progress { + .ant-progress-inner { + background-color: rgba(22, 119, 255, 0.15); + } + } + + &.downloading { + border-color: #1677ff; + background: linear-gradient(135deg, rgba(22, 119, 255, 0.15) 0%, rgba(22, 119, 255, 0.08) 100%); + } + + &.download-complete { + background: linear-gradient(135deg, rgba(82, 196, 26, 0.15) 0%, rgba(82, 196, 26, 0.08) 100%); + box-shadow: 0 2px 6px rgba(82, 196, 26, 0.2); + + .download-complete-btn { + background: linear-gradient(135deg, #52c41a 0%, #73d13d 100%); + border-color: #52c41a; + animation: pulse-green 2s infinite; + + &:hover { + background: linear-gradient(135deg, #73d13d 0%, #95de64 100%); + } + } + } + } } .lm-studio-demo{ width: 575px; height: 312px; background-size: contain; -} \ No newline at end of file +} + +@keyframes pulse-green { + 0% { + box-shadow: 0 0 0 0 rgba(82, 196, 26, 0.4); + } + 70% { + box-shadow: 0 0 0 8px rgba(82, 196, 26, 0); + } + 100% { + box-shadow: 0 0 0 0 rgba(82, 196, 26, 0); + } +} diff --git a/src/renderer/pages/lm-service/index.tsx b/src/renderer/pages/lm-service/index.tsx index 57582bc..6424f33 100644 --- a/src/renderer/pages/lm-service/index.tsx +++ b/src/renderer/pages/lm-service/index.tsx @@ -1,7 +1,15 @@ -import { Button, List, notification, Popconfirm, Typography } from 'antd'; +import { + Button, + List, + message, + notification, + Popconfirm, + Progress, + Typography, +} from 'antd'; import { Link } from 'react-router-dom'; import './index.scss'; -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import { ActionName, LMModel, @@ -61,6 +69,150 @@ export default function LMService() { serviceName: 'WSL', actionName: 'install', }); + + // LM Studio P2P 下载状态 + const [downloading, setDownloading] = useState(false); + const [downloadProgress, setDownloadProgress] = useState(0); + const [isDownloadComplete, setIsDownloadComplete] = useState(false); + const [latestVersion, setLatestVersion] = useState(null); + const [lmStudioMagnet, setLmStudioMagnet] = useState(null); + + useEffect(() => { + checkLMStudioUpdate(); + }, []); + + useEffect(() => { + const intervalId = setInterval(() => { + if (downloading && !isDownloadComplete) { + updateDownloadProgress(); + } + }, 2000); + + return () => clearInterval(intervalId); + }, [downloading, isDownloadComplete]); + + const checkLMStudioUpdate = async () => { + // 检查是否已经有下载完成的文件,或正在下载中(用于恢复后台下载状态) + try { + const dlcIndex = await window.mainHandle.queryWebtorrentHandle(); + const lmStudioDLC = dlcIndex.find( + (item) => item.id === 'LM_STUDIO_SETUP_EXE', + ); + if (lmStudioDLC) { + const version = Object.keys(lmStudioDLC.versions).sort().pop(); + if (version) { + setLatestVersion(version); + const versionInfo = lmStudioDLC.versions[version]; + if (versionInfo.progress) { + const progress = versionInfo.progress.progress || 0; + if (progress >= 1) { + // 下载已完成 + setIsDownloadComplete(true); + setDownloadProgress(100); + setDownloading(false); + } else if (progress > 0) { + // 正在下载中,恢复下载状态 + setDownloading(true); + setDownloadProgress(Math.floor(progress * 100)); + setLmStudioMagnet(versionInfo.magnet); + setIsDownloadComplete(false); + } + } + } + } + } catch (error) { + console.error('检查LM Studio下载状态失败:', error); + } + }; + + const updateDownloadProgress = async () => { + try { + const dlcIndex = await window.mainHandle.queryWebtorrentHandle(); + const lmStudioDLC = dlcIndex.find( + (item) => item.id === 'LM_STUDIO_SETUP_EXE', + ); + if (lmStudioDLC) { + const version = Object.keys(lmStudioDLC.versions).sort().pop(); + if (version) { + const versionInfo = lmStudioDLC.versions[version]; + if (versionInfo.progress) { + const progress = versionInfo.progress.progress || 0; + setDownloadProgress(Math.floor(progress * 100)); + if (progress >= 1) { + setDownloading(false); + setIsDownloadComplete(true); + message.success('LM Studio下载完成,可以点击安装按钮进行安装'); + } + } + } + } + } catch (error) { + console.error('获取LM Studio下载进度失败:', error); + } + }; + + const handleDownloadOrInstallLMStudio = async () => { + // 如果已经下载完成,直接安装 + if (isDownloadComplete) { + clickCmd('install', 'lm-studio'); + return; + } + + // 否则开始下载 + try { + setDownloading(true); + setDownloadProgress(0); + message.info('正在启动下载LM Studio...'); + + const dlcIndex = await window.mainHandle.queryWebtorrentHandle(); + const lmStudioDLC = dlcIndex.find( + (item) => item.id === 'LM_STUDIO_SETUP_EXE', + ); + + if (!lmStudioDLC) { + throw new Error('未找到LM Studio安装包信息'); + } + + const version = Object.keys(lmStudioDLC.versions).sort().pop(); + if (!version) { + throw new Error('未找到可用版本'); + } + + setLatestVersion(version); + const versionInfo = lmStudioDLC.versions[version]; + const magnet = versionInfo.magnet; + setLmStudioMagnet(magnet); + + const result = await window.mainHandle.startWebtorrentHandle(magnet); + if (result.success) { + message.success(`开始下载LM Studio ${version}`); + } else { + throw new Error('error' in result ? result.error : '启动下载失败'); + } + } catch (error) { + console.error('下载LM Studio失败:', error); + message.error('下载失败:' + (error as Error).message); + setDownloading(false); + setLmStudioMagnet(null); + } + }; + + const handleCancelLMStudioDownload = async () => { + if (!lmStudioMagnet) { + message.warning('没有正在进行的下载'); + return; + } + try { + await window.mainHandle.pauseWebtorrentHandle(lmStudioMagnet); + setDownloading(false); + setDownloadProgress(0); + setLmStudioMagnet(null); + message.info('已取消下载'); + } catch (error) { + console.error('取消下载失败:', error); + message.error('取消下载失败'); + } + }; // const llmContainer = containers.filter( // (item) => item.Names.indexOf() >= 0, // )[0]; @@ -144,22 +296,59 @@ export default function LMService() {
- + {/* 更新/安装 LM Studio */} + {isInstallLMStudio ? ( + + ) : ( +
+ {downloading && !isDownloadComplete && ( + + )} + {downloading && !isDownloadComplete ? ( + + ) : ( + + )} +
+ )} } diff --git a/src/renderer/pages/obsidian-app/index.scss b/src/renderer/pages/obsidian-app/index.scss index 7af0edb..b2095b8 100644 --- a/src/renderer/pages/obsidian-app/index.scss +++ b/src/renderer/pages/obsidian-app/index.scss @@ -13,4 +13,53 @@ display: flex; justify-content: space-between; } + + .download-wrapper { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 4px 8px; + background: linear-gradient(135deg, rgba(22, 119, 255, 0.1) 0%, rgba(22, 119, 255, 0.05) 100%); + border-radius: 8px; + box-shadow: 0 2px 6px rgba(22, 119, 255, 0.15); + transition: all 0.3s ease; + + .ant-progress { + .ant-progress-inner { + background-color: rgba(22, 119, 255, 0.15); + } + } + + &.downloading { + border-color: #1677ff; + background: linear-gradient(135deg, rgba(22, 119, 255, 0.15) 0%, rgba(22, 119, 255, 0.08) 100%); + } + + &.download-complete { + background: linear-gradient(135deg, rgba(82, 196, 26, 0.15) 0%, rgba(82, 196, 26, 0.08) 100%); + box-shadow: 0 2px 6px rgba(82, 196, 26, 0.2); + + .download-complete-btn { + background: linear-gradient(135deg, #52c41a 0%, #73d13d 100%); + border-color: #52c41a; + animation: pulse-green 2s infinite; + + &:hover { + background: linear-gradient(135deg, #73d13d 0%, #95de64 100%); + } + } + } + } +} + +@keyframes pulse-green { + 0% { + box-shadow: 0 0 0 0 rgba(82, 196, 26, 0.4); + } + 70% { + box-shadow: 0 0 0 8px rgba(82, 196, 26, 0); + } + 100% { + box-shadow: 0 0 0 0 rgba(82, 196, 26, 0); + } } diff --git a/src/renderer/pages/obsidian-app/index.tsx b/src/renderer/pages/obsidian-app/index.tsx index ead9183..c3e8a4a 100644 --- a/src/renderer/pages/obsidian-app/index.tsx +++ b/src/renderer/pages/obsidian-app/index.tsx @@ -1,5 +1,5 @@ -import { useCallback } from 'react'; -import { Button, List, Skeleton } from 'antd'; +import { useCallback, useEffect, useState } from 'react'; +import { Button, List, Skeleton, message, Progress } from 'antd'; import { Link, NavLink } from 'react-router-dom'; import './index.scss'; import { channel } from '../../../main/cmd/type-info'; @@ -19,6 +19,176 @@ export default function ObsidianApp() { loading: configsLoading, } = useConfigs(); + const [downloading, setDownloading] = useState(false); + const [downloadProgress, setDownloadProgress] = useState(0); + const [isDownloadComplete, setIsDownloadComplete] = useState(false); + const [currentMagnet, setCurrentMagnet] = useState(null); + + useEffect(() => { + checkObsidianUpdate(); + }, []); + + useEffect(() => { + const intervalId = setInterval(() => { + if (downloading && !isDownloadComplete) { + updateDownloadProgress(); + } + }, 2000); + + return () => clearInterval(intervalId); + }, [downloading, isDownloadComplete]); + + const checkObsidianUpdate = async () => { + // 检查是否已经有下载完成的文件,或正在下载中(用于恢复后台下载状态) + try { + const dlcIndex = await window.mainHandle.queryWebtorrentHandle(); + const obsidianDLC = dlcIndex.find( + (item) => item.id === 'OBSIDIAN_SETUP_EXE', + ); + if (obsidianDLC) { + const latestVersion = Object.keys(obsidianDLC.versions).sort().pop(); + if (latestVersion) { + const versionInfo = obsidianDLC.versions[latestVersion]; + if (versionInfo.progress) { + const progress = versionInfo.progress.progress || 0; + if (progress >= 1) { + // 下载已完成 + setIsDownloadComplete(true); + setDownloadProgress(100); + setDownloading(false); + } else if (progress > 0) { + // 正在下载中,恢复下载状态 + setDownloading(true); + setDownloadProgress(Math.floor(progress * 100)); + setCurrentMagnet(versionInfo.magnet); + setIsDownloadComplete(false); + } + } + } + } + } catch (error) { + console.error('检查下载状态失败:', error); + } + }; + + const updateDownloadProgress = async () => { + try { + const dlcIndex = await window.mainHandle.queryWebtorrentHandle(); + const obsidianDLC = dlcIndex.find( + (item) => item.id === 'OBSIDIAN_SETUP_EXE', + ); + if (obsidianDLC) { + const latestVersion = Object.keys(obsidianDLC.versions).sort().pop(); + if (latestVersion) { + const versionInfo = obsidianDLC.versions[latestVersion]; + if (versionInfo.progress) { + const progress = versionInfo.progress.progress || 0; + setDownloadProgress(Math.floor(progress * 100)); + if (progress >= 1) { + setDownloading(false); + setIsDownloadComplete(true); + message.success('下载完成,可以点击安装按钮进行安装'); + } + } + } + } + } catch (error) { + console.error('获取下载进度失败:', error); + } + }; + + const handleDownloadOrInstall = async () => { + // 如果已经下载完成,直接安装 + if (isDownloadComplete) { + handleInstallObsidian(); + return; + } + + // 否则开始下载 + try { + setDownloading(true); + setDownloadProgress(0); + message.info('正在启动下载...'); + + const dlcIndex = await window.mainHandle.queryWebtorrentHandle(); + const obsidianDLC = dlcIndex.find( + (item) => item.id === 'OBSIDIAN_SETUP_EXE', + ); + + if (!obsidianDLC) { + throw new Error('未找到Obsidian安装包信息'); + } + + const latestVersion = Object.keys(obsidianDLC.versions).sort().pop(); + if (!latestVersion) { + throw new Error('未找到可用版本'); + } + + const versionInfo = obsidianDLC.versions[latestVersion]; + const magnet = versionInfo.magnet; + setCurrentMagnet(magnet); + + const result = await window.mainHandle.startWebtorrentHandle(magnet); + if (result.success) { + message.success(`开始下载Obsidian ${latestVersion}`); + } else { + throw new Error('error' in result ? result.error : '启动下载失败'); + } + } catch (error) { + console.error('下载Obsidian失败:', error); + message.error('下载失败:' + error.message); + setDownloading(false); + setCurrentMagnet(null); + } + }; + + const handleCancelDownload = async () => { + if (!currentMagnet) { + message.warning('没有正在进行的下载'); + return; + } + try { + await window.mainHandle.pauseWebtorrentHandle(currentMagnet); + setDownloading(false); + setDownloadProgress(0); + setCurrentMagnet(null); + message.info('已取消下载'); + } catch (error) { + console.error('取消下载失败:', error); + message.error('取消下载失败'); + } + }; + + const handleInstallObsidian = async () => { + try { + const dlcIndex = await window.mainHandle.queryWebtorrentHandle(); + const obsidianDLC = dlcIndex.find( + (item) => item.id === 'OBSIDIAN_SETUP_EXE', + ); + + if (!obsidianDLC) { + throw new Error('未找到Obsidian安装包'); + } + + const latestVersion = Object.keys(obsidianDLC.versions).sort().pop(); + if (!latestVersion) { + throw new Error('未找到可用版本'); + } + + const versionInfo = obsidianDLC.versions[latestVersion]; + if (!versionInfo.progress || versionInfo.progress.progress < 1) { + message.warning('请先完成下载'); + return; + } + + message.info('正在打开安装程序...'); + cmdAction('install', 'obsidianApp'); + } catch (error) { + console.error('打开安装程序失败:', error); + message.error('失败:' + error.message); + } + }; + return (
cmdAction('install', 'obsidianApp')} +
- 安装阅读器 - + {downloading && !isDownloadComplete && ( + + )} + {downloading && !isDownloadComplete ? ( + + ) : ( + + )} +
), , isInstallObsidian && ( + ), + ].filter((item) => item)} + > + + + {/* 老版本兼容 - 直接安装 */} + {/* 老版本兼容 - 直接安装 */} + cmdAction('install', 'obsidianApp')} + > + 本地安装 ), ].filter((item) => item)} >
diff --git a/src/renderer/pages/welcome/WelcomeModal.css b/src/renderer/pages/welcome/WelcomeModal.css new file mode 100644 index 0000000..d4f1451 --- /dev/null +++ b/src/renderer/pages/welcome/WelcomeModal.css @@ -0,0 +1,75 @@ +.welcome-modal-content { + padding: 10px 0; + text-align: left; +} + +.welcome-modal-icon { + font-size: 32px; + margin-bottom: 16px; +} + +.welcome-modal-title { + font-size: 16px; + font-weight: 600; + color: #000; + margin: 0 0 12px 0; + line-height: 1.5; + display: flex; + align-items: center; + justify-content: flex-start; + gap: 8px; +} + +.welcome-title-icon { + width: 24px; + height: 24px; + vertical-align: middle; +} + +.welcome-modal-description { + font-size: 14px; + color: #666; + margin: 0 0 8px 0; + line-height: 1.6; +} + +.welcome-modal-note { + font-size: 13px; + color: #999; + margin: 0 0 24px 0; +} + +.welcome-modal-buttons { + display: flex; + gap: 12px; + justify-content: center; +} + +.welcome-modal-buttons button { + flex: 1; + max-width: 180px; + padding: 10px 20px; + border: none; + border-radius: 4px; + font-size: 14px; + cursor: pointer; + transition: all 0.3s; +} + +.btn-reject { + background: #f5f5f5; + color: #666; +} + +.btn-reject:hover { + background: #e8e8e8; +} + +.btn-accept { + background: #000; + color: #fff; +} + +.btn-accept:hover { + background: #333; +} diff --git a/src/renderer/pages/welcome/WelcomeModal.tsx b/src/renderer/pages/welcome/WelcomeModal.tsx new file mode 100644 index 0000000..f0a9f65 --- /dev/null +++ b/src/renderer/pages/welcome/WelcomeModal.tsx @@ -0,0 +1,59 @@ +import { Modal } from 'antd'; +import { useState, useEffect } from 'react'; +import './WelcomeModal.css'; +import jointBuildIcon from '../../../../icons/joint_build.png'; + +const STORAGE_KEY = 'ai_learning_assistant_welcome_shown'; + +export default function WelcomeModal() { + const [visible, setVisible] = useState(false); + + useEffect(() => { + // 检查是否已经显示过欢迎弹窗 + const hasShown = localStorage.getItem(STORAGE_KEY); + if (!hasShown) { + setVisible(true); + } + }, []); + + const handleAccept = () => { + localStorage.setItem(STORAGE_KEY, 'true'); + setVisible(false); + }; + + const handleReject = () => { + localStorage.setItem(STORAGE_KEY, 'false'); + setVisible(false); + }; + + return ( + +
+

+ 共建 加入"AI学习助手-共建计划",为知识共享添把柴 +

+

+ 通过闲时分享少量带宽,不仅能加速您的下载,也能帮助其他学习者更快获取大模型与课程资源。 +

+
+ (推荐开启,后续随时可关闭) +
+
+ + +
+
+
+ ); +}