From ec35ddabda85a27043e2ae16e0e01c263964b9f6 Mon Sep 17 00:00:00 2001 From: ZTCS Date: Wed, 30 Sep 2026 14:45:57 +0200 Subject: [PATCH 01/33] update Tauri to 2.12, raise Rust to 1.90, argon2 0.6, Vitest 5 and npm minors --- .github/workflows/ci.yml | 6 +- .github/workflows/release.yml | 8 +- README.md | 4 +- package-lock.json | 711 ++++++++---------- package.json | 36 +- src-tauri/Cargo.lock | 1292 ++++++++++++++++----------------- src-tauri/Cargo.toml | 7 +- src-tauri/src/security.rs | 32 +- vitest.config.ts | 2 +- 9 files changed, 955 insertions(+), 1143 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 77b294f..9c262ef 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,7 +66,7 @@ jobs: # Pinned to the same toolchain as release.yml so a surprise rustc # release can't make CI and the release build disagree. Bump both # together. - - uses: dtolnay/rust-toolchain@1.88.0 + - uses: dtolnay/rust-toolchain@1.90.0 - uses: Swatinem/rust-cache@v2 with: @@ -91,7 +91,7 @@ jobs: steps: - uses: actions/checkout@v7 - - uses: dtolnay/rust-toolchain@1.88.0 + - uses: dtolnay/rust-toolchain@1.90.0 - uses: Swatinem/rust-cache@v2 with: @@ -120,7 +120,7 @@ jobs: steps: - uses: actions/checkout@v7 - - uses: dtolnay/rust-toolchain@1.88.0 + - uses: dtolnay/rust-toolchain@1.90.0 - uses: Swatinem/rust-cache@v2 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5945e49..cb21452 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -185,10 +185,10 @@ jobs: # opaque failure that costs hours to diagnose. Bump this manually # when intentionally adopting a new toolchain. # - # 1.88.0 is the floor imposed by current transitive deps: `toml 0.9` / - # `serde_spanned 1.1` need edition2024 (1.85+), `icu_*` need 1.86+, - # and `darling`, `image`, `serde_with`, `time` need 1.88+. - - uses: dtolnay/rust-toolchain@1.88.0 + # 1.90.0 is the floor imposed by current deps: `tauri` 2.12 and its + # plugins, `muda` and `tray-icon` need 1.90+; before them `darling`, + # `image`, `serde_with`, `time` set it at 1.88. + - uses: dtolnay/rust-toolchain@1.90.0 - uses: Swatinem/rust-cache@v2 with: diff --git a/README.md b/README.md index 99971e1..06b554e 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Run local LLMs with [Ollama](https://ollama.com) or connect any OpenAI-compatibl ![Tauri 2](https://img.shields.io/badge/Tauri-2-FFC131?logo=tauri&logoColor=white) ![React 19](https://img.shields.io/badge/React-19-61DAFB?logo=react&logoColor=white) -![Rust 1.88+](https://img.shields.io/badge/Rust-1.88+-000000?logo=rust&logoColor=white) +![Rust 1.90+](https://img.shields.io/badge/Rust-1.90+-000000?logo=rust&logoColor=white) ![Vite](https://img.shields.io/badge/Vite-8-646CFF?logo=vite&logoColor=white) ![Tailwind CSS](https://img.shields.io/badge/Tailwind-3-38BDF8?logo=tailwindcss&logoColor=white) ![Ollama](https://img.shields.io/badge/Ollama-compatible-000000?logo=ollama&logoColor=white) @@ -137,7 +137,7 @@ Auto-updates are delivered through Loach's own signed updater (independent of Ap #### Prerequisites - **Node.js 20.19+** (or 22.12+) and **npm** — Vite 8 won't run on older 20.x point releases. -- **Rust 1.88+** via [`rustup`](https://rustup.rs) — the dependency tree's minimum; CI builds on 1.88.0 +- **Rust 1.90+** via [`rustup`](https://rustup.rs) — the dependency tree's minimum; CI builds on 1.90.0 - Platform build tooling — install once via the official Tauri prerequisites guide: - **Windows**: Microsoft Visual Studio Build Tools, WebView2 runtime (preinstalled on Windows 11) - **Linux**: `libwebkit2gtk-4.1-dev`, `libappindicator3-dev` (or `libayatana-appindicator3-dev`), `librsvg2-dev`, `build-essential`, `libssl-dev`, `pkg-config`; bundling `.AppImage` / `.rpm` installers also needs `patchelf`, `rpm`, `file`, `wget` and `desktop-file-utils`. No Secret Service headers are needed — the keyring backend is pure Rust. diff --git a/package-lock.json b/package-lock.json index 639c41a..35c3ca2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "loach", - "version": "1.3.0", + "version": "1.5.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "loach", - "version": "1.3.0", + "version": "1.5.0", "license": "MIT", "dependencies": { "@radix-ui/react-dialog": "^1.1.23", @@ -18,19 +18,19 @@ "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-switch": "^1.3.7", "@radix-ui/react-tabs": "^1.1.21", - "@tauri-apps/api": "^2.11.1", - "@tauri-apps/plugin-process": "^2.3.1", - "@tauri-apps/plugin-shell": "^2.3.5", - "@tauri-apps/plugin-updater": "^2.10.1", + "@tauri-apps/api": "^2.12.0", + "@tauri-apps/plugin-process": "^2.4.0", + "@tauri-apps/plugin-shell": "^2.4.0", + "@tauri-apps/plugin-updater": "^2.13.1", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "highlight.js": "^11.12.0", "katex": "^0.16.47", - "lucide-react": "^1.33.0", - "mammoth": "^1.12.1", - "pdfjs-dist": "^6.2.108", - "react": "^19.2.8", - "react-dom": "^19.2.8", + "lucide-react": "^1.49.0", + "mammoth": "^1.13.0", + "pdfjs-dist": "^6.3.289", + "react": "^19.3.0", + "react-dom": "^19.3.0", "react-markdown": "^10.1.0", "rehype-highlight": "^7.0.2", "rehype-katex": "^7.0.1", @@ -42,17 +42,17 @@ }, "devDependencies": { "@tailwindcss/typography": "^0.5.20", - "@tauri-apps/cli": "^2.11.4", - "@types/node": "^22.20.1", - "@types/react": "^19.2.18", - "@types/react-dom": "^19.2.4", - "@vitejs/plugin-react": "^6.1.0", - "autoprefixer": "^10.5.4", - "postcss": "^8.5.26", + "@tauri-apps/cli": "^2.12.0", + "@types/node": "^22.20.4", + "@types/react": "^19.3.0", + "@types/react-dom": "^19.3.0", + "@vitejs/plugin-react": "^6.1.1", + "autoprefixer": "^10.6.1", + "postcss": "^8.5.28", "tailwindcss": "^3.4.19", "typescript": "^7.0.2", - "vite": "^8.2.2", - "vitest": "^4.1.11" + "vite": "^8.3.1", + "vitest": "^5.0.3" } }, "node_modules/@alloc/quick-lru": { @@ -125,9 +125,9 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz", + "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==", "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { @@ -426,13 +426,13 @@ } }, "node_modules/@oxc-project/types": { - "version": "0.146.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.146.0.tgz", - "integrity": "sha512-XC0QsnnhVe7sLIWmYmdPw7x5P0h4W8vUU3Nv1ySgWXtvCz8NizoAEpGXA0sOYoJQV2Rl13LgURAHQ5cI5ILCSA==", + "version": "0.151.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.151.0.tgz", + "integrity": "sha512-J1yXrIlNDZVzE3ada310xeAw7nH8yCAyLPuUIsjKatFPmfn5bS1oW+cM+QsGOtVWd5nhSpbwZWx/rue+r5Z+PA==", "dev": true, "license": "MIT", "funding": { - "url": "https://github.com/sponsors/Boshen" + "url": "https://github.com/sponsors/oxc-project" } }, "node_modules/@radix-ui/number": { @@ -1194,9 +1194,9 @@ "license": "MIT" }, "node_modules/@rolldown/binding-android-arm-eabi": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.5.tgz", - "integrity": "sha512-DLe/i+l8ynIBY7XEQ191TeZvCoowIGa18R+dIV30GW7DiOtp74i/xX8hs8GUjW5ARV7VZuie3d6AumSmCwbeRA==", + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.11.tgz", + "integrity": "sha512-A5kXfGKvKWWZE0TtPrfsvT+q4Y5d1QG8gGUzpYjGydM+fARM9MuX90PrXYXe0XbsDVgyxxNzHo6giCj90bsFNw==", "cpu": [ "arm" ], @@ -1211,9 +1211,9 @@ } }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.5.tgz", - "integrity": "sha512-zXcwKlQApYAOELHd8PwKDFkagYF9Wy4e0RJ+0qnzl9Pjnpj75TEG8ufv40p2J7kCEfwZAsNiuzRIyNNMWT38ig==", + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.11.tgz", + "integrity": "sha512-z6cTycz+iJ4PVkuL4HHW4DfTfoeU/2nqYYuSOrTmH7yHK5Y0LCOnA03V4ZNxavyVaU1oOqUgIg2klN/s+USGOA==", "cpu": [ "arm64" ], @@ -1228,9 +1228,9 @@ } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.5.tgz", - "integrity": "sha512-dK4QakI42nzWgJT5sm4y4y/O//D4OxM75/cH28RLV+nzIN9AY+YsbuUVrUTjlLjXR6vpyxFbSsbmNuJ6BP9sww==", + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.11.tgz", + "integrity": "sha512-jShvqNtP6vDC6/A5JOAzbVV+DkgHqhl/ScVCJEbt+TUY6QYz7YnXcrg3sLtFBniro0f/Ld50ZwCWA6f7KYD1nQ==", "cpu": [ "arm64" ], @@ -1245,9 +1245,9 @@ } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.5.tgz", - "integrity": "sha512-fqSALaUu1Wjd1nK2uW2kJDWdLCc8lx1IcY+MTY26Aurfdx19anlzhqXOgCFbBFQnlFDTn4TC1/7Nz4Bl2mLP3A==", + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.11.tgz", + "integrity": "sha512-f2i2xiNWq1Z1l2++q2fuhZRdLAT3aqxD6vRNm1RAxpUoBcdqNB3C0s1Bt+K+PbEx2F5F4gQp6hqKkphCY/xF9w==", "cpu": [ "x64" ], @@ -1262,9 +1262,9 @@ } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.5.tgz", - "integrity": "sha512-/vCnNxlkxs9tKxNDcyWUePpJ/PgTzxIaVhoM5SmG8UV+GR/IcPam4VYxi7GIMo7PSDuNqlJqvprqii9NqqVCMw==", + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.11.tgz", + "integrity": "sha512-4Ir5FSOKIAMr4r0kExpt1s3bMgzJU3rA45AYOHtQpls0oNeqcYBKrWMlckrYH4KCfGLfkfn1tN1dmZPMVsdXow==", "cpu": [ "x64" ], @@ -1279,9 +1279,9 @@ } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.5.tgz", - "integrity": "sha512-abk0NLA519LxRCszmbE0jYKuQ9YPocOXTiOXOo6Yr+YAT95VH+PtqYAjOJvGKt3viEd/x4qzabAlwd5bHOOARg==", + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.11.tgz", + "integrity": "sha512-/gnRDM+39BROzAN/k1OZjDPnDMcZxB/0EUxKjONO5yVkNEvlsoMDrxGNKgZi/ttFriS2gwlDNzB65pvNbFOXIQ==", "cpu": [ "arm" ], @@ -1296,9 +1296,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.5.tgz", - "integrity": "sha512-Y7eALiJ8lr0M2HH103Js+g7V34wf6snlpZLAsHI90uLhr3PVlNsbFVAXJC9d/V6BnPyKtpSwI+NcB/RLxsQxuA==", + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.11.tgz", + "integrity": "sha512-PFaK8HwvAHbaKbBcDNQihjMKYvFnA5hiENx/l5tphTDz1E0WFp32l0A7aq7lyUwGsRw/xSrNIy/gIK4thrSCrw==", "cpu": [ "arm64" ], @@ -1313,9 +1313,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.5.tgz", - "integrity": "sha512-xMvZgnbZg4YVnR/AX2b3oOPDTFYJvUVaJg5FedA/LuvexAtXibZQej4cnTkw3rjsJ/ggUROB64TdtETiim+FYA==", + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.11.tgz", + "integrity": "sha512-AskzJUIKRLPxkruR1wLKewGbOw+EYfU/9lOrBFj4AFrEA8hPpKFnODWNu2WLaNs0QNkEb9QIJufmVZZIL/bJlg==", "cpu": [ "arm64" ], @@ -1330,9 +1330,9 @@ } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.5.tgz", - "integrity": "sha512-GRjeqTUDHTo5GwntsLaAMcBahG3nlpjftXWZLN73HiYQlhwEowvarFgQnRnQZtIp4keXX7quXFbG38uPZBa2EA==", + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.11.tgz", + "integrity": "sha512-qlUGAheh2yh8afH7QBgx0PrRHN85hKnNd78x8MeMhXivuevgd8vgf6/CstOzmNKY/lLTHvNTrPy98cLnAugzJw==", "cpu": [ "ppc64" ], @@ -1347,9 +1347,9 @@ } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.5.tgz", - "integrity": "sha512-vLNTR45F2Uwc8AufkNXPmB4VliaXs+FvcheEogIzOXzO4l+LzieXF5A/TWxLy5HtqpsRCHUfd0lPVrrdgXdLHQ==", + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.11.tgz", + "integrity": "sha512-secpEad+0vCbSfn8upFySkDskv+bGPk3THSDS9Y89yc4rb4kzqHp8Dmyd9BkQW4SnhNXBZCl/6CrO//hZahNJQ==", "cpu": [ "s390x" ], @@ -1364,9 +1364,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.5.tgz", - "integrity": "sha512-Mgj59/HTuYeK9Gz2MA+mBWKnHsAgkBSec15ZMb1st3oIfFbX7gCjOae7GydHhzcyQi9Z/7M1QuN9bR3oFqF0jQ==", + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.11.tgz", + "integrity": "sha512-mOVBT3dPpkWm8XBWPmU4bf+U6dYDLeMo/9ojUmis4N0L5uu10qra5vOyngZ7/PSdoE4G9KvRt4bloRxNjLas7A==", "cpu": [ "x64" ], @@ -1381,9 +1381,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.5.tgz", - "integrity": "sha512-mY8AP0/ichsbhAxGnLa3d3+MwV0EfgrPND2bplI3Ym8T6R2pJ0N87bvrKVwNXmdy3jnr6eQBecdqx/HMknBmpA==", + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.11.tgz", + "integrity": "sha512-Is78i9A8Ui4SqcxUwFJ9uMmjDn58IbVTjFWYdQestFEgeuEmHMLGNriXnVJKkwG2YiZjw8cP0zCTyDMdDGtOOg==", "cpu": [ "x64" ], @@ -1398,9 +1398,9 @@ } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.5.tgz", - "integrity": "sha512-8SLssA2oweAxyRgDp789ACfRb/3P+zNRJpzZxSizxF9m8NUDQ4+3xjo8ttjhVGGw6Qxb70oZiEtIjaKikCO7Yw==", + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.11.tgz", + "integrity": "sha512-dUCXneZ87INUMyQ0D+C0HrEBNUPNXHaPmU5GTjyKTJEiussw9Kaj5Ln8UztPe4epV/ffvgNBEadksdYhmW6xJA==", "cpu": [ "arm64" ], @@ -1415,9 +1415,9 @@ } }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.5.tgz", - "integrity": "sha512-vGbruD5zquhoc8D9SViXgN2FBJtNdTyQ4DtG+SWiEGlJiAzoKcZ2xp+xuXCffhubVdt0NJlTZqkeRuERy7g8Cw==", + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.11.tgz", + "integrity": "sha512-jByxb6qfd+bH1xUd0qnfFnb17i9sWBPY2tOavJ0l3tdr3OTu+Kvtm8cd/JV5nFt657b1VqGltxg9olOEfofXWw==", "cpu": [ "arm64" ], @@ -1432,9 +1432,9 @@ } }, "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.5.tgz", - "integrity": "sha512-e/SXpgISz+IoqVcSSI0rx/d/he8zqLex+/rCWpnHpmVfmPIUjag9H6P7zotf0gJHwPUhQxZ/mF8tr6acebT9yw==", + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.11.tgz", + "integrity": "sha512-/PzKqzAJ03i19oy2ItPvyvaVjOjBCNnfaJs8yvUdGBKmiESgnrJSQ2awd81QzFbbnAmu7YO9ZnJrDCb9VSJPRA==", "cpu": [ "x64" ], @@ -1455,13 +1455,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@standard-schema/spec": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", - "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", - "dev": true, - "license": "MIT" - }, "node_modules/@tailwindcss/typography": { "version": "0.5.20", "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.20.tgz", @@ -1476,9 +1469,9 @@ } }, "node_modules/@tauri-apps/api": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.11.1.tgz", - "integrity": "sha512-M2FPuYND2m+wh5hfW9ZpSdxMPdEJovPBWwoHJmwUpysTYNHaOkVFN419m/K0LIgjb/7KU2vBgsUepJWugQCvAA==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.12.0.tgz", + "integrity": "sha512-fUSxFX8VABYe9W9K5ROdEaKVkNUFRcMSRofjruvaxztXA+I0XnQHcYHF8m/a6iExRUxsUf0HsFWhPBuH9IgzJw==", "license": "Apache-2.0 OR MIT", "funding": { "type": "opencollective", @@ -1486,9 +1479,9 @@ } }, "node_modules/@tauri-apps/cli": { - "version": "2.11.4", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.11.4.tgz", - "integrity": "sha512-R8xGtMpwyetawSqm9kYOuMmEqkhUbvcUy8n0aNXIxollKBLESUu5f4Fx+64hgASYm1H+jSWq6jCW6zqTnH6hqQ==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.12.0.tgz", + "integrity": "sha512-GIShnAR4C16kSTA8NO02fo8fOw/I5z5sAUEB5S2HlPHFnBkbihL4c9a/MpkxOm1+q5S+tFd3X4QUjHWxfyGzpQ==", "dev": true, "license": "Apache-2.0 OR MIT", "bin": { @@ -1502,23 +1495,23 @@ "url": "https://opencollective.com/tauri" }, "optionalDependencies": { - "@tauri-apps/cli-darwin-arm64": "2.11.4", - "@tauri-apps/cli-darwin-x64": "2.11.4", - "@tauri-apps/cli-linux-arm-gnueabihf": "2.11.4", - "@tauri-apps/cli-linux-arm64-gnu": "2.11.4", - "@tauri-apps/cli-linux-arm64-musl": "2.11.4", - "@tauri-apps/cli-linux-riscv64-gnu": "2.11.4", - "@tauri-apps/cli-linux-x64-gnu": "2.11.4", - "@tauri-apps/cli-linux-x64-musl": "2.11.4", - "@tauri-apps/cli-win32-arm64-msvc": "2.11.4", - "@tauri-apps/cli-win32-ia32-msvc": "2.11.4", - "@tauri-apps/cli-win32-x64-msvc": "2.11.4" + "@tauri-apps/cli-darwin-arm64": "2.12.0", + "@tauri-apps/cli-darwin-x64": "2.12.0", + "@tauri-apps/cli-linux-arm-gnueabihf": "2.12.0", + "@tauri-apps/cli-linux-arm64-gnu": "2.12.0", + "@tauri-apps/cli-linux-arm64-musl": "2.12.0", + "@tauri-apps/cli-linux-riscv64-gnu": "2.12.0", + "@tauri-apps/cli-linux-x64-gnu": "2.12.0", + "@tauri-apps/cli-linux-x64-musl": "2.12.0", + "@tauri-apps/cli-win32-arm64-msvc": "2.12.0", + "@tauri-apps/cli-win32-ia32-msvc": "2.12.0", + "@tauri-apps/cli-win32-x64-msvc": "2.12.0" } }, "node_modules/@tauri-apps/cli-darwin-arm64": { - "version": "2.11.4", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.11.4.tgz", - "integrity": "sha512-1ryOF3ZhpZ/nemHV5zVwBQBz9jDGKmKPvWPADOhc83ig0P4bMc2iER4NbC6r9sjeIZ6RVQ4g3RZIYvezhcl4TQ==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.12.0.tgz", + "integrity": "sha512-v5J+jISihLGtih1+3yWagbsL+5dbLZORu4vaSI0vhY0Heb+MAW+T/1s1RyKxrQrwEPGBG5kqwfDDTnSbmVkuqA==", "cpu": [ "arm64" ], @@ -1533,9 +1526,9 @@ } }, "node_modules/@tauri-apps/cli-darwin-x64": { - "version": "2.11.4", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.11.4.tgz", - "integrity": "sha512-uFsGQAAfuyz1k/yGLmkWfkBlgKAqZfxqlHmLWx81QU27RJWfmbNHCIq8T8w1e+VClleIuZUjpHWfoE4E3DLo3A==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.12.0.tgz", + "integrity": "sha512-g27I07pfW/dMS8vcNqB9lamgKF0TqLlcy8e7t9qDGsB1iaeyjJWb2TgBF4tM9ZwLqPAZUXbsz28oXljO12WC4g==", "cpu": [ "x64" ], @@ -1550,9 +1543,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": { - "version": "2.11.4", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.11.4.tgz", - "integrity": "sha512-IaHZn5CdBL21oUmjiVOS1ctw6Ip1O0pjp70FwOWmYz1myWe0SY96ZIj2FYf7pT0m8bI2h/hrs5ZbEXXh44/MkQ==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.12.0.tgz", + "integrity": "sha512-gXyQ710fNc99YuxFxNyeX9PLSrIpbtgBBj7GQo9tSeRT6fIK40q3/gm7X5jqZo7mWLR2m0R/2ALd3vAWo0Z32Q==", "cpu": [ "arm" ], @@ -1567,9 +1560,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-gnu": { - "version": "2.11.4", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.11.4.tgz", - "integrity": "sha512-N41/ukTRVe6XSuUTESuFdGeOW2i7k62tK+6gHK5Kd5/q5RPvvi19GaWAVPPb9u95HSGmTChSolBfzynUsssFaA==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.12.0.tgz", + "integrity": "sha512-H9cyXuq9WgxoHh2NZ+R+oN+W78x5UwaBDEp0/fmqUUkaBoioCuOZErM9xKiIV6bpNAhmw1RoWZ49u37q/vaiAg==", "cpu": [ "arm64" ], @@ -1584,9 +1577,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-musl": { - "version": "2.11.4", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.11.4.tgz", - "integrity": "sha512-v277UnT/fB64xAfSroL5N3Km3tLmvATWqJJw/wRI+g6o+HkeD0slyE7gOhNs1MbjE41R7bQOTxMVoL3aomUJmw==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.12.0.tgz", + "integrity": "sha512-5tFuk3JKMBa1M/iN4gN32OYlSfhY3aqb5PO3zCugxaT+sfecyMKpc3EM9VDbhmwWBE9QD4Tfj7wGhlqx2yy2pQ==", "cpu": [ "arm64" ], @@ -1601,9 +1594,9 @@ } }, "node_modules/@tauri-apps/cli-linux-riscv64-gnu": { - "version": "2.11.4", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-riscv64-gnu/-/cli-linux-riscv64-gnu-2.11.4.tgz", - "integrity": "sha512-qqgNkQ2u1yZHxjhxsZaxUtRDW8dIqIYm33rx/mzwQv0SfY9x1B+iraj8vWeFiXjjSVVhEMepXSOts1TqPzvXNQ==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-riscv64-gnu/-/cli-linux-riscv64-gnu-2.12.0.tgz", + "integrity": "sha512-LOrMyV+nb7pKq8P0BZtTBQuyzm1ORjn16R9MlupmxuT5LqxtuYJlw3VMwbaeXCToJ8jbP5u9JnkfmbqDlvETXw==", "cpu": [ "riscv64" ], @@ -1618,9 +1611,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-gnu": { - "version": "2.11.4", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.11.4.tgz", - "integrity": "sha512-2VRNWl84FOH0m2giiDkO2h0QXlcMJeX+zJDpI5kDIQAx6s+geF3v48F4DXfJez4GS/FdoDGnPnw1C2iYGbQ7bQ==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.12.0.tgz", + "integrity": "sha512-aMIkI+X9qvD2+k80QZB3tuOYT41/cEheikC510CwAIZ31KLXORsRASYYzM4mi1/58ICmtzSLFhCC08keir7COw==", "cpu": [ "x64" ], @@ -1635,9 +1628,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-musl": { - "version": "2.11.4", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.11.4.tgz", - "integrity": "sha512-o9GyhYor/nc7xarmwDE3ka2szuW3uuZzXjHWh64Q8YX5AtSgxdQkFWzrY4O8KiGtVNvFBI14H3Q49Qj5TOIP/A==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.12.0.tgz", + "integrity": "sha512-9gl3NhUbfuGhSKjeGCypKSdtoezOQRcDUrkhTWtLQEjnajets6peO6NadgI2DF0OzbiiFOzrnnIGMwBS+Ap6Iw==", "cpu": [ "x64" ], @@ -1652,9 +1645,9 @@ } }, "node_modules/@tauri-apps/cli-win32-arm64-msvc": { - "version": "2.11.4", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.11.4.tgz", - "integrity": "sha512-ld5Ehb598m0VkYyylRPNeCFsBe/km0jxis6KgMpl3IGY6I/i1RwQXO05I1AsXUXO2WC6AvB/Lw4qTf/asiuEiQ==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.12.0.tgz", + "integrity": "sha512-1W+v86wsYLuyBDN0iDessD4CD9o+yNyO0m8Dp3+/vfjiZrJ/v7R7/aTRBeikaq2tLGgxeag0gxnFggBNBGw91A==", "cpu": [ "arm64" ], @@ -1669,9 +1662,9 @@ } }, "node_modules/@tauri-apps/cli-win32-ia32-msvc": { - "version": "2.11.4", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.11.4.tgz", - "integrity": "sha512-12Hxi0XX/H5VFxO/bGgHkFWhml9VMgEOu9CidjeCeTNQ1l6fpUlbiGgSP7CLI3PFtW9/FfbeHieZ+kyWK5H7CA==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.12.0.tgz", + "integrity": "sha512-SsBjvq4f7YaBGqcWoE3cycoItPf0SrQeqFqWWgfxoeZWAIz01E31LDSeZ2p/etJiIY0R9oi045chkFfb0O7WGw==", "cpu": [ "ia32" ], @@ -1686,9 +1679,9 @@ } }, "node_modules/@tauri-apps/cli-win32-x64-msvc": { - "version": "2.11.4", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.11.4.tgz", - "integrity": "sha512-+vDiqBIU5dMISg/wNvX3sF+ZHfgJGJ5T0AcO+EHNXV9GGAG+P5fzodlDXD3QdKCRgZxMoCm5PPvj3BqLNjBthw==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.12.0.tgz", + "integrity": "sha512-9zzDKYUH4TKKBgRdDdVQX8fiRO5gJ8hD1nGsHU9DOHG5Jpm3arjbu9Xg1frR20EusG3Sl8X0dppoO/4EoUXUGg==", "cpu": [ "x64" ], @@ -1703,30 +1696,30 @@ } }, "node_modules/@tauri-apps/plugin-process": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-process/-/plugin-process-2.3.1.tgz", - "integrity": "sha512-nCa4fGVaDL/B9ai03VyPOjfAHRHSBz5v6F/ObsB73r/dA3MHHhZtldaDMIc0V/pnUw9ehzr2iEG+XkSEyC0JJA==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-process/-/plugin-process-2.4.0.tgz", + "integrity": "sha512-GddrmsSLAYrLa/yTXlXK/YRDzUgYeeOnUXTbiyvJWkmI424RmDPD3FVLeqcon7rv6O6ZfhBilcrHWnSo7o6hIQ==", "license": "MIT OR Apache-2.0", "dependencies": { - "@tauri-apps/api": "^2.8.0" + "@tauri-apps/api": "^2.12.0" } }, "node_modules/@tauri-apps/plugin-shell": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-shell/-/plugin-shell-2.3.5.tgz", - "integrity": "sha512-jewtULhiQ7lI7+owCKAjc8tYLJr92U16bPOeAa472LHJdgaibLP83NcfAF2e+wkEcA53FxKQAZ7byDzs2eeizg==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-shell/-/plugin-shell-2.4.0.tgz", + "integrity": "sha512-kto+mIv8reX1iryIDdjfsdv3l3BtMN0tvQ6dhs3uMO1MgjvdHsD9zql4cBE6W44qnRw/GMtsiThWsgcQASd+ig==", "license": "MIT OR Apache-2.0", "dependencies": { - "@tauri-apps/api": "^2.10.1" + "@tauri-apps/api": "^2.12.0" } }, "node_modules/@tauri-apps/plugin-updater": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-updater/-/plugin-updater-2.10.1.tgz", - "integrity": "sha512-NFYMg+tWOZPJdzE/PpFj2qfqwAWwNS3kXrb1tm1gnBJ9mYzZ4WDRrwy8udzWoAnfGCHLuePNLY1WVCNHnh3eRA==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-updater/-/plugin-updater-2.13.1.tgz", + "integrity": "sha512-+STDzJ0sdQLImjc63zkv6Nncimqeo6jyCWoTQtbSwgGLNj1qbP9I6LC4p5R5ocBk3gNKAZs6i/AJz0jxysytiw==", "license": "MIT OR Apache-2.0", "dependencies": { - "@tauri-apps/api": "^2.10.1" + "@tauri-apps/api": "^2.12.0" } }, "node_modules/@types/chai": { @@ -1802,9 +1795,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.20.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.1.tgz", - "integrity": "sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==", + "version": "22.20.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.4.tgz", + "integrity": "sha512-zJRE40jpHtKqE/C4fgHrAKQLJuSpzEnP9ff9Y7YtoR3Wd2pwqzlekDeEuUQXjRd+QCYnVnNwuJYmhdk9XV8gvA==", "dev": true, "license": "MIT", "dependencies": { @@ -1812,22 +1805,22 @@ } }, "node_modules/@types/react": { - "version": "19.2.18", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.18.tgz", - "integrity": "sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w==", + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.3.0.tgz", + "integrity": "sha512-N0rFCuH9YoxG9/m61l9MfpJKfmLOVU0em7ipIz6TRgSSkvReLB9vL85GB+yr8Bs5leqpvg96JSwF4ZS1s4viQg==", "license": "MIT", "dependencies": { "csstype": "^3.2.2" } }, "node_modules/@types/react-dom": { - "version": "19.2.5", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.5.tgz", - "integrity": "sha512-fMPwH9v7r/pp43yUd2/Mbiex5KouJwwR3dzHkhLREUC6764VyDsqxhAxv6OFEYR1RhjOyD1naqba8ECDBe7ZQg==", + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.3.0.tgz", + "integrity": "sha512-ZI7bU42mZXXKHn/qNLEw2IrbiINU7X5+vfgdixBHkCNpYWXjKgfQ/P+uyGb5CjOLB9UcnTeg3rylQtV2hym44Q==", "devOptional": true, "license": "MIT", "peerDependencies": { - "@types/react": "^19.2.0" + "@types/react": "^19.3.0" } }, "node_modules/@types/unist": { @@ -2183,9 +2176,9 @@ "license": "ISC" }, "node_modules/@vitejs/plugin-react": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.1.0.tgz", - "integrity": "sha512-qd2BzUBehkov86WFhg0JkEFEYyCLG9uPCe6qWTY/kRlss9OvJrOF2UbIWT7p+8IzZHkEu0DNGHc4HSv+JdDLsw==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.1.1.tgz", + "integrity": "sha512-yxLaQV9gkhS8ezJqCM6+ndU7mDY6gqAg75NQ+0IjwEI8IYOmQCgkRwHKVSfWXW076DsqMo0Dk+0FK1U+M5RgFw==", "dev": true, "license": "MIT", "dependencies": { @@ -2212,34 +2205,17 @@ } } }, - "node_modules/@vitest/expect": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.11.tgz", - "integrity": "sha512-VX2x5vNJXET47KAFzwERI+KRMtTTCSWTfSMKsW7JsUsXV4psq++e3DvZpuTDOpHcxytiDs6p2nhVb2tVDiiUYw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@standard-schema/spec": "^1.1.0", - "@types/chai": "^5.2.2", - "@vitest/spy": "4.1.11", - "@vitest/utils": "4.1.11", - "chai": "^6.2.2", - "tinyrainbow": "^3.1.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, "node_modules/@vitest/mocker": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.11.tgz", - "integrity": "sha512-2XJVD55d1o5AZous5CCGKS74g/riOj9odEt2bQpCVZeblHyHdnMeFl4jl0XjU21stf4mbjUkew2eXQZt65g5CQ==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-5.0.3.tgz", + "integrity": "sha512-T8sWAIbkSyAjkwTcaEc3Iu0o9A27X1/kdXrizhZkGuSKScRQtRzclfAMpOTcGdXCsqxeWlpGy3XjqaW8CpLORg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "4.1.11", + "@jridgewell/trace-mapping": "0.3.31", + "@vitest/spy": "5.0.3", "estree-walker": "^3.0.3", - "magic-string": "^0.30.21" + "magic-string": "^1.2.3" }, "funding": { "url": "https://opencollective.com/vitest" @@ -2257,74 +2233,16 @@ } } }, - "node_modules/@vitest/pretty-format": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.11.tgz", - "integrity": "sha512-yiZzPbGTS9Sr/JpFl8zHrcIkAofNbFV6k21vIgQN/cY/oxZeXhJv5sc/MBJ5jFKWmWs+oJHw0UXLZjmf931+Vw==", - "dev": true, - "license": "MIT", - "dependencies": { - "tinyrainbow": "^3.1.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.11.tgz", - "integrity": "sha512-LztvUgdwMNJMIkj3hQnnxiC2Xy1zNxq928W/xhjCLaNCzqTZOudjwbQf6v9IntZGPw132i2Lq2rgTRZHD3JHNw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/utils": "4.1.11", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/snapshot": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.11.tgz", - "integrity": "sha512-pN7ikn1ON7h8ee4gIAp4AzyK+zBtJPzVbqOgu5LCEh4VaJVbPQcgYQYJIMGQPXVeJJq1fnfazis7a5pFNPahog==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "4.1.11", - "@vitest/utils": "4.1.11", - "magic-string": "^0.30.21", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, "node_modules/@vitest/spy": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.11.tgz", - "integrity": "sha512-apNa/prQy2qCeywhnixOHPRCgGNhvg7T4Dapfl1GahLp/R+uhBm5cPyFoNVyqsNd2h1nJxL6BqqdIjiABL60YA==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-5.0.3.tgz", + "integrity": "sha512-XhFysQTB8AZ+P4gMi+Lpo99vg2AZi0qKpaB9yXQl37+CaMEAPO3iH/wGVnSyL5MPERiLezpqTVtrR6UZH5GCXg==", "dev": true, "license": "MIT", "funding": { "url": "https://opencollective.com/vitest" } }, - "node_modules/@vitest/utils": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.11.tgz", - "integrity": "sha512-zTCVGpyFsGWBhllOyKlTw/vnr6D9qxsfSDyfbyZmTyjHw5N/VuvzHpHoQjm2ZJzn4RJgx5w4r7V0er69CmLgPQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "4.1.11", - "convert-source-map": "^2.0.0", - "tinyrainbow": "^3.1.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, "node_modules/@xmldom/xmldom": { "version": "0.8.15", "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.15.tgz", @@ -2391,9 +2309,9 @@ } }, "node_modules/autoprefixer": { - "version": "10.5.4", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.4.tgz", - "integrity": "sha512-MaU0U/za7N3r6brxD4YB/l4NSrFzLPlANv6wEuQVaIPlD3L4W9rFcQPbL/EilY9BHhHvhfcz3gInDLrEtWT4EA==", + "version": "10.6.1", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.6.1.tgz", + "integrity": "sha512-cL1Qz6ADZhcEbny/8HPfe99J6HhNoYtpX2LFLIbhgGE7Q1hlQVkYFdetDN7Id3KiQxhDrHwzlHr/YQCnZ8+xSA==", "dev": true, "funding": [ { @@ -2411,8 +2329,8 @@ ], "license": "MIT", "dependencies": { - "browserslist": "^4.28.6", - "caniuse-lite": "^1.0.30001806", + "browserslist": "^4.28.9", + "caniuse-lite": "^1.0.30001810", "fraction.js": "^5.3.4", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" @@ -2458,9 +2376,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.11.18", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.18.tgz", - "integrity": "sha512-1iEmLEYSiE1SeBoAfPo/Mnx3PzfzHUkDK61ASkCpuk3YXugYLH5DYK1SzqV55F8FMI6s0F+/tCP7Polz1QRjxw==", + "version": "2.11.26", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.26.tgz", + "integrity": "sha512-GLQdD3y6UF8iVuMJl5fHgE4jdn/ua7n+toKfLgNlg3BqQtOZjpy68T8Tup8/wGWZCDlm7KMg7tPb4MPn7oN0TQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -2482,12 +2400,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/bluebird": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", - "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==", - "license": "MIT" - }, "node_modules/braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", @@ -2501,9 +2413,9 @@ } }, "node_modules/browserslist": { - "version": "4.28.8", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.8.tgz", - "integrity": "sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==", + "version": "4.29.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.29.3.tgz", + "integrity": "sha512-1R4kiYKXGViqEN0CnoDrXc1StD9niAwu+j2dukWzrD4bJgsD4lDmEp0CRbc6E/vYJIfTHwPmwyaKtVSudICdPA==", "dev": true, "funding": [ { @@ -2521,11 +2433,11 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.11.12", - "caniuse-lite": "^1.0.30001809", - "electron-to-chromium": "^1.5.402", - "node-releases": "^2.0.53", - "update-browserslist-db": "^1.3.0" + "baseline-browser-mapping": "^2.11.26", + "caniuse-lite": "^1.0.30001813", + "electron-to-chromium": "^1.5.439", + "node-releases": "^2.0.57", + "update-browserslist-db": "^1.3.3" }, "bin": { "browserslist": "cli.js" @@ -2544,9 +2456,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001809", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001809.tgz", - "integrity": "sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ==", + "version": "1.0.30001814", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001814.tgz", + "integrity": "sha512-/Uaf1lAzr59XcMpW0o96WoEfr+VXK2OX4U9AgFoiSHsVJ4HppnIFUjtYzsyDH2+tgANaQb2/oxYGwCPapN1FpA==", "dev": true, "funding": [ { @@ -2700,13 +2612,6 @@ "node": ">= 6" } }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", @@ -2827,9 +2732,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.413", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.413.tgz", - "integrity": "sha512-F1XPKvt7HVfly5WND90ec16nFsdr4g5x/cVUP3EqjeyXynupabGDqpMa84wwvuYGDnldXLBz6DLXyZXWO9TPvw==", + "version": "1.5.442", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.442.tgz", + "integrity": "sha512-najZYZ3+ZpjN1z3VOsrBiv5ej18vQgfV2lvEmxWzfmKrk4bdm3Owseyud4yGU6DfFn9pyunoAHDDyM4KmP78Ew==", "dev": true, "license": "ISC" }, @@ -3742,38 +3647,42 @@ } }, "node_modules/lucide-react": { - "version": "1.34.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.34.0.tgz", - "integrity": "sha512-vnjGJNI7Htk5+oWW8gXGuaLgwgAb0T6/iZbBrp9JCfRFwdNWZ0YTm3eyxjOLgwN6r8iyAf3UA70zNmBRBNv7yg==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.49.0.tgz", + "integrity": "sha512-ApfaNM4/7jBrVopqLJ84Jz8TMQ1Q1JeZ1PmKh25aeS3E1FTVcMkSh1bEQB7dfzdIrwXRP8p3z4AJjTIHHb5IIA==", "license": "ISC", "peerDependencies": { + "@types/react": "*", "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.4.2.tgz", + "integrity": "sha512-vG+rjFRj1PqdIBozIxAGMjPlOhaVe+GXpbttY/iSK7rGcJRMlwNJO7dcUwmUqkymsFLJiNGI06t4D7Fr7yRC9g==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" + "@jridgewell/sourcemap-codec": "^1.6.0" } }, "node_modules/mammoth": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/mammoth/-/mammoth-1.12.1.tgz", - "integrity": "sha512-nCH9KKjWi3jQ+i8bUKs7k1yrXtSEGpWgF8IYkzsFMcbn+5S6l4bZEBbyx2hOQErFiXPuAs9RPa6qjXVxhyx/8g==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/mammoth/-/mammoth-1.13.0.tgz", + "integrity": "sha512-2cawcYFcP7ISfXbBcL9lmVgTNWo88v/52ND1gnywHtVT/pX0//puPnf0iMPV9ZgmuvNOE+zkIhDgZ9M2c2dDDg==", "license": "BSD-2-Clause", "dependencies": { "@xmldom/xmldom": "^0.8.6", "argparse": "~1.0.3", "base64-js": "^1.5.1", - "bluebird": "~3.4.0", "dingbat-to-unicode": "^1.0.1", "jszip": "^3.7.1", "lop": "^0.4.2", - "path-is-absolute": "^1.0.0", "underscore": "^1.13.1", "xmlbuilder": "^10.0.0" }, @@ -4723,9 +4632,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.53", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.53.tgz", - "integrity": "sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ==", + "version": "2.0.57", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.57.tgz", + "integrity": "sha512-kQK9LGGFiHtrWiNhZtA7Qbw17AQz+dmsEKODRIVTXA9+e5MS/2gZEBhYJt13GrAz5/IOZKddH/0Z3TP/Zgo+yw==", "dev": true, "license": "MIT", "engines": { @@ -4822,32 +4731,16 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "license": "MIT" }, - "node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true, - "license": "MIT" - }, "node_modules/pdfjs-dist": { - "version": "6.2.108", - "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-6.2.108.tgz", - "integrity": "sha512-YxFb+SQcodN2rnX9Tn3dHYlqfb7NjlzzfONPpJd+AKoKtUjEdevTfbC07d5TcczzOK6261auRkP/M8OBHs9vFQ==", + "version": "6.3.289", + "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-6.3.289.tgz", + "integrity": "sha512-ZHjSVpDa3D6izMq8/04lvkhkATUmL9px6ChPaXc1k6nU2Mrhlg1/7F0bdUqCwUjw3NsPTfPZsMDUU6ZIcRaeQw==", "license": "Apache-2.0", "engines": { "node": ">=22.13.0 || >=24" @@ -4884,9 +4777,9 @@ } }, "node_modules/postcss": { - "version": "8.5.26", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", - "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", + "version": "8.5.28", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.28.tgz", + "integrity": "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==", "funding": [ { "type": "opencollective", @@ -4903,7 +4796,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.17", + "nanoid": "^3.3.18", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -5090,24 +4983,24 @@ "license": "MIT" }, "node_modules/react": { - "version": "19.2.8", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.8.tgz", - "integrity": "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==", + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.3.0.tgz", + "integrity": "sha512-E8LUcbtBWt20bbl2YoHfx4ZDBdxVTfOKtCZn9cDSJ4l6/nuoApcpIBcj47t2wZoVX8g2ZHuMHbiShgCR1T5Sog==", "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/react-dom": { - "version": "19.2.8", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.8.tgz", - "integrity": "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==", + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.3.0.tgz", + "integrity": "sha512-JDk8dgif51OjFoDE70+OT9ICyYr+69HlmihNwp1+Nsfbna3t5sIiCa9ZJktDmQ4/1b/rn26hIAR2uYXDMr5r0Q==", "license": "MIT", "dependencies": { - "scheduler": "^0.27.0" + "scheduler": "^0.28.0" }, "peerDependencies": { - "react": "^19.2.8" + "react": "^19.3.0" } }, "node_modules/react-markdown": { @@ -5389,13 +5282,13 @@ } }, "node_modules/rolldown": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.5.tgz", - "integrity": "sha512-VD2IE5PUG4Oj8zz2VGykiYd5wbnjdIiSsNQb8Qu5B+noEp+A78mu2iVvpp27g8es14Tk9rofNs5Tku9iQCS4fA==", + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.11.tgz", + "integrity": "sha512-qpSwIyz0jHQq5qXBTNxFmE6664rJ7O+4TvPFOiOaBSrz8IOHc1koKKSqTM2H6u1UG1+TveuC6vaDHKXFOvb1Kw==", "dev": true, "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.146.0", + "@oxc-project/types": "=0.151.0", "@rolldown/pluginutils": "^1.0.0" }, "bin": { @@ -5405,21 +5298,21 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm-eabi": "1.2.5", - "@rolldown/binding-android-arm64": "1.2.5", - "@rolldown/binding-darwin-arm64": "1.2.5", - "@rolldown/binding-darwin-x64": "1.2.5", - "@rolldown/binding-freebsd-x64": "1.2.5", - "@rolldown/binding-linux-arm-gnueabihf": "1.2.5", - "@rolldown/binding-linux-arm64-gnu": "1.2.5", - "@rolldown/binding-linux-arm64-musl": "1.2.5", - "@rolldown/binding-linux-ppc64-gnu": "1.2.5", - "@rolldown/binding-linux-s390x-gnu": "1.2.5", - "@rolldown/binding-linux-x64-gnu": "1.2.5", - "@rolldown/binding-linux-x64-musl": "1.2.5", - "@rolldown/binding-openharmony-arm64": "1.2.5", - "@rolldown/binding-win32-arm64-msvc": "1.2.5", - "@rolldown/binding-win32-x64-msvc": "1.2.5" + "@rolldown/binding-android-arm-eabi": "1.2.11", + "@rolldown/binding-android-arm64": "1.2.11", + "@rolldown/binding-darwin-arm64": "1.2.11", + "@rolldown/binding-darwin-x64": "1.2.11", + "@rolldown/binding-freebsd-x64": "1.2.11", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.11", + "@rolldown/binding-linux-arm64-gnu": "1.2.11", + "@rolldown/binding-linux-arm64-musl": "1.2.11", + "@rolldown/binding-linux-ppc64-gnu": "1.2.11", + "@rolldown/binding-linux-s390x-gnu": "1.2.11", + "@rolldown/binding-linux-x64-gnu": "1.2.11", + "@rolldown/binding-linux-x64-musl": "1.2.11", + "@rolldown/binding-openharmony-arm64": "1.2.11", + "@rolldown/binding-win32-arm64-msvc": "1.2.11", + "@rolldown/binding-win32-x64-msvc": "1.2.11" } }, "node_modules/run-parallel": { @@ -5452,9 +5345,9 @@ "license": "MIT" }, "node_modules/scheduler": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", - "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.28.0.tgz", + "integrity": "sha512-juorfCmIkIw8tT+p5BXSm6PJjQF/ycEYmKyzURCIt/RaZIhL+PulbQ9Yu2z1HdOJDdqDTlxA1+xKBmHXJsczAw==", "license": "MIT" }, "node_modules/setimmediate": { @@ -5463,13 +5356,6 @@ "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", "license": "MIT" }, - "node_modules/siginfo": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", - "dev": true, - "license": "ISC" - }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -5495,13 +5381,6 @@ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "license": "BSD-3-Clause" }, - "node_modules/stackback": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", - "dev": true, - "license": "MIT" - }, "node_modules/std-env": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.2.0.tgz", @@ -5675,11 +5554,14 @@ } }, "node_modules/tinybench": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-6.2.0.tgz", + "integrity": "sha512-78U2TlB2CnVenajOFzf3BKSm0J6oz5L0NV7g32LCPccvYc0lbWvys4d3uUUCS2B1N8PAf2+aekR8i1KbC3HO7Q==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=20.0.0" + } }, "node_modules/tinyexec": { "version": "1.3.0", @@ -5736,16 +5618,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/tinyrainbow": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.1.tgz", - "integrity": "sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -5954,9 +5826,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.1.tgz", - "integrity": "sha512-ZZ61DsRsOnakl74HAmp3oSN4aXUmEWXf+i/yv0h7tIBfICc3VdrFErQKUUKPgu3AMsTUMbcongALEN4l6GSUrQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.3.tgz", + "integrity": "sha512-pJ2sYawQS0R/WI928Gj5GlPhTGzbMelq0+4INtSYNDV9ErKJcX6xjGWkoG/VnB3dpUm00zALaqkrUD77pO5TDQ==", "dev": true, "funding": [ { @@ -6076,16 +5948,16 @@ } }, "node_modules/vite": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.2.tgz", - "integrity": "sha512-cFKLV/PRgAUlIRm5WjMjJ86jrftzpqcgH+Us+DS8mI3CDNiH30Whrz8uHL3+MOLPAgqbMBAqWdAHAphOAM+z/Q==", + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.3.1.tgz", + "integrity": "sha512-/bvH9E9tmCXRGp2uXY3WbOldqpTwFkbha/8ANaEQ6VkxhH60KyqLwgZq6lG2y+4uT55x9+9eUHMpQ7uGnOCKjA==", "dev": true, "license": "MIT", "dependencies": { "lightningcss": "^1.33.0", - "picomatch": "^4.0.5", - "postcss": "^8.5.26", - "rolldown": "~1.2.4", + "picomatch": "^4.0.7", + "postcss": "^8.5.28", + "rolldown": "~1.2.9", "tinyglobby": "^0.2.17" }, "bin": { @@ -6102,7 +5974,7 @@ }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", - "@vitejs/devtools": "^0.4.0 || ^0.5.0", + "@vitejs/devtools": "^0.7.1", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", @@ -6154,9 +6026,9 @@ } }, "node_modules/vite/node_modules/picomatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", - "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", "dev": true, "license": "MIT", "engines": { @@ -6167,38 +6039,31 @@ } }, "node_modules/vitest": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.11.tgz", - "integrity": "sha512-fhACrNXUidIbGSBr5FlbuBkO7VWC1ZyLl0DO4CU2DrQoAPxX84Ysxs+HeGQpii5lZWV1Q4gBZTTu49mF+A6Edw==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-5.0.3.tgz", + "integrity": "sha512-xMw97S3rjdtj5dkVat7jCsqWBpvchs3RlpQctUqwJD0KkERk40vz2fJ77lDwW/Vzh/pk18eItYAzkodhSes3jQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "4.1.11", - "@vitest/mocker": "4.1.11", - "@vitest/pretty-format": "4.1.11", - "@vitest/runner": "4.1.11", - "@vitest/snapshot": "4.1.11", - "@vitest/spy": "4.1.11", - "@vitest/utils": "4.1.11", - "es-module-lexer": "^2.0.0", - "expect-type": "^1.3.0", - "magic-string": "^0.30.21", - "obug": "^2.1.1", - "pathe": "^2.0.3", - "picomatch": "^4.0.3", - "std-env": "^4.0.0-rc.1", - "tinybench": "^2.9.0", - "tinyexec": "^1.0.2", - "tinyglobby": "^0.2.15", - "tinyrainbow": "^3.1.0", - "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", - "why-is-node-running": "^2.3.0" + "@types/chai": "^5.2.2", + "@vitest/mocker": "5.0.3", + "chai": "^6.2.2", + "es-module-lexer": "^2.3.2", + "expect-type": "^1.4.0", + "magic-string": "^1.2.3", + "obug": "^2.1.4", + "picomatch": "^4.0.7", + "std-env": "^4.2.0", + "tinybench": "^6.1.4", + "tinyexec": "^1.3.0", + "tinyglobby": "^0.2.17", + "why-is-node-running": "3.2.1" }, "bin": { "vitest": "vitest.mjs" }, "engines": { - "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^22.12.0 || ^24.0.0 || >=26.0.0" }, "funding": { "url": "https://opencollective.com/vitest" @@ -6206,16 +6071,16 @@ "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", - "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.1.11", - "@vitest/browser-preview": "4.1.11", - "@vitest/browser-webdriverio": "4.1.11", - "@vitest/coverage-istanbul": "4.1.11", - "@vitest/coverage-v8": "4.1.11", - "@vitest/ui": "4.1.11", + "@types/node": "^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "5.0.3", + "@vitest/browser-preview": "5.0.3", + "@vitest/browser-webdriverio": "^5.0.0-beta.5 || >=5.0.0", + "@vitest/coverage-istanbul": "5.0.3", + "@vitest/coverage-v8": "5.0.3", + "@vitest/ui": "5.0.3", "happy-dom": "*", "jsdom": "*", - "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + "vite": "^6.4.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "@edge-runtime/vm": { @@ -6257,9 +6122,9 @@ } }, "node_modules/vitest/node_modules/picomatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", - "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", "dev": true, "license": "MIT", "engines": { @@ -6280,20 +6145,16 @@ } }, "node_modules/why-is-node-running": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", - "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-3.2.1.tgz", + "integrity": "sha512-Tb2FUhB4vUsGQlfSquQLYkApkuPAFQXGFzxWKHHumVz2dK+X1RUm/HnID4+TfIGYJ1kTcwOaCk/buYCEJr6YjQ==", "dev": true, "license": "MIT", - "dependencies": { - "siginfo": "^2.0.0", - "stackback": "0.0.2" - }, "bin": { "why-is-node-running": "cli.js" }, "engines": { - "node": ">=8" + "node": ">=20.11" } }, "node_modules/xmlbuilder": { diff --git a/package.json b/package.json index 7313234..4ae0177 100644 --- a/package.json +++ b/package.json @@ -24,19 +24,19 @@ "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-switch": "^1.3.7", "@radix-ui/react-tabs": "^1.1.21", - "@tauri-apps/api": "^2.11.1", - "@tauri-apps/plugin-process": "^2.3.1", - "@tauri-apps/plugin-shell": "^2.3.5", - "@tauri-apps/plugin-updater": "^2.10.1", + "@tauri-apps/api": "^2.12.0", + "@tauri-apps/plugin-process": "^2.4.0", + "@tauri-apps/plugin-shell": "^2.4.0", + "@tauri-apps/plugin-updater": "^2.13.1", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "highlight.js": "^11.12.0", "katex": "^0.16.47", - "lucide-react": "^1.33.0", - "mammoth": "^1.12.1", - "pdfjs-dist": "^6.2.108", - "react": "^19.2.8", - "react-dom": "^19.2.8", + "lucide-react": "^1.49.0", + "mammoth": "^1.13.0", + "pdfjs-dist": "^6.3.289", + "react": "^19.3.0", + "react-dom": "^19.3.0", "react-markdown": "^10.1.0", "rehype-highlight": "^7.0.2", "rehype-katex": "^7.0.1", @@ -48,17 +48,17 @@ }, "devDependencies": { "@tailwindcss/typography": "^0.5.20", - "@tauri-apps/cli": "^2.11.4", - "@types/node": "^22.20.1", - "@types/react": "^19.2.18", - "@types/react-dom": "^19.2.4", - "@vitejs/plugin-react": "^6.1.0", - "autoprefixer": "^10.5.4", - "postcss": "^8.5.26", + "@tauri-apps/cli": "^2.12.0", + "@types/node": "^22.20.4", + "@types/react": "^19.3.0", + "@types/react-dom": "^19.3.0", + "@vitejs/plugin-react": "^6.1.1", + "autoprefixer": "^10.6.1", + "postcss": "^8.5.28", "tailwindcss": "^3.4.19", "typescript": "^7.0.2", - "vite": "^8.2.2", - "vitest": "^4.1.11" + "vite": "^8.3.1", + "vitest": "^5.0.3" }, "overrides": { "@xmldom/xmldom": "^0.8.13" diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 98d3a28..c533b9a 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -10,24 +10,13 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aes" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" -dependencies = [ - "cfg-if", - "cipher 0.4.4", - "cpufeatures 0.2.17", -] - -[[package]] -name = "aes" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8eb277bec05f56a0e0591f155a484cbd0f4f07ff2905051a48c72f004f7ed58" +checksum = "35f0f96ce78e38c3dc6d8948aa8163d06385be74000f3c7a95bf1eef35d3ea32" dependencies = [ - "cipher 0.5.2", + "cipher", "cpubits", - "cpufeatures 0.3.0", + "cpufeatures 0.3.1", ] [[package]] @@ -51,13 +40,28 @@ version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" +[[package]] +name = "alloc-no-stdlib" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2fb6cfd47bf496ff64095c20eaba0c201404ee38714d4142fcfa1dc334fcc7a" + [[package]] name = "alloc-stdlib" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e76a019e91224d279006ff972f1e984179a6e9feb050adba6ce8274aef23195" dependencies = [ - "alloc-no-stdlib", + "alloc-no-stdlib 2.0.4", +] + +[[package]] +name = "alloc-stdlib" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5c1865780388bfa186411ab5f247819487fc4864c6e9c3106611fa347586e1" +dependencies = [ + "alloc-no-stdlib 3.0.0", ] [[package]] @@ -66,8 +70,8 @@ version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab097a7be305dd66b2b6917f5efb6b723129ce4b2cd11aa1a0afcc293c7dc08e" dependencies = [ - "bitflags 2.13.1", - "brotli-decompressor", + "bitflags 2.13.2", + "brotli-decompressor 5.0.3", "encoding_rs", "enumflags2", "flate2", @@ -120,13 +124,13 @@ dependencies = [ [[package]] name = "argon2" -version = "0.5.3" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" +checksum = "134c52ddac6d63c576bef8168db10c83c49c26444ecbc68060fef078925a901c" dependencies = [ "base64ct", "blake2", - "cpufeatures 0.2.17", + "cpufeatures 0.3.1", "password-hash", ] @@ -156,9 +160,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.43" +version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3976abdc8fe7d1133d43d304afd42abdf5bc3e1319d263d223bde07b5efc4be8" +checksum = "ee19bd99b43e3691acbad4e840420a4881cea6c0b66a208125a824f8fd53f5a1" dependencies = [ "compression-codecs", "compression-core", @@ -292,7 +296,7 @@ checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.6", ] [[package]] @@ -377,20 +381,20 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.13.1" +version = "2.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" +checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" dependencies = [ "serde_core", ] [[package]] name = "blake2" -version = "0.10.6" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +checksum = "5b5d4d889834ee8ecfc0f8426ad30faf7cdcb10f741a8e6d7224d95325479f6f" dependencies = [ - "digest 0.10.7", + "digest 0.11.3", ] [[package]] @@ -411,15 +415,6 @@ dependencies = [ "hybrid-array", ] -[[package]] -name = "block-padding" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" -dependencies = [ - "generic-array", -] - [[package]] name = "block-padding" version = "0.4.2" @@ -453,13 +448,13 @@ dependencies = [ [[package]] name = "brotli" -version = "8.0.4" +version = "9.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc91aac060a7a1e25823bdccbfb6af1875b88f17c6daac97894eed8207166b3" +checksum = "f8b851b75c23ca7873623d612fe49bd1989aeb03d08fb9432187eb253d3d4c6b" dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", - "brotli-decompressor", + "alloc-no-stdlib 3.0.0", + "alloc-stdlib 0.3.0", + "brotli-decompressor 6.0.1", ] [[package]] @@ -468,8 +463,18 @@ version = "5.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a32acac15fe1967bc3986b2a6347dffc965602354ea6f450ad07e8bfd253583" dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", + "alloc-no-stdlib 2.0.4", + "alloc-stdlib 0.2.4", +] + +[[package]] +name = "brotli-decompressor" +version = "6.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "941cd9bd4ddab83cb46fa5a2d428f1c857b24ac78cb876cf7beb710840934bd7" +dependencies = [ + "alloc-no-stdlib 3.0.0", + "alloc-stdlib 0.3.0", ] [[package]] @@ -530,7 +535,7 @@ version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.2", "cairo-sys-rs", "glib", "libc", @@ -551,9 +556,9 @@ dependencies = [ [[package]] name = "camino" -version = "1.2.5" +version = "1.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d" +checksum = "bbbad30e4b4c14a39e3cc8aed085a12a327257c316619c93581e017bc52be591" dependencies = [ "serde_core", ] @@ -578,26 +583,18 @@ dependencies = [ "semver", "serde", "serde_json", - "thiserror 2.0.20", + "thiserror 2.0.21", ] [[package]] name = "cargo_toml" -version = "0.22.3" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374b7c592d9c00c1f4972ea58390ac6b18cbb6ab79011f3bdc90a0b82ca06b77" +checksum = "82f4b26e751e711a5302649417f2da046dce6391b2ea30a4820f37462314f0b9" dependencies = [ + "semver", "serde", - "toml 0.9.12+spec-1.1.0", -] - -[[package]] -name = "cbc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" -dependencies = [ - "cipher 0.4.4", + "toml 1.1.6+spec-1.1.0", ] [[package]] @@ -606,14 +603,14 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce2dc9ee5f88d11e0beb842c88b33c8a5cf0d1329c4b19494af42b07dbfe8896" dependencies = [ - "cipher 0.5.2", + "cipher", ] [[package]] name = "cc" -version = "1.4.4" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad534f4357a5264cce5019c989cf66a4f0dc4e0d1b1d15f8aacec0ff7360273" +checksum = "f360145194ee8e21db5ee7f3fcd4fe52210864c75c985dae33218202c8bbe040" dependencies = [ "find-msvc-tools", "shlex", @@ -627,13 +624,13 @@ checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" [[package]] name = "cfb" -version = "0.7.3" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d38f2da7a0a2c4ccf0065be06397cc26a81f4e528be095826eee9d4adbb8c60f" +checksum = "a347dcabdae9c31b0825fd6a8bed285ec9c2acb89c47827126d52fa4f59cece3" dependencies = [ - "byteorder", "fnv", "uuid", + "web-time", ] [[package]] @@ -648,9 +645,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" [[package]] name = "cfg_aliases" @@ -660,13 +657,13 @@ checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" [[package]] name = "chacha20" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81" +checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06" dependencies = [ "cfg-if", - "cpufeatures 0.3.0", - "rand_core 0.10.1", + "cpufeatures 0.3.1", + "rand_core", ] [[package]] @@ -691,7 +688,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -704,16 +701,6 @@ dependencies = [ "phf 0.12.1", ] -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common 0.1.7", - "inout 0.1.4", -] - [[package]] name = "cipher" version = "0.5.2" @@ -721,14 +708,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8cf2a2c93cd704877c0858356ed03480ff301ee950b43f1cbe4573b088bfa6c" dependencies = [ "crypto-common 0.2.2", - "inout 0.2.2", + "inout", ] +[[package]] +name = "cmov" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" + [[package]] name = "combine" -version = "4.6.7" +version = "4.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +checksum = "cfc320937d09e6de266b31b9afb480f197d7a861be86be7cb2ea7e5d1bfffc5e" dependencies = [ "bytes", "memchr", @@ -736,9 +729,9 @@ dependencies = [ [[package]] name = "compression-codecs" -version = "0.4.38" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce2548391e9c1929c21bf6aa2680af86fe4c1b33e6cea9ac1cfeec0bd11218cf" +checksum = "98fc98460ba0ad5317075d3632b8dfc45d0be8c4a49347c2a38272019717614a" dependencies = [ "brotli", "compression-core", @@ -748,9 +741,9 @@ dependencies = [ [[package]] name = "compression-core" -version = "0.4.32" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc14f565cf027a105f7a44ccf9e5b424348421a1d8952a8fc9d499d313107789" +checksum = "6e8ccc4ea9f6acc32d102c0f6d471d11d913ad15f20c04de743374861fa1d414" [[package]] name = "concurrent-queue" @@ -777,6 +770,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation" version = "0.10.1" @@ -799,8 +802,8 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97" dependencies = [ - "bitflags 2.13.1", - "core-foundation", + "bitflags 2.13.2", + "core-foundation 0.10.1", "core-graphics-types", "foreign-types", "libc", @@ -812,11 +815,17 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ - "bitflags 2.13.1", - "core-foundation", + "bitflags 2.13.2", + "core-foundation 0.10.1", "libc", ] +[[package]] +name = "core_detect" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f8f80099a98041a3d1622845c271458a2d73e688351bf3cb999266764b81d48" + [[package]] name = "cpubits" version = "0.1.1" @@ -834,36 +843,36 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.5.0" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +checksum = "01a7799fd6b852db0e61728dde9a204c423b44d689dbd432522543614b490e78" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-channel" -version = "0.5.16" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d85363c37faeca707aef026efa9f3b34d077bce547e48f770770625c6013679e" +checksum = "98b0cc327b5bc766e7fda9c9260cc0fa81b43a8e240440422dff70788e3f9ef1" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.22" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" +checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6" [[package]] name = "crypto-common" @@ -886,9 +895,9 @@ dependencies = [ [[package]] name = "cssparser" -version = "0.36.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dae61cf9c0abb83bd659dab65b7e4e38d8236824c85f0f804f173567bda257d2" +checksum = "8c9cdaae01d5ed7882b04d795e7f752f46ff52d2fa3b50a20d28c464510bba98" dependencies = [ "cssparser-macros", "dtoa-short", @@ -899,35 +908,34 @@ dependencies = [ [[package]] name = "cssparser-macros" -version = "0.6.1" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +checksum = "d045de693cb712d0b22c6a64be5b953f67b3ce00ab5ad3dd5d8b441886ab8e1a" dependencies = [ "quote", - "syn 2.0.119", + "syn 3.0.6", ] [[package]] name = "ctor" -version = "0.8.0" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "352d39c2f7bef1d6ad73db6f5160efcaed66d94ef8c6c573a8410c00bf909a98" -dependencies = [ - "ctor-proc-macro", - "dtor", -] +checksum = "914a755b7c2d4af2bdcff7ce1739e2db9a1b81a9b07123d8015786ae03c0980d" [[package]] -name = "ctor-proc-macro" -version = "0.0.7" +name = "ctutils" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52560adf09603e58c9a7ee1fe1dcb95a16927b17c127f0ac02d6e768a0e25bc1" +checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" +dependencies = [ + "cmov", +] [[package]] name = "darling" -version = "0.23.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" +checksum = "ed17f5901b6630b993ca003def43f2f8ef4014fc13b047b57aad617ff32bc2ec" dependencies = [ "darling_core", "darling_macro", @@ -935,26 +943,26 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.23.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" +checksum = "6837e2cf7485aaae18f86181d2f0e9a7ed297a025e220aeabf63fdebd3a2ddff" dependencies = [ "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.119", + "syn 3.0.6", ] [[package]] name = "darling_macro" -version = "0.23.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" +checksum = "2ac7135c3ef02b2f7833bbeb1be5ba7f966dcde8a87c6b87f65a778d71a02785" dependencies = [ "darling_core", "quote", - "syn 2.0.119", + "syn 3.0.6", ] [[package]] @@ -1010,7 +1018,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" dependencies = [ - "thiserror 2.0.20", + "thiserror 2.0.21", ] [[package]] @@ -1062,7 +1070,6 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", "crypto-common 0.1.7", - "subtle", ] [[package]] @@ -1074,13 +1081,14 @@ dependencies = [ "block-buffer 0.12.1", "const-oid", "crypto-common 0.2.2", + "ctutils", ] [[package]] name = "dirs" -version = "6.0.0" +version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +checksum = "8d57d423b3c82e89b9a24ca3091fee61f456a26edbd28d26c65906f4bc1dcd8f" dependencies = [ "dirs-sys", ] @@ -1103,7 +1111,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.2", "block2", "libc", "objc2", @@ -1117,7 +1125,7 @@ checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.6", ] [[package]] @@ -1145,9 +1153,9 @@ dependencies = [ [[package]] name = "dom_query" -version = "0.27.0" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521e380c0c8afb8d9a1e83a1822ee03556fc3e3e7dbc1fd30be14e37f9cb3f89" +checksum = "fac5fca71e65e94cc718a6e2af65d6e0f9c6027751c2aa562fbb5087fda639bc" dependencies = [ "bit-set", "cssparser", @@ -1182,21 +1190,6 @@ dependencies = [ "dtoa", ] -[[package]] -name = "dtor" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1057d6c64987086ff8ed0fd3fbf377a6b7d205cc7715868cd401705f715cbe4" -dependencies = [ - "dtor-proc-macro", -] - -[[package]] -name = "dtor-proc-macro" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5" - [[package]] name = "dunce" version = "1.0.5" @@ -1215,7 +1208,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26f2a8b3e564eba0877223dc343703ad0385794e882e6d13f3a4dd5c6b1f41ac" dependencies = [ - "cipher 0.5.2", + "cipher", ] [[package]] @@ -1227,7 +1220,7 @@ dependencies = [ "cc", "memchr", "rustc_version", - "toml 1.1.4+spec-1.1.0", + "toml 1.1.6+spec-1.1.0", "vswhom", "winreg", ] @@ -1240,11 +1233,16 @@ checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7" [[package]] name = "encoding_rs" -version = "0.8.35" +version = "0.8.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +checksum = "8e985e0451871ad22fb8d2b6b076e2028a502a0d3950998c2c5c0a4f9b5d9679" dependencies = [ "cfg-if", + "core_detect", + "multiversion_no_op", + "rustversion", + "scopeguard", + "simdutf8", ] [[package]] @@ -1380,18 +1378,19 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.11" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890" +checksum = "aedcfb3409746eddb02b9e19ebda1c3394f759a152e48ee875a0844d1b955484" [[package]] name = "flate2" -version = "1.1.9" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +checksum = "6e634e2e0ebac1ee034020da1ca582e17ffe4e0f5e985823721e168928136dcb" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.9.1", + "zlib-rs", ] [[package]] @@ -1424,7 +1423,7 @@ checksum = "ea5190182e6915eb873ddbc16e23b711b6eb1f9c00a0d0a3a91b5f6228475225" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.6", ] [[package]] @@ -1495,7 +1494,7 @@ checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.6", ] [[package]] @@ -1670,7 +1669,7 @@ dependencies = [ "js-sys", "libc", "r-efi 6.0.0", - "rand_core 0.10.1", + "rand_core", "wasm-bindgen", ] @@ -1712,7 +1711,7 @@ version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.2", "futures-channel", "futures-core", "futures-executor", @@ -1830,9 +1829,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.18" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "839c0e8a181239723652be9062bb56ca5bf5f64011f73b623f6f4fc59086a228" +checksum = "ef8e5e5a340588f4452631496976cf8636d4a7ecf600239fdc27615d2530bc16" dependencies = [ "atomic-waker", "bytes", @@ -1840,7 +1839,7 @@ dependencies = [ "futures-core", "futures-sink", "http", - "indexmap 2.14.0", + "indexmap 2.14.2", "slab", "tokio", "tokio-util", @@ -1879,9 +1878,9 @@ dependencies = [ [[package]] name = "hashlink" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32069d97bb81e38fa67eab65e3393bf804bb85969f2bc06bf13f64aef5aba248" +checksum = "a596f1b20ed2cc5ecac41a164aaebc7258057060f06c0cf7a2ba3991ee7990fb" dependencies = [ "hashbrown 0.17.1", ] @@ -1900,9 +1899,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" +checksum = "e17592d60ebacc7d5e169f4663c5f84f9161cc90328abcfe8456f41e4dfcb284" [[package]] name = "hex" @@ -1912,27 +1911,27 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hkdf" -version = "0.12.4" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +checksum = "4aaa26c720c68b866f2c96ef5c1264b3e6f473fe5d4ce61cd44bbe913e553018" dependencies = [ "hmac", ] [[package]] name = "hmac" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" dependencies = [ - "digest 0.10.7", + "digest 0.11.3", ] [[package]] name = "html5ever" -version = "0.38.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1054432bae2f14e0061e33d23402fbaa67a921d319d56adc6bcf887ddad1cbc2" +checksum = "46a1761807faccc9a19e86944bbf40610014066306f96edcdedc2fb714bcb7b8" dependencies = [ "log", "markup5ever", @@ -1979,18 +1978,18 @@ checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "hybrid-array" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707114b52a152fa7bdb290cd7cd5912d9467273b6d74e21b8d81aca1f8533f6b" +checksum = "27f864f10dfb56725ce5ce5472bc52252c8f93a4ab86327122cebf62c5f59a17" dependencies = [ "typenum", ] [[package]] name = "hyper" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22053281f852e11534f5198498373cbb59295120a20771d90f7ed1897490a72" +checksum = "27b501faa50e7a26c3d3560ca625132f4078a17771f4810baf70475ae48cbe43" dependencies = [ "atomic-waker", "bytes", @@ -2009,9 +2008,9 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.9" +version = "0.27.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" +checksum = "dfa8e654703247911e29c23fbeaa261834bd9bb74efba2f9acddc37bfb127f53" dependencies = [ "http", "hyper", @@ -2025,25 +2024,28 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +checksum = "ddc03d96684f9226b8a787cdb71488417b53ab5ea8fdb1dac946cb9431cc8bff" dependencies = [ - "base64 0.22.1", + "base64 0.23.1", "bytes", "futures-channel", "futures-util", "http", "http-body", + "httparse", "hyper", "ipnet", "libc", "percent-encoding", "pin-project-lite", "socket2", + "system-configuration", "tokio", "tower-service", "tracing", + "windows-registry", ] [[package]] @@ -2058,7 +2060,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core 0.62.2", + "windows-core", ] [[package]] @@ -2216,9 +2218,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.14.0" +version = "2.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855" dependencies = [ "equivalent", "hashbrown 0.17.1", @@ -2228,38 +2230,28 @@ dependencies = [ [[package]] name = "infer" -version = "0.19.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a588916bfdfd92e71cacef98a63d9b1f0d74d6599980d11894290e7ddefffcf7" +checksum = "f4200d433cbd5178df7797c9c2e75b348b728e39631cf14520d1e2fc424201f4" dependencies = [ "cfb", ] -[[package]] -name = "inout" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" -dependencies = [ - "block-padding 0.3.3", - "generic-array", -] - [[package]] name = "inout" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7" dependencies = [ - "block-padding 0.4.2", + "block-padding", "hybrid-array", ] [[package]] name = "ipnet" -version = "2.12.1" +version = "2.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a756c3fac73139e83f14c2d742155dd2b78d3ee56597b419a0579b7bdd6dd78" +checksum = "791930b43c0d5973160d90a8f3894509f2b273430f5c5c73b668636d0287c5c0" [[package]] name = "is-docker" @@ -2311,9 +2303,9 @@ dependencies = [ [[package]] name = "jiff" -version = "0.2.35" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668b7183bd07af9a4885f5c35b0cc5c83c4607a913c16b7e17291832910d2dcc" +checksum = "0ab1baf72f08796de0260609515130699b890ac25f30e610ad894bc5856cafdb" dependencies = [ "defmt", "jiff-core", @@ -2323,23 +2315,24 @@ dependencies = [ "portable-atomic", "portable-atomic-util", "serde_core", - "windows-link 0.2.1", + "windows-link", ] [[package]] name = "jiff-core" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7feca88439efe53da3754500c1851dedf3cb36c524dd5cf8225cc0794de95d09" +checksum = "5e52fe76043ccecc9005d2305ebaadf7d7fc0cc89ca6baa10a94d6bc68c7128c" dependencies = [ "defmt", + "log", ] [[package]] name = "jiff-static" -version = "0.2.35" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a69dcb3a21cfb32ce1cd056169337ca284af0766dd766e7878819b251a49204" +checksum = "378268a1116ad67ae6228701118ac9f491d78fda38a40a1f1a9e1348de6f7212" dependencies = [ "jiff-core", "proc-macro2", @@ -2378,6 +2371,36 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if", + "combine", + "jni-macros", + "jni-sys 0.4.1", + "log", + "simd_cesu8", + "thiserror 2.0.21", + "walkdir", + "windows-link", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.119", +] + [[package]] name = "jni-sys" version = "0.3.1" @@ -2408,9 +2431,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.104" +version = "0.3.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a" +checksum = "7883d941dae510fb2d978fc3fe018c71c9e2892fd38854de3e8b92c2e5ad9cc5" dependencies = [ "cfg-if", "futures-util", @@ -2419,21 +2442,21 @@ dependencies = [ [[package]] name = "json-patch" -version = "3.0.1" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "863726d7afb6bc2590eeff7135d923545e5e964f004c2ccf8716c25e70a86f08" +checksum = "7421438de105a0827e44fadd05377727847d717c80ce29a229f85fd04c427b72" dependencies = [ "jsonptr", "serde", "serde_json", - "thiserror 1.0.69", + "thiserror 2.0.21", ] [[package]] name = "jsonptr" -version = "0.6.3" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dea2b27dd239b2556ed7a25ba842fe47fd602e7fc7433c2a8d6106d4d9edd70" +checksum = "a5a3cc660ba5d72bce0b3bb295bf20847ccbb40fd423f3f05b61273672e561fe" dependencies = [ "serde", "serde_json", @@ -2441,20 +2464,19 @@ dependencies = [ [[package]] name = "keyboard-types" -version = "0.7.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" +checksum = "0fbe853b403ae61a04233030ae8a79d94975281ed9770a1f9e246732b534b28d" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.2", "serde", - "unicode-segmentation", ] [[package]] name = "keyring" -version = "4.1.6" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72585bb6cc9bc370d1d545b7e23fcce71dfd4461c5e15275e3cf51bdfd9a980a" +checksum = "2270074a3d26bcac93c1dc5d2845eb4c089e8d761ccf6e0ea266a16004640627" dependencies = [ "apple-native-keyring-store", "keyring-core", @@ -2528,9 +2550,9 @@ dependencies = [ [[package]] name = "libredox" -version = "0.1.20" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d0a00925a9f930d679b6789b721e3a7f9ed110f41b86d2497caa780c3a070a" +checksum = "61ff90caf6077a803a240f62fdbe88645a890bbca49ef8174c3cb0404362171d" dependencies = [ "libc", ] @@ -2585,7 +2607,6 @@ dependencies = [ "printpdf", "r2d2", "r2d2_sqlite", - "rand_core 0.6.4", "regex", "reqwest 0.12.28", "rfd", @@ -2607,7 +2628,7 @@ dependencies = [ "tracing-subscriber", "uuid", "walkdir", - "windows 0.62.2", + "windows", ] [[package]] @@ -2621,9 +2642,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.33" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" +checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" [[package]] name = "lopdf" @@ -2631,14 +2652,14 @@ version = "0.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e2ec995d822e05cabc3f06d196ee43650af3fe4fe38012cacb35e0c3d113b68" dependencies = [ - "aes 0.9.2", - "bitflags 2.13.1", - "cbc 0.2.1", + "aes", + "bitflags 2.13.2", + "cbc", "ecb", "encoding_rs", "flate2", "getrandom 0.4.3", - "indexmap 2.14.0", + "indexmap 2.14.2", "itoa", "log", "md-5", @@ -2647,21 +2668,21 @@ dependencies = [ "rangemap", "sha2 0.11.0", "stringprep", - "thiserror 2.0.20", + "thiserror 2.0.21", "weezl", ] [[package]] name = "lru-slab" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" +checksum = "4050469837a6ff301cd14c1f8f24f88549e6d548f24f64e2148eb0f72cebc51f" [[package]] name = "markup5ever" -version = "0.38.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8983d30f2915feeaaab2d6babdd6bc7e9ed1a00b66b5e6d74df19aa9c0e91862" +checksum = "7122d987ec5f704ee56f6e5b41a7d93722e9aae27ae07cafa4036c4d3f9757de" dependencies = [ "log", "tendril", @@ -2724,11 +2745,21 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "miniz_oxide" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63fbc4a50860e98e7b2aa7804ded1db5cbc3aff9193adaff57a6931bf7c4b4c" +dependencies = [ + "adler2", + "simd-adler32", +] + [[package]] name = "mio" -version = "1.2.2" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427" +checksum = "4b18443e9c262bfe8fa82f51666e2642c53393f7e5c27b3e1aeab922cff5b9d8" dependencies = [ "libc", "wasi", @@ -2747,9 +2778,9 @@ dependencies = [ [[package]] name = "muda" -version = "0.19.3" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd04e60bc0b07438a6771710ee1698f98f6ebbc7f89b61264af1563b8aeb878" +checksum = "cca139e57da4383727f189e43e66e84fa372347027fc996f9f1a007ec0a37996" dependencies = [ "crossbeam-channel", "dpi", @@ -2762,10 +2793,16 @@ dependencies = [ "once_cell", "png 0.18.1", "serde", - "thiserror 2.0.20", + "thiserror 2.0.21", "windows-sys 0.61.2", ] +[[package]] +name = "multiversion_no_op" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743fb55ba31b18fb1ecef6bdc9aa2743314978ac084044301a7eee33fb99a20d" + [[package]] name = "natord" version = "1.0.9" @@ -2778,7 +2815,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.2", "jni-sys 0.3.1", "log", "ndk-sys", @@ -2787,6 +2824,12 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + [[package]] name = "ndk-sys" version = "0.6.0+11769913" @@ -2945,11 +2988,12 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.2", "block2", "objc2", "objc2-core-foundation", "objc2-foundation", + "objc2-quartz-core", ] [[package]] @@ -2958,7 +3002,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.2", "objc2", "objc2-foundation", ] @@ -2979,7 +3023,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.2", "dispatch2", "objc2", ] @@ -2990,7 +3034,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.2", "dispatch2", "objc2", "objc2-core-foundation", @@ -3023,7 +3067,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.2", "objc2", "objc2-core-foundation", "objc2-core-graphics", @@ -3050,7 +3094,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.2", "block2", "libc", "objc2", @@ -3073,7 +3117,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.2", "objc2", "objc2-core-foundation", ] @@ -3084,7 +3128,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f112d1746737b0da274ef79a23aac283376f335f4095a083a267a082f21db0c0" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.2", "objc2", "objc2-app-kit", "objc2-foundation", @@ -3096,7 +3140,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.2", "objc2", "objc2-core-foundation", "objc2-foundation", @@ -3108,7 +3152,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.2", "block2", "objc2", "objc2-cloud-kit", @@ -3139,7 +3183,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2e5aaab980c433cf470df9d7af96a7b46a9d892d521a2cbbb2f8a4c16751e7f" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.2", "block2", "objc2", "objc2-app-kit", @@ -3155,9 +3199,9 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "open" -version = "5.4.1" +version = "5.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9cfef937e9c486488c7e3d949ae31c0f1d06bdacd75b99c086cb35356e30408" +checksum = "aa576c76302b7b808eecc68061e67336c47833ef9d22caa74dda10fa9675eebc" dependencies = [ "dunce", "is-wsl", @@ -3207,7 +3251,7 @@ dependencies = [ "objc2-osa-kit", "serde", "serde_json", - "thiserror 2.0.20", + "thiserror 2.0.21", ] [[package]] @@ -3285,18 +3329,17 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-link 0.2.1", + "windows-link", ] [[package]] name = "password-hash" -version = "0.5.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" +checksum = "aab41826031698d6ffcd9cff78ef56ef998e39dc7e5067cdfebe373842d4723b" dependencies = [ - "base64ct", - "rand_core 0.6.4", - "subtle", + "getrandom 0.4.3", + "phc", ] [[package]] @@ -3324,6 +3367,17 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "phc" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44dc769b75f93afdddd8c7fa12d685292ddeff1e66f7f0f3a234cf1818afe892" +dependencies = [ + "base64ct", + "ctutils", + "getrandom 0.4.3", +] + [[package]] name = "phf" version = "0.12.1" @@ -3420,12 +3474,12 @@ checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548" [[package]] name = "plist" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da1d65da6dd5d1e44199ac0f58712d241c0f439f80adea8924d832384087f85" +checksum = "2896bade328c13f7042a297ea5ac5b0951f6cf989dea5f32c2fd98da398195cb" dependencies = [ - "base64 0.22.1", - "indexmap 2.14.0", + "base64 0.23.1", + "indexmap 2.14.2", "quick-xml", "serde", "time", @@ -3441,7 +3495,7 @@ dependencies = [ "crc32fast", "fdeflate", "flate2", - "miniz_oxide", + "miniz_oxide 0.8.9", ] [[package]] @@ -3450,11 +3504,11 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.2", "crc32fast", "fdeflate", "flate2", - "miniz_oxide", + "miniz_oxide 0.8.9", ] [[package]] @@ -3479,9 +3533,9 @@ checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" [[package]] name = "portable-atomic-util" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" +checksum = "10ab3eb7f3becc3a1cbc4f2c6f20267996cfc1a6467a873763411b136a122715" dependencies = [ "portable-atomic", ] @@ -3509,9 +3563,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "printpdf" -version = "0.12.6" +version = "0.12.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e75e1f6d16f80c8f34918a4cc68743d703e8ee5016fac9508e223eb8e60445a0" +checksum = "95d50369c5e18e18d4716bd855172db3a70f9e82c966687ae051ea58138f285c" dependencies = [ "allsorts-azul", "base64 0.22.1", @@ -3554,7 +3608,7 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.25.13+spec-1.1.0", + "toml_edit 0.25.15+spec-1.1.0", ] [[package]] @@ -3611,18 +3665,18 @@ checksum = "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea" [[package]] name = "quick-xml" -version = "0.41.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1" +checksum = "41b1177fdf999d2321d3fb46ff47159d9c1fb9ad66a4879f8c50a0b504615e9b" dependencies = [ "memchr", ] [[package]] name = "quinn" -version = "0.11.11" +version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c1a41e437b6bbd489372cd4971de128e85c855f56c57f283d20ff016cf7c0a8" +checksum = "4051e23e9185c255a7e33ef59cdbca87a22d359052eecd22fc6b901fb37d9d11" dependencies = [ "bytes", "cfg_aliases", @@ -3632,7 +3686,7 @@ dependencies = [ "rustc-hash", "rustls", "socket2", - "thiserror 2.0.20", + "thiserror 2.0.21", "tokio", "tracing", "web-time", @@ -3640,9 +3694,9 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.17" +version = "0.11.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04759210543be93709136e28212294a659ef5001836ff4eab4d663e4529bba83" +checksum = "0e750cca55fe4f0439a15d0bb529da9651e79993e8e72c61a899a36d462befbe" dependencies = [ "bytes", "getrandom 0.4.3", @@ -3654,7 +3708,7 @@ dependencies = [ "rustls", "rustls-pki-types", "slab", - "thiserror 2.0.20", + "thiserror 2.0.21", "tinyvec", "tracing", "web-time", @@ -3662,9 +3716,9 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.15" +version = "0.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35a133f956daabe89a61a685c2649f13d82d5aa4bd5d12d1277e1072a21c0694" +checksum = "af66907df18639dcf4db56ca65490cabc4b27a97dbadd96f2926cca73298f016" dependencies = [ "cfg_aliases", "libc", @@ -3719,22 +3773,13 @@ dependencies = [ [[package]] name = "rand" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" +checksum = "65c9fb96cbc91e3478eaae79a69fcd3f1ae4ad052e471fe6732fff548984b4af" dependencies = [ "chacha20", "getrandom 0.4.3", - "rand_core 0.10.1", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.17", + "rand_core", ] [[package]] @@ -3749,7 +3794,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a" dependencies = [ - "rand_core 0.10.1", + "rand_core", ] [[package]] @@ -3770,18 +3815,17 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.2", ] [[package]] name = "redox_users" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" +checksum = "60dc65c0ff1a7ae1294b0c67b9f14baf70b644404010370171787bfac1038fc0" dependencies = [ - "getrandom 0.2.17", "libredox", - "thiserror 2.0.20", + "thiserror 2.0.21", ] [[package]] @@ -3801,7 +3845,7 @@ checksum = "92ecd8964f8453721699a1ed72037b0db49ce2f5a5138486ee89bed6f67cdf3a" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.6", ] [[package]] @@ -3870,18 +3914,18 @@ dependencies = [ "url", "wasm-bindgen", "wasm-bindgen-futures", - "wasm-streams", + "wasm-streams 0.4.2", "web-sys", "webpki-roots", ] [[package]] name = "reqwest" -version = "0.13.1" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04e9018c9d814e5f30cc16a0f03271aeab3571e609612d9fe78c1aa8d11c2f62" +checksum = "16a1cfa75cc186dd73d5818e510e042e40927bccc9c236b061cea97e1eb08029" dependencies = [ - "base64 0.22.1", + "base64 0.23.1", "bytes", "futures-core", "futures-util", @@ -3910,7 +3954,7 @@ dependencies = [ "url", "wasm-bindgen", "wasm-bindgen-futures", - "wasm-streams", + "wasm-streams 0.5.0", "web-sys", ] @@ -3959,7 +4003,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c51c9ae4df8a7fba42103df5c621fa3c37eccf3a3c650879e90fc48b11cc192c" dependencies = [ "hashbrown 0.16.1", - "thiserror 2.0.20", + "thiserror 2.0.21", ] [[package]] @@ -3968,7 +4012,7 @@ version = "0.40.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23f2a97da3e3873c73cb2a2e71b35c40ff95e0b1eefa8d72d8499a6928c3b5b3" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.2", "fallible-iterator", "fallible-streaming-iterator", "hashlink", @@ -3994,11 +4038,11 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +checksum = "891efababe418670775f199f0d233d84843c227a0949a883ce15b37c78d6629d" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.2", "errno", "libc", "linux-raw-sys", @@ -4007,9 +4051,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.43" +version = "0.23.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0283386ce02abc0151e1761d08802dfe86c173b0b494af5cbc086574e453da06" +checksum = "0d41d731c7d2f962d1ccc364cec258de3c0e93b38c2fb3ba97ac74513048d634" dependencies = [ "once_cell", "ring", @@ -4043,13 +4087,13 @@ dependencies = [ [[package]] name = "rustls-platform-verifier" -version = "0.6.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" +checksum = "1167586491e2b18b8bfbb293e8180ec17c201c4f076d7cb3070ca964e7598f98" dependencies = [ - "core-foundation", + "core-foundation 0.10.1", "core-foundation-sys", - "jni", + "jni 0.22.4", "log", "once_cell", "rustls", @@ -4064,15 +4108,15 @@ dependencies = [ [[package]] name = "rustls-platform-verifier-android" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" +checksum = "eec689c0bc40ff2458a5977b6619cb718087084a18e02a131c599b62d05e1a5f" [[package]] name = "rustls-webpki" -version = "0.103.14" +version = "0.103.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0527518605e68109d875e248ea259b6758801cf165e4b2c2733ae3b51f12535a" +checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2" dependencies = [ "ring", "rustls-pki-types", @@ -4177,20 +4221,20 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "secret-service" -version = "5.1.0" +version = "5.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a62d7f86047af0077255a29494136b9aaaf697c76ff70b8e49cded4e2623c14" +checksum = "5107b24b91445dd2aa449a258a1807b63240942157292354dc5bfdbeb8bc6db8" dependencies = [ - "aes 0.8.4", - "cbc 0.1.2", + "aes", + "cbc", "futures-util", - "generic-array", - "getrandom 0.2.17", + "getrandom 0.4.3", "hkdf", + "hybrid-array", "num", "once_cell", "serde", - "sha2 0.10.9", + "sha2 0.11.0", "zbus", ] @@ -4200,8 +4244,8 @@ version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags 2.13.1", - "core-foundation", + "bitflags 2.13.2", + "core-foundation 0.10.1", "core-foundation-sys", "libc", "security-framework-sys", @@ -4219,11 +4263,11 @@ dependencies = [ [[package]] name = "selectors" -version = "0.36.1" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5d9c0c92a92d33f08817311cf3f2c29a3538a8240e94a6a3c622ce652d7e00c" +checksum = "8adfa1c298912827b8a28b223b3b874357397ae706e6190acd9bf28cee99114d" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.2", "cssparser", "derive_more", "log", @@ -4285,7 +4329,7 @@ checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.6", ] [[package]] @@ -4320,7 +4364,7 @@ checksum = "8d3b1629de253c70a0508c3899572da79ca359fdab27c7920ff00406df418906" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.6", ] [[package]] @@ -4355,16 +4399,16 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.22.0" +version = "3.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee78f1fbe43ac4a0e47aadb3dbd357b69eb0d3793e948624cd03dd2750ab1c0a" +checksum = "df9adc193c780ef8f159aee8b61e2d5801aaa555e6eb0947fe45530ec506296f" dependencies = [ - "base64 0.22.1", + "base64 0.23.1", "bs58", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.14.0", + "indexmap 2.14.2", "jiff", "schemars 0.9.0", "schemars 1.2.2", @@ -4376,14 +4420,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.22.0" +version = "3.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8705578779c2b6bd90d84d66eb2e206b708b1a4d7b9f17641b293545bf1c7e46" +checksum = "3e17bbc68e28663bbbb90df47e058aa7eda4fb445b89fe70457bb94fbccf6e49" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.6", ] [[package]] @@ -4435,7 +4479,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" dependencies = [ "cfg-if", - "cpufeatures 0.3.0", + "cpufeatures 0.3.1", "digest 0.11.3", ] @@ -4450,13 +4494,13 @@ dependencies = [ [[package]] name = "shared_child" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e362d9935bc50f019969e2f9ecd66786612daae13e8f277be7bfb66e8bed3f7" +checksum = "607549934f6cc26b89cfecfdc46fa90f1e5d1536a68349b0c3a4f9d1c0d37959" dependencies = [ "libc", "sigchld", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -4467,9 +4511,9 @@ checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" [[package]] name = "sigchld" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47106eded3c154e70176fc83df9737335c94ce22f821c32d17ed1db1f83badb1" +checksum = "24f2b37f04360cd465089b87a9c3869c08220a2f3458463f0adf8badf5e77f2c" dependencies = [ "libc", "os_pipe", @@ -4478,9 +4522,9 @@ dependencies = [ [[package]] name = "signal-hook" -version = "0.3.18" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" +checksum = "b2a0c28ca5908dbdbcd52e6fdaa00358ab88637f8ab33e1f188dd510eb44b53d" dependencies = [ "libc", "signal-hook-registry", @@ -4502,6 +4546,22 @@ version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" +[[package]] +name = "simd_cesu8" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11031e251abf8611c80f460e19dbdeb54a66db918e49c65a7065b46ac7aec520" +dependencies = [ + "rustc_version", + "simdutf8", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "similar" version = "3.2.0" @@ -4513,9 +4573,9 @@ dependencies = [ [[package]] name = "siphasher" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" +checksum = "33f4fe9184a62d842c9ef383018f3306d8ba224fd9d836f56d7288308847c256" [[package]] name = "slab" @@ -4525,9 +4585,9 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.15.2" +version = "1.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" +checksum = "f9395f0f0eee849a9b707b2f06bb92a6a422090e2123bb2ef8e87a0e61892a8e" dependencies = [ "serde", ] @@ -4695,9 +4755,9 @@ dependencies = [ [[package]] name = "syn" -version = "3.0.3" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee" dependencies = [ "proc-macro2", "quote", @@ -4715,13 +4775,13 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.13.2" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +checksum = "901704edd0dfe137f1987838ee4f259e4e063c31371bdb423f7ae38ec6f77f02" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.6", ] [[package]] @@ -4735,7 +4795,28 @@ dependencies = [ "ntapi", "objc2-core-foundation", "objc2-io-kit", - "windows 0.62.2", + "windows", +] + +[[package]] +name = "system-configuration" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" +dependencies = [ + "bitflags 2.13.2", + "core-foundation 0.9.4", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", ] [[package]] @@ -4753,13 +4834,13 @@ dependencies = [ [[package]] name = "tao" -version = "0.35.3" +version = "0.37.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1c93047acf68669466a34690ac58cca7010bd1b201e1ec86f1fd0a75d3dd4a9" +checksum = "f37f381f4e048e6cdf038b5705f8cf14ad108279d46eb968140a7b291aba9400" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.2", "block2", - "core-foundation", + "core-foundation 0.10.1", "core-graphics", "crossbeam-channel", "dbus", @@ -4769,24 +4850,24 @@ dependencies = [ "gdkwayland-sys", "gdkx11-sys", "gtk", - "jni", + "jni 0.21.1", "libc", "log", "ndk", + "ndk-context", "ndk-sys", "objc2", "objc2-app-kit", "objc2-foundation", "objc2-ui-kit", - "once_cell", "parking_lot", "percent-encoding", "raw-window-handle", "tao-macros", "unicode-segmentation", "url", - "windows 0.61.3", - "windows-core 0.61.2", + "windows", + "windows-core", "windows-version", "x11-dl", ] @@ -4821,9 +4902,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tauri" -version = "2.11.5" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "667b20e2726d572dea2de7370da16e188eb06008faf9a92fab7cdc46791190b5" +checksum = "cb20ef8e6f97d6fe03039666cd82861f09a38b56291fa2f0f9fe140023f61c1a" dependencies = [ "anyhow", "bytes", @@ -4837,7 +4918,7 @@ dependencies = [ "heck 0.5.0", "http", "image", - "jni", + "jni 0.21.1", "libc", "log", "mime", @@ -4850,7 +4931,7 @@ dependencies = [ "percent-encoding", "plist", "raw-window-handle", - "reqwest 0.13.1", + "reqwest 0.13.5", "serde", "serde_json", "serde_repr", @@ -4861,21 +4942,21 @@ dependencies = [ "tauri-runtime", "tauri-runtime-wry", "tauri-utils", - "thiserror 2.0.20", + "thiserror 2.0.21", "tokio", "tray-icon", "url", "webkit2gtk", "webview2-com", "window-vibrancy", - "windows 0.61.3", + "windows", ] [[package]] name = "tauri-build" -version = "2.6.3" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc9ce40b16101cb6ea63d3e221567affd1c3a9205f95d7bc574941a10636b632" +checksum = "5b5ae674f48836f5dd2eeaf9e221c095bd3e78a8d0439c77ca93b48740a1b644" dependencies = [ "anyhow", "cargo_toml", @@ -4894,16 +4975,16 @@ dependencies = [ [[package]] name = "tauri-codegen" -version = "2.6.3" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08279169ff42f8fc45a1dbc9dcae888893ba95288142e5880c59b93a26d2cfc5" +checksum = "3926b73ac01df7c14f19ff872cd56e67213a87acc0000ea37ddb300f3d11a3e3" dependencies = [ "base64 0.22.1", "brotli", "ico", "json-patch", "plist", - "png 0.17.16", + "png 0.18.1", "proc-macro2", "quote", "semver", @@ -4912,7 +4993,7 @@ dependencies = [ "sha2 0.10.9", "syn 2.0.119", "tauri-utils", - "thiserror 2.0.20", + "thiserror 2.0.21", "time", "url", "uuid", @@ -4921,9 +5002,9 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "2.6.3" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8b394794f399a421811d06966343e7933fcae92d59f5180b9388d1174497a45" +checksum = "d21d0fa2c0529972ea6ecaf7404fcf40efac098eda0beb06ca682f41e33a6aa5" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -4935,9 +5016,9 @@ dependencies = [ [[package]] name = "tauri-plugin" -version = "2.6.3" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74be5dd4bed9afbd145e5716b5fa2ec28cbc29c34ffa61c258c9273d896c8020" +checksum = "c9ff3ebb9fda56ceb93d46f6cbb126bae82951bf43498543a5163dde5def49a1" dependencies = [ "anyhow", "glob", @@ -4951,9 +5032,9 @@ dependencies = [ [[package]] name = "tauri-plugin-dialog" -version = "2.7.2" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2d3c1dbe38037e7f590cdf2492594d5ceebe031e7bc7e827509b22a999d2940" +checksum = "7527c5fd1678032d116c1a82e5d609c67370e56f858ae6cfd376bbca37fe0490" dependencies = [ "log", "raw-window-handle", @@ -4963,15 +5044,15 @@ dependencies = [ "tauri", "tauri-plugin", "tauri-plugin-fs", - "thiserror 2.0.20", + "thiserror 2.0.21", "url", ] [[package]] name = "tauri-plugin-fs" -version = "2.5.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7ecc274121aca0c036a2b42d1cbe83d368d348f54e0bb8a735c2b1548e8f371" +checksum = "466eb32466fe5021b6728b06862f9ff14a9f7e1af890047654e03a96d7c0e1bb" dependencies = [ "anyhow", "dunce", @@ -4986,16 +5067,16 @@ dependencies = [ "tauri", "tauri-plugin", "tauri-utils", - "thiserror 2.0.20", - "toml 1.1.4+spec-1.1.0", + "thiserror 2.0.21", + "toml 1.1.6+spec-1.1.0", "url", ] [[package]] name = "tauri-plugin-process" -version = "2.3.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d55511a7bf6cd70c8767b02c97bf8134fa434daf3926cfc1be0a0f94132d165a" +checksum = "74ae3d8549ae564c0397377373e262f340908eb23a5b9fbe03f2a00007dc0038" dependencies = [ "tauri", "tauri-plugin", @@ -5003,9 +5084,9 @@ dependencies = [ [[package]] name = "tauri-plugin-shell" -version = "2.3.5" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8457dbf9e2bab1edd8df22bb2c20857a59a9868e79cb3eac5ed639eec4d0c73b" +checksum = "094bdbc47e5efe36544ba21b3a53ab5c724150236cf55e6c9be46191deb6eab6" dependencies = [ "encoding_rs", "log", @@ -5018,15 +5099,15 @@ dependencies = [ "shared_child", "tauri", "tauri-plugin", - "thiserror 2.0.20", + "thiserror 2.0.21", "tokio", ] [[package]] name = "tauri-plugin-updater" -version = "2.10.1" +version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806d9dac662c2e4594ff03c647a552f2c9bd544e7d0f683ec58f872f952ce4af" +checksum = "3cb0b2ea3e85ca287990d3859a29cc5cb18024240fd78f62e027fb7963670f18" dependencies = [ "base64 0.22.1", "dirs", @@ -5038,7 +5119,7 @@ dependencies = [ "minisign-verify", "osakit", "percent-encoding", - "reqwest 0.13.1", + "reqwest 0.13.5", "rustls", "semver", "serde", @@ -5047,25 +5128,25 @@ dependencies = [ "tauri", "tauri-plugin", "tempfile", - "thiserror 2.0.20", + "thiserror 2.0.21", "time", "tokio", "url", - "windows-sys 0.60.2", + "windows-sys 0.61.2", "zip", ] [[package]] name = "tauri-runtime" -version = "2.11.3" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0b4bc95aed361b0019067d189a1174a603d460d0f6c72606512d59fc9c12ec8" +checksum = "c9e6d5ef76985b32ff012a43b58df205d25a285e400ca878afcacddc5d5f3238" dependencies = [ "cookie", "dpi", "gtk", "http", - "jni", + "jni 0.21.1", "objc2", "objc2-ui-kit", "objc2-web-kit", @@ -5073,22 +5154,22 @@ dependencies = [ "serde", "serde_json", "tauri-utils", - "thiserror 2.0.20", + "thiserror 2.0.21", "url", "webkit2gtk", "webview2-com", - "windows 0.61.3", + "windows", ] [[package]] name = "tauri-runtime-wry" -version = "2.11.4" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e6fac707727b7a2f48e4ded90976324267371073edbb415ffb73bb0458d203f" +checksum = "fa829eb69860cf1fb0bedb21d2d5f1effce3527d054a68ca1cd7355c654400a3" dependencies = [ "gtk", "http", - "jni", + "jni 0.21.1", "log", "objc2", "objc2-app-kit", @@ -5102,15 +5183,15 @@ dependencies = [ "url", "webkit2gtk", "webview2-com", - "windows 0.61.3", + "windows", "wry", ] [[package]] name = "tauri-utils" -version = "2.9.3" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e176a18e67764923c4f1ce66f25ae4abe5f688384d5eb1a0fa6c77f3d90f887" +checksum = "4dd257082deff79550de3409ed146104aeaf86fe38649615b04a304144939677" dependencies = [ "anyhow", "brotli", @@ -5136,8 +5217,8 @@ dependencies = [ "serde_json", "serde_with", "swift-rs", - "thiserror 2.0.20", - "toml 1.1.4+spec-1.1.0", + "thiserror 2.0.21", + "toml 1.1.6+spec-1.1.0", "url", "urlpattern", "uuid", @@ -5152,7 +5233,7 @@ checksum = "cc65d45c68858bfe420dd29e834b5d15dbecf8a07a8a16cf4d532c7b1f69d4b6" dependencies = [ "dunce", "embed-resource", - "toml 1.1.4+spec-1.1.0", + "toml 1.1.6+spec-1.1.0", ] [[package]] @@ -5188,11 +5269,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.20" +version = "2.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +checksum = "09e52cb86a36cede5cb101bf8908837b3e4c6e5e59fe7fd85c23fb56200d189e" dependencies = [ - "thiserror-impl 2.0.20", + "thiserror-impl 2.0.21", ] [[package]] @@ -5208,13 +5289,13 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.20" +version = "2.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.6", ] [[package]] @@ -5268,18 +5349,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +checksum = "fd3ca314f692efd6c868f8408f53fe444634a845f96c028b97d35f6a1f79f0ee" [[package]] name = "tokio" @@ -5306,14 +5378,14 @@ checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.6", ] [[package]] name = "tokio-rustls" -version = "0.26.4" +version = "0.26.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +checksum = "c9cc2678c2cdd569ef8215e2afd7954ada2ae20b4fdd2c5fe6139a3b02d105db" dependencies = [ "rustls", "tokio", @@ -5347,26 +5419,11 @@ dependencies = [ [[package]] name = "toml" -version = "0.9.12+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" -dependencies = [ - "indexmap 2.14.0", - "serde_core", - "serde_spanned 1.1.1", - "toml_datetime 0.7.5+spec-1.1.0", - "toml_parser", - "toml_writer", - "winnow 0.7.15", -] - -[[package]] -name = "toml" -version = "1.1.4+spec-1.1.0" +version = "1.1.6+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3aace63f4bbcdfc2c965b059de67119c89c4017a70d633be6c104910f67056f5" +checksum = "920602543f0911ab71da12c50d59701da54c196d1a2bf5cb4b75667f137a406a" dependencies = [ - "indexmap 2.14.0", + "indexmap 2.14.2", "serde_core", "serde_spanned 1.1.1", "toml_datetime 1.1.1+spec-1.1.0", @@ -5384,15 +5441,6 @@ dependencies = [ "serde", ] -[[package]] -name = "toml_datetime" -version = "0.7.5+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" -dependencies = [ - "serde_core", -] - [[package]] name = "toml_datetime" version = "1.1.1+spec-1.1.0" @@ -5408,7 +5456,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.14.0", + "indexmap 2.14.2", "toml_datetime 0.6.3", "winnow 0.5.40", ] @@ -5419,7 +5467,7 @@ version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" dependencies = [ - "indexmap 2.14.0", + "indexmap 2.14.2", "serde", "serde_spanned 0.6.9", "toml_datetime 0.6.3", @@ -5428,11 +5476,11 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.25.13+spec-1.1.0" +version = "0.25.15+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6975367e4d2ef766d86af01ffad14b622fecc8d4357a998fbc4deb6e9bacaf9b" +checksum = "1340ea94a5856333492c9064b02c778b191dd2c853778d9609debdcdfea3a614" dependencies = [ - "indexmap 2.14.0", + "indexmap 2.14.2", "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", "winnow 1.0.4", @@ -5475,7 +5523,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ "async-compression", - "bitflags 2.13.1", + "bitflags 2.13.2", "bytes", "futures-core", "futures-util", @@ -5566,9 +5614,9 @@ dependencies = [ [[package]] name = "tray-icon" -version = "0.24.2" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "045979e3f037cd18ad1cb2a419dfda133c5c29c9f3453370079f2255d46c257e" +checksum = "b2b9c52859a94554803ccd4a24b98f74148ebc73b90676d783f3490b1bff9d72" dependencies = [ "crossbeam-channel", "dirs", @@ -5582,7 +5630,7 @@ dependencies = [ "once_cell", "png 0.18.1", "serde", - "thiserror 2.0.20", + "thiserror 2.0.21", "windows-sys 0.61.2", ] @@ -5621,47 +5669,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "unic-char-property" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" -dependencies = [ - "unic-char-range", -] - -[[package]] -name = "unic-char-range" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" - -[[package]] -name = "unic-common" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" - -[[package]] -name = "unic-ucd-ident" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e230a37c0381caa9219d67cf063aa3a375ffed5bf541a452db16e744bdab6987" -dependencies = [ - "unic-char-property", - "unic-char-range", - "unic-ucd-version", -] - -[[package]] -name = "unic-ucd-version" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" -dependencies = [ - "unic-common", -] - [[package]] name = "unicode-bidi" version = "0.3.18" @@ -5682,9 +5689,9 @@ checksum = "0b993bddc193ae5bd0d623b49ec06ac3e9312875fdae725a975c51db1cc1677f" [[package]] name = "unicode-ident" -version = "1.0.24" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954" [[package]] name = "unicode-joining-type" @@ -5734,13 +5741,13 @@ dependencies = [ [[package]] name = "urlpattern" -version = "0.3.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70acd30e3aa1450bc2eece896ce2ad0d178e9c079493819301573dae3c37ba6d" +checksum = "df16f50ef4cc145211879a3867ba757076b25dfee812040dcb0658bd9ae7904b" dependencies = [ + "icu_properties", "regex", "serde", - "unic-ucd-ident", "url", ] @@ -5752,9 +5759,9 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" -version = "1.24.1" +version = "1.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cefc03fd367c0c6d4305de1b312cf00248c4114f4a0418ce6a6af769e3b0bd9" +checksum = "2ef6dac1e96601b4fb3acccccff2139741fcb757cb9a36089bf5be91cfb285ce" dependencies = [ "getrandom 0.4.3", "js-sys", @@ -5843,9 +5850,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.127" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70" +checksum = "9bb54f33acc68fd454578d9820b0bde1a1a3d17aa17bb7b6595806d02886d409" dependencies = [ "cfg-if", "once_cell", @@ -5856,19 +5863,20 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.77" +version = "0.4.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b7777d5cc23d0e91404e53ce2d5e8ec7acae3026b16233dba62cd3246457950" +checksum = "3cbab34de2d982e9b48e18d216d04c4a6f641066ff19ffb699980f591ee3610e" dependencies = [ "js-sys", + "tokio", "wasm-bindgen", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.127" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1" +checksum = "2e29d0c35b16e224a7eeb5cd2d25e3e1968fbd65604117b44d3b789d00ee8535" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5876,22 +5884,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.127" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284" +checksum = "6f501a8bc3719dba86ef8ae4728879c08001bea749eb1333ac5b91e040e2a6b7" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.6", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.127" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf" +checksum = "23f0c9c52aa7cd7d77769a4cfe2a9adb1b331f489a41d912ce14513d5ab995c6" dependencies = [ "unicode-ident", ] @@ -5909,11 +5917,24 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wasm-streams" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "web-sys" -version = "0.3.104" +version = "0.3.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c435338968042f4f59a557f690a253676d47ce13ceb55d70100e7facf6620a30" +checksum = "88261b9deccee56594c11a3460c462c41f58d148598fe70ad77070126a68aba4" dependencies = [ "js-sys", "wasm-bindgen", @@ -6005,16 +6026,14 @@ dependencies = [ [[package]] name = "webview2-com" -version = "0.38.2" +version = "0.39.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7130243a7a5b33c54a444e54842e6a9e133de08b5ad7b5861cd8ed9a6a5bc96a" +checksum = "3f89fca7a704cee10dcb3654c1dbb8941d1783132f1917358af75bec37a7d7e6" dependencies = [ "webview2-com-macros", "webview2-com-sys", - "windows 0.61.3", - "windows-core 0.61.2", - "windows-implement", - "windows-interface", + "windows", + "windows-core", ] [[package]] @@ -6030,13 +6049,13 @@ dependencies = [ [[package]] name = "webview2-com-sys" -version = "0.38.2" +version = "0.39.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "381336cfffd772377d291702245447a5251a2ffa5bad679c99e61bc48bacbf9c" +checksum = "b3a07132775117d6065853d9d1178157b8c90e228de47129d6bce2c7edebedfb" dependencies = [ - "thiserror 2.0.20", - "windows 0.61.3", - "windows-core 0.61.2", + "thiserror 2.0.21", + "windows", + "windows-core", ] [[package]] @@ -6078,51 +6097,30 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "window-vibrancy" -version = "0.6.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9bec5a31f3f9362f2258fd0e9c9dd61a9ca432e7306cc78c444258f0dce9a9c" +checksum = "111e51caca442cafd9bab396628ac4d814880eaea4e63dfd76a12e9f342b5580" dependencies = [ "objc2", "objc2-app-kit", "objc2-core-foundation", "objc2-foundation", + "objc2-quartz-core", "raw-window-handle", - "windows-sys 0.59.0", + "windows-sys 0.61.2", "windows-version", ] -[[package]] -name = "windows" -version = "0.61.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" -dependencies = [ - "windows-collections 0.2.0", - "windows-core 0.61.2", - "windows-future 0.2.1", - "windows-link 0.1.3", - "windows-numerics 0.2.0", -] - [[package]] name = "windows" version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" dependencies = [ - "windows-collections 0.3.2", - "windows-core 0.62.2", - "windows-future 0.3.2", - "windows-numerics 0.3.1", -] - -[[package]] -name = "windows-collections" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" -dependencies = [ - "windows-core 0.61.2", + "windows-collections", + "windows-core", + "windows-future", + "windows-numerics", ] [[package]] @@ -6131,20 +6129,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" dependencies = [ - "windows-core 0.62.2", -] - -[[package]] -name = "windows-core" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link 0.1.3", - "windows-result 0.3.4", - "windows-strings 0.4.2", + "windows-core", ] [[package]] @@ -6155,20 +6140,9 @@ checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement", "windows-interface", - "windows-link 0.2.1", - "windows-result 0.4.1", - "windows-strings 0.5.1", -] - -[[package]] -name = "windows-future" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" -dependencies = [ - "windows-core 0.61.2", - "windows-link 0.1.3", - "windows-threading 0.1.0", + "windows-link", + "windows-result", + "windows-strings", ] [[package]] @@ -6177,9 +6151,9 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" dependencies = [ - "windows-core 0.62.2", - "windows-link 0.2.1", - "windows-threading 0.2.1", + "windows-core", + "windows-link", + "windows-threading", ] [[package]] @@ -6204,12 +6178,6 @@ dependencies = [ "syn 2.0.119", ] -[[package]] -name = "windows-link" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" - [[package]] name = "windows-link" version = "0.2.1" @@ -6229,33 +6197,25 @@ dependencies = [ "zeroize", ] -[[package]] -name = "windows-numerics" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" -dependencies = [ - "windows-core 0.61.2", - "windows-link 0.1.3", -] - [[package]] name = "windows-numerics" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" dependencies = [ - "windows-core 0.62.2", - "windows-link 0.2.1", + "windows-core", + "windows-link", ] [[package]] -name = "windows-result" -version = "0.3.4" +name = "windows-registry" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" dependencies = [ - "windows-link 0.1.3", + "windows-link", + "windows-result", + "windows-strings", ] [[package]] @@ -6264,16 +6224,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-link 0.2.1", -] - -[[package]] -name = "windows-strings" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" -dependencies = [ - "windows-link 0.1.3", + "windows-link", ] [[package]] @@ -6282,7 +6233,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -6327,7 +6278,7 @@ version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -6367,7 +6318,7 @@ version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows-link 0.2.1", + "windows-link", "windows_aarch64_gnullvm 0.53.1", "windows_aarch64_msvc 0.53.1", "windows_i686_gnu 0.53.1", @@ -6378,22 +6329,13 @@ dependencies = [ "windows_x86_64_msvc 0.53.1", ] -[[package]] -name = "windows-threading" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" -dependencies = [ - "windows-link 0.1.3", -] - [[package]] name = "windows-threading" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" dependencies = [ - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -6402,7 +6344,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4060a1da109b9d0326b7262c8e12c84df67cc0dbc9e33cf49e01ccc2eb63631" dependencies = [ - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -6552,12 +6494,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "winnow" -version = "0.7.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" - [[package]] name = "winnow" version = "1.0.4" @@ -6591,9 +6527,9 @@ checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc" [[package]] name = "wry" -version = "0.55.1" +version = "0.57.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186f9871daa55fd9c016578b810d149de58367113db7fb72b462d2323ce19514" +checksum = "a819957a01b3119af85e638a38d242af76dbc87d130dca67bfd0441072e21ff0" dependencies = [ "base64 0.22.1", "block2", @@ -6607,7 +6543,7 @@ dependencies = [ "gtk", "http", "javascriptcore-rs", - "jni", + "jni 0.21.1", "libc", "ndk", "objc2", @@ -6622,13 +6558,13 @@ dependencies = [ "sha2 0.10.9", "soup3", "tao-macros", - "thiserror 2.0.20", + "thiserror 2.0.21", "url", "webkit2gtk", "webkit2gtk-sys", "webview2-com", - "windows 0.61.3", - "windows-core 0.61.2", + "windows", + "windows-core", "windows-version", "x11-dl", ] @@ -6683,13 +6619,13 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" +checksum = "33811428bee40dbceb6d545e95754741d17a6aef9a4849f0fd62e2ba4f412a78" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.6", "synstructure", ] @@ -6748,7 +6684,7 @@ dependencies = [ "proc-macro-crate 3.5.0", "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.6", "zbus_names", "zvariant", "zvariant_utils", @@ -6785,13 +6721,13 @@ dependencies = [ [[package]] name = "zerofrom-derive" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" +checksum = "f75b4683f6c7f45248d4d64056a24298c6281e0993356d7d1b4a1a962ef10d4a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.6", "synstructure", ] @@ -6831,7 +6767,7 @@ checksum = "34df6fc39dbd26ddc9c10e6a2984476e13acce22e64e4487636ef494369225da" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.6", ] [[package]] @@ -6842,10 +6778,16 @@ checksum = "caa8cd6af31c3b31c6631b8f483848b91589021b28fffe50adada48d4f4d2ed1" dependencies = [ "arbitrary", "crc32fast", - "indexmap 2.14.0", + "indexmap 2.14.2", "memchr", ] +[[package]] +name = "zlib-rs" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b268e58e7c693d7c271f93ffc4ba3b380412554231c85bf61ca7af91042a4112" + [[package]] name = "zmij" version = "1.0.23" @@ -6876,7 +6818,7 @@ dependencies = [ "proc-macro-crate 3.5.0", "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.6", "zvariant_utils", ] @@ -6889,6 +6831,6 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 3.0.3", + "syn 3.0.6", "winnow 1.0.4", ] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 29289bc..2f359a3 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -5,7 +5,7 @@ description = "Native local LLM chat client (Ollama + OpenAI-compatible)." authors = ["Loach"] license = "MIT" edition = "2021" -rust-version = "1.88" +rust-version = "1.90" [lib] name = "loach_lib" @@ -43,8 +43,7 @@ r2d2_sqlite = "0.35" # Secrets keyring = { version = "4", default-features = false, features = ["v1"] } -argon2 = "0.5" -rand_core = { version = "0.6", features = ["getrandom"] } +argon2 = "0.6" # Utilities uuid = { version = "1", features = ["v4", "v7", "serde"] } @@ -133,7 +132,7 @@ chardetng = "1" # the Ollama catalog against the machine instead of quoting raw GB. Only the # `system` and `disk` collectors are compiled in — the default feature set also # pulls process enumeration, networks, components and users, none of which we -# read. Held at 0.38: 0.39 raises its MSRV to 1.95, above our 1.88. +# read. Held at 0.38: 0.39 raises its MSRV to 1.95, above our 1.90. sysinfo = { version = "0.38", default-features = false, features = ["system", "disk"] } # Windows VRAM + adapter name for the onboarding model recommendation, read via diff --git a/src-tauri/src/security.rs b/src-tauri/src/security.rs index 67d4bde..ca32c42 100644 --- a/src-tauri/src/security.rs +++ b/src-tauri/src/security.rs @@ -20,13 +20,9 @@ use parking_lot::Mutex; use std::time::{Duration, Instant}; use anyhow::{anyhow, bail, Result}; -use argon2::{ - password_hash::{PasswordHash, PasswordHasher, PasswordVerifier, SaltString}, - Algorithm, Argon2, Params, Version, -}; +use argon2::{Algorithm, Argon2, Params, PasswordHash, PasswordHasher, PasswordVerifier, Version}; use keyring::Entry; use once_cell::sync::Lazy; -use rand_core::OsRng; use serde::{Deserialize, Serialize}; const SERVICE: &str = "dev.loach.app"; @@ -136,12 +132,11 @@ fn argon2_instance() -> Argon2<'static> { } fn hash(secret: &str) -> Result { - let salt = SaltString::generate(&mut OsRng); - let phc = argon2_instance() - .hash_password(secret.as_bytes(), &salt) - .map_err(|e| anyhow!("argon2 hash failed: {e}"))? - .to_string(); - Ok(phc) + // `hash_password` draws the salt from the OS RNG itself. + let phc: PasswordHash = argon2_instance() + .hash_password(secret.as_bytes()) + .map_err(|e| anyhow!("argon2 hash failed: {e}"))?; + Ok(phc.to_string()) } fn verify(secret: &str, phc: &str) -> bool { @@ -479,6 +474,21 @@ mod tests { assert!(!verify("anything", "")); } + #[test] + fn verify_accepts_hashes_stored_by_argon2_0_5() { + // Made by argon2 0.5.3, the version that shipped up to Loach 1.5.0, + // and sitting in users' credential stores. A crate bump that stops + // verifying them locks those users out of the app. + let current_params = "$argon2id$v=19$m=65536,t=3,p=1$Hr9IRw89uglbWlWcxOZrJw$rr0xcfZgwJYES0b7Kf1M8bnY2m1csUk30fTLYapBVzI"; + assert!(verify("1234", current_params)); + assert!(!verify("0000", current_params)); + + // `Argon2::default()` parameters, from before the cost was raised. + let default_params = "$argon2id$v=19$m=19456,t=2,p=1$FXKWcHr77AyDYYzmY+CrwA$Zto6EKKlbuktJuMGNwUMpdpmdpC/dM9Ir+XeawQvRx4"; + assert!(verify("correct-horse", default_params)); + assert!(!verify("wrong", default_params)); + } + #[test] fn verify_against_config_requires_all_factors() { let pin_phc = hash("1234").unwrap(); diff --git a/vitest.config.ts b/vitest.config.ts index 22a7f1e..801daf4 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -11,7 +11,7 @@ import path from "node:path"; // components needs the plugin plus a DOM environment, not just the globs. export default defineConfig({ resolve: { - alias: { "@": path.resolve(__dirname, "./src") }, + alias: { "@": path.resolve(import.meta.dirname, "./src") }, }, test: { // `tests/` holds repo-level invariants (e.g. the release version From c40989447cefc54ee88ca5c42e7916bc8189bb33 Mon Sep 17 00:00:00 2001 From: ZTCS Date: Wed, 30 Sep 2026 14:53:22 +0200 Subject: [PATCH 02/33] Rename update notes caption to "Release notes" to stop duplicate "What's new" heading --- releases/README.md | 2 +- src/components/UpdateAvailableDialog.tsx | 2 +- src/components/UpdatesPanel.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/releases/README.md b/releases/README.md index f6541eb..7a5797a 100644 --- a/releases/README.md +++ b/releases/README.md @@ -8,7 +8,7 @@ the merged version and uses its content as **both**: - the GitHub release body, and - the `notes` field inside `latest.json` (what users see in-app under - Settings → Updates → "What's new"). + Settings → Updates → "Release notes"). Keeping them in sync means there's no post-publish edit step. diff --git a/src/components/UpdateAvailableDialog.tsx b/src/components/UpdateAvailableDialog.tsx index 70bb823..0d0cdd0 100644 --- a/src/components/UpdateAvailableDialog.tsx +++ b/src/components/UpdateAvailableDialog.tsx @@ -126,7 +126,7 @@ export function UpdateAvailableDialog() { {info.notes && (
- What's new + Release notes
diff --git a/src/components/UpdatesPanel.tsx b/src/components/UpdatesPanel.tsx index 6a35370..660333a 100644 --- a/src/components/UpdatesPanel.tsx +++ b/src/components/UpdatesPanel.tsx @@ -131,7 +131,7 @@ export function UpdatesPanel() { {state.info.notes && (
- What's new + Release notes
From 6605d18e7e7767e2a45ab5013793f7e1941320e4 Mon Sep 17 00:00:00 2001 From: ZTCS Date: Wed, 30 Sep 2026 15:39:11 +0200 Subject: [PATCH 03/33] add /stop, /find, /import, /label, /folder, /tone, /set, /unload, /theme and /lock slash commands --- src/components/ChatCanvas.tsx | 7 +- src/components/ChatHeader.tsx | 13 ++ src/lib/commands/dispatch.ts | 231 ++++++++++++++++++++++++++++++++ src/lib/commands/folder.test.ts | 70 ++++++++++ src/lib/commands/registry.ts | 76 +++++++++++ src/lib/commands/set.test.ts | 75 +++++++++++ src/lib/commands/stop.test.ts | 53 ++++++++ src/stores/uiStore.ts | 12 ++ 8 files changed, 536 insertions(+), 1 deletion(-) create mode 100644 src/lib/commands/folder.test.ts create mode 100644 src/lib/commands/set.test.ts create mode 100644 src/lib/commands/stop.test.ts diff --git a/src/components/ChatCanvas.tsx b/src/components/ChatCanvas.tsx index f64e9b0..74373ff 100644 --- a/src/components/ChatCanvas.tsx +++ b/src/components/ChatCanvas.tsx @@ -268,7 +268,12 @@ export function ChatCanvas() { }, [sessionId]); useEffect(() => { - const open = () => setSearchOpen(true); + // `/find ` passes its text as `detail.query` to prefill the finder. + const open = (e: Event) => { + const query = (e as CustomEvent<{ query?: string } | null>).detail?.query; + if (query) setSearchQuery(query); + setSearchOpen(true); + }; window.addEventListener("loach:open-chat-search", open); return () => window.removeEventListener("loach:open-chat-search", open); }, []); diff --git a/src/components/ChatHeader.tsx b/src/components/ChatHeader.tsx index 9887d2d..ad69c50 100644 --- a/src/components/ChatHeader.tsx +++ b/src/components/ChatHeader.tsx @@ -112,6 +112,10 @@ export function ChatHeader({ session }: { session: Session | undefined }) { const consumePendingOpenExport = useUIStore( (s) => s.consumePendingOpenExport, ); + const pendingOpenImport = useUIStore((s) => s.pendingOpenImport); + const consumePendingOpenImport = useUIStore( + (s) => s.consumePendingOpenImport, + ); useEffect(() => { if (!pendingOpenModelPicker) return; if (!session) return; @@ -286,6 +290,15 @@ export function ChatHeader({ session }: { session: Session | undefined }) { setImportHidden(false); }; + // `/import` counterpart of the `/export` one-shot above. + useEffect(() => { + if (!pendingOpenImport || !session) return; + consumePendingOpenImport(); + openImport(); + // openImport is recreated each render; deps kept minimal for this one-shot. + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [pendingOpenImport, session]); + const doImport = async () => { if (!session) return; if (importPreview.messages.length === 0) { diff --git a/src/lib/commands/dispatch.ts b/src/lib/commands/dispatch.ts index 73b7152..b17952c 100644 --- a/src/lib/commands/dispatch.ts +++ b/src/lib/commands/dispatch.ts @@ -3,11 +3,14 @@ import { useGlobalMemoryStore } from "@/stores/globalMemoryStore"; import { connectionLabel, useMcpStore } from "@/stores/mcpStore"; import { useModelsStore } from "@/stores/modelsStore"; import { usePrivateChatStore } from "@/stores/privateChatStore"; +import { useSecurityStore } from "@/stores/securityStore"; import { useSettingsStore } from "@/stores/settingsStore"; import { useSnippetStore } from "@/stores/snippetStore"; import { useSpaceStore } from "@/stores/spaceStore"; import { useUIStore, type SettingsTab } from "@/stores/uiStore"; +import { CHAT_LABELS } from "@/lib/labels"; import { DEFAULT_PERSONA_ID, PERSONAS } from "@/lib/personas"; +import { DEFAULT_TONE_ID, TONES } from "@/lib/tones"; import { expandAndPrimeSnippet } from "@/lib/runSnippet"; import { extractSummary, @@ -20,6 +23,7 @@ import { clearSessionMessages, fetchUrl, mcpTools, + ollamaUnloadModel, } from "@/lib/tauri"; import type { GenerationParams, @@ -209,6 +213,26 @@ async function run( return runPrivate(); case "compact": return runCompact(); + case "stop": + return runStop(); + case "find": + return runFind(rest); + case "import": + return runImport(); + case "label": + return runLabel(rest); + case "folder": + return runFolder(rest); + case "tone": + return runTone(rest); + case "set": + return runSet(rest); + case "unload": + return runUnload(); + case "theme": + return runTheme(rest); + case "lock": + return runLock(); default: // Defensive — `dispatch` already filtered unknown commands. Treat as a // toast error so the bug surfaces if a new entry in `COMMANDS` is @@ -900,3 +924,210 @@ async function runCompact(): Promise { return { kind: "noop" }; } +async function runStop(): Promise { + const session = requireSession(); + // Same scope as the composer's Stop button: this chat only. A prompt still + // waiting in the queue counts too — `cancelForSession` evicts it. + const state = useChatStore.getState(); + const running = state.runningTask?.sessionId === session.id; + if (!running && !state.queue.some((t) => t.sessionId === session.id)) { + return ok("Nothing to stop"); + } + await state.cancelForSession(session.id); + return ok(running ? "Stopped reply" : "Removed queued prompt"); +} + +async function runFind(rest: string): Promise { + requireSession(); + // ChatCanvas owns the finder overlay; this is the event the header's + // "Search in chat" item fires, plus the text to prefill. + window.dispatchEvent( + new CustomEvent("loach:open-chat-search", { detail: { query: rest.trim() } }), + ); + return { kind: "noop" }; +} + +async function runImport(): Promise { + // Same one-shot hand-off as `/export`: the dialog's state lives in the + // ChatHeader. + requireSession(); + useUIStore.getState().setPendingOpenImport(true); + return { kind: "noop" }; +} + +async function runLabel(rest: string): Promise { + const session = requireSession(); + const arg = rest.trim().toLowerCase(); + if (arg === "clear") { + await useChatStore.getState().setLabel(session.id, null); + return ok("Cleared label"); + } + const label = CHAT_LABELS.find((l) => l.id === arg); + if (!label) { + throw new Error(`Usage: /label <${CHAT_LABELS.map((l) => l.id).join("|")}|clear>`); + } + await useChatStore.getState().setLabel(session.id, label.id); + return ok("Labelled chat", label.name); +} + +async function runFolder(rest: string): Promise { + const session = requireSession(); + const name = rest.trim(); + if (!name) throw new Error("Usage: /folder "); + const chat = useChatStore.getState(); + if (name.toLowerCase() === "none") { + if (!session.folder_id) return ok("Chat isn't in a folder"); + await chat.moveToFolder(session.id, null); + return ok("Removed from folder"); + } + // Exact (case-insensitive) name only — anything else creates a folder with + // the typed name. Substring matching like `/space` would let a near-miss + // file the chat into the wrong existing folder without saying so. + const lower = name.toLowerCase(); + const existing = chat.folders.find((f) => f.name.toLowerCase() === lower); + if (existing) { + await chat.moveToFolder(session.id, existing.id); + return ok("Moved to folder", existing.name); + } + const folder = await chat.createFolderWith(name, [session.id]); + return ok("Created folder", folder.name); +} + +async function runTone(rest: string): Promise { + const query = rest.trim(); + if (!query) throw new Error("Usage: /tone "); + const session = requireSession(); + const lower = query.toLowerCase(); + const exact = TONES.find( + (t) => t.id.toLowerCase() === lower || t.label.toLowerCase() === lower, + ); + const matches = exact + ? [exact] + : TONES.filter( + (t) => + t.id.toLowerCase().includes(lower) || + t.label.toLowerCase().includes(lower), + ); + if (matches.length === 0) { + throw new Error(`No tone matches "${query}". Try one of: ${TONES.map((t) => t.id).join(", ")}.`); + } + if (matches.length > 1) { + return listItems( + `Multiple tones match "${query}"`, + matches.map((t) => ({ label: t.label, detail: t.id, hint: t.shortDescription })), + ); + } + const tone = matches[0]!; + useUIStore.getState().setSessionTone(session.id, tone.id); + return ok(tone.id === DEFAULT_TONE_ID ? "Cleared tone" : "Applied tone", tone.label); +} + +interface ParamRule { + integer: boolean; + min?: number; + max?: number; + /** The only values accepted, when the panel's control snaps to a list. */ + stops?: readonly number[]; +} + +// What `/set` accepts, matching the Parameter panel's controls so a value set +// here reads back the same there — its Temperature slider stops at 1, and its +// Context Length slider can only show the `CTX_STOPS` it snaps to. No `max` +// means the panel doesn't cap it either. +const PARAM_RULES: Partial> = { + temperature: { integer: false, min: 0, max: 1 }, + top_p: { integer: false, min: 0, max: 1 }, + top_k: { integer: true, min: 0, max: 200 }, + min_p: { integer: false, min: 0, max: 0.5 }, + num_ctx: { + integer: true, + stops: [4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576], + }, + max_tokens: { integer: true, min: 128, max: 32768 }, + repeat_penalty: { integer: false, min: 0.8, max: 2 }, + frequency_penalty: { integer: false, min: -2, max: 2 }, + presence_penalty: { integer: false, min: -2, max: 2 }, + num_gpu: { integer: true, min: 0 }, + seed: { integer: true }, +}; + +async function runSet(rest: string): Promise { + const session = requireSession(); + const [rawKey = "", rawValue = "", ...extra] = rest.split(/\s+/).filter(Boolean); + const key = rawKey.toLowerCase() as keyof GenerationParams; + if (rawKey.toLowerCase() === "reset" && !rawValue) { + // Same as the panel's Reset: drop the override so the chat follows the + // Space / model / app defaults again. + await useChatStore.getState().setSessionParams(session.id, null); + return ok("Reset parameters", "Back to the defaults"); + } + // `hasOwn`, not a bare lookup: `/set constructor 1` would otherwise find + // Object.prototype's and write it into the chat's params. + const rule = Object.hasOwn(PARAM_RULES, key) ? PARAM_RULES[key] : undefined; + if (!rule) { + throw new Error( + `Usage: /set or /set reset. Params: ${Object.keys(PARAM_RULES).join(", ")}.`, + ); + } + // Plain decimals only, like `/copy`: `Number` alone would also accept + // `0x10`, `1e2` and an empty string (as 0). + const shape = rule.integer ? /^-?\d+$/ : /^-?(\d+(\.\d*)?|\.\d+)$/; + const n = Number(rawValue); + const valid = + shape.test(rawValue) && + extra.length === 0 && + (!rule.integer || Number.isSafeInteger(n)) && + (rule.stops + ? rule.stops.includes(n) + : (rule.min === undefined || n >= rule.min) && + (rule.max === undefined || n <= rule.max)); + if (!valid) { + const allowed = rule.stops + ? `one of ${rule.stops.join(", ")}` + : `${rule.integer ? "a whole number" : "a number"}${ + rule.min !== undefined && rule.max !== undefined + ? ` from ${rule.min} to ${rule.max}` + : rule.min !== undefined + ? ` of at least ${rule.min}` + : "" + }`; + throw new Error(`Usage: /set ${key} — ${allowed}.`); + } + await patchParams({ [key]: n }); + return ok(`Set ${key}`, String(n)); +} + +async function runUnload(): Promise { + const session = requireSession(); + if (!session.model) throw new Error("This chat has no model yet."); + if (session.provider !== "ollama") { + throw new Error("Only Ollama models can be unloaded — the server manages OpenAI-compatible ones."); + } + // Ollama expires the runner without loading anything first; if a reply is + // still using the model, it goes once that reply ends. + await ollamaUnloadModel(useSettingsStore.getState().ollama_base_url, session.model); + return ok("Unloaded model", `${session.model} — it loads again on your next message`); +} + +async function runTheme(rest: string): Promise { + const arg = rest.trim().toLowerCase(); + if (arg !== "light" && arg !== "dark" && arg !== "system") { + throw new Error("Usage: /theme light|dark|system"); + } + // No success toast: the repaint is the confirmation, and `update` toasts + // (and reverts) on its own if the save fails. + await useSettingsStore.getState().update("theme", arg); + return { kind: "noop" }; +} + +async function runLock(): Promise { + const security = useSecurityStore.getState(); + // `lock()` silently no-ops without a configured lock, which would read as + // a dead command. + if (!security.status.configured) { + throw new Error("App lock isn't set up. Add a PIN or password in Settings → Security."); + } + security.lock(); + return { kind: "noop" }; +} + diff --git a/src/lib/commands/folder.test.ts b/src/lib/commands/folder.test.ts new file mode 100644 index 0000000..7e140b4 --- /dev/null +++ b/src/lib/commands/folder.test.ts @@ -0,0 +1,70 @@ +// `/folder ` files the chat into the folder with exactly that name +// (case-insensitive) or creates one — never a substring match, which could +// file it into the wrong existing folder. + +import { beforeEach, describe, it, expect, vi } from "vitest"; +import type { Folder, Session } from "@/types"; + +const setSessionFolder = vi.hoisted(() => + vi.fn(async (_args: { id: string; folder_id: string | null }) => {}), +); +const createFolder = vi.hoisted(() => + vi.fn(async (name: string) => ({ id: "new-folder", name, created_at: 1, updated_at: 1 })), +); + +vi.mock("@/lib/tauri", async (importOriginal) => { + const actual = await importOriginal(); + return { ...actual, setSessionFolder, createFolder }; +}); + +import { dispatch } from "./dispatch"; +import { useChatStore } from "@/stores/chatStore"; + +const deps = { confirm: async () => true }; + +function openChat(folder_id: string | null) { + useChatStore.setState({ + folders: [{ id: "work", name: "Work" } as Folder], + sessions: [{ id: "chat-1", space_id: null, folder_id } as Session], + activeSessionId: "chat-1", + }); +} + +function folderOfChat(): string | null { + return useChatStore.getState().sessions[0]!.folder_id; +} + +describe("/folder", () => { + beforeEach(() => { + setSessionFolder.mockClear(); + createFolder.mockClear(); + }); + + it("moves the chat into an existing folder, ignoring case", async () => { + openChat(null); + const outcome = await dispatch("/folder work", deps); + expect(outcome).toMatchObject({ + result: { kind: "toast", title: "Moved to folder", body: "Work" }, + }); + expect(createFolder).not.toHaveBeenCalled(); + expect(folderOfChat()).toBe("work"); + }); + + it("creates a folder rather than guessing from a partial name", async () => { + openChat(null); + const outcome = await dispatch("/folder Wor", deps); + expect(outcome).toMatchObject({ + result: { kind: "toast", title: "Created folder", body: "Wor" }, + }); + expect(createFolder).toHaveBeenCalledWith("Wor"); + expect(folderOfChat()).toBe("new-folder"); + }); + + it("none takes the chat out of its folder", async () => { + openChat("work"); + const outcome = await dispatch("/folder none", deps); + expect(outcome).toMatchObject({ result: { kind: "toast", title: "Removed from folder" } }); + expect(setSessionFolder).toHaveBeenCalledWith({ id: "chat-1", folder_id: null }); + expect(folderOfChat()).toBeNull(); + }); +}); diff --git a/src/lib/commands/registry.ts b/src/lib/commands/registry.ts index ba1bd84..e0cda73 100644 --- a/src/lib/commands/registry.ts +++ b/src/lib/commands/registry.ts @@ -1,3 +1,5 @@ +import { CHAT_LABELS } from "@/lib/labels"; +import { TONES } from "@/lib/tones"; import type { CommandSpec } from "./types"; // Canonical list of slash commands. The dispatcher reads `name` to route to a @@ -28,6 +30,20 @@ export const COMMANDS: readonly CommandSpec[] = [ description: "Pin or unpin the current chat", group: "Chat", }, + { + name: "label", + description: "Colour-label the current chat", + usage: "", + subcommands: [...CHAT_LABELS.map((l) => l.id), "clear"], + group: "Chat", + }, + { + name: "folder", + description: "Move the current chat into a folder, creating it if needed", + usage: "", + subcommands: ["none"], + group: "Chat", + }, { name: "archive", description: "Archive the current chat", @@ -48,17 +64,33 @@ export const COMMANDS: readonly CommandSpec[] = [ description: "Re-stream the last assistant reply", group: "Chat", }, + { + name: "stop", + description: "Stop the reply running (or queued) in this chat", + group: "Chat", + }, { name: "copy", description: "Copy the last (or Nth-latest) assistant reply", usage: "[N]", group: "Chat", }, + { + name: "find", + description: "Find text in the current chat", + usage: "[text]", + group: "Chat", + }, { name: "export", description: "Export this chat's context", group: "Chat", }, + { + name: "import", + description: "Import context into this chat", + group: "Chat", + }, { name: "stats", description: "Show token / speed metrics for this chat", @@ -88,6 +120,38 @@ export const COMMANDS: readonly CommandSpec[] = [ usage: "", group: "Model & persona", }, + { + name: "tone", + description: "Set the response tone for this chat", + usage: "", + subcommands: TONES.map((t) => t.id), + group: "Model & persona", + }, + { + name: "set", + description: "Set a generation parameter for this chat", + usage: " |reset", + subcommands: [ + "temperature", + "top_p", + "top_k", + "min_p", + "num_ctx", + "max_tokens", + "repeat_penalty", + "frequency_penalty", + "presence_penalty", + "num_gpu", + "seed", + "reset", + ], + group: "Model & persona", + }, + { + name: "unload", + description: "Unload this chat's Ollama model from memory", + group: "Model & persona", + }, // ----- listings ----- { @@ -172,6 +236,18 @@ export const COMMANDS: readonly CommandSpec[] = [ usage: "[tab]", group: "App", }, + { + name: "theme", + description: "Switch the colour theme", + usage: "light|dark|system", + subcommands: ["light", "dark", "system"], + group: "App", + }, + { + name: "lock", + description: "Lock Loach now", + group: "App", + }, { name: "help", description: "Show this command reference", diff --git a/src/lib/commands/set.test.ts b/src/lib/commands/set.test.ts new file mode 100644 index 0000000..8cda721 --- /dev/null +++ b/src/lib/commands/set.test.ts @@ -0,0 +1,75 @@ +// `/set ` accepts only what the Parameter panel can show, and +// `/set reset` drops the chat's override like the panel's Reset button. + +import { beforeEach, describe, it, expect, vi } from "vitest"; +import type { Session } from "@/types"; + +const updateSessionParams = vi.hoisted(() => + vi.fn(async (_args: { id: string; params_json: string | null }) => {}), +); + +vi.mock("@/lib/tauri", async (importOriginal) => { + const actual = await importOriginal(); + return { ...actual, updateSessionParams }; +}); + +import { dispatch } from "./dispatch"; +import { useChatStore } from "@/stores/chatStore"; + +const deps = { confirm: async () => true }; + +function openChat(params_json: string | null) { + useChatStore.setState({ + sessions: [{ id: "chat-1", space_id: null, params_json } as Session], + activeSessionId: "chat-1", + }); +} + +function storedParams(): string | null { + return useChatStore.getState().sessions[0]!.params_json; +} + +describe("/set", () => { + beforeEach(() => { + updateSessionParams.mockClear(); + }); + + it("merges one value into the chat's existing overrides", async () => { + openChat(JSON.stringify({ top_k: 20 })); + const outcome = await dispatch("/set temperature 0.3", deps); + expect(outcome).toMatchObject({ + result: { kind: "toast", title: "Set temperature", body: "0.3" }, + }); + expect(JSON.parse(storedParams()!)).toEqual({ top_k: 20, temperature: 0.3 }); + }); + + it("accepts a context length the panel's slider can show", async () => { + openChat(null); + await dispatch("/set num_ctx 16384", deps); + expect(JSON.parse(storedParams()!)).toEqual({ num_ctx: 16384 }); + }); + + it.each([ + ["above the panel's cap", "/set temperature 1.5"], + ["a non-decimal number", "/set top_k 0x10"], + ["a fraction for a whole-number param", "/set max_tokens 512.5"], + ["a context length between the stops", "/set num_ctx 10000"], + ["a missing value", "/set seed"], + ["an unknown param", "/set warmth 3"], + ["an Object.prototype key", "/set constructor 1"], + ])("rejects %s", async (_label, input) => { + openChat(null); + const outcome = await dispatch(input, deps); + expect(outcome).toMatchObject({ result: { kind: "toast", tone: "error" } }); + expect(updateSessionParams).not.toHaveBeenCalled(); + expect(storedParams()).toBeNull(); + }); + + it("reset clears the override", async () => { + openChat(JSON.stringify({ temperature: 0.3, seed: 42 })); + const outcome = await dispatch("/set reset", deps); + expect(outcome).toMatchObject({ result: { kind: "toast", title: "Reset parameters" } }); + expect(updateSessionParams).toHaveBeenCalledWith({ id: "chat-1", params_json: null }); + expect(storedParams()).toBeNull(); + }); +}); diff --git a/src/lib/commands/stop.test.ts b/src/lib/commands/stop.test.ts new file mode 100644 index 0000000..a9289d5 --- /dev/null +++ b/src/lib/commands/stop.test.ts @@ -0,0 +1,53 @@ +// `/stop` has the composer Stop button's scope: the running reply or queued +// prompt of the chat it's typed in, never another chat's stream. + +import { beforeEach, describe, it, expect, vi } from "vitest"; +import type { Session } from "@/types"; +import { dispatch } from "./dispatch"; +import { useChatStore } from "@/stores/chatStore"; + +const deps = { confirm: async () => true }; + +const cancelForSession = vi.fn(async (_sessionId: string) => {}); + +function openChat(state: { running?: string; queued?: string }) { + useChatStore.setState({ + sessions: [ + { id: "chat-1", space_id: null } as Session, + { id: "chat-2", space_id: null } as Session, + ], + activeSessionId: "chat-1", + runningTask: state.running + ? ({ id: "t-run", sessionId: state.running } as never) + : null, + queue: state.queued ? [{ id: "t-wait", sessionId: state.queued } as never] : [], + cancelForSession, + }); +} + +describe("/stop", () => { + beforeEach(() => { + cancelForSession.mockClear(); + }); + + it("stops this chat's running reply", async () => { + openChat({ running: "chat-1" }); + const outcome = await dispatch("/stop", deps); + expect(outcome).toMatchObject({ result: { kind: "toast", title: "Stopped reply" } }); + expect(cancelForSession).toHaveBeenCalledWith("chat-1"); + }); + + it("removes this chat's queued prompt", async () => { + openChat({ running: "chat-2", queued: "chat-1" }); + const outcome = await dispatch("/stop", deps); + expect(outcome).toMatchObject({ result: { kind: "toast", title: "Removed queued prompt" } }); + expect(cancelForSession).toHaveBeenCalledWith("chat-1"); + }); + + it("leaves another chat's stream alone", async () => { + openChat({ running: "chat-2" }); + const outcome = await dispatch("/stop", deps); + expect(outcome).toMatchObject({ result: { kind: "toast", title: "Nothing to stop" } }); + expect(cancelForSession).not.toHaveBeenCalled(); + }); +}); diff --git a/src/stores/uiStore.ts b/src/stores/uiStore.ts index bc55df2..4877d5f 100644 --- a/src/stores/uiStore.ts +++ b/src/stores/uiStore.ts @@ -78,6 +78,9 @@ interface UIState { * Set by the `/export` slash command, which can't reach the dialog's * local state directly. Mirrors `pendingOpenModelPicker`. */ pendingOpenExport: boolean; + /** One-shot flag for the ChatHeader's "Import context" dialog, set by the + * `/import` slash command. Mirrors `pendingOpenExport`. */ + pendingOpenImport: boolean; /** One-shot: a message the transcript should scroll to and flash as soon as * it's mounted. Set by the Cmd/Ctrl-K palette when the user picks a message * result, consumed by ChatCanvas. It can't be a plain call because the @@ -109,6 +112,8 @@ interface UIState { consumePendingOpenModelPicker: () => boolean; setPendingOpenExport: (v: boolean) => void; consumePendingOpenExport: () => boolean; + setPendingOpenImport: (v: boolean) => void; + consumePendingOpenImport: () => boolean; setPendingJumpMessage: (messageId: string | null) => void; consumePendingJumpMessage: () => string | null; } @@ -131,6 +136,7 @@ export const useUIStore = create((set, get) => ({ toneIdBySession: {}, pendingOpenModelPicker: false, pendingOpenExport: false, + pendingOpenImport: false, toggleSidebar: () => set((s) => ({ sidebarOpen: !s.sidebarOpen, sidebarAutoCollapsed: false })), toggleParams: () => set((s) => ({ paramsOpen: !s.paramsOpen })), @@ -192,6 +198,12 @@ export const useUIStore = create((set, get) => ({ if (v) set({ pendingOpenExport: false }); return v; }, + setPendingOpenImport: (v) => set({ pendingOpenImport: v }), + consumePendingOpenImport: (): boolean => { + const v = get().pendingOpenImport; + if (v) set({ pendingOpenImport: false }); + return v; + }, setPendingJumpMessage: (pendingJumpMessageId) => set({ pendingJumpMessageId }), consumePendingJumpMessage: (): string | null => { const id = get().pendingJumpMessageId; From 024575a88faa14c5d045ad63b143e7cf0bc7e3c3 Mon Sep 17 00:00:00 2001 From: ZTCS Date: Wed, 30 Sep 2026 15:48:30 +0200 Subject: [PATCH 04/33] complete model, space, snippet and persona names in the slash palette and make bare /model, /persona and /tone useful --- src/components/ChatInput.tsx | 26 +++++++++++- src/lib/commands/bare.test.ts | 61 +++++++++++++++++++++++++++ src/lib/commands/dispatch.ts | 31 +++++++++++--- src/lib/commands/parser.test.ts | 53 ++++++++++++++++++++++++ src/lib/commands/parser.ts | 71 +++++++++++++++++++++++++------- src/lib/commands/recency.test.ts | 10 +++++ src/lib/commands/recency.ts | 10 ++++- src/lib/commands/registry.ts | 10 +++-- 8 files changed, 243 insertions(+), 29 deletions(-) create mode 100644 src/lib/commands/bare.test.ts create mode 100644 src/lib/commands/parser.test.ts diff --git a/src/components/ChatInput.tsx b/src/components/ChatInput.tsx index 2e646da..d38d0a9 100644 --- a/src/components/ChatInput.tsx +++ b/src/components/ChatInput.tsx @@ -30,7 +30,10 @@ import { FileTooLargeError, } from "@/lib/files"; import { useChatStore } from "@/stores/chatStore"; +import { useModelsStore } from "@/stores/modelsStore"; import { usePrivateChatStore } from "@/stores/privateChatStore"; +import { useSnippetStore } from "@/stores/snippetStore"; +import { useSpaceStore } from "@/stores/spaceStore"; import { useUIStore } from "@/stores/uiStore"; import { useSettingsStore } from "@/stores/settingsStore"; import { useToastStore } from "@/stores/toastStore"; @@ -49,6 +52,7 @@ import { isCommandInput, matchCommands, parseInput, + type ArgSources, type PaletteEntry, } from "@/lib/commands/parser"; import { orderByRecency, parseRecentCommands } from "@/lib/commands/recency"; @@ -169,6 +173,19 @@ export function ChatInput({ centered = false }: ChatInputProps) { const [paletteIndex, setPaletteIndex] = useState(0); const [paletteDismissed, setPaletteDismissed] = useState(false); const [commandResult, setCommandResult] = useState(null); + // Names the palette completes after `/model `, `/space ` and `/snippet `. + // They live in stores, which the commands layer doesn't import. + const models = useModelsStore((s) => s.models); + const spaces = useSpaceStore((s) => s.spaces); + const snippets = useSnippetStore((s) => s.snippets); + const argSources: ArgSources = useMemo( + () => ({ + model: models.map((m) => m.id), + space: spaces.map((s) => s.name), + snippet: snippets.map((s) => s.title), + }), + [models, spaces, snippets], + ); // Recency is applied HERE rather than inside the palette: `paletteIndex` // indexes into this array, and both the keyboard handler and the palette // must agree on the order or Enter would accept a different row than the @@ -177,11 +194,11 @@ export function ChatInput({ centered = false }: ChatInputProps) { () => isCommandInput(text) ? orderByRecency( - matchCommands(text.slice(1)), + matchCommands(text.slice(1), argSources), parseRecentCommands(recentCommands), ) : [], - [text, recentCommands], + [text, recentCommands, argSources], ); const fileInputRef = useRef(null); const textareaRef = useRef(null); @@ -208,6 +225,11 @@ export function ChatInput({ centered = false }: ChatInputProps) { const acceptPaletteEntry = (entry: PaletteEntry) => { setText(entry.insertText); setComposerDraft(entry.insertText); + // Back to the top row, where the exact match for the accepted text + // lands. A highlight left further down could point at a longer name + // that also contains it (`llama3` → `llama3:70b`), and Enter would + // swap that in instead of running the command. + setPaletteIndex(0); requestAnimationFrame(() => { const el = textareaRef.current; if (!el) return; diff --git a/src/lib/commands/bare.test.ts b/src/lib/commands/bare.test.ts new file mode 100644 index 0000000..8599add --- /dev/null +++ b/src/lib/commands/bare.test.ts @@ -0,0 +1,61 @@ +// Bare `/model`, `/persona` and `/tone`: the first opens the model picker, +// the other two report what the chat currently uses instead of failing with +// a usage error. + +import { beforeEach, describe, it, expect } from "vitest"; +import type { Session } from "@/types"; +import { dispatch } from "./dispatch"; +import { useChatStore } from "@/stores/chatStore"; +import { useSettingsStore } from "@/stores/settingsStore"; +import { useUIStore } from "@/stores/uiStore"; + +const deps = { confirm: async () => true }; + +describe("bare invocations", () => { + beforeEach(() => { + useChatStore.setState({ + sessions: [{ id: "chat-1", space_id: null } as Session], + activeSessionId: "chat-1", + }); + useUIStore.setState({ + pendingOpenModelPicker: false, + personaIdBySession: {}, + toneIdBySession: {}, + }); + useSettingsStore.setState({ default_tone_id: "default" }); + }); + + it("/model opens the model picker", async () => { + expect(await dispatch("/model", deps)).toMatchObject({ result: { kind: "noop" } }); + expect(useUIStore.getState().pendingOpenModelPicker).toBe(true); + }); + + it("/persona reports the chat's persona", async () => { + expect(await dispatch("/persona", deps)).toMatchObject({ + result: { kind: "toast", title: "No persona set" }, + }); + useUIStore.getState().setSessionPersona("chat-1", "code-reviewer"); + expect(await dispatch("/persona", deps)).toMatchObject({ + result: { kind: "toast", title: "Current persona", body: "Code Reviewer" }, + }); + }); + + it("/tone reports the effective tone and where it comes from", async () => { + expect(await dispatch("/tone", deps)).toMatchObject({ + result: { kind: "toast", title: "No tone set" }, + }); + useSettingsStore.setState({ default_tone_id: "casual" }); + expect(await dispatch("/tone", deps)).toMatchObject({ + result: { kind: "toast", title: "Current tone", body: "Casual (app default)" }, + }); + useUIStore.getState().setSessionTone("chat-1", "direct"); + expect(await dispatch("/tone", deps)).toMatchObject({ + result: { kind: "toast", title: "Current tone", body: "Direct" }, + }); + // An explicit Default for this chat overrides the app-wide tone. + useUIStore.getState().setSessionTone("chat-1", "default"); + expect(await dispatch("/tone", deps)).toMatchObject({ + result: { kind: "toast", title: "No tone set" }, + }); + }); +}); diff --git a/src/lib/commands/dispatch.ts b/src/lib/commands/dispatch.ts index b17952c..60c5483 100644 --- a/src/lib/commands/dispatch.ts +++ b/src/lib/commands/dispatch.ts @@ -9,8 +9,8 @@ import { useSnippetStore } from "@/stores/snippetStore"; import { useSpaceStore } from "@/stores/spaceStore"; import { useUIStore, type SettingsTab } from "@/stores/uiStore"; import { CHAT_LABELS } from "@/lib/labels"; -import { DEFAULT_PERSONA_ID, PERSONAS } from "@/lib/personas"; -import { DEFAULT_TONE_ID, TONES } from "@/lib/tones"; +import { DEFAULT_PERSONA_ID, PERSONAS, getPersona } from "@/lib/personas"; +import { DEFAULT_TONE_ID, TONES, getTone } from "@/lib/tones"; import { expandAndPrimeSnippet } from "@/lib/runSnippet"; import { extractSummary, @@ -331,8 +331,13 @@ async function runExport(): Promise { async function runModel(rest: string): Promise { const query = rest.trim(); - if (!query) throw new Error("Usage: /model "); const session = requireSession(); + if (!query) { + // Bare `/model` opens the header's model picker — the same one-shot + // hand-off `/export` uses, since the picker's state lives there. + useUIStore.getState().setPendingOpenModelPicker(true); + return { kind: "noop" }; + } const models = useModelsStore.getState().models; const lower = query.toLowerCase(); const exact = models.find( @@ -362,8 +367,15 @@ async function runModel(rest: string): Promise { async function runPersona(rest: string): Promise { const query = rest.trim(); - if (!query) throw new Error("Usage: /persona "); const session = requireSession(); + if (!query) { + // Bare `/persona` reports the current one, like bare `/instructions`. + const current = getPersona(useUIStore.getState().personaIdBySession[session.id]); + if (!current || current.id === DEFAULT_PERSONA_ID) { + return ok("No persona set", "Apply one with /persona ."); + } + return ok("Current persona", current.label); + } const lower = query.toLowerCase(); const exact = PERSONAS.find( (p) => p.id.toLowerCase() === lower || p.label.toLowerCase() === lower, @@ -995,8 +1007,17 @@ async function runFolder(rest: string): Promise { async function runTone(rest: string): Promise { const query = rest.trim(); - if (!query) throw new Error("Usage: /tone "); const session = requireSession(); + if (!query) { + // Bare `/tone` reports the effective tone: this chat's own, else the + // app-wide default — the order the composer's tone chip reads them in. + const own = useUIStore.getState().toneIdBySession[session.id]; + const current = getTone(own ?? useSettingsStore.getState().default_tone_id); + if (!current || current.id === DEFAULT_TONE_ID) { + return ok("No tone set", "Apply one with /tone ."); + } + return ok("Current tone", own ? current.label : `${current.label} (app default)`); + } const lower = query.toLowerCase(); const exact = TONES.find( (t) => t.id.toLowerCase() === lower || t.label.toLowerCase() === lower, diff --git a/src/lib/commands/parser.test.ts b/src/lib/commands/parser.test.ts new file mode 100644 index 0000000..85981c3 --- /dev/null +++ b/src/lib/commands/parser.test.ts @@ -0,0 +1,53 @@ +// Palette completion for command arguments. +// +// Names that live in app state (models, Spaces, snippets) arrive as +// `argSources`; a command whose argument is optional keeps its bare form +// reachable, or Enter on `/model` would complete the first model instead of +// opening the picker. + +import { describe, it, expect } from "vitest"; +import { matchCommands } from "./parser"; + +const sources = { + model: ["llama3:70b", "llama3", "qwen3:8b"], + space: ["Work", "Home"], +}; + +const inserts = (query: string) => + matchCommands(query, sources).map((e) => e.insertText); + +describe("argument completion", () => { + it("completes state-backed names, putting an exact match first", () => { + expect(inserts("model llama3")).toEqual(["/model llama3", "/model llama3:70b"]); + }); + + it("matches anywhere in a name, ignoring case", () => { + expect(inserts("model 8B")).toEqual(["/model qwen3:8b"]); + }); + + it("lists nothing once the typed value matches no name", () => { + expect(inserts("model mistral")).toEqual([]); + }); + + it("heads an optional argument's list with the bare command", () => { + const entries = matchCommands("model", sources); + // insertText equals the typed text, so Enter runs it rather than + // completing the row. + expect(entries[0]).toMatchObject({ sub: null, insertText: "/model" }); + expect(entries.slice(1).map((e) => e.sub)).toEqual(["llama3:70b", "llama3", "qwen3:8b"]); + expect(inserts("instructions")).toEqual(["/instructions", "/instructions clear"]); + }); + + it("offers no bare row when the argument is required", () => { + expect(inserts("space")).toEqual(["/space Work", "/space Home"]); + }); + + it("completes an optional-argument name without a trailing space", () => { + expect(inserts("mode")).toEqual(["/model"]); + expect(inserts("spac")).toEqual(["/space "]); + }); + + it("falls back to the bare command when there are no names to offer", () => { + expect(matchCommands("model").map((e) => e.insertText)).toEqual(["/model"]); + }); +}); diff --git a/src/lib/commands/parser.ts b/src/lib/commands/parser.ts index 4ba45aa..27f2cdc 100644 --- a/src/lib/commands/parser.ts +++ b/src/lib/commands/parser.ts @@ -43,40 +43,62 @@ export function findCommand(name: string): CommandSpec | undefined { return COMMANDS.find((c) => c.name === name); } +/** Argument values that live in app state rather than the registry — model + * ids, Space names, snippet titles — keyed by command name. The composer + * supplies them so this module stays free of store imports. */ +export type ArgSources = Readonly>; + /** Suggestions for the autocomplete palette. Returns commands whose name * starts with the typed prefix, plus any sub-command entries when the * parent matches. Empty query (just `/`) returns every command. */ -export function matchCommands(query: string): PaletteEntry[] { +export function matchCommands(query: string, argSources: ArgSources = {}): PaletteEntry[] { const parsed = parseInput("/" + query.replace(/^\/+/, "")); if (!parsed) return []; const name = parsed.name; const rest = parsed.rest; const out: PaletteEntry[] = []; for (const cmd of COMMANDS) { + // `[arg]` usage marks an optional argument: the bare command runs too. + const optionalArg = cmd.usage?.startsWith("[") ?? false; + const argValues = argSources[cmd.name] ?? []; // Exact-name match + the user is typing an argument → suggest the - // sub-commands as their own palette entries (`/list ` → `/list models`, - // `/list snippets`, …). - if (cmd.name === name && cmd.subcommands && cmd.subcommands.length > 0) { - for (const sub of cmd.subcommands) { - if (sub.startsWith(rest.toLowerCase())) { - out.push({ - cmd, - sub, - display: `/${cmd.name} ${sub}`, - insertText: `/${cmd.name} ${sub}`, - description: cmd.description, - }); - } + // sub-commands (and any state-backed values) as their own palette + // entries (`/list ` → `/list models`, `/list snippets`, …). + if (cmd.name === name && ((cmd.subcommands?.length ?? 0) > 0 || argValues.length > 0)) { + // The bare command heads the list when it can run on its own — + // otherwise Enter on a fully typed `/model` would complete the first + // option instead of running it. + if (optionalArg && rest.length === 0) { + out.push({ + cmd, + sub: null, + display: `/${cmd.name}`, + insertText: `/${cmd.name}`, + description: cmd.description, + }); + } + const subs = (cmd.subcommands ?? []).filter((sub) => + sub.startsWith(rest.toLowerCase()), + ); + for (const sub of [...subs, ...matchArgValues(argValues, rest)]) { + out.push({ + cmd, + sub, + display: `/${cmd.name} ${sub}`, + insertText: `/${cmd.name} ${sub}`, + description: cmd.description, + }); } continue; } - // Otherwise filter by prefix on the canonical name. + // Otherwise filter by prefix on the canonical name. No trailing space + // for an optional argument, so Enter on the completed name runs it. if (cmd.name.startsWith(name) && rest.length === 0) { out.push({ cmd, sub: null, display: `/${cmd.name}${cmd.usage ? " " + cmd.usage : ""}`, - insertText: `/${cmd.name}${cmd.subcommands?.length ? " " : cmd.usage ? " " : ""}`, + insertText: `/${cmd.name}${!optionalArg && (cmd.subcommands?.length || cmd.usage) ? " " : ""}`, description: cmd.description, }); } @@ -84,6 +106,23 @@ export function matchCommands(query: string): PaletteEntry[] { return out; } +/** Filter free-text argument values (names, titles) against what's typed. + * Looser than the sub-command prefix match — case-insensitive and + * anywhere in the name, the way the handlers resolve them — so exact + * matches go first, then prefix, then substring: once a value is typed in + * full, it's the highlighted row and Enter runs it rather than swapping in + * a longer name that contains it. */ +function matchArgValues(values: readonly string[], rest: string): string[] { + const q = rest.toLowerCase(); + const rank = (v: string) => { + const lower = v.toLowerCase(); + return lower === q ? 0 : lower.startsWith(q) ? 1 : lower.includes(q) ? 2 : 3; + }; + return [...new Set(values)] + .filter((v) => rank(v) < 3) + .sort((a, b) => rank(a) - rank(b)); +} + export interface PaletteEntry { cmd: CommandSpec; /** Selected sub-command, when this entry was synthesised from one. */ diff --git a/src/lib/commands/recency.test.ts b/src/lib/commands/recency.test.ts index 1eb9732..15ddab8 100644 --- a/src/lib/commands/recency.test.ts +++ b/src/lib/commands/recency.test.ts @@ -100,6 +100,16 @@ describe("orderByRecency", () => { expect(out.every((e) => e.groupOverride === undefined)).toBe(true); }); + it("leaves the bare row heading an argument list where it is", () => { + const args = [ + entry("model", "Model & persona"), + entry("model", "Model & persona", "llama3"), + ]; + const out = orderByRecency(args, ["model"]); + expect(out).toEqual(args); + expect(out.every((e) => e.groupOverride === undefined)).toBe(true); + }); + it("no-ops on an empty history or a single row", () => { expect(orderByRecency(base, [])).toBe(base); const one = [entry("new", "Chat")]; diff --git a/src/lib/commands/recency.ts b/src/lib/commands/recency.ts index cf1896f..8236dc3 100644 --- a/src/lib/commands/recency.ts +++ b/src/lib/commands/recency.ts @@ -66,7 +66,8 @@ export function pushRecentCommand(encoded: string, name: string): string { * - sub-command rows (`/list models`) never hoist. They only appear when * the parent command was typed in full, so every row would share one * `cmd.name` and a matching parent would hoist the entire list under a - * pointless "Recent" header. + * pointless "Recent" header. The same goes for the bare `/model` row + * heading its own argument list. */ export function orderByRecency( entries: PaletteEntry[], @@ -75,8 +76,13 @@ export function orderByRecency( if (entries.length < 2 || recent.length === 0) return entries; const rank = new Map(recent.map((name, i) => [name, i])); + const withArgRows = new Set( + entries.filter((e) => e.sub !== null).map((e) => e.cmd.name), + ); const hoisted = entries - .filter((e) => e.sub === null && rank.has(e.cmd.name)) + .filter( + (e) => e.sub === null && !withArgRows.has(e.cmd.name) && rank.has(e.cmd.name), + ) .sort((a, b) => rank.get(a.cmd.name)! - rank.get(b.cmd.name)!) .slice(0, RECENT_COMMANDS_SHOWN); if (hoisted.length === 0) return entries; diff --git a/src/lib/commands/registry.ts b/src/lib/commands/registry.ts index e0cda73..fe14f46 100644 --- a/src/lib/commands/registry.ts +++ b/src/lib/commands/registry.ts @@ -1,4 +1,5 @@ import { CHAT_LABELS } from "@/lib/labels"; +import { PERSONAS } from "@/lib/personas"; import { TONES } from "@/lib/tones"; import type { CommandSpec } from "./types"; @@ -111,19 +112,20 @@ export const COMMANDS: readonly CommandSpec[] = [ { name: "model", description: "Switch model for this chat", - usage: "", + usage: "[name]", group: "Model & persona", }, { name: "persona", description: "Apply a persona to this chat", - usage: "", + usage: "[name]", + subcommands: PERSONAS.map((p) => p.id), group: "Model & persona", }, { name: "tone", description: "Set the response tone for this chat", - usage: "", + usage: "[name]", subcommands: TONES.map((t) => t.id), group: "Model & persona", }, @@ -173,7 +175,7 @@ export const COMMANDS: readonly CommandSpec[] = [ { name: "instructions", description: "Set or clear per-chat instructions", - usage: "", + usage: "[text|clear]", subcommands: ["clear"], group: "Prompts", }, From 2eef0f2676057742939ddd52c217d4e67b31aa52 Mon Sep 17 00:00:00 2001 From: ZTCS Date: Wed, 30 Sep 2026 16:25:03 +0200 Subject: [PATCH 05/33] add sandboxed HTML preview to the code canvas --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 06b554e..9f61854 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ Behind a calm, beautifully crafted UI sits a rich feature set - ready when you n - **Temporal awareness** - inject current date, weekday and timezone into the system prompt so models can answer to "what day is it today?". #### Viewing content -- **Code canvas** - open any code block in a wider view that's resizable and updates live as the model streams, with copy, export and Open in VS Code actions. +- **Code canvas** - open any code block in a wider view that's resizable and updates live as the model streams, with copy, export and Open in VS Code actions. HTML renders as a live page in an offline sandbox. - **Attachment previews** - click an attachment to open the right viewer: image lightbox, multi-page PDF preview, code canvas, or a file-info card with Save. - **Share a message** - copy any message as text or as a rendered chat-bubble image, save the image as a PNG, or open a pre-filled post on Facebook, X, Reddit or LinkedIn. From b2434f3d735e3f7d5a9fea17932ee0d0d1a43eeb Mon Sep 17 00:00:00 2001 From: ZTCS Date: Wed, 30 Sep 2026 16:25:09 +0200 Subject: [PATCH 06/33] add sandboxed HTML preview to the code canvas --- docs/FEATURES.md | 19 +++- src-tauri/assets/sandbox/preview.html | 43 +++++++++ src-tauri/src/lib.rs | 2 + src-tauri/src/sandbox.rs | 124 ++++++++++++++++++++++++++ src-tauri/tauri.conf.json | 2 +- src/components/CodeBlock.tsx | 24 +++-- src/components/CodeCanvas.tsx | 75 ++++++++++++++-- src/components/HtmlPreview.tsx | 59 ++++++++++++ src/lib/tauri.ts | 11 ++- src/stores/canvasStore.ts | 23 ++++- tests/csp.test.ts | 39 ++++++++ 11 files changed, 403 insertions(+), 18 deletions(-) create mode 100644 src-tauri/assets/sandbox/preview.html create mode 100644 src-tauri/src/sandbox.rs create mode 100644 src/components/HtmlPreview.tsx create mode 100644 tests/csp.test.ts diff --git a/docs/FEATURES.md b/docs/FEATURES.md index 148b512..8265be4 100644 --- a/docs/FEATURES.md +++ b/docs/FEATURES.md @@ -1112,6 +1112,20 @@ Inline code blocks in assistant messages get an **Open** button (tooltip canvas keeps mirroring the latest code block as more tokens arrive. - **Resizable** — drag the left edge to set the panel width; the choice is remembered. +- **HTML preview** — for HTML (an `html` code block, or an `.html` / + `.htm` attachment) a **Code / Preview** switch renders the page, and + HTML code blocks get a **Preview** button that opens the canvas straight + on it. Scripts, styles and form handlers work; **Reload** starts the page + over. On a reply that's still streaming, the preview appears once the + code block is complete. + + The page runs in a sandbox, on an origin of its own: it can't reach + Loach, your chats or your files, can't open windows or navigate away, + and runs **offline** — scripts, stylesheets, images and fonts linked from + the web don't load, so a page built on a CDN library (Tailwind, + Chart.js, …) shows without it. `localStorage` and `sessionStorage` + work but last only until the page reloads; cookies aren't available, and + `alert()` does nothing. The canvas and the parameters sidebar share the right slot — the canvas wins when both would be open. @@ -1506,7 +1520,10 @@ verification happens before the binary is replaced. check against the GitHub releases endpoint. - **CSP is locked down** — no remote scripts, no inline scripts, no eval. The Tauri global is disabled; the renderer talks to the backend only - through registered commands. + through registered commands. The one place inline scripts run is the + canvas's HTML preview (§10), and only inside its sandboxed frame, which + has its own policy: nothing it loads comes from outside the page, and it + can't reach the network or Loach's commands. - **File I/O is backend-owned** — every save dialog, the Data import dialog, the workspace folder picker (§8.4), and the actual read / write happen in Rust. The renderer can't pick a path itself (it only learns diff --git a/src-tauri/assets/sandbox/preview.html b/src-tauri/assets/sandbox/preview.html new file mode 100644 index 0000000..2c1dcb0 --- /dev/null +++ b/src-tauri/assets/sandbox/preview.html @@ -0,0 +1,43 @@ + + + diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index b0c104e..55183b5 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -5,6 +5,7 @@ mod mcp; mod ollama_launch; mod preload; mod providers; +mod sandbox; mod secrets; mod security; mod sse; @@ -90,6 +91,7 @@ pub fn run() { .plugin(tauri_plugin_dialog::init()) .plugin(tauri_plugin_process::init()) .plugin(tauri_plugin_updater::Builder::new().build()) + .register_uri_scheme_protocol(sandbox::SCHEME, |_ctx, request| sandbox::handle(&request)) .setup(|app| { // Replace the prior `.expect(...)` chain with explicit user- // facing error dialogs. The old behaviour silent-crashed the diff --git a/src-tauri/src/sandbox.rs b/src-tauri/src/sandbox.rs new file mode 100644 index 0000000..e837932 --- /dev/null +++ b/src-tauri/src/sandbox.rs @@ -0,0 +1,124 @@ +//! The `loach-sandbox` URI scheme: an origin of its own for content Loach +//! renders but must not trust — the Code canvas's HTML preview. +//! +//! The protocol serves one fixed host page. The canvas frames it in +//! `