diff --git a/.github/workflows/jan-tauri-build-nightly-external.yaml b/.github/workflows/jan-tauri-build-nightly-external.yaml index b281cdbc1..167b4d223 100644 --- a/.github/workflows/jan-tauri-build-nightly-external.yaml +++ b/.github/workflows/jan-tauri-build-nightly-external.yaml @@ -15,7 +15,6 @@ on: - 'pre-install/**' - 'Makefile' - 'package.json' - - 'mise.toml' jobs: get-update-version: diff --git a/.github/workflows/jan-tauri-build-nightly.yaml b/.github/workflows/jan-tauri-build-nightly.yaml index 65a035c38..7949c0723 100644 --- a/.github/workflows/jan-tauri-build-nightly.yaml +++ b/.github/workflows/jan-tauri-build-nightly.yaml @@ -35,7 +35,6 @@ on: - 'pre-install/**' - 'Makefile' - 'package.json' - - 'mise.toml' jobs: diff --git a/.github/workflows/template-tauri-build-linux-x64-external.yml b/.github/workflows/template-tauri-build-linux-x64-external.yml index a88c48267..5c39e17c7 100644 --- a/.github/workflows/template-tauri-build-linux-x64-external.yml +++ b/.github/workflows/template-tauri-build-linux-x64-external.yml @@ -70,10 +70,9 @@ jobs: run: | echo "Version: ${{ inputs.new_version }}" jq --arg version "${{ inputs.new_version }}" '.version = $version | .bundle.createUpdaterArtifacts = false' ./src-tauri/tauri.conf.json > /tmp/tauri.conf.json - mv /tmp/tauri.conf.json ./src-tauri/tauri.conf.json + mv /tmp/tauri.conf.json ./src-tauri/tauri.conf.json if [ "${{ inputs.channel }}" != "stable" ]; then - jq '.bundle.linux.deb.files = {"usr/bin/bun": "resources/bin/bun", - "usr/lib/Jan-${{ inputs.channel }}/resources/lib/libvulkan.so": "resources/lib/libvulkan.so"}' ./src-tauri/tauri.linux.conf.json > /tmp/tauri.linux.conf.json + jq '.bundle.linux.deb.files = {"usr/bin/bun": "resources/bin/bun"}' ./src-tauri/tauri.linux.conf.json > /tmp/tauri.linux.conf.json mv /tmp/tauri.linux.conf.json ./src-tauri/tauri.linux.conf.json fi jq --arg version "${{ inputs.new_version }}" '.version = $version' web-app/package.json > /tmp/package.json @@ -83,7 +82,7 @@ jobs: jq --arg version "${{ inputs.new_version }}" '.version = $version' ./src-tauri/plugins/tauri-plugin-hardware/package.json > /tmp/package.json mv /tmp/package.json ./src-tauri/plugins/tauri-plugin-hardware/package.json - + echo "---------./src-tauri/plugins/tauri-plugin-hardware/package.json---------" cat ./src-tauri/plugins/tauri-plugin-hardware/package.json @@ -96,7 +95,7 @@ jobs: ctoml ./src-tauri/plugins/tauri-plugin-hardware/Cargo.toml package.version "${{ inputs.new_version }}" echo "---------./src-tauri/plugins/tauri-plugin-hardware/Cargo.toml---------" cat ./src-tauri/plugins/tauri-plugin-hardware/Cargo.toml - + ctoml ./src-tauri/plugins/tauri-plugin-llamacpp/Cargo.toml package.version "${{ inputs.new_version }}" echo "---------./src-tauri/plugins/tauri-plugin-llamacpp/Cargo.toml---------" cat ./src-tauri/plugins/tauri-plugin-llamacpp/Cargo.toml @@ -125,7 +124,7 @@ jobs: env: RELEASE_CHANNEL: '${{ inputs.channel }}' AUTO_UPDATER_DISABLED: ${{ inputs.disable_updater && 'true' || 'false' }} - + - name: Upload Artifact uses: actions/upload-artifact@v4 with: @@ -136,4 +135,4 @@ jobs: uses: actions/upload-artifact@v4 with: name: jan-linux-amd64-${{ inputs.new_version }}-AppImage - path: ./src-tauri/target/release/bundle/appimage/*.AppImage \ No newline at end of file + path: ./src-tauri/target/release/bundle/appimage/*.AppImage diff --git a/.github/workflows/template-tauri-build-linux-x64-flatpak.yml b/.github/workflows/template-tauri-build-linux-x64-flatpak.yml index 15d4827f7..d63fae3e7 100644 --- a/.github/workflows/template-tauri-build-linux-x64-flatpak.yml +++ b/.github/workflows/template-tauri-build-linux-x64-flatpak.yml @@ -91,10 +91,9 @@ jobs: echo "Version: ${{ inputs.new_version }}" # Update tauri.conf.json jq --arg version "${{ inputs.new_version }}" '.version = $version | .bundle.createUpdaterArtifacts = true' ./src-tauri/tauri.conf.json > /tmp/tauri.conf.json - mv /tmp/tauri.conf.json ./src-tauri/tauri.conf.json + mv /tmp/tauri.conf.json ./src-tauri/tauri.conf.json if [ "${{ inputs.channel }}" != "stable" ]; then - jq '.bundle.linux.deb.files = {"usr/bin/bun": "resources/bin/bun", - "usr/lib/Jan-${{ inputs.channel }}/resources/lib/libvulkan.so": "resources/lib/libvulkan.so"}' ./src-tauri/tauri.linux.conf.json > /tmp/tauri.linux.conf.json + jq '.bundle.linux.deb.files = {"usr/bin/bun": "resources/bin/bun"}' ./src-tauri/tauri.linux.conf.json > /tmp/tauri.linux.conf.json mv /tmp/tauri.linux.conf.json ./src-tauri/tauri.linux.conf.json fi jq --arg version "${{ inputs.new_version }}" '.version = $version' web-app/package.json > /tmp/package.json @@ -104,7 +103,7 @@ jobs: jq --arg version "${{ inputs.new_version }}" '.version = $version' ./src-tauri/plugins/tauri-plugin-hardware/package.json > /tmp/package.json mv /tmp/package.json ./src-tauri/plugins/tauri-plugin-hardware/package.json - + echo "---------./src-tauri/plugins/tauri-plugin-hardware/package.json---------" cat ./src-tauri/plugins/tauri-plugin-hardware/package.json @@ -117,7 +116,7 @@ jobs: ctoml ./src-tauri/plugins/tauri-plugin-hardware/Cargo.toml package.version "${{ inputs.new_version }}" echo "---------./src-tauri/plugins/tauri-plugin-hardware/Cargo.toml---------" cat ./src-tauri/plugins/tauri-plugin-hardware/Cargo.toml - + ctoml ./src-tauri/plugins/tauri-plugin-llamacpp/Cargo.toml package.version "${{ inputs.new_version }}" echo "---------./src-tauri/plugins/tauri-plugin-llamacpp/Cargo.toml---------" cat ./src-tauri/plugins/tauri-plugin-llamacpp/Cargo.toml @@ -128,7 +127,7 @@ jobs: # Temporarily enable devtool on prod build ctoml ./src-tauri/Cargo.toml dependencies.tauri.features[] "devtools" - cat ./src-tauri/Cargo.toml + cat ./src-tauri/Cargo.toml # Change app name for beta and nightly builds if [ "${{ inputs.channel }}" != "stable" ]; then @@ -139,7 +138,7 @@ jobs: .github/scripts/rename-tauri-app.sh ./src-tauri/tauri.conf.json ${{ inputs.channel }} cat ./src-tauri/tauri.conf.json - + # Update Cargo.toml ctoml ./src-tauri/Cargo.toml package.name "Jan-${{ inputs.channel }}" ctoml ./src-tauri/Cargo.toml dependencies.tauri.features[] "devtools" @@ -184,4 +183,3 @@ jobs: with: name: jan-linux-amd64-flatpak-${{ inputs.new_version }}-AppImage path: ./src-tauri/target/release/bundle/appimage/*.AppImage - diff --git a/.github/workflows/template-tauri-build-linux-x64.yml b/.github/workflows/template-tauri-build-linux-x64.yml index bd9b38369..487571595 100644 --- a/.github/workflows/template-tauri-build-linux-x64.yml +++ b/.github/workflows/template-tauri-build-linux-x64.yml @@ -108,10 +108,9 @@ jobs: echo "Version: ${{ inputs.new_version }}" # Update tauri.conf.json jq --arg version "${{ inputs.new_version }}" '.version = $version | .bundle.createUpdaterArtifacts = true' ./src-tauri/tauri.conf.json > /tmp/tauri.conf.json - mv /tmp/tauri.conf.json ./src-tauri/tauri.conf.json + mv /tmp/tauri.conf.json ./src-tauri/tauri.conf.json if [ "${{ inputs.channel }}" != "stable" ]; then - jq '.bundle.linux.deb.files = {"usr/bin/bun": "resources/bin/bun", - "usr/lib/Jan-${{ inputs.channel }}/resources/lib/libvulkan.so": "resources/lib/libvulkan.so"}' ./src-tauri/tauri.linux.conf.json > /tmp/tauri.linux.conf.json + jq '.bundle.linux.deb.files = {"usr/bin/bun": "resources/bin/bun"}' ./src-tauri/tauri.linux.conf.json > /tmp/tauri.linux.conf.json mv /tmp/tauri.linux.conf.json ./src-tauri/tauri.linux.conf.json fi jq --arg version "${{ inputs.new_version }}" '.version = $version' web-app/package.json > /tmp/package.json @@ -121,7 +120,7 @@ jobs: jq --arg version "${{ inputs.new_version }}" '.version = $version' ./src-tauri/plugins/tauri-plugin-hardware/package.json > /tmp/package.json mv /tmp/package.json ./src-tauri/plugins/tauri-plugin-hardware/package.json - + echo "---------./src-tauri/plugins/tauri-plugin-hardware/package.json---------" cat ./src-tauri/plugins/tauri-plugin-hardware/package.json @@ -134,7 +133,7 @@ jobs: ctoml ./src-tauri/plugins/tauri-plugin-hardware/Cargo.toml package.version "${{ inputs.new_version }}" echo "---------./src-tauri/plugins/tauri-plugin-hardware/Cargo.toml---------" cat ./src-tauri/plugins/tauri-plugin-hardware/Cargo.toml - + ctoml ./src-tauri/plugins/tauri-plugin-llamacpp/Cargo.toml package.version "${{ inputs.new_version }}" echo "---------./src-tauri/plugins/tauri-plugin-llamacpp/Cargo.toml---------" cat ./src-tauri/plugins/tauri-plugin-llamacpp/Cargo.toml @@ -156,7 +155,7 @@ jobs: .github/scripts/rename-tauri-app.sh ./src-tauri/tauri.conf.json ${{ inputs.channel }} cat ./src-tauri/tauri.conf.json - + # Update Cargo.toml ctoml ./src-tauri/Cargo.toml package.name "Jan-${{ inputs.channel }}" ctoml ./src-tauri/Cargo.toml dependencies.tauri.features[] "devtools" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 16379e575..2876e4598 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -126,8 +126,7 @@ jan/ ├── scripts/ # Build utilities │ ├── package.json # Root workspace configuration -├── Makefile # Build automation commands -├── mise.toml # Mise tool configuration +├── Makefile # Build automation commands ├── LICENSE # Apache 2.0 license └── README.md # Project overview ``` @@ -149,19 +148,6 @@ cd jan make dev ``` -**Option 2: The Easier Way (Mise)** -```bash -git clone https://github.com/menloresearch/jan -cd jan - -# Install mise -curl https://mise.run | sh - -# Let mise handle everything -mise install # installs Node.js, Rust, and other tools -mise dev # runs the full development setup -``` - ## How Can I Contribute? ### Reporting Bugs diff --git a/Makefile b/Makefile index da43f4960..890f612c8 100644 --- a/Makefile +++ b/Makefile @@ -60,7 +60,6 @@ install-ios-rust-targets: dev: install-and-build yarn download:bin - yarn download:lib yarn dev # Web application targets @@ -75,7 +74,7 @@ build-web-app: install-web-app yarn build:core yarn build:web-app -serve-web-app: +serve-web-app: yarn serve:web-app build-serve-web-app: build-web-app @@ -117,7 +116,6 @@ lint: install-and-build # Testing test: lint yarn download:bin - yarn download:lib ifeq ($(OS),Windows_NT) yarn download:windows-installer endif diff --git a/README.md b/README.md index b90cc8907..b2de4407f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# Jan - Local AI Assistant +# Jan - Open-source ChatGPT replacement -![Jan AI](docs/src/pages/docs/_assets/jan-app.png) +github jan banner

@@ -12,15 +12,13 @@

- Getting Started - - Docs + Getting Started + - Community - Changelog - Bug reports - - Discord

-Jan is an AI assistant that can run 100% offline on your device. Download and run LLMs with -**full control** and **privacy**. +Jan is bringing the best of open-source AI in an easy-to-use product. Download and run LLMs with **full control** and **privacy**. ## Installation @@ -29,41 +27,36 @@ The easiest way to get started is by downloading one of the following versions f - - + - - - -
PlatformStableNightlyDownload
Windows jan.exejan.exe
macOS jan.dmgjan.dmg
Linux (deb) jan.debjan.deb
Linux (AppImage) jan.AppImagejan.AppImage
-Download from [jan.ai](https://jan.ai/) or [GitHub Releases](https://github.com/menloresearch/jan/releases). +Download from [jan.ai](https://jan.ai/) or [GitHub Releases](https://github.com/menloresearch/jan/releases). ## Features -- **Local AI Models**: Download and run LLMs (Llama, Gemma, Qwen, etc.) from HuggingFace -- **Cloud Integration**: Connect to OpenAI, Anthropic, Mistral, Groq, and others +- **Local AI Models**: Download and run LLMs (Llama, Gemma, Qwen, GPT-oss etc.) from HuggingFace +- **Cloud Integration**: Connect to GPT models via OpenAI, Claude models via Anthropic, Mistral, Groq, and others - **Custom Assistants**: Create specialized AI assistants for your tasks - **OpenAI-Compatible API**: Local server at `localhost:1337` for other applications -- **Model Context Protocol**: MCP integration for enhanced capabilities +- **Model Context Protocol**: MCP integration for agentic capabilities - **Privacy First**: Everything runs locally when you want it to ## Build from Source @@ -93,29 +86,6 @@ This handles everything: installs dependencies, builds core components, and laun - `make test` - Run tests and linting - `make clean` - Delete everything and start fresh -### Run with Mise (easier) - -You can also run with [mise](https://mise.jdx.dev/), which is a bit easier as it ensures Node.js, Rust, and other dependency versions are automatically managed: - -```bash -git clone https://github.com/menloresearch/jan -cd jan - -# Install mise (if not already installed) -curl https://mise.run | sh - -# Install tools and start development -mise install # installs Node.js, Rust, and other tools -mise dev # runs the full development setup -``` - -**Available mise commands:** -- `mise dev` - Full development setup and launch -- `mise build` - Production build -- `mise test` - Run tests and linting -- `mise clean` - Delete everything and start fresh -- `mise tasks` - List all available tasks - ### Manual Commands ```bash diff --git a/core/src/browser/extensions/engines/AIEngine.ts b/core/src/browser/extensions/engines/AIEngine.ts index af63d9b19..a4f98e71c 100644 --- a/core/src/browser/extensions/engines/AIEngine.ts +++ b/core/src/browser/extensions/engines/AIEngine.ts @@ -274,6 +274,10 @@ export abstract class AIEngine extends BaseExtension { */ abstract delete(modelId: string): Promise + /** + * Updates a model + */ + abstract update(modelId: string, model: Partial): Promise /** * Imports a model */ diff --git a/core/src/browser/fs.ts b/core/src/browser/fs.ts index 0a05d4c56..42d43ca65 100644 --- a/core/src/browser/fs.ts +++ b/core/src/browser/fs.ts @@ -43,6 +43,12 @@ const mkdir = (...args: any[]) => globalThis.core.api?.mkdir({ args }) */ const rm = (...args: any[]) => globalThis.core.api?.rm({ args }) +/** + * Moves a file from the source path to the destination path. + * @returns {Promise} A Promise that resolves when the file is moved successfully. + */ +const mv = (...args: any[]) => globalThis.core.api?.mv({ args }) + /** * Deletes a file from the local file system. * @param {string} path - The path of the file to delete. @@ -92,6 +98,7 @@ export const fs = { readdirSync, mkdir, rm, + mv, unlinkSync, appendFileSync, copyFile, diff --git a/core/src/types/api/index.ts b/core/src/types/api/index.ts index d40aab852..6d6d1c4a6 100644 --- a/core/src/types/api/index.ts +++ b/core/src/types/api/index.ts @@ -91,6 +91,7 @@ export enum FileSystemRoute { existsSync = 'existsSync', readdirSync = 'readdirSync', rm = 'rm', + mv = 'mv', mkdir = 'mkdir', readFileSync = 'readFileSync', writeFileSync = 'writeFileSync', diff --git a/docs/_redirects b/docs/_redirects index 90846d1f2..ef126ea63 100644 --- a/docs/_redirects +++ b/docs/_redirects @@ -50,15 +50,72 @@ /docs/shortcuts /docs/ 302 /docs/models /docs/ 302 /integrations/function-calling/interpreter /docs/ 302 +/docs/desktop/built-in/tensorrt-llm /docs 302 +/docs/desktop/beta /docs/desktop 302 +/platforms /docs/desktop 302 /docs/built-in/llama-cpp /docs/desktop/llama-cpp 302 /docs/install-engines /docs/desktop/llama-cpp 302 /docs/local-api /docs/desktop/api-server 302 /docs/local-engines/llama-cpp /docs/desktop/llama-cpp 302 +/docs/api-server /docs/desktop/api-server 302 +/docs/assistants /docs/desktop/assistants 302 /docs/models/manage-models /docs/desktop/manage-models 302 +/docs/data-folder /docs/desktop/data-folder 302 /cortex/vision /handbook/open-superintelligence 302 /docs/models/model-parameters /docs/desktop/model-parameters 302 /docs/remote-models/generic-openai /docs/desktop/remote-models/openai 302 /docs/threads /changelog/2024-01-16-settings-options-right-panel 302 +/docs/desktop/docs/data-folder /docs/desktop/data-folder 302 +/docs/desktop/docs/desktop/install/linux /docs/desktop/install/linux 302 +/docs/desktop/docs/desktop/troubleshooting /docs/desktop/troubleshooting 302 +/docs/desktop/linux /docs/desktop/install/linux 302 +/docs/desktop/local-engines/llama-cpp /docs/desktop/llama-cpp-server 302 +/docs/desktop/models/model-parameters /docs/desktop/model-parameters 302 +/docs/desktop/windows /docs/desktop/install/windows 302 +/docs/docs/data-folder /docs/desktop/data-folder 302 +/docs/docs/desktop/linux /docs/desktop/install/linux 302 +/docs/docs/troubleshooting /docs/desktop/troubleshooting 302 +/docs/jan-models/jan-nano-32 /docs/desktop/jan-models/jan-nano-32 302 +/docs/jan-models/jan-v1 /docs/desktop/jan-models/jan-v1 302 +/docs/jan-models/lucy /docs/desktop/jan-models/lucy 302 +/docs/llama-cpp /docs/desktop/llama-cpp 302 +/docs/manage-models /docs/desktop/manage-models 302 +/docs/mcp /docs/desktop/mcp 302 +/docs/mcp-examples/data-analysis/e2b /docs/desktop/mcp-examples/data-analysis/e2b 302 +/docs/mcp-examples/deepresearch/octagon /docs/desktop/mcp-examples/deepresearch/octagon 302 +/docs/mcp-examples/design/canva /docs/desktop/mcp-examples/design/canva 302 +/docs/mcp-examples/productivity/linear /docs/desktop/mcp-examples/productivity/linear 302 +/docs/mcp-examples/search/exa /docs/desktop/mcp-examples/search/exa 302 +/docs/model-parameters /docs/desktop/model-parameters 302 +/docs/remote-models/cohere /docs/desktop/remote-models/cohere 302 +/docs/remote-models/google /docs/desktop/remote-models/google 302 +/docs/remote-models/groq /docs/desktop/remote-models/groq 302 +/docs/remote-models/huggingface /docs/desktop/remote-models/huggingface 302 +/docs/remote-models/mistralai /docs/desktop/remote-models/mistralai 302 +/docs/remote-models/openai /docs/desktop/remote-models/openai 302 +/docs/server-examples/continue-dev /docs/desktop/server-examples/continue-dev 302 +/docs/server-examples/n8n /docs/desktop/server-examples/n8n 302 +/docs/server-troubleshooting /docs/desktop/troubleshooting 302 +/docs/privacy-policy /privacy 302 +/docs/server-settings /docs/desktop/server-settings 302 +/docs/settings /docs/desktop/settings 302 +/docs/llama-cpp-server /docs/desktop/llama-cpp-server 302 +/docs/install/linux /docs/desktop/install/linux 302 +/docs/install/macos /docs/desktop/install/mac 302 +/docs/install/windows /docs/desktop/install/windows 302 +/docs/mcp-examples/browser/browserbase /docs/desktop/mcp-examples/browser/browserbase 302 +/docs/jan-models/jan-nano-128 /docs/desktop/jan-models/jan-nano-128 302 +/docs/mcp-examples/search/serper /docs/desktop/mcp-examples/search/serper 302 +/docs/mcp-examples/data-analysis/jupyter /docs/desktop/mcp-examples/data-analysis/jupyter 302 +/docs/mcp-examples/productivity/todoist /docs/desktop/mcp-examples/productivity/todoist 302 +/docs/remote-models/anthropic /docs/desktop/remote-models/anthropic 302 +/docs/remote-models/openrouter /docs/desktop/remote-models/openrouter 302 +/docs/server-examples/llmcord /docs/desktop/server-examples/llmcord 302 +/docs/server-examples/tabby /docs/desktop/server-examples/tabby 302 +/docs/built-in/tensorrt-llm /docs/desktop/llama-cpp 302 +/docs/desktop/docs/desktop/linux /docs/desktop/install/linux 302 +/windows /docs/desktop/install/windows 302 + /guides/integrations/continue/ /docs/desktop/server-examples/continue-dev 302 /continue-dev /docs/desktop/server-examples/continue-dev 302 /integrations /docs/desktop/server-examples/continue-dev 302 diff --git a/docs/public/sitemap-0.xml b/docs/public/sitemap-0.xml deleted file mode 100644 index 131222295..000000000 --- a/docs/public/sitemap-0.xml +++ /dev/null @@ -1,125 +0,0 @@ - - -https://jan.ai2025-09-24T03:40:05.491Zdaily1 -https://jan.ai/api-reference2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/api-reference/api-reference2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/api-reference/architecture2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/api-reference/configuration2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/api-reference/development2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/api-reference/installation2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/blog2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2023-12-21-faster-inference-across-platform2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2024-01-16-settings-options-right-panel2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2024-01-29-local-api-server2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2024-02-05-jan-data-folder2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2024-02-10-jan-is-more-stable2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2024-02-26-home-servers-with-helm2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2024-03-06-ui-revamp-settings2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2024-03-11-import-models2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2024-03-19-nitro-tensorrt-llm-extension2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2024-04-02-groq-api-integration2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2024-04-15-new-mistral-extension2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2024-04-25-llama3-command-r-hugginface2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2024-05-20-llamacpp-upgrade-new-remote-models2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2024-05-28-cohere-aya-23-8b-35b-phi-3-medium2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2024-06-21-nvidia-nim-support2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2024-07-15-claude-3-5-support2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2024-09-01-llama3-1-gemma2-support2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2024-09-17-improved-cpu-performance2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2024-10-24-jan-stable2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2024-11-22-jan-bugs2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2024-11.14-jan-supports-qwen-coder2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2024-12-03-jan-is-faster2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2024-12-05-jan-hot-fix-mac2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2024-12-30-jan-new-privacy2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2025-01-06-key-issues-resolved2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2025-01-23-deepseek-r1-jan2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2025-02-18-advanced-llama.cpp-settings2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2025-03-14-jan-security-patch2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2025-05-14-jan-qwen3-patch2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2025-06-19-jan-ui-revamp2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2025-06-26-jan-nano-mcp2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2025-07-17-responsive-ui2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2025-07-31-llamacpp-tutorials2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2025-08-07-gpt-oss2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2025-08-14-general-improvs2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2025-08-28-image-support2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/changelog/2025-09-18-auto-optimize-vision-imports2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/api-server2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/assistants2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/data-folder2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/install/linux2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/install/mac2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/install/windows2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/jan-models/jan-nano-1282025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/jan-models/jan-nano-322025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/jan-models/jan-v12025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/jan-models/lucy2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/llama-cpp2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/llama-cpp-server2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/manage-models2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/mcp2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/mcp-examples/browser/browserbase2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/mcp-examples/data-analysis/e2b2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/mcp-examples/data-analysis/jupyter2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/mcp-examples/deepresearch/octagon2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/mcp-examples/design/canva2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/mcp-examples/productivity/linear2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/mcp-examples/productivity/todoist2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/mcp-examples/search/exa2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/mcp-examples/search/serper2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/model-parameters2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/privacy2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/privacy-policy2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/quickstart2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/remote-models/anthropic2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/remote-models/cohere2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/remote-models/google2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/remote-models/groq2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/remote-models/huggingface2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/remote-models/mistralai2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/remote-models/openai2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/remote-models/openrouter2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/server-examples/continue-dev2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/server-examples/llmcord2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/server-examples/n8n2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/server-examples/tabby2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/server-settings2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/server-troubleshooting2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/settings2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/desktop/troubleshooting2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/server2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/server/api-reference2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/server/api-reference-administration2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/server/api-reference-authentication2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/server/api-reference-chat2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/server/api-reference-chat-conversations2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/server/api-reference-conversations2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/server/api-reference-jan-responses2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/server/api-reference-jan-server2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/server/architecture2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/server/configuration2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/server/development2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/server/installation2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/docs/server/overview2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/download2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/handbook2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/handbook/betting-on-open-source2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/handbook/open-superintelligence2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/post/benchmarking-nvidia-tensorrt-llm2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/post/bitdefender2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/post/data-is-moat2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/post/deepresearch2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/post/deepseek-r1-locally2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/post/jan-v1-for-research2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/post/offline-chatgpt-alternative2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/post/qwen3-settings2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/post/rag-is-not-enough2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/post/run-ai-models-locally2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/post/run-gpt-oss-locally2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/privacy2025-09-24T03:40:05.492Zdaily1 -https://jan.ai/support2025-09-24T03:40:05.492Zdaily1 - \ No newline at end of file diff --git a/docs/src/components/FooterMenu/index.tsx b/docs/src/components/FooterMenu/index.tsx index 68e1e6e78..317def75f 100644 --- a/docs/src/components/FooterMenu/index.tsx +++ b/docs/src/components/FooterMenu/index.tsx @@ -16,7 +16,10 @@ const FOOTER_MENUS: FooterMenu[] = [ { title: 'Company', links: [ - { name: 'Vision', href: '/', comingSoon: true }, + { + name: 'Open Superintelligence', + href: '/handbook/why/open-superintelligence', + }, { name: 'Handbook', href: '/handbook' }, { name: 'Community', href: 'https://discord.com/invite/FTk2MvZwJH' }, { name: 'Careers', href: 'https://menlo.bamboohr.com/careers' }, diff --git a/docs/src/components/Home/index.tsx b/docs/src/components/Home/index.tsx index 1d577b6d8..61d96be1f 100644 --- a/docs/src/components/Home/index.tsx +++ b/docs/src/components/Home/index.tsx @@ -95,7 +95,7 @@ const Home = () => {
-
+
@@ -127,12 +127,17 @@ const Home = () => { The best of open-source AI in an easy-to-use product.

-
-
+
{
- {formatCompactNumber( + 15k+ + {/* {formatCompactNumber( discordWidget.presence_count - )} + )} */}
@@ -483,9 +490,10 @@ const Home = () => {
- {formatCompactNumber( + 15k+ + {/* {formatCompactNumber( discordWidget.presence_count - )} + )} */}
diff --git a/docs/src/components/Navbar.tsx b/docs/src/components/Navbar.tsx index 51044e9c7..b12fcaa73 100644 --- a/docs/src/components/Navbar.tsx +++ b/docs/src/components/Navbar.tsx @@ -4,7 +4,7 @@ import { useRouter } from 'next/router' import { cn } from '@/lib/utils' import { FaDiscord, FaGithub } from 'react-icons/fa' import { FiDownload } from 'react-icons/fi' -import { FaXTwitter } from 'react-icons/fa6' +import { FaXTwitter, FaLinkedinIn } from 'react-icons/fa6' import { Button } from './ui/button' import LogoJanSVG from '@/assets/icons/logo-jan.svg' @@ -113,6 +113,43 @@ const Navbar = ({ noScroll }: { noScroll?: boolean }) => {
+ +
  • + +
  • @@ -232,6 +269,14 @@ const Navbar = ({ noScroll }: { noScroll?: boolean }) => { > + + + +} + +const StatusIcon = ({ status }: { status: string }) => { + switch (status) { + case 'operational': + return + case 'degraded': + case 'partial_outage': + return + case 'major_outage': + return + case 'under_maintenance': + return + default: + return + } +} + +const getStatusColor = (status: string) => { + switch (status) { + case 'operational': + return 'bg-green-100 text-green-800 border-green-200 dark:bg-green-900/20 dark:text-green-300 dark:border-green-800' + case 'degraded': + case 'partial_outage': + return 'bg-yellow-100 text-yellow-800 border-yellow-200 dark:bg-yellow-900/20 dark:text-yellow-300 dark:border-yellow-800' + case 'major_outage': + return 'bg-red-100 text-red-800 border-red-200 dark:bg-red-900/20 dark:text-red-300 dark:border-red-800' + case 'under_maintenance': + return 'bg-blue-100 text-blue-800 border-blue-200 dark:bg-blue-900/20 dark:text-blue-300 dark:border-blue-800' + default: + return 'bg-gray-100 text-gray-800 border-gray-200 dark:bg-gray-900/20 dark:text-gray-300 dark:border-gray-800' + } +} + +const getStatusText = (status: string) => { + switch (status) { + case 'operational': + return 'All Systems Operational' + case 'degraded': + return 'Degraded Performance' + case 'partial_outage': + return 'Partial Service Outage' + case 'major_outage': + return 'Major Service Outage' + case 'under_maintenance': + return 'Under Maintenance' + default: + return 'Status Unknown' + } +} + +export const OpenAIStatusChecker: React.FC = () => { + const [statusData, setStatusData] = useState(null) + const [loading, setLoading] = useState(true) + const [error, setError] = useState(null) + const [lastRefresh, setLastRefresh] = useState(new Date()) + + const fetchStatus = useCallback(async () => { + setLoading(true) + setError(null) + + try { + console.log('Fetching real OpenAI status...') + + // Use CORS proxy to fetch real OpenAI status + const proxyUrl = 'https://api.allorigins.win/get?url=' + const targetUrl = 'https://status.openai.com/api/v2/status.json' + + const response = await fetch(proxyUrl + encodeURIComponent(targetUrl)) + + if (!response.ok) { + throw new Error(`Proxy returned ${response.status}`) + } + + const proxyData = await response.json() + const openaiData = JSON.parse(proxyData.contents) + + console.log('Real OpenAI data received:', openaiData) + + // Transform real OpenAI data to our format + const transformedData: StatusData = { + status: mapOpenAIStatusClient( + openaiData.status?.indicator || 'operational' + ), + lastUpdated: openaiData.page?.updated_at || new Date().toISOString(), + incidents: (openaiData.incidents || []).slice(0, 3), + } + + setStatusData(transformedData) + setLastRefresh(new Date()) + console.log('✅ Real OpenAI status loaded successfully!') + } catch (err) { + console.error('Failed to fetch real status:', err) + + // Fallback: try alternative proxy + try { + console.log('Trying alternative proxy...') + const altResponse = await fetch( + `https://cors-anywhere.herokuapp.com/https://status.openai.com/api/v2/summary.json` + ) + + if (altResponse.ok) { + const altData = await altResponse.json() + setStatusData({ + status: mapOpenAIStatusClient( + altData.status?.indicator || 'operational' + ), + lastUpdated: new Date().toISOString(), + incidents: [], + }) + setLastRefresh(new Date()) + console.log('✅ Alternative proxy worked!') + return + } + } catch (altErr) { + console.log('Alternative proxy also failed') + } + + // Final fallback + setError('Unable to fetch real-time status') + setStatusData({ + status: 'operational' as const, + lastUpdated: new Date().toISOString(), + incidents: [], + }) + setLastRefresh(new Date()) + console.log('Using fallback status') + } finally { + setLoading(false) + } + }, []) + + // Client-side status mapping function + const mapOpenAIStatusClient = (indicator: string): StatusData['status'] => { + switch (indicator.toLowerCase()) { + case 'none': + case 'operational': + return 'operational' + case 'minor': + return 'degraded' + case 'major': + return 'partial_outage' + case 'critical': + return 'major_outage' + case 'maintenance': + return 'under_maintenance' + default: + return 'operational' as const // Default to operational + } + } + + useEffect(() => { + fetchStatus() + // Refresh every 2 minutes for more real-time updates + const interval = setInterval(fetchStatus, 2 * 60 * 1000) + return () => clearInterval(interval) + }, [fetchStatus]) + + const handleRefresh = () => { + fetchStatus() + } + + if (loading && !statusData) { + return ( +
    +
    + + + Checking OpenAI Status... + +
    +
    + ) + } + + if (error) { + return ( +
    +
    +
    + +
    +

    + Unable to Check Status +

    +

    {error}

    +
    +
    + +
    +
    + ) + } + + return ( +
    + ) +} diff --git a/docs/src/pages/api-reference/installation.mdx b/docs/src/pages/api-reference/installation.mdx index de0609a08..266962089 100644 --- a/docs/src/pages/api-reference/installation.mdx +++ b/docs/src/pages/api-reference/installation.mdx @@ -3,7 +3,7 @@ title: Installation description: Install and deploy Jan Server on Kubernetes using minikube and Helm. --- -## Prerequisites +# Prerequisites Jan Server requires the following tools installed on your system: diff --git a/docs/src/pages/docs/_meta.json b/docs/src/pages/docs/_meta.json index 5b6962032..ee07f5d54 100644 --- a/docs/src/pages/docs/_meta.json +++ b/docs/src/pages/docs/_meta.json @@ -9,7 +9,7 @@ }, "desktop": { "type": "page", - "title": "Jan Desktop & Mobile" + "title": "Jan Desktop" }, "server": { "type": "page", diff --git a/docs/src/pages/docs/desktop/_meta.json b/docs/src/pages/docs/desktop/_meta.json index 36c70cf27..1745297cb 100644 --- a/docs/src/pages/docs/desktop/_meta.json +++ b/docs/src/pages/docs/desktop/_meta.json @@ -42,6 +42,5 @@ }, "settings": "Settings", "data-folder": "Jan Data Folder", - "troubleshooting": "Troubleshooting", - "privacy": "Privacy" + "troubleshooting": "Troubleshooting" } diff --git a/docs/src/pages/docs/desktop/index.mdx b/docs/src/pages/docs/desktop/index.mdx index a6ebed221..852f097a5 100644 --- a/docs/src/pages/docs/desktop/index.mdx +++ b/docs/src/pages/docs/desktop/index.mdx @@ -22,228 +22,52 @@ keywords: import { Callout } from 'nextra/components' import FAQBox from '@/components/FaqBox' -# Jan - -![Jan's Cover Image](./_assets/jan-app-new.png) - -## Jan's Goal - -> We're working towards open superintelligence to make a viable open-source alternative to platforms like ChatGPT -and Claude that anyone can own and run. - -## What is Jan Today - -Jan is an open-source AI platform that runs on your hardware. We believe AI should be in the hands of many, not -controlled by a few tech giants. - -Today, Jan is: -- **A desktop app** that runs AI models locally or connects to cloud providers -- **A model hub** making the latest open-source models accessible -- **A connector system** that lets AI interact with real-world tools via MCP - -Tomorrow, Jan aims to be a complete ecosystem where open models rival or exceed closed alternatives. +# Overview -We're building this with the open-source AI community, using the best available tools, and sharing everything -we learn along the way. +We're building [Open Superintelligence](https://jan.ai/handbook/open-superintelligence) together. -## The Jan Ecosystem +Jan is an open-source replacement for ChatGPT: +- AI Models: Use AI models with agentic capabilities + - [Open-source Models](/docs/desktop/manage-models): Run open-source locally + - [Cloud Models](/docs/desktop/remote-models/anthropic): Connect to remote models with API keys +- [Assistants](/docs/desktop/assistants): Create custom AI assistants +- [MCP Servers](/docs/desktop/mcp): Integrate MCP Servers to give agentic capabilities to AI models +- Jan Hub: Browse, install, and [manage models](/docs/desktop/manage-models) +- Local API Server: Expose an [OpenAI-compatible API](/docs/desktop/api-server) from your own machine or server -### Jan Apps -**Available Now:** -- **Desktop**: Full-featured AI workstation for Windows, Mac, and Linux +## Product Suite -**Coming Late 2025:** -- **Mobile**: Jan on your phone -- **Web**: Browser-based access at jan.ai -- **Server**: Self-hosted for teams -- **Extensions**: Browser extension for Chrome-based browsers +Jan is a full [product suite](https://en.wikipedia.org/wiki/Software_suite) that offers an alternative to Big AI: +- [Jan Desktop](/docs/desktop/quickstart): macOS, Windows, and Linux apps with offline mode +- [Jan Web](https://chat.jan.ai): Jan on browser, a direct alternative to chatgpt.com +- Jan Mobile: iOS and Android apps (Coming Soon) +- [Jan Server](/docs/server): deploy locally, in your cloud, or on-prem +- [Jan Models](/docs/models): Open-source models optimized for deep research, tool use, and reasoning -### Jan Model Hub -Making open-source AI accessible to everyone: -- **Easy Downloads**: One-click model installation -- **Jan Models**: Our own models optimized for local use - - **Jan-v1**: 4B reasoning model specialized in web search - - **Research Models** - - **Jan-Nano (32k/128k)**: 4B model for web search with MCP tools - - **Lucy**: 1.7B mobile-optimized for web search -- **Community Models**: Any GGUF from Hugging Face works in Jan -- **Cloud Models**: Connect your API keys for OpenAI, Anthropic, Gemini, and more +### Extending Jan (Coming Soon) +Jan helps you customize and align Open Superintelligence: +- Jan Connectors: Extend Jan with integrations +- Jan Studio: Fine-tune, align, and guardrail +- Evals: Benchmark models across industries, regions, and alignment dimensions +## Principles -### Jan Connectors Hub -Connect AI to the tools you use daily via [Model Context Protocol](./mcp): +- [Open source](https://www.redhat.com/en/blog/open-source-culture-9-core-principles-and-values): [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0) licensed, built in public. +- No [vendor lock-in](https://en.wikipedia.org/wiki/Vendor_lock-in): Switch freely between local and frontier models. +- [Right to Repair](https://en.wikipedia.org/wiki/Right_to_repair): Inspect, audit, and modify your AI stack. -**Creative & Design:** -- **Canva**: Generate and edit designs - -**Data & Analysis:** -- **Jupyter**: Run Python notebooks -- **E2B**: Execute code in sandboxes - -**Web & Search:** -- **Browserbase & Browser Use**: Browser automation -- **Exa, Serper, Perplexity**: Advanced web search -- **Octagon**: Deep research capabilities - -**Productivity:** -- **Linear**: Project management -- **Todoist**: Task management - -## Core Features - -- **Run Models Locally**: Download any GGUF model from Hugging Face, use OpenAI's gpt-oss models, -or connect to cloud providers -- **OpenAI-Compatible API**: Local server at `localhost:1337` works with tools like -[Continue](./server-examples/continue-dev) and [Cline](https://cline.bot/) -- **Extend with MCP Tools**: Browser automation, web search, data analysis, and design tools, all -through natural language -- **Your Choice of Infrastructure**: Run on your laptop, self-host on your servers (soon), or use -cloud when you need it - -## Philosophy - -Jan is built to be user-owned: -- **Open Source**: Apache 2.0 license -- **Local First**: Your data stays on your device. Internet is optional -- **Privacy Focused**: We don't collect or sell user data. See our [Privacy Policy](./privacy) -- **No Lock-in**: Export your data anytime. Use any model. Switch between local and cloud - - -The best AI is the one you control. Not the one that others control for you. - - -## The Path Forward - -### What Works Today -- Run powerful models locally on consumer hardware -- Connect to any cloud provider with your API keys -- Use MCP tools for real-world tasks -- Access transparent model evaluations - -### What We're Building -- More specialized models that excel at specific tasks -- Expanded app ecosystem (mobile, web, extensions) -- Richer connector ecosystem -- An evaluation framework to build better models - -### The Long-Term Vision -We're working towards open superintelligence where: -- Open models match or exceed closed alternatives -- Anyone can run powerful AI on their own hardware -- The community drives innovation, not corporations -- AI capabilities are owned by users, not rented - - -This is an ambitious goal without a guaranteed path. We're betting on the open-source community, improved -hardware, and better techniques, but we're honest that this is a journey, not a destination we've reached. - - -## Quick Start - -1. [Download Jan](./quickstart) for your operating system -2. Choose a model - download locally or add cloud API keys -3. Start chatting or connect tools via MCP -4. Build with our [local API](./api-server) +Jan grows through contribution. It is shaped by many and belongs to everyone who uses it. ## Acknowledgements -Jan is built on the shoulders of giants: -- [Llama.cpp](https://github.com/ggerganov/llama.cpp) for inference -- [Model Context Protocol](https://modelcontextprotocol.io) for tool integration -- The open-source community that makes this possible +> Good artists copy, great artists steal. -## FAQs +Jan exists because we've borrowed, learned, and built on the work of others. - - Jan is an open-source AI platform working towards a viable alternative to Big Tech AI. Today it's a desktop app that runs models locally or connects to cloud providers. Tomorrow it aims to be a complete ecosystem rivaling platforms like ChatGPT and Claude. - - - - Other platforms are models behind APIs you rent. Jan is a complete AI ecosystem you own. Run any model, use real tools through MCP, keep your data private, and never pay subscriptions for local use. - - - - **Jan Models:** - - Jan-Nano (32k/128k) - Research and analysis with MCP integration - - Lucy - Mobile-optimized search (1.7B) - - Jan-v1 - Reasoning and tool use (4B) - - **Open Source:** - - OpenAI's gpt-oss models (120b and 20b) - - Any GGUF model from Hugging Face - - **Cloud (with your API keys):** - - OpenAI, Anthropic, Mistral, Groq, and more - - - - MCP (Model Context Protocol) lets AI interact with real applications. Instead of just generating text, your AI can create designs in Canva, analyze data in Jupyter, browse the web, and execute code - all through conversation. - - - - **Supported OS**: - - [Windows 10+](/docs/desktop/install/windows#compatibility) - - [macOS 12+](/docs/desktop/install/mac#compatibility) - - [Linux (Ubuntu 20.04+)](/docs/desktop/install/linux) - - **Hardware**: - - Minimum: 8GB RAM, 10GB storage - - Recommended: 16GB RAM, GPU (NVIDIA/AMD/Intel/Apple), 50GB storage - - - - Honestly? It's ambitious and uncertain. We believe the combination of rapidly improving open models, better consumer hardware, community innovation, and specialized models working together can eventually rival closed platforms. But this is a multi-year journey with no guarantees. What we can guarantee is that we'll keep building in the open, with the community, towards this goal. - - - - Right now, Jan can: - - Run models like Llama, Mistral, and our own Jan models locally - - Connect to cloud providers if you want more power - - Use MCP tools to create designs, analyze data, browse the web, and more - - Work completely offline once models are downloaded - - Provide an OpenAI-compatible API for developers - - - - **Local use**: Always free, no catches - **Cloud models**: You pay providers directly (we add no markup) - **Jan cloud**: Optional paid services coming 2025 - - The core platform will always be free and open source. - - - - - Runs 100% offline once models are downloaded - - All data stored locally in [Jan Data Folder](/docs/desktop/data-folder) - - No telemetry without explicit consent - - Open source code you can audit - - - When using cloud providers through Jan, their privacy policies apply. - - - - - Yes. Download directly or build from [source](https://github.com/menloresearch/jan). Jan Server for production deployments coming late 2025. - - - - - **Jan Web**: Beta late 2025 - - **Jan Mobile**: Late 2025 - - **Jan Server**: Late 2025 - - All versions will sync seamlessly. - - - - - Code: [GitHub](https://github.com/menloresearch/jan) - - Community: [Discord](https://discord.gg/FTk2MvZwJH) - - Testing: Help evaluate models and report bugs - - Documentation: Improve guides and tutorials - - - - Yes! We love hiring from our community. Check [Careers](https://menlo.bamboohr.com/careers). - +- [llama.cpp](https://github.com/ggerganov/llama.cpp) and [GGML](https://github.com/ggerganov/ggml) for efficient inference +- [r/LocalLLaMA](https://www.reddit.com/r/LocalLLaMA/) for ideas, feedback, and debate +- [Model Context Protocol](https://modelcontextprotocol.io) for MCP integrations +- [PostHog](https://posthog.com/docs) for docs inspiration +- The open-source community for contributions, bug reports, and improvements diff --git a/docs/src/pages/docs/desktop/install/linux.mdx b/docs/src/pages/docs/desktop/install/linux.mdx index 2d42a59f1..2d9d39f9f 100644 --- a/docs/src/pages/docs/desktop/install/linux.mdx +++ b/docs/src/pages/docs/desktop/install/linux.mdx @@ -1,11 +1,12 @@ --- title: Linux -description: Get started quickly with Jan, an AI chat application that runs 100% offline on your desktop & mobile (*coming soon*). +description: Download Jan on Linux to run AI models locally. Jan is a free, open-source ChatGPT alternative to run offline. keywords: [ Jan, Customizable Intelligence, LLM, local AI, + Jan on Linux, privacy focus, free and open source, private and offline, @@ -18,15 +19,17 @@ keywords: installation, "desktop" ] +twitter: + card: summary_large_image + site: "@jandotai" + title: "Jan on Linux" + description: "Download Jan on Linux to run AI models locally. Jan is a free, open-source ChatGPT alternative to run offline." --- - import FAQBox from '@/components/FaqBox' import { Tabs, Callout, Steps } from 'nextra/components' import { Settings } from 'lucide-react' - - # Linux Installation Instructions for installing Jan on Linux. @@ -244,7 +247,7 @@ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda/lib64 ### Step 2: Enable GPU Acceleration 1. Navigate to **Settings** () > **Local Engine** > **Llama.cpp** -2. Select appropriate backend in **llama-cpp Backend**. Details in our [guide](/docs/desktop/local-engines/llama-cpp). +2. Select appropriate backend in **llama-cpp Backend**. Details in our [llama.cpp guide](/docs/desktop/llama-cpp). CUDA offers better performance than Vulkan. diff --git a/docs/src/pages/docs/desktop/install/mac.mdx b/docs/src/pages/docs/desktop/install/mac.mdx index 827329d6e..b784f2ecf 100644 --- a/docs/src/pages/docs/desktop/install/mac.mdx +++ b/docs/src/pages/docs/desktop/install/mac.mdx @@ -1,11 +1,11 @@ --- title: Mac -description: Get started quickly with Jan - a local AI that runs on your computer. Install Jan and pick your model to start chatting. -keywords: +description: Download Jan on Mac to run AI models locally. Jan is a free, open-source ChatGPT alternative to run offline. [ Jan, Customizable Intelligence, LLM, local AI, + Jan on Mac, privacy focus, free and open source, private and offline, @@ -18,6 +18,11 @@ keywords: installation, "desktop" ] +twitter: + card: summary_large_image + site: "@jandotai" + title: "Jan on Mac" + description: "Download Jan on Mac to run AI models locally. Jan is a free, open-source ChatGPT alternative to run offline." --- import { Tabs } from 'nextra/components' diff --git a/docs/src/pages/docs/desktop/install/windows.mdx b/docs/src/pages/docs/desktop/install/windows.mdx index 2c56e2319..6e858a2b5 100644 --- a/docs/src/pages/docs/desktop/install/windows.mdx +++ b/docs/src/pages/docs/desktop/install/windows.mdx @@ -1,10 +1,11 @@ --- title: Windows -description: Run AI models locally on your Windows machine with Jan. Quick setup guide for local inference and chat. +description: Download Jan on Windows to run AI models locally. Jan is a free, open-source ChatGPT alternative to run offline. keywords: [ Jan, Customizable Intelligence, LLM, + Jan on Windows, local AI, privacy focus, free and open source, @@ -18,6 +19,11 @@ keywords: installation, "desktop" ] +twitter: + card: summary_large_image + site: "@jandotai" + title: "Jan on Windows" + description: "Download Jan on Windows to run AI models locally. Jan is a free, open-source ChatGPT alternative to run offline." --- import { Tabs, Callout, Steps } from 'nextra/components' diff --git a/docs/src/pages/docs/desktop/jan-models/jan-nano-32.mdx b/docs/src/pages/docs/desktop/jan-models/jan-nano-32.mdx index b216f3b96..5f1446e42 100644 --- a/docs/src/pages/docs/desktop/jan-models/jan-nano-32.mdx +++ b/docs/src/pages/docs/desktop/jan-models/jan-nano-32.mdx @@ -59,7 +59,7 @@ The model and its different model variants are fully supported by Jan. ## Using Jan-Nano-32k **Step 1** -Download Jan from [here](https://jan.ai/docs/desktop/). +Download Jan from [here](https://jan.ai/download/). **Step 2** Go to the Hub Tab, search for Jan-Nano-Gguf, and click on the download button to the best model size for your system. @@ -118,8 +118,8 @@ Here are some example queries to showcase Jan-Nano's web search capabilities: - 4xA6000 for vllm server (inferencing) - What frontend should I use? - - Jan Beta (recommended) - Minimalistic and polished interface - - Download link: https://jan.ai/docs/desktop/beta + - Jan (recommended) + - Download link: https://jan.ai/download - Getting Jinja errors in LM Studio? - Use Qwen3 template from other LM Studio compatible models diff --git a/docs/src/pages/docs/desktop/server-examples/tabby.mdx b/docs/src/pages/docs/desktop/server-examples/tabby.mdx index 917f40550..f25c89dab 100644 --- a/docs/src/pages/docs/desktop/server-examples/tabby.mdx +++ b/docs/src/pages/docs/desktop/server-examples/tabby.mdx @@ -90,7 +90,7 @@ Refer to the following documentation to install the Tabby extension on your favo Tabby offers an [Answer Engine](https://tabby.tabbyml.com/docs/administration/answer-engine/) on the homepage, which can leverage the Jan LLM and related contexts like code, documentation, and web pages to answer user questions. -Simply open the Tabby homepage at [localhost:8080](http://localhost:8080) and ask your questions. +Simply open the Tabby homepage at http://localhost:8080 and ask your questions. ### IDE Chat Sidebar diff --git a/docs/src/pages/docs/desktop/settings.mdx b/docs/src/pages/docs/desktop/settings.mdx index 6bc750f43..cd4d01ede 100644 --- a/docs/src/pages/docs/desktop/settings.mdx +++ b/docs/src/pages/docs/desktop/settings.mdx @@ -108,7 +108,7 @@ You can help improve Jan by sharing anonymous usage data: 2. You can change this setting at any time -Read more about that we collect with opt-in users at [Privacy](/docs/desktop/privacy). +Read more about that we collect with opt-in users at [Privacy](/privacy).
    @@ -141,7 +141,7 @@ This action cannot be undone. ### Jan Data Folder -Jan stores your data locally in your own filesystem in a universal file format. See detailed [Jan Folder Structure](docs/data-folder#folder-structure). +Jan stores your data locally in your own filesystem in a universal file format. See detailed [Jan Folder Structure](/docs/desktop/data-folder#directory-structure). **1. Open Jan Data Folder** diff --git a/docs/src/pages/docs/desktop/troubleshooting.mdx b/docs/src/pages/docs/desktop/troubleshooting.mdx index 16bbdfa9a..6d6c02703 100644 --- a/docs/src/pages/docs/desktop/troubleshooting.mdx +++ b/docs/src/pages/docs/desktop/troubleshooting.mdx @@ -328,14 +328,14 @@ This command ensures that the necessary permissions are granted for Jan's instal When you start a chat with a model and encounter a **Failed to Fetch** or **Something's Amiss** error, here are some possible solutions to resolve it: **1. Check System & Hardware Requirements** -- Hardware dependencies: Ensure your device meets all [hardware requirements](docs/desktop/troubleshooting#step-1-verify-hardware-and-system-requirements) -- OS: Ensure your operating system meets the minimum requirements ([Mac](/docs/desktop/install/mac#minimum-requirements), [Windows](/docs/desktop/install/windows#compatibility), [Linux](/docs/desktop/install/linux#compatibility)) +- Hardware dependencies: Ensure your device meets all [hardware requirements](troubleshooting) +- OS: Ensure your operating system meets the minimum requirements ([Mac](https://www.jan.ai/docs/desktop/install/mac#minimum-requirements), [Windows](/windows#compatibility), [Linux](https://www.jan.ai/docs/desktop/install/linux#compatibility) - RAM: Choose models that use less than 80% of your available RAM - For 8GB systems: Use models under 6GB - For 16GB systems: Use models under 13GB **2. Check Model Parameters** -- In **Engine Settings** in right sidebar, check your `ngl` ([number of GPU layers](/docs/desktop/models/model-parameters#engine-parameters)) setting to see if it's too high +- In **Engine Settings** in right sidebar, check your `ngl` ([number of GPU layers](/docs/desktop/model-parameters)) setting to see if it's too high - Start with a lower NGL value and increase gradually based on your GPU memory **3. Port Conflicts** diff --git a/docs/src/pages/handbook/_meta.json b/docs/src/pages/handbook/_meta.json index 482ca4f93..4a44a889f 100644 --- a/docs/src/pages/handbook/_meta.json +++ b/docs/src/pages/handbook/_meta.json @@ -1,5 +1,4 @@ { "index": "Overview", - "open-superintelligence": "Open Superintelligence", - "betting-on-open-source": "Betting on Open-Source" + "why": "Why does Jan exist?" } diff --git a/docs/src/pages/handbook/index.mdx b/docs/src/pages/handbook/index.mdx index 2c64eff72..64f0abdf8 100644 --- a/docs/src/pages/handbook/index.mdx +++ b/docs/src/pages/handbook/index.mdx @@ -18,31 +18,6 @@ Jan's Handbook is a [living document](https://en.wikipedia.org/wiki/Living_docum ## Why does Jan exist? -### [Open Superintelligence](/handbook/open-superintelligence) -Building superintelligence that belongs to everyone, not just a few tech giants. We believe the future of AI should be open, accessible, and owned by the people who use it. - -### [Betting on Open-Source](/handbook/betting-on-open-source) +- [Open Superintelligence](/handbook/open-superintelligence) - Building superintelligence that belongs to everyone, not just a few tech giants. We believe the future of AI should be open, accessible, and owned by the people who use it. +- [Betting on Open-Source](/handbook/betting-on-open-source) Why we're betting on open-source as the future of AI and technology. Open-source has consistently won in the long term, and AI will be no different. - ---- - -## Quick Links - -- **For the curious**: Start with [Open Superintelligence](/handbook/open-superintelligence) -- **For developers**: Learn about [Betting on Open-Source](/handbook/betting-on-open-source) -- **For contributors**: Check out our [GitHub](https://github.com/menloresearch/jan) and [Discord](https://discord.gg/FTk2MvZwJH) - -## Our North Star - -We're building superintelligence that: - -- **Works anywhere**: From your laptop to your data center -- **Belongs to you**: Download it, own it, modify it -- **Scales infinitely**: One person or ten thousand, same platform -- **Improves constantly**: Community-driven development - -This isn't just about making AI accessible. It's about ensuring the most transformative technology in human history can be owned by those who use it. - ---- - -_"The future of AI isn't about choosing between local or cloud. It's about having both, and everything in between, working perfectly together."_ diff --git a/docs/src/pages/handbook/why/_meta.json b/docs/src/pages/handbook/why/_meta.json new file mode 100644 index 000000000..b201b2e5f --- /dev/null +++ b/docs/src/pages/handbook/why/_meta.json @@ -0,0 +1,4 @@ +{ + "open-superintelligence": "Why Jan exists", + "betting-on-open-source": "Why we're betting on open-source" +} diff --git a/docs/src/pages/handbook/betting-on-open-source.mdx b/docs/src/pages/handbook/why/betting-on-open-source.mdx similarity index 73% rename from docs/src/pages/handbook/betting-on-open-source.mdx rename to docs/src/pages/handbook/why/betting-on-open-source.mdx index a0560d53e..bac971cbc 100644 --- a/docs/src/pages/handbook/betting-on-open-source.mdx +++ b/docs/src/pages/handbook/why/betting-on-open-source.mdx @@ -1,11 +1,11 @@ --- -title: "Why Open-Source" +title: "Why Jan is betting on Open-Source" description: "Why we're betting on open-source." --- # Why Open-Source -AI today is concentrated in the hands of a few companies. They ask for trust, while keeping the levers of control hidden. We think that's a mistake. +AI today is concentrated in the hands of [a few companies](https://stratechery.com/2025/tech-philosophy-and-ai-opportunity/). They ask for trust, while keeping the levers of control hidden. We think that's a mistake. When you depend on one vendor, your future is tied to their roadmap, their politics, their survival. If they get acquired, pivot, or shut down; you're stuck. @@ -16,9 +16,9 @@ Depending on a closed vendor means giving up more than flexibility: AI has become critical infrastructure. Nations, enterprises, even small teams rely on it to think and decide. And yet, control sits with a few vendors who decide the terms of access. We believe that's not control. That's dependency dressed up as convenience. One of the most powerful invention is being steered by a handful of executives. Their values shape what billions can say, build, or ask. -*This cannot stand. It must be changed.* +This can't stand. It must be changed. -## Jan's Bet +## How we see We don't believe the future of AI should be dictated by a few firms in San Francisco, Beijing, or anywhere else. @@ -30,4 +30,4 @@ That's why we're building Jan, a full product suite: - Jan Server - Hub, Store, evals, guardrails, the ecosystem around it -The goal is to be the open-source replacement for ChatGPT and other BigAI products, with models and tools you can run, own, and trust. +The goal is to be the [open-source replacement for ChatGPT](https://jan.ai/) and other BigAI products, with models and tools you can run, own, and trust. diff --git a/docs/src/pages/handbook/open-superintelligence.mdx b/docs/src/pages/handbook/why/open-superintelligence.mdx similarity index 67% rename from docs/src/pages/handbook/open-superintelligence.mdx rename to docs/src/pages/handbook/why/open-superintelligence.mdx index 5174f712b..68ab46311 100644 --- a/docs/src/pages/handbook/open-superintelligence.mdx +++ b/docs/src/pages/handbook/why/open-superintelligence.mdx @@ -5,9 +5,13 @@ description: "Short answer: Open Superintelligence." # Why does Jan exist? -> Short answer: Open Superintelligence. +import { Callout } from 'nextra/components' -In 1879, Edison lit a single street in [Menlo Park](https://en.wikipedia.org/wiki/Menlo_Park,_California). What mattered wasn't the bulb. It was that power could reach homes, schools, and factories. + +Short answer: Open Superintelligence. + + +In 1879, [Edison](https://en.wikipedia.org/wiki/Thomas_Edison) lit a single street in [Menlo Park](https://en.wikipedia.org/wiki/Menlo_Park,_California). What mattered wasn't the bulb. It was that power could reach homes, schools, and factories. Electricity changed the world only when it became universal. Standard plugs, cheap generation, lines everywhere. People stopped talking about electricity and started using light, cold chains, and machines. @@ -19,13 +23,13 @@ Jan exists to push intelligence toward the first path: Open Superintelligence yo > The world is made, and can be remade. -Every industrial wave redefined critical aspects of our daily lives: -- Factories introduced shift clocks and wage rhythms -- Steam gave way to electricity and standardized parts -- Rail, telegraph, and later networks changed how decisions travel -- Each wave pulled new bargains into being skills, schools, safety nets, labor law +Every industrial wave redefined new defaults of our daily lives: +- [Factories](https://en.wikipedia.org/wiki/Factory) created the modern job +- [Electricity](https://en.wikipedia.org/wiki/Electricity) created the modern home +- [Railroads](https://en.wikipedia.org/wiki/Rail_transport#History) and [telegraphs](https://en.wikipedia.org/wiki/Telegraphy#History) created the modern nation +- [The Internet](https://en.wikipedia.org/wiki/Internet) created the modern world -So what we're interested in is who is going to write the new defaults and share in the gains. +Open Superintelligence will create what comes next. What we're interested in is who is going to write the new defaults and share in the gains. Technology doesn’t choose its path, people do. Power accrues to whoever designs, deploys, and profits from the system: - If intelligence is closed and centralized, the gains concentrate diff --git a/docs/src/pages/post/_assets/chatgpt-alternative-jan.jpeg b/docs/src/pages/post/_assets/chatgpt-alternative-jan.jpeg new file mode 100644 index 000000000..c4e18913a Binary files /dev/null and b/docs/src/pages/post/_assets/chatgpt-alternative-jan.jpeg differ diff --git a/docs/src/pages/post/_assets/claude.jpeg b/docs/src/pages/post/_assets/claude.jpeg new file mode 100644 index 000000000..1b5dc1158 Binary files /dev/null and b/docs/src/pages/post/_assets/claude.jpeg differ diff --git a/docs/src/pages/post/_assets/gemini.jpeg b/docs/src/pages/post/_assets/gemini.jpeg new file mode 100644 index 000000000..acd333607 Binary files /dev/null and b/docs/src/pages/post/_assets/gemini.jpeg differ diff --git a/docs/src/pages/post/_assets/is-chatgpt-down.jpg b/docs/src/pages/post/_assets/is-chatgpt-down.jpg new file mode 100644 index 000000000..2a515d344 Binary files /dev/null and b/docs/src/pages/post/_assets/is-chatgpt-down.jpg differ diff --git a/docs/src/pages/post/_assets/lm-studio.jpeg b/docs/src/pages/post/_assets/lm-studio.jpeg new file mode 100644 index 000000000..ee6ee3825 Binary files /dev/null and b/docs/src/pages/post/_assets/lm-studio.jpeg differ diff --git a/docs/src/pages/post/_assets/perplexity.jpeg b/docs/src/pages/post/_assets/perplexity.jpeg new file mode 100644 index 000000000..6a73f9b55 Binary files /dev/null and b/docs/src/pages/post/_assets/perplexity.jpeg differ diff --git a/docs/src/pages/post/benchmarking-nvidia-tensorrt-llm.mdx b/docs/src/pages/post/benchmarking-nvidia-tensorrt-llm.mdx index 0d4bc9aa2..9fa67ea07 100644 --- a/docs/src/pages/post/benchmarking-nvidia-tensorrt-llm.mdx +++ b/docs/src/pages/post/benchmarking-nvidia-tensorrt-llm.mdx @@ -17,7 +17,7 @@ Jan now supports [NVIDIA TensorRT-LLM](https://github.com/NVIDIA/TensorRT-LLM) i We've been excited for TensorRT-LLM for a while, and [had a lot of fun implementing it](https://github.com/menloresearch/nitro-tensorrt-llm). As part of the process, we've run some benchmarks, to see how TensorRT-LLM fares on consumer hardware (e.g. [4090s](https://www.nvidia.com/en-us/geforce/graphics-cards/40-series/), [3090s](https://www.nvidia.com/en-us/geforce/graphics-cards/30-series/)) we commonly see in the [Jan's hardware community](https://discord.com/channels/1107178041848909847/1201834752206974996). - **Give it a try!** Jan's [TensorRT-LLM extension](/docs/desktop/built-in/tensorrt-llm) is available in Jan v0.4.9 and up ([see more](/docs/desktop/built-in/tensorrt-llm)). We precompiled some TensorRT-LLM models for you to try: `Mistral 7b`, `TinyLlama-1.1b`, `TinyJensen-1.1b` 😂 + **Give it a try!** Jan's TensorRT-LLM extension is available in Jan v0.4.9. We precompiled some TensorRT-LLM models for you to try: `Mistral 7b`, `TinyLlama-1.1b`, `TinyJensen-1.1b` 😂 Bugs or feedback? Let us know on [GitHub](https://github.com/menloresearch/jan) or via [Discord](https://discord.com/channels/1107178041848909847/1201832734704795688). diff --git a/docs/src/pages/post/chatgpt-alternatives.mdx b/docs/src/pages/post/chatgpt-alternatives.mdx new file mode 100644 index 000000000..208bda1bc --- /dev/null +++ b/docs/src/pages/post/chatgpt-alternatives.mdx @@ -0,0 +1,120 @@ +--- +title: "ChatGPT alternatives that actually replace it" +description: "See the best ChatGPT alternatives in 2025. We've listed tools that are alternatives to ChatGPT." +tags: AI, ChatGPT alternative, ChatGPT alternatives, alternative to chatgpt, Jan, local AI, privacy, open source, offline AI +categories: guides +date: 2025-09-29 +ogImage: _assets/chatgpt-alternative-jan.jpeg +twitter: + card: summary_large_image + site: "@jandotai" + title: "ChatGPT alternatives that actually replace it." + description: "See the best ChatGPT alternatives in 2025. We've listed tools that are alternatives to ChatGPT." + image: _assets/chatgpt-alternative-jan.jpeg +--- +import { Callout } from 'nextra/components' +import CTABlog from '@/components/Blog/CTA' + +# Best ChatGPT Alternatives + +ChatGPT works well, but it always needs internet, has usage limits, and isn't private. + +If you want options that fit different needs, offline use, privacy, or specialized tasks, see the best alternatives to ChatGPT available for specific use cases. + +## Comparison: ChatGPT Alternatives + +| ChatGPT Alternative | Offline | Key Strength | Best For | +| ------------------------- | ------- | ---------------------------- | -------------------------- | +| **[Jan](https://jan.ai)** | Yes | Runs Cloud + Offline, open-source | Best overall ChatGPT replacement | +| Claude | - | Strong writing and reasoning | Creative text & code | +| Gemini | - | Integrated with Google | Research tasks, image generation | +| Perplexity | - | Fast, with cited answers | Research and fact-checking | +| LM Studio | Yes | Runs open models on PC | Coding and experiments | + +### Jan is the best ChatGPT alternative + +![Use Jan to chat with AI models without internet access](./_assets/chatgpt-alternative-jan.jpeg) +*Jan as an open-source alternative to ChatGPT* + +Jan is the most complete ChatGPT alternative available today. It enables: +- Use AI in online & offline (even on a plain) +- Agentic actions supported +- MCP servers supported for tools + +Unlike ChatGPT, it runs on your computer, which means: +- Offline AI capabilities (see [Offline ChatGPT post](https://www.jan.ai/post/offline-chatgpt-alternative) for details) +- 100% private +- Open-source & Free + + Jan is an [open-source replacement for ChatGPT.](https://www.jan.ai/) + +### Claude is the most notable online alternative +![Claude](./_assets/claude.jpeg) + +Claude has become the main online rival to ChatGPT. It stands out for writing, reasoning, and coding. + +- Handles very long documents and context well +- Strong for essays, research papers, and structured text +- Popular with developers for code explanations and debugging +- Cloud-only, no offline mode +- Filters outputs heavily, sometimes too restrictive + +### Gemini is the Google's integrated alternative +![Gemini](./_assets/gemini.jpeg) + +Gemini ties directly into Google’s apps and search. Great for users in the Google ecosystem. + +- Built into Gmail, Docs, and Google Search +- Good for real-time research and fact-checking +- Strong at pulling web context into answers +- Requires Google account, fully online +- Privacy concerns: all tied to Google services + +### Perplexity is the research-focused alternative +![Perplexity](./_assets/perplexity.jpeg) + +Perplexity is built for fact-checking and quick research, not creativity. + +- Always cites sources for answers +- Strong at summarizing current web info +- Very fast for Q&A style use +- Limited in creativity and open-ended writing +- Cloud-only, daily free usage caps + +### LM Studio is the experimental alternative + +![LM Studio](./_assets/lm-studio.jpeg) + +LM Studio is not a ChatGPT replacement but a local tool for running open models. + +- Lets you test and run open-source models on PC +- Offline by default, works without internet +- Flexible setup for developers and technical users +- Requires decent hardware (RAM/VRAM) + +LM Studio is not beginner-friendly compared to Jan. + +## Choosing the right ChatGPT alternative for you: + +- Best overall replacement: [Jan](https://www.jan.ai/) +- For writing & storytelling: Claude +- For research & web knowledge: Perplexity or Gemini +- For productivity & office work: Microsoft Copilot +- For experimentation with open-source models for technical people: LM Studio + +Most ChatGPT alternatives are still cloud-based and limited. If you want full privacy, offline use, and no restrictions, the best ChatGPT alternative is [Jan](https://www.jan.ai/). + +### Can I use ChatGPT offline? +No. ChatGPT always requires internet. For offline AI, use Jan. + +### What’s the best free ChatGPT alternative? +Jan is free, open-source, and runs offline. Others like Claude or Perplexity have limited free tiers but are cloud-based. + +### Which ChatGPT alternative is best for writing? +Claude is strong for essays, reports, and structured writing. You could use [open-source models](https://www.jan.ai/post/run-ai-models-locally) in Jan too. + +### Which ChatGPT alternative is best for research? +Perplexity and Gemini pull real-time web data with citations. + +### What’s the closest full replacement to ChatGPT? +Jan. It runs locally, works offline, and feels like ChatGPT without restrictions. \ No newline at end of file diff --git a/docs/src/pages/post/deepresearch.mdx b/docs/src/pages/post/deepresearch.mdx index 11edd4f04..f3f1c0ee7 100644 --- a/docs/src/pages/post/deepresearch.mdx +++ b/docs/src/pages/post/deepresearch.mdx @@ -125,8 +125,8 @@ any version with Model Context Protocol in it (>`v0.6.3`). **The Key: Assistants + Tools** -Running deep research in Jan can be accomplished by combining [custom assistants](https://jan.ai/docs/assistants) -with [MCP search tools](https://jan.ai/docs/desktop/mcp-examples/search/exa). This pairing allows any model—local or +Running deep research in Jan can be accomplished by combining [custom assistants](https://jan.ai/docs/desktop/assistants) +with [MCP search tools](https://jan.ai/docs/mcp-examples/search/exa). This pairing allows any model—local or cloud—to follow a systematic research workflow, to create a report similar to that of other providers, with some visible limitations (for now). diff --git a/docs/src/pages/post/is-chatgpt-down-use-jan.mdx b/docs/src/pages/post/is-chatgpt-down-use-jan.mdx new file mode 100644 index 000000000..bed499d19 --- /dev/null +++ b/docs/src/pages/post/is-chatgpt-down-use-jan.mdx @@ -0,0 +1,124 @@ +--- +title: "If ChatGPT is down, switch to AI that never goes down" +description: "Check if ChatGPT down right now, and learn how to use AI that never goes down." +tags: AI, ChatGPT down, ChatGPT alternative, Jan, local AI, offline AI, ChatGPT at capacity +categories: guides +date: 2025-09-30 +ogImage: _assets/is-chatgpt-down.jpg +twitter: + card: summary_large_image + site: "@jandotai" + title: "Realtime Status Checker: Is ChatGPT down?" + description: "Check if ChatGPT is down right now with our real-time status checker, and learn how to use AI that never goes offline." + image: _assets/is-chatgpt-down.jpg +--- +import { Callout } from 'nextra/components' +import CTABlog from '@/components/Blog/CTA' +import { OpenAIStatusChecker } from '@/components/OpenAIStatusChecker' + +# If ChatGPT is down, switch to AI that never goes down + +If you're seeing ChatGPT is down, it could a good signal to switch to [Jan](https://www.jan.ai/), AI that never goes down. + +## 🔴 Realtime Status Checker: Is ChatGPT down? + +This live tracker shows if ChatGPT is down right now. + + + +### ChatGPT Status Indicators + +
    +
    +
    +
    + Operational +
    +

    All systems are functioning normally with no reported issues.

    +
    + +
    +
    +
    + Degraded Performance +
    +

    Services are running but may be slower than usual.

    +
    + +
    +
    +
    + Partial Outage +
    +

    Some features or regions may be experiencing issues.

    +
    + +
    +
    +
    + Major Outage +
    +

    Significant service disruption affecting most users.

    +
    +
    + +## Skip the downtime with Jan + +When ChatGPT is down, Jan keeps working. Jan is an open-source ChatGPT alternative that runs on your computer - no servers, no outages, no waiting. + +![Jan running when ChatGPT is down](./_assets/chatgpt-alternative-jan.jpeg) +*Jan works even when ChatGPT doesn't.* + +### Why Jan never goes down: +- **Runs locally** - No dependency on external servers +- **Always available** - Works offline, even on flights +- **No capacity limits** - Uses your computer's resources +- **100% private** - Your conversations stay on your device + +### Get started in 3 mins: +1. Download Jan: [jan.ai](https://jan.ai) +2. Install a model: Choose from Jan, Qwen, or other top models +3. Start chatting: Similar design as ChatGPT, but always available if you use local models + + +**Pro tip:** Keep both ChatGPT and Jan. You'll never lose productivity to outages again. + + +Jan runs AI models locally, so you don't need internet access. That means Jan is unaffected when ChatGPT is down. + +### Why does ChatGPT goes down? +There could be multiple reasons: +- Too many users at once +- Data center or API downtime +- Planned or uplanned updates +- Limited in some locations + +ChatGPT depends on OpenAI’s servers. If those go down, so does ChatGPT. Jan users don't affect by ChatGPT's outage. + +### Common ChatGPT Errors + +When ChatGPT experiences issues, you might see these error messages: + +- "ChatGPT is at capacity right now": Too many users online, try again later +- "Error in message stream": Connection problems with OpenAI servers +- "Something went wrong": General server error, refresh and retry +- "Network error": Internet connectivity issues on your end or OpenAI's +- "Rate limit exceeded": Too many requests sent, wait before trying again +- "This model is currently overloaded": High demand for specific model + +## Quick answers about ChatGPT status + +### Is ChatGPT down today? +Check the ChatGPT realtime status above. If ChatGPT is down, you'll see it here. + +### Why is ChatGPT down? +Usually server overload, maintenance, or outages at OpenAI. + +### What does “ChatGPT is at capacity” mean? +Too many users are online at the same time. You’ll need to wait or switch to Jan instead. + +### Is ChatGPT shutting down? +No, ChatGPT isn’t shutting down. Outages are temporary. + +### Can I use ChatGPT offline? +No. ChatGPT always requires internet. For [offline AI](https://www.jan.ai/post/offline-chatgpt-alternative), use [Jan](https://jan.ai). \ No newline at end of file diff --git a/docs/src/pages/post/offline-chatgpt-alternative.mdx b/docs/src/pages/post/offline-chatgpt-alternative.mdx index d73bec712..6f16b0334 100644 --- a/docs/src/pages/post/offline-chatgpt-alternative.mdx +++ b/docs/src/pages/post/offline-chatgpt-alternative.mdx @@ -1,7 +1,7 @@ --- title: "Offline ChatGPT: You can't run ChatGPT offline, do this instead" -description: "Learn how to use AI offline with Jan - a free, open-source alternative to ChatGPT that works 100% offline on your computer." -tags: AI, ChatGPT alternative, offline AI, Jan, local AI, privacy +description: "Use offline AI with Jan, a free & open-source alternative to ChatGPT that runs 100% offline." +tags: AI, chatgpt offline, ChatGPT alternative, offline AI, Jan, local AI, privacy categories: guides date: 2025-02-08 ogImage: _assets/offline-chatgpt-alternatives-jan.jpg @@ -9,7 +9,7 @@ twitter: card: summary_large_image site: "@jandotai" title: "Offline ChatGPT: You can't run ChatGPT offline, do this instead" - description: "Want to use ChatGPT offline? Learn how to run AI models locally with Jan - free, open-source, and works without internet." + description: "Use offline AI with Jan, a free & open-source alternative to ChatGPT that runs 100% offline." image: _assets/offline-chatgpt-alternatives-jan.jpg --- import { Callout } from 'nextra/components' @@ -17,16 +17,20 @@ import CTABlog from '@/components/Blog/CTA' # Offline ChatGPT: You can't run ChatGPT offline, do this instead -ChatGPT is a cloud-based service that requires internet access. However, it's not the only way to use AI. You can run AI models offline on your device with [Jan](https://jan.ai/). It's completely free, open-source, and gives you 100% offline capability. You can even use AI on a plane! +ChatGPT itself can't run offline. ChatGPT can't run offline. You can’t download it. It always needs internet, because it runs on OpenAI's servers. - +If you want offline AI, you need local models. The easiest way: [Jan, an open-source replacement of ChatGPT](https://jan.ai/). It's free, open-source, and works 100% offline. With Jan, you can even use AI on a plane. + + **Quick Summary:** -- ChatGPT always needs internet - it can't run offline -- Jan lets you run AI models 100% offline on your computer -- It's free and open-source -- Works on Mac, Windows, and Linux +- ChatGPT always needs internet - no offline mode +- Use Jan to use AI models 100% offline +- It's free & open-source, and works on Mac, Windows, and Linux +## How to use AI offline? +Offline AI means the model runs on your computer. So no internet needed, 100% private, and data never leaves your device. With Jan you can run offline AI models locally. + ## Jan as an offline ChatGPT alternative ![Use Jan to chat with AI models without internet access](./_assets/offline-chatgpt-alternative-ai-without-internet.jpg) @@ -42,20 +46,22 @@ Go to [jan.ai](https://jan.ai) and download the version for your computer (Mac, ### 2. Download an AI model -You'll need an AI model to use AI offline, so download a model from Jan. Once it's on your computer, you don't need internet anymore. +You'll need an AI model to use AI offline, so download a model from Jan. Once it's on your computer, you don't need internet anymore. You can also use GPT models via Jan - check [running gpt-oss locally](https://www.jan.ai/post/run-gpt-oss-locally) post to see it. ![Choose an AI model that works offline](./_assets/jan-model-selection.jpg "Find the perfect AI model for offline use") *Select an AI model that matches your needs and computer capabilities* - -**Which model should you choose?** +### Which model should you choose? - For most computers: Try Mistral 7B or DeepSeek - they're similar to ChatGPT 3.5 - For older computers: Use smaller 3B models - For gaming PCs: You can try larger 13B models + Don't worry about choosing - Jan will automatically recommend models that work well on your computer. +If you'd like to learn more about local AI, check [how to run AI models locally as a beginner](https://www.jan.ai/post/run-ai-models-locally) article. + ### 3. Start using AI offline ![Chat with AI offline using Jan's interface](./_assets/run-ai-locally-with-jan.jpg "Experience ChatGPT-like interactions without internet") @@ -71,12 +77,7 @@ Once downloaded, you can use AI anywhere, anytime: ## How to chat with your docs in Jan? -To chat with your docs in Jan, you need to activate experimental mode. - -![Activate experimental mode in Jan's settings](./_assets/chat-with-your-docs-offline-ai.jpg "Enable experimental features to chat with your documents") -*Turn on experimental mode in settings to chat with your docs* - -After activating experimental mode, simply add your files and ask questions about them. +Simply add your files and ask questions about them. ![Chat with your documents using Jan](./_assets/chat-with-docs-prompt.jpg "Ask questions about your documents offline") *Chat with your documents privately - no internet needed* @@ -97,17 +98,17 @@ Local AI makes possible offline AI use, so Jan is going to be your first step to 4. **No Server Issues:** No more "ChatGPT is at capacity" 5. **Your Choice of Models:** Use newer models as they come out -**"Is it really free? What's the catch?"** +### "Is Jan really free? What's the catch?" Yes, it's completely free and open source. Jan is built by developers who believe in making AI accessible to everyone. -**"How does it compare to ChatGPT?"** +### How does Jan compare to ChatGPT?" Modern open-source models like DeepSeek and Mistral are very capable. While they might not match GPT-4, they're perfect for most tasks and getting better every month. -**"Do I need a powerful computer?"** +### "Do I need a powerful computer?" If your computer is from the last 5 years, it will likely work fine. You need about 8GB of RAM and 10GB of free space for comfortable usage. -**"What about my privacy?"** -Everything stays on your computer. Your conversations, documents, and data never leave your device unless you choose to share them. +### "What about my privacy?" +Everything stays on your computer with Jan. Your conversations, documents, and data never leave your device unless you choose to share them. Want to learn more about the technical side? Check our detailed [guide on running AI models locally](/post/run-ai-models-locally). It's not required to [use AI offline](https://jan.ai/) but helps understand how it all works. @@ -116,3 +117,20 @@ Want to learn more about the technical side? Check our detailed [guide on runnin [Join our Discord community](https://discord.gg/Exe46xPMbK) for support and tips on using Jan as your offline ChatGPT alternative. + +### FAQ + +#### Can I download ChatGPT for offline use? +No. ChatGPT is cloud-only. + +#### How to use ChatGPT offline? +You can't. ChatGPT has no offline mode. Use Jan instead for a ChatGPT-like offline experience. + +#### Does ChatGPT have internet access? +Yes. It runs in the cloud. + +#### What's the best way to use AI offline? +Download Jan and run models like Mistral, DeepSeek, or GPT-OSS locally. + +#### What's GPT offline? +OpenAI has open-source models you can run locally but not via ChatGPT. One of them is [gpt-oss](https://www.jan.ai/post/run-gpt-oss-locally) and you can run it via Jan. \ No newline at end of file diff --git a/extensions-web/package.json b/extensions-web/package.json index c6517bde0..232ba13fa 100644 --- a/extensions-web/package.json +++ b/extensions-web/package.json @@ -22,16 +22,16 @@ }, "devDependencies": { "@janhq/core": "workspace:*", - "typescript": "^5.3.3", - "vite": "^5.0.0", - "vitest": "^2.0.0", - "zustand": "^5.0.8" + "typescript": "5.9.2", + "vite": "5.4.20", + "vitest": "2.1.9", + "zustand": "5.0.8" }, "peerDependencies": { "@janhq/core": "*", - "zustand": "^5.0.0" + "zustand": "5.0.3" }, "dependencies": { - "@modelcontextprotocol/sdk": "^1.17.5" + "@modelcontextprotocol/sdk": "1.17.5" } } diff --git a/extensions-web/src/jan-provider-web/provider.ts b/extensions-web/src/jan-provider-web/provider.ts index dfdfe01b4..cfbe18e2e 100644 --- a/extensions-web/src/jan-provider-web/provider.ts +++ b/extensions-web/src/jan-provider-web/provider.ts @@ -16,6 +16,9 @@ import { import { janApiClient, JanChatMessage } from './api' import { janProviderStore } from './store' +// Jan models support tools via MCP +const JAN_MODEL_CAPABILITIES = ['tools'] as const + export default class JanProviderWeb extends AIEngine { readonly provider = 'jan' private activeSessions: Map = new Map() @@ -24,6 +27,9 @@ export default class JanProviderWeb extends AIEngine { console.log('Loading Jan Provider Extension...') try { + // Check and clear invalid Jan models (capabilities mismatch) + this.validateJanModelsLocalStorage() + // Initialize authentication and fetch models await janApiClient.initialize() console.log('Jan Provider Extension loaded successfully') @@ -35,6 +41,54 @@ export default class JanProviderWeb extends AIEngine { super.onLoad() } + // Verify Jan models capabilities in localStorage + private validateJanModelsLocalStorage() { + try { + console.log("Validating Jan models in localStorage...") + const storageKey = 'model-provider' + const data = localStorage.getItem(storageKey) + if (!data) return + + const parsed = JSON.parse(data) + if (!parsed?.state?.providers) return + + // Check if any Jan model has incorrect capabilities + let hasInvalidModel = false + + for (const provider of parsed.state.providers) { + if (provider.provider === 'jan' && provider.models) { + for (const model of provider.models) { + console.log(`Checking Jan model: ${model.id}`, model.capabilities) + if (JSON.stringify(model.capabilities) !== JSON.stringify(JAN_MODEL_CAPABILITIES)) { + hasInvalidModel = true + console.log(`Found invalid Jan model: ${model.id}, clearing localStorage`) + break + } + } + } + if (hasInvalidModel) break + } + + // If any invalid model found, just clear the storage + if (hasInvalidModel) { + // Force clear the storage + localStorage.removeItem(storageKey) + // Verify it's actually removed + const afterRemoval = localStorage.getItem(storageKey) + // If still present, try setting to empty state + if (afterRemoval) { + // Try alternative clearing method + localStorage.setItem(storageKey, JSON.stringify({ state: { providers: [] }, version: parsed.version || 3 })) + } + console.log('Cleared model-provider from localStorage due to invalid Jan capabilities') + // Force a page reload to ensure clean state + window.location.reload() + } + } catch (error) { + console.error('Failed to check Jan models:', error) + } + } + override async onUnload() { console.log('Unloading Jan Provider Extension...') @@ -64,7 +118,7 @@ export default class JanProviderWeb extends AIEngine { path: undefined, // Remote model, no local path owned_by: model.owned_by, object: model.object, - capabilities: ['tools'], // Jan models support both tools via MCP + capabilities: [...JAN_MODEL_CAPABILITIES], } : undefined ) @@ -85,7 +139,7 @@ export default class JanProviderWeb extends AIEngine { path: undefined, // Remote model, no local path owned_by: model.owned_by, object: model.object, - capabilities: ['tools'], // Jan models support both tools via MCP + capabilities: [...JAN_MODEL_CAPABILITIES], })) } catch (error) { console.error('Failed to list Jan models:', error) @@ -332,6 +386,12 @@ export default class JanProviderWeb extends AIEngine { ) } + async update(modelId: string, model: Partial): Promise { + throw new Error( + `Update operation not supported for remote Jan API model: ${modelId}` + ) + } + async import(modelId: string, _opts: ImportOptions): Promise { throw new Error( `Import operation not supported for remote Jan API model: ${modelId}` diff --git a/extensions-web/src/shared/auth/service.ts b/extensions-web/src/shared/auth/service.ts index ecedb4d62..1895ff8c4 100644 --- a/extensions-web/src/shared/auth/service.ts +++ b/extensions-web/src/shared/auth/service.ts @@ -48,6 +48,18 @@ export class JanAuthService { * Called on app load to check existing session */ async initialize(): Promise { + // Ensure refreshtoken is valid (in case of expired session or secret change) + try { + await refreshToken() + } catch (error) { + console.log('Failed to refresh token on init:', error) + // If refresh fails, logout to clear any invalid state + console.log('Logging out and clearing auth state to clear invalid session...') + await logoutUser() + this.clearAuthState() + this.authBroadcast.broadcastLogout() + } + // Authentication state check try { if (!this.isAuthenticated()) { // Not authenticated - ensure guest access diff --git a/extensions/assistant-extension/package.json b/extensions/assistant-extension/package.json index f17d42588..fd98b79ce 100644 --- a/extensions/assistant-extension/package.json +++ b/extensions/assistant-extension/package.json @@ -12,11 +12,11 @@ "build:publish": "rimraf *.tgz --glob || true && yarn build && npm pack && cpx *.tgz ../../pre-install" }, "devDependencies": { - "cpx": "^1.5.0", - "rimraf": "^6.0.1", + "cpx": "1.5.0", + "rimraf": "6.0.1", "rolldown": "1.0.0-beta.1", - "run-script-os": "^1.1.6", - "typescript": "^5.3.3" + "run-script-os": "1.1.6", + "typescript": "5.9.2" }, "dependencies": { "@janhq/core": "../../core/package.tgz", diff --git a/extensions/conversational-extension/package.json b/extensions/conversational-extension/package.json index 8e3392ada..603677516 100644 --- a/extensions/conversational-extension/package.json +++ b/extensions/conversational-extension/package.json @@ -15,11 +15,11 @@ "./main": "./dist/module.js" }, "devDependencies": { - "cpx": "^1.5.0", - "rimraf": "^6.0.1", + "cpx": "1.5.0", + "rimraf": "6.0.1", "rolldown": "1.0.0-beta.1", "ts-loader": "^9.5.0", - "typescript": "^5.7.2" + "typescript": "5.9.2" }, "dependencies": { "@janhq/core": "../../core/package.tgz" diff --git a/extensions/download-extension/package.json b/extensions/download-extension/package.json index f15f12bdb..2f93977d7 100644 --- a/extensions/download-extension/package.json +++ b/extensions/download-extension/package.json @@ -12,12 +12,12 @@ "build:publish": "rimraf *.tgz --glob || true && yarn build && npm pack && cpx *.tgz ../../pre-install" }, "devDependencies": { - "cpx": "^1.5.0", - "rimraf": "^6.0.1", + "cpx": "1.5.0", + "rimraf": "6.0.1", "rolldown": "1.0.0-beta.1", - "run-script-os": "^1.1.6", + "run-script-os": "1.1.6", "typescript": "5.8.3", - "vitest": "^3.0.6" + "vitest": "3.2.4" }, "files": [ "dist/*", @@ -26,7 +26,7 @@ ], "dependencies": { "@janhq/core": "../../core/package.tgz", - "@tauri-apps/api": "^2.5.0" + "@tauri-apps/api": "2.8.0" }, "bundleDependencies": [], "installConfig": { diff --git a/extensions/llamacpp-extension/package.json b/extensions/llamacpp-extension/package.json index 585365130..b6b7b01cd 100644 --- a/extensions/llamacpp-extension/package.json +++ b/extensions/llamacpp-extension/package.json @@ -17,24 +17,24 @@ "test:coverage": "vitest run --coverage" }, "devDependencies": { - "@vitest/ui": "^3.2.4", - "cpx": "^1.5.0", - "jsdom": "^26.1.0", - "rimraf": "^3.0.2", + "@vitest/ui": "2.1.9", + "cpx": "1.5.0", + "jsdom": "26.1.0", + "rimraf": "3.0.2", "rolldown": "1.0.0-beta.1", "ts-loader": "^9.5.0", - "typescript": "^5.7.2", - "vitest": "^3.2.4" + "typescript": "5.9.2", + "vitest": "3.2.4" }, "dependencies": { "@janhq/core": "../../core/package.tgz", "@janhq/tauri-plugin-hardware-api": "link:../../src-tauri/plugins/tauri-plugin-hardware", "@janhq/tauri-plugin-llamacpp-api": "link:../../src-tauri/plugins/tauri-plugin-llamacpp", - "@tauri-apps/api": "^2.5.0", - "@tauri-apps/plugin-http": "^2.5.1", + "@tauri-apps/api": "2.8.0", + "@tauri-apps/plugin-http": "2.5.0", "@tauri-apps/plugin-log": "^2.6.0", "fetch-retry": "^5.0.6", - "ulidx": "^2.3.0" + "ulidx": "2.4.1" }, "engines": { "node": ">=18.0.0" diff --git a/extensions/llamacpp-extension/src/backend.ts b/extensions/llamacpp-extension/src/backend.ts index d60ecc138..a313e01c6 100644 --- a/extensions/llamacpp-extension/src/backend.ts +++ b/extensions/llamacpp-extension/src/backend.ts @@ -1,9 +1,8 @@ import { getJanDataFolderPath, fs, joinPath, events } from '@janhq/core' import { invoke } from '@tauri-apps/api/core' -import { getProxyConfig } from './util' +import { getProxyConfig, basenameNoExt } from './util' import { dirname, basename } from '@tauri-apps/api/path' import { getSystemInfo } from '@janhq/tauri-plugin-hardware-api' - /* * Reads currently installed backends in janDataFolderPath * @@ -73,10 +72,7 @@ async function fetchRemoteSupportedBackends( if (!name.startsWith(prefix)) continue - const backend = name - .replace(prefix, '') - .replace('.tar.gz', '') - .replace('.zip', '') + const backend = basenameNoExt(name).slice(prefix.length) if (supportedBackends.includes(backend)) { remote.push({ version, backend }) diff --git a/extensions/llamacpp-extension/src/index.ts b/extensions/llamacpp-extension/src/index.ts index 78e7c04f3..07d49cd53 100644 --- a/extensions/llamacpp-extension/src/index.ts +++ b/extensions/llamacpp-extension/src/index.ts @@ -1155,6 +1155,49 @@ export default class llamacpp_extension extends AIEngine { } } + /** + * Update a model with new information. + * @param modelId + * @param model + */ + async update(modelId: string, model: Partial): Promise { + const modelFolderPath = await joinPath([ + await this.getProviderPath(), + 'models', + modelId, + ]) + const modelConfig = await invoke('read_yaml', { + path: await joinPath([modelFolderPath, 'model.yml']), + }) + const newFolderPath = await joinPath([ + await this.getProviderPath(), + 'models', + model.id, + ]) + // Check if newFolderPath exists + if (await fs.existsSync(newFolderPath)) { + throw new Error(`Model with ID ${model.id} already exists`) + } + const newModelConfigPath = await joinPath([newFolderPath, 'model.yml']) + await fs.mv(modelFolderPath, newFolderPath).then(() => + // now replace what values have previous model name with format + invoke('write_yaml', { + data: { + ...modelConfig, + model_path: modelConfig?.model_path?.replace( + `${this.providerId}/models/${modelId}`, + `${this.providerId}/models/${model.id}` + ), + mmproj_path: modelConfig?.mmproj_path?.replace( + `${this.providerId}/models/${modelId}`, + `${this.providerId}/models/${model.id}` + ), + }, + savePath: newModelConfigPath, + }) + ) + } + override async import(modelId: string, opts: ImportOptions): Promise { const isValidModelId = (id: string) => { // only allow alphanumeric, underscore, hyphen, and dot characters in modelId diff --git a/extensions/llamacpp-extension/src/util.ts b/extensions/llamacpp-extension/src/util.ts index 1511eafec..b72766579 100644 --- a/extensions/llamacpp-extension/src/util.ts +++ b/extensions/llamacpp-extension/src/util.ts @@ -1,3 +1,23 @@ +// File path utilities +export function basenameNoExt(filePath: string): string { + const VALID_EXTENSIONS = [".tar.gz", ".zip"]; + + // handle VALID extensions first + for (const ext of VALID_EXTENSIONS) { + if (filePath.toLowerCase().endsWith(ext)) { + return filePath.slice(0, -ext.length); + } + } + + // fallback: remove only the last extension + const lastDotIndex = filePath.lastIndexOf('.'); + if (lastDotIndex > 0) { + return filePath.slice(0, lastDotIndex); + } + + return filePath; +} + // Zustand proxy state structure interface ProxyState { proxyEnabled: boolean diff --git a/extensions/llamacpp-extension/tsconfig.json b/extensions/llamacpp-extension/tsconfig.json index 6db951c9e..34d31fe4a 100644 --- a/extensions/llamacpp-extension/tsconfig.json +++ b/extensions/llamacpp-extension/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "es2016", + "target": "es2018", "module": "ES6", "moduleResolution": "node", "outDir": "./dist", diff --git a/extensions/yarn.lock b/extensions/yarn.lock index 49ed702db..9196aa06f 100644 --- a/extensions/yarn.lock +++ b/extensions/yarn.lock @@ -92,13 +92,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/aix-ppc64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/aix-ppc64@npm:0.24.2" - conditions: os=aix & cpu=ppc64 - languageName: node - linkType: hard - "@esbuild/aix-ppc64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/aix-ppc64@npm:0.25.9" @@ -106,13 +99,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/android-arm64@npm:0.24.2" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - "@esbuild/android-arm64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/android-arm64@npm:0.25.9" @@ -120,13 +106,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/android-arm@npm:0.24.2" - conditions: os=android & cpu=arm - languageName: node - linkType: hard - "@esbuild/android-arm@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/android-arm@npm:0.25.9" @@ -134,13 +113,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-x64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/android-x64@npm:0.24.2" - conditions: os=android & cpu=x64 - languageName: node - linkType: hard - "@esbuild/android-x64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/android-x64@npm:0.25.9" @@ -148,13 +120,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/darwin-arm64@npm:0.24.2" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - "@esbuild/darwin-arm64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/darwin-arm64@npm:0.25.9" @@ -162,13 +127,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/darwin-x64@npm:0.24.2" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - "@esbuild/darwin-x64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/darwin-x64@npm:0.25.9" @@ -176,13 +134,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/freebsd-arm64@npm:0.24.2" - conditions: os=freebsd & cpu=arm64 - languageName: node - linkType: hard - "@esbuild/freebsd-arm64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/freebsd-arm64@npm:0.25.9" @@ -190,13 +141,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/freebsd-x64@npm:0.24.2" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - "@esbuild/freebsd-x64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/freebsd-x64@npm:0.25.9" @@ -204,13 +148,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/linux-arm64@npm:0.24.2" - conditions: os=linux & cpu=arm64 - languageName: node - linkType: hard - "@esbuild/linux-arm64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/linux-arm64@npm:0.25.9" @@ -218,13 +155,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/linux-arm@npm:0.24.2" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - "@esbuild/linux-arm@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/linux-arm@npm:0.25.9" @@ -232,13 +162,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/linux-ia32@npm:0.24.2" - conditions: os=linux & cpu=ia32 - languageName: node - linkType: hard - "@esbuild/linux-ia32@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/linux-ia32@npm:0.25.9" @@ -246,13 +169,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/linux-loong64@npm:0.24.2" - conditions: os=linux & cpu=loong64 - languageName: node - linkType: hard - "@esbuild/linux-loong64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/linux-loong64@npm:0.25.9" @@ -260,13 +176,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/linux-mips64el@npm:0.24.2" - conditions: os=linux & cpu=mips64el - languageName: node - linkType: hard - "@esbuild/linux-mips64el@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/linux-mips64el@npm:0.25.9" @@ -274,13 +183,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/linux-ppc64@npm:0.24.2" - conditions: os=linux & cpu=ppc64 - languageName: node - linkType: hard - "@esbuild/linux-ppc64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/linux-ppc64@npm:0.25.9" @@ -288,13 +190,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/linux-riscv64@npm:0.24.2" - conditions: os=linux & cpu=riscv64 - languageName: node - linkType: hard - "@esbuild/linux-riscv64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/linux-riscv64@npm:0.25.9" @@ -302,13 +197,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/linux-s390x@npm:0.24.2" - conditions: os=linux & cpu=s390x - languageName: node - linkType: hard - "@esbuild/linux-s390x@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/linux-s390x@npm:0.25.9" @@ -316,13 +204,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/linux-x64@npm:0.24.2" - conditions: os=linux & cpu=x64 - languageName: node - linkType: hard - "@esbuild/linux-x64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/linux-x64@npm:0.25.9" @@ -330,13 +211,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/netbsd-arm64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/netbsd-arm64@npm:0.24.2" - conditions: os=netbsd & cpu=arm64 - languageName: node - linkType: hard - "@esbuild/netbsd-arm64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/netbsd-arm64@npm:0.25.9" @@ -344,13 +218,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/netbsd-x64@npm:0.24.2" - conditions: os=netbsd & cpu=x64 - languageName: node - linkType: hard - "@esbuild/netbsd-x64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/netbsd-x64@npm:0.25.9" @@ -358,13 +225,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/openbsd-arm64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/openbsd-arm64@npm:0.24.2" - conditions: os=openbsd & cpu=arm64 - languageName: node - linkType: hard - "@esbuild/openbsd-arm64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/openbsd-arm64@npm:0.25.9" @@ -372,13 +232,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/openbsd-x64@npm:0.24.2" - conditions: os=openbsd & cpu=x64 - languageName: node - linkType: hard - "@esbuild/openbsd-x64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/openbsd-x64@npm:0.25.9" @@ -393,13 +246,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/sunos-x64@npm:0.24.2" - conditions: os=sunos & cpu=x64 - languageName: node - linkType: hard - "@esbuild/sunos-x64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/sunos-x64@npm:0.25.9" @@ -407,13 +253,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/win32-arm64@npm:0.24.2" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - "@esbuild/win32-arm64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/win32-arm64@npm:0.25.9" @@ -421,13 +260,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/win32-ia32@npm:0.24.2" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - "@esbuild/win32-ia32@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/win32-ia32@npm:0.25.9" @@ -435,13 +267,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/win32-x64@npm:0.24.2" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - "@esbuild/win32-x64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/win32-x64@npm:0.25.9" @@ -493,12 +318,12 @@ __metadata: resolution: "@janhq/assistant-extension@workspace:assistant-extension" dependencies: "@janhq/core": ../../core/package.tgz - cpx: "npm:^1.5.0" - rimraf: "npm:^6.0.1" + cpx: "npm:1.5.0" + rimraf: "npm:6.0.1" rolldown: "npm:1.0.0-beta.1" - run-script-os: "npm:^1.1.6" + run-script-os: "npm:1.1.6" ts-loader: "npm:^9.5.0" - typescript: "npm:^5.3.3" + typescript: "npm:5.9.2" languageName: unknown linkType: soft @@ -507,11 +332,11 @@ __metadata: resolution: "@janhq/conversational-extension@workspace:conversational-extension" dependencies: "@janhq/core": ../../core/package.tgz - cpx: "npm:^1.5.0" - rimraf: "npm:^6.0.1" + cpx: "npm:1.5.0" + rimraf: "npm:6.0.1" rolldown: "npm:1.0.0-beta.1" ts-loader: "npm:^9.5.0" - typescript: "npm:^5.7.2" + typescript: "npm:5.9.2" languageName: unknown linkType: soft @@ -560,13 +385,13 @@ __metadata: resolution: "@janhq/download-extension@workspace:download-extension" dependencies: "@janhq/core": ../../core/package.tgz - "@tauri-apps/api": "npm:^2.5.0" - cpx: "npm:^1.5.0" - rimraf: "npm:^6.0.1" + "@tauri-apps/api": "npm:2.8.0" + cpx: "npm:1.5.0" + rimraf: "npm:6.0.1" rolldown: "npm:1.0.0-beta.1" - run-script-os: "npm:^1.1.6" + run-script-os: "npm:1.1.6" typescript: "npm:5.8.3" - vitest: "npm:^3.0.6" + vitest: "npm:3.2.4" languageName: unknown linkType: soft @@ -577,19 +402,19 @@ __metadata: "@janhq/core": ../../core/package.tgz "@janhq/tauri-plugin-hardware-api": "link:../../src-tauri/plugins/tauri-plugin-hardware" "@janhq/tauri-plugin-llamacpp-api": "link:../../src-tauri/plugins/tauri-plugin-llamacpp" - "@tauri-apps/api": "npm:^2.5.0" - "@tauri-apps/plugin-http": "npm:^2.5.1" + "@tauri-apps/api": "npm:2.8.0" + "@tauri-apps/plugin-http": "npm:2.5.0" "@tauri-apps/plugin-log": "npm:^2.6.0" - "@vitest/ui": "npm:^3.2.4" - cpx: "npm:^1.5.0" + "@vitest/ui": "npm:2.1.9" + cpx: "npm:1.5.0" fetch-retry: "npm:^5.0.6" - jsdom: "npm:^26.1.0" - rimraf: "npm:^3.0.2" + jsdom: "npm:26.1.0" + rimraf: "npm:3.0.2" rolldown: "npm:1.0.0-beta.1" ts-loader: "npm:^9.5.0" - typescript: "npm:^5.7.2" - ulidx: "npm:^2.3.0" - vitest: "npm:^3.2.4" + typescript: "npm:5.9.2" + ulidx: "npm:2.4.1" + vitest: "npm:3.2.4" languageName: unknown linkType: soft @@ -745,13 +570,6 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-android-arm-eabi@npm:4.34.8": - version: 4.34.8 - resolution: "@rollup/rollup-android-arm-eabi@npm:4.34.8" - conditions: os=android & cpu=arm - languageName: node - linkType: hard - "@rollup/rollup-android-arm-eabi@npm:4.50.1": version: 4.50.1 resolution: "@rollup/rollup-android-arm-eabi@npm:4.50.1" @@ -759,13 +577,6 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-android-arm64@npm:4.34.8": - version: 4.34.8 - resolution: "@rollup/rollup-android-arm64@npm:4.34.8" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - "@rollup/rollup-android-arm64@npm:4.50.1": version: 4.50.1 resolution: "@rollup/rollup-android-arm64@npm:4.50.1" @@ -773,13 +584,6 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-darwin-arm64@npm:4.34.8": - version: 4.34.8 - resolution: "@rollup/rollup-darwin-arm64@npm:4.34.8" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - "@rollup/rollup-darwin-arm64@npm:4.50.1": version: 4.50.1 resolution: "@rollup/rollup-darwin-arm64@npm:4.50.1" @@ -787,13 +591,6 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-darwin-x64@npm:4.34.8": - version: 4.34.8 - resolution: "@rollup/rollup-darwin-x64@npm:4.34.8" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - "@rollup/rollup-darwin-x64@npm:4.50.1": version: 4.50.1 resolution: "@rollup/rollup-darwin-x64@npm:4.50.1" @@ -801,13 +598,6 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-freebsd-arm64@npm:4.34.8": - version: 4.34.8 - resolution: "@rollup/rollup-freebsd-arm64@npm:4.34.8" - conditions: os=freebsd & cpu=arm64 - languageName: node - linkType: hard - "@rollup/rollup-freebsd-arm64@npm:4.50.1": version: 4.50.1 resolution: "@rollup/rollup-freebsd-arm64@npm:4.50.1" @@ -815,13 +605,6 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-freebsd-x64@npm:4.34.8": - version: 4.34.8 - resolution: "@rollup/rollup-freebsd-x64@npm:4.34.8" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - "@rollup/rollup-freebsd-x64@npm:4.50.1": version: 4.50.1 resolution: "@rollup/rollup-freebsd-x64@npm:4.50.1" @@ -829,13 +612,6 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-linux-arm-gnueabihf@npm:4.34.8": - version: 4.34.8 - resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.34.8" - conditions: os=linux & cpu=arm & libc=glibc - languageName: node - linkType: hard - "@rollup/rollup-linux-arm-gnueabihf@npm:4.50.1": version: 4.50.1 resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.50.1" @@ -843,13 +619,6 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-linux-arm-musleabihf@npm:4.34.8": - version: 4.34.8 - resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.34.8" - conditions: os=linux & cpu=arm & libc=musl - languageName: node - linkType: hard - "@rollup/rollup-linux-arm-musleabihf@npm:4.50.1": version: 4.50.1 resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.50.1" @@ -857,13 +626,6 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-linux-arm64-gnu@npm:4.34.8": - version: 4.34.8 - resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.34.8" - conditions: os=linux & cpu=arm64 & libc=glibc - languageName: node - linkType: hard - "@rollup/rollup-linux-arm64-gnu@npm:4.50.1": version: 4.50.1 resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.50.1" @@ -871,13 +633,6 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-linux-arm64-musl@npm:4.34.8": - version: 4.34.8 - resolution: "@rollup/rollup-linux-arm64-musl@npm:4.34.8" - conditions: os=linux & cpu=arm64 & libc=musl - languageName: node - linkType: hard - "@rollup/rollup-linux-arm64-musl@npm:4.50.1": version: 4.50.1 resolution: "@rollup/rollup-linux-arm64-musl@npm:4.50.1" @@ -885,13 +640,6 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-linux-loongarch64-gnu@npm:4.34.8": - version: 4.34.8 - resolution: "@rollup/rollup-linux-loongarch64-gnu@npm:4.34.8" - conditions: os=linux & cpu=loong64 & libc=glibc - languageName: node - linkType: hard - "@rollup/rollup-linux-loongarch64-gnu@npm:4.50.1": version: 4.50.1 resolution: "@rollup/rollup-linux-loongarch64-gnu@npm:4.50.1" @@ -899,13 +647,6 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-linux-powerpc64le-gnu@npm:4.34.8": - version: 4.34.8 - resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.34.8" - conditions: os=linux & cpu=ppc64 & libc=glibc - languageName: node - linkType: hard - "@rollup/rollup-linux-ppc64-gnu@npm:4.50.1": version: 4.50.1 resolution: "@rollup/rollup-linux-ppc64-gnu@npm:4.50.1" @@ -913,13 +654,6 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-linux-riscv64-gnu@npm:4.34.8": - version: 4.34.8 - resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.34.8" - conditions: os=linux & cpu=riscv64 & libc=glibc - languageName: node - linkType: hard - "@rollup/rollup-linux-riscv64-gnu@npm:4.50.1": version: 4.50.1 resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.50.1" @@ -934,13 +668,6 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-linux-s390x-gnu@npm:4.34.8": - version: 4.34.8 - resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.34.8" - conditions: os=linux & cpu=s390x & libc=glibc - languageName: node - linkType: hard - "@rollup/rollup-linux-s390x-gnu@npm:4.50.1": version: 4.50.1 resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.50.1" @@ -948,13 +675,6 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-linux-x64-gnu@npm:4.34.8": - version: 4.34.8 - resolution: "@rollup/rollup-linux-x64-gnu@npm:4.34.8" - conditions: os=linux & cpu=x64 & libc=glibc - languageName: node - linkType: hard - "@rollup/rollup-linux-x64-gnu@npm:4.50.1": version: 4.50.1 resolution: "@rollup/rollup-linux-x64-gnu@npm:4.50.1" @@ -962,13 +682,6 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-linux-x64-musl@npm:4.34.8": - version: 4.34.8 - resolution: "@rollup/rollup-linux-x64-musl@npm:4.34.8" - conditions: os=linux & cpu=x64 & libc=musl - languageName: node - linkType: hard - "@rollup/rollup-linux-x64-musl@npm:4.50.1": version: 4.50.1 resolution: "@rollup/rollup-linux-x64-musl@npm:4.50.1" @@ -983,13 +696,6 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-win32-arm64-msvc@npm:4.34.8": - version: 4.34.8 - resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.34.8" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - "@rollup/rollup-win32-arm64-msvc@npm:4.50.1": version: 4.50.1 resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.50.1" @@ -997,13 +703,6 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-win32-ia32-msvc@npm:4.34.8": - version: 4.34.8 - resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.34.8" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - "@rollup/rollup-win32-ia32-msvc@npm:4.50.1": version: 4.50.1 resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.50.1" @@ -1011,13 +710,6 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-win32-x64-msvc@npm:4.34.8": - version: 4.34.8 - resolution: "@rollup/rollup-win32-x64-msvc@npm:4.34.8" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - "@rollup/rollup-win32-x64-msvc@npm:4.50.1": version: 4.50.1 resolution: "@rollup/rollup-win32-x64-msvc@npm:4.50.1" @@ -1025,26 +717,19 @@ __metadata: languageName: node linkType: hard -"@tauri-apps/api@npm:^2.5.0": - version: 2.6.0 - resolution: "@tauri-apps/api@npm:2.6.0" - checksum: 10c0/211353d951c7e3e5298f074ec762b5853ff0cdee261478c27db1e450fcf3d6f2c03a616483abbf9dfc79f13c6dfcfa7db0b790c1384c113951c0d694809f05ef - languageName: node - linkType: hard - -"@tauri-apps/api@npm:^2.8.0": +"@tauri-apps/api@npm:2.8.0, @tauri-apps/api@npm:^2.6.0, @tauri-apps/api@npm:^2.8.0": version: 2.8.0 resolution: "@tauri-apps/api@npm:2.8.0" checksum: 10c0/fb111e4d7572372997b440ebe6879543fa8c4765151878e3fddfbfe809b18da29eed142ce83061d14a9ca6d896b3266dc8a4927c642d71cdc0b4277dc7e3aabf languageName: node linkType: hard -"@tauri-apps/plugin-http@npm:^2.5.1": - version: 2.5.2 - resolution: "@tauri-apps/plugin-http@npm:2.5.2" +"@tauri-apps/plugin-http@npm:2.5.0": + version: 2.5.0 + resolution: "@tauri-apps/plugin-http@npm:2.5.0" dependencies: - "@tauri-apps/api": "npm:^2.8.0" - checksum: 10c0/14ca96a1f3cca03a7f391bc04e3d4cb693bd56595ce01b9ce037342733b428c4ca781aa573968352332361fe7c3a438be7603db4d03f681db90b890daaa3e152 + "@tauri-apps/api": "npm:^2.6.0" + checksum: 10c0/eed47bb2adf012cde4409c4decae30e6b759f5828cb959cf43fc34c5fdfe68e6670f14f1134c8c4c941bc3fdb00e312772ebd72ec94e15c56ed1b7fbd47dd91c languageName: node linkType: hard @@ -1082,13 +767,6 @@ __metadata: languageName: node linkType: hard -"@types/estree@npm:1.0.6, @types/estree@npm:^1.0.0": - version: 1.0.6 - resolution: "@types/estree@npm:1.0.6" - checksum: 10c0/cdfd751f6f9065442cd40957c07fd80361c962869aa853c1c2fd03e101af8b9389d8ff4955a43a6fcfa223dd387a089937f95be0f3eec21ca527039fd2d9859a - languageName: node - linkType: hard - "@types/estree@npm:1.0.8": version: 1.0.8 resolution: "@types/estree@npm:1.0.8" @@ -1096,15 +774,10 @@ __metadata: languageName: node linkType: hard -"@vitest/expect@npm:3.0.6": - version: 3.0.6 - resolution: "@vitest/expect@npm:3.0.6" - dependencies: - "@vitest/spy": "npm:3.0.6" - "@vitest/utils": "npm:3.0.6" - chai: "npm:^5.2.0" - tinyrainbow: "npm:^2.0.0" - checksum: 10c0/1273d80d3f523dd390016d89c037e6088688342cc1961f1b0b8b54103f94212c7f6efa275c263fbcfc77e1adcf0fc9faa7285782b85eb4fe49a3bc999e7a61d4 +"@types/estree@npm:^1.0.0": + version: 1.0.6 + resolution: "@types/estree@npm:1.0.6" + checksum: 10c0/cdfd751f6f9065442cd40957c07fd80361c962869aa853c1c2fd03e101af8b9389d8ff4955a43a6fcfa223dd387a089937f95be0f3eec21ca527039fd2d9859a languageName: node linkType: hard @@ -1121,25 +794,6 @@ __metadata: languageName: node linkType: hard -"@vitest/mocker@npm:3.0.6": - version: 3.0.6 - resolution: "@vitest/mocker@npm:3.0.6" - dependencies: - "@vitest/spy": "npm:3.0.6" - estree-walker: "npm:^3.0.3" - magic-string: "npm:^0.30.17" - peerDependencies: - msw: ^2.4.9 - vite: ^5.0.0 || ^6.0.0 - peerDependenciesMeta: - msw: - optional: true - vite: - optional: true - checksum: 10c0/41911fbdf2c6afe099aa8d039079495dfd3dec2cd13e660fbc43488457181065c043d889ed17395bbc76e29e7253bcffbe9ad6a2fb407be33929470089e0b06b - languageName: node - linkType: hard - "@vitest/mocker@npm:3.2.4": version: 3.2.4 resolution: "@vitest/mocker@npm:3.2.4" @@ -1159,12 +813,12 @@ __metadata: languageName: node linkType: hard -"@vitest/pretty-format@npm:3.0.6, @vitest/pretty-format@npm:^3.0.6": - version: 3.0.6 - resolution: "@vitest/pretty-format@npm:3.0.6" +"@vitest/pretty-format@npm:2.1.9": + version: 2.1.9 + resolution: "@vitest/pretty-format@npm:2.1.9" dependencies: - tinyrainbow: "npm:^2.0.0" - checksum: 10c0/339b47598f2c77da0d0b7d373c2ceb94995d6154cd30b7de778bbf396d21c570de0be765f1d66793d2a30a6cc673a471be45f093a074acb8a1a71d7665713dd9 + tinyrainbow: "npm:^1.2.0" + checksum: 10c0/155f9ede5090eabed2a73361094bb35ed4ec6769ae3546d2a2af139166569aec41bb80e031c25ff2da22b71dd4ed51e5468e66a05e6aeda5f14b32e30bc18f00 languageName: node linkType: hard @@ -1177,16 +831,6 @@ __metadata: languageName: node linkType: hard -"@vitest/runner@npm:3.0.6": - version: 3.0.6 - resolution: "@vitest/runner@npm:3.0.6" - dependencies: - "@vitest/utils": "npm:3.0.6" - pathe: "npm:^2.0.3" - checksum: 10c0/a20cd27d6c91947866b35080db7b8f2fc4568c62878d4175cad38914c2bb769c49791be8601d5ffe27c80cefbc0310e6c0b4256c621581daecdc508d60270d31 - languageName: node - linkType: hard - "@vitest/runner@npm:3.2.4": version: 3.2.4 resolution: "@vitest/runner@npm:3.2.4" @@ -1198,17 +842,6 @@ __metadata: languageName: node linkType: hard -"@vitest/snapshot@npm:3.0.6": - version: 3.0.6 - resolution: "@vitest/snapshot@npm:3.0.6" - dependencies: - "@vitest/pretty-format": "npm:3.0.6" - magic-string: "npm:^0.30.17" - pathe: "npm:^2.0.3" - checksum: 10c0/9baf575d23ef262de6ff180dca156ccd327c02a507d8380b3d59d3b714e3754c45aa588aaa57e3a115cec572a5dd552b8613736d14ac3759b98e068bfe220bed - languageName: node - linkType: hard - "@vitest/snapshot@npm:3.2.4": version: 3.2.4 resolution: "@vitest/snapshot@npm:3.2.4" @@ -1220,15 +853,6 @@ __metadata: languageName: node linkType: hard -"@vitest/spy@npm:3.0.6": - version: 3.0.6 - resolution: "@vitest/spy@npm:3.0.6" - dependencies: - tinyspy: "npm:^3.0.2" - checksum: 10c0/575cf28a370b9f9909e54578460a14234eddf449621b0d28f0fb22b872d2c5302c7ea7df39b680836efc729a1290fa562eee129cef73c5223dfe5b58e6a13b1b - languageName: node - linkType: hard - "@vitest/spy@npm:3.2.4": version: 3.2.4 resolution: "@vitest/spy@npm:3.2.4" @@ -1238,31 +862,31 @@ __metadata: languageName: node linkType: hard -"@vitest/ui@npm:^3.2.4": - version: 3.2.4 - resolution: "@vitest/ui@npm:3.2.4" +"@vitest/ui@npm:2.1.9": + version: 2.1.9 + resolution: "@vitest/ui@npm:2.1.9" dependencies: - "@vitest/utils": "npm:3.2.4" + "@vitest/utils": "npm:2.1.9" fflate: "npm:^0.8.2" - flatted: "npm:^3.3.3" - pathe: "npm:^2.0.3" - sirv: "npm:^3.0.1" - tinyglobby: "npm:^0.2.14" - tinyrainbow: "npm:^2.0.0" + flatted: "npm:^3.3.1" + pathe: "npm:^1.1.2" + sirv: "npm:^3.0.0" + tinyglobby: "npm:^0.2.10" + tinyrainbow: "npm:^1.2.0" peerDependencies: - vitest: 3.2.4 - checksum: 10c0/c3de1b757905d050706c7ab0199185dd8c7e115f2f348b8d5a7468528c6bf90c2c46096e8901602349ac04f5ba83ac23cd98c38827b104d5151cf8ba21739a0c + vitest: 2.1.9 + checksum: 10c0/b091f5afd5e7327d1dfc37e26af16d58066bd6c37ec0a1547796f1843eff3170c59062243475fb250ca36d8d7c7293ab78b36b2d112d7839ba8331625ab9b1d3 languageName: node linkType: hard -"@vitest/utils@npm:3.0.6": - version: 3.0.6 - resolution: "@vitest/utils@npm:3.0.6" +"@vitest/utils@npm:2.1.9": + version: 2.1.9 + resolution: "@vitest/utils@npm:2.1.9" dependencies: - "@vitest/pretty-format": "npm:3.0.6" - loupe: "npm:^3.1.3" - tinyrainbow: "npm:^2.0.0" - checksum: 10c0/6b0e89e26c96fcfd825e0795f586336df6a02524a11e9ac3e576b7ed9738a9e4b69cd79d0b69b23c195cc4c6bdd907f1d8f7aa79a4ee0cb85393c94a1aa85267 + "@vitest/pretty-format": "npm:2.1.9" + loupe: "npm:^3.1.2" + tinyrainbow: "npm:^1.2.0" + checksum: 10c0/81a346cd72b47941f55411f5df4cc230e5f740d1e97e0d3f771b27f007266fc1f28d0438582f6409ea571bc0030ed37f684c64c58d1947d6298d770c21026fdf languageName: node linkType: hard @@ -1684,7 +1308,7 @@ __metadata: languageName: node linkType: hard -"cpx@npm:^1.5.0": +"cpx@npm:1.5.0": version: 1.5.0 resolution: "cpx@npm:1.5.0" dependencies: @@ -1736,7 +1360,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4.3.4, debug@npm:^4.4.0": +"debug@npm:4, debug@npm:^4.3.4": version: 4.4.0 resolution: "debug@npm:4.4.0" dependencies: @@ -1886,13 +1510,6 @@ __metadata: languageName: node linkType: hard -"es-module-lexer@npm:^1.6.0": - version: 1.6.0 - resolution: "es-module-lexer@npm:1.6.0" - checksum: 10c0/667309454411c0b95c476025929881e71400d74a746ffa1ff4cb450bd87f8e33e8eef7854d68e401895039ac0bac64e7809acbebb6253e055dd49ea9e3ea9212 - languageName: node - linkType: hard - "es-module-lexer@npm:^1.7.0": version: 1.7.0 resolution: "es-module-lexer@npm:1.7.0" @@ -1900,92 +1517,6 @@ __metadata: languageName: node linkType: hard -"esbuild@npm:^0.24.2": - version: 0.24.2 - resolution: "esbuild@npm:0.24.2" - dependencies: - "@esbuild/aix-ppc64": "npm:0.24.2" - "@esbuild/android-arm": "npm:0.24.2" - "@esbuild/android-arm64": "npm:0.24.2" - "@esbuild/android-x64": "npm:0.24.2" - "@esbuild/darwin-arm64": "npm:0.24.2" - "@esbuild/darwin-x64": "npm:0.24.2" - "@esbuild/freebsd-arm64": "npm:0.24.2" - "@esbuild/freebsd-x64": "npm:0.24.2" - "@esbuild/linux-arm": "npm:0.24.2" - "@esbuild/linux-arm64": "npm:0.24.2" - "@esbuild/linux-ia32": "npm:0.24.2" - "@esbuild/linux-loong64": "npm:0.24.2" - "@esbuild/linux-mips64el": "npm:0.24.2" - "@esbuild/linux-ppc64": "npm:0.24.2" - "@esbuild/linux-riscv64": "npm:0.24.2" - "@esbuild/linux-s390x": "npm:0.24.2" - "@esbuild/linux-x64": "npm:0.24.2" - "@esbuild/netbsd-arm64": "npm:0.24.2" - "@esbuild/netbsd-x64": "npm:0.24.2" - "@esbuild/openbsd-arm64": "npm:0.24.2" - "@esbuild/openbsd-x64": "npm:0.24.2" - "@esbuild/sunos-x64": "npm:0.24.2" - "@esbuild/win32-arm64": "npm:0.24.2" - "@esbuild/win32-ia32": "npm:0.24.2" - "@esbuild/win32-x64": "npm:0.24.2" - dependenciesMeta: - "@esbuild/aix-ppc64": - optional: true - "@esbuild/android-arm": - optional: true - "@esbuild/android-arm64": - optional: true - "@esbuild/android-x64": - optional: true - "@esbuild/darwin-arm64": - optional: true - "@esbuild/darwin-x64": - optional: true - "@esbuild/freebsd-arm64": - optional: true - "@esbuild/freebsd-x64": - optional: true - "@esbuild/linux-arm": - optional: true - "@esbuild/linux-arm64": - optional: true - "@esbuild/linux-ia32": - optional: true - "@esbuild/linux-loong64": - optional: true - "@esbuild/linux-mips64el": - optional: true - "@esbuild/linux-ppc64": - optional: true - "@esbuild/linux-riscv64": - optional: true - "@esbuild/linux-s390x": - optional: true - "@esbuild/linux-x64": - optional: true - "@esbuild/netbsd-arm64": - optional: true - "@esbuild/netbsd-x64": - optional: true - "@esbuild/openbsd-arm64": - optional: true - "@esbuild/openbsd-x64": - optional: true - "@esbuild/sunos-x64": - optional: true - "@esbuild/win32-arm64": - optional: true - "@esbuild/win32-ia32": - optional: true - "@esbuild/win32-x64": - optional: true - bin: - esbuild: bin/esbuild - checksum: 10c0/5a25bb08b6ba23db6e66851828d848bd3ff87c005a48c02d83e38879058929878a6baa5a414e1141faee0d1dece3f32b5fbc2a87b82ed6a7aa857cf40359aeb5 - languageName: node - linkType: hard - "esbuild@npm:^0.25.0": version: 0.25.9 resolution: "esbuild@npm:0.25.9" @@ -2117,13 +1648,6 @@ __metadata: languageName: node linkType: hard -"expect-type@npm:^1.1.0": - version: 1.1.0 - resolution: "expect-type@npm:1.1.0" - checksum: 10c0/5af0febbe8fe18da05a6d51e3677adafd75213512285408156b368ca471252565d5ca6e59e4bddab25121f3cfcbbebc6a5489f8cc9db131cc29e69dcdcc7ae15 - languageName: node - linkType: hard - "expect-type@npm:^1.2.1": version: 1.2.2 resolution: "expect-type@npm:1.2.2" @@ -2263,7 +1787,7 @@ __metadata: languageName: node linkType: hard -"flatted@npm:^3.3.3": +"flatted@npm:^3.3.1": version: 3.3.3 resolution: "flatted@npm:3.3.3" checksum: 10c0/e957a1c6b0254aa15b8cce8533e24165abd98fadc98575db082b786b5da1b7d72062b81bfdcd1da2f4d46b6ed93bec2434e62333e9b4261d79ef2e75a10dd538 @@ -2860,7 +2384,7 @@ __metadata: languageName: node linkType: hard -"jsdom@npm:^26.1.0": +"jsdom@npm:26.1.0": version: 26.1.0 resolution: "jsdom@npm:26.1.0" dependencies: @@ -2925,14 +2449,14 @@ __metadata: languageName: node linkType: hard -"loupe@npm:^3.1.0, loupe@npm:^3.1.3": +"loupe@npm:^3.1.0": version: 3.1.3 resolution: "loupe@npm:3.1.3" checksum: 10c0/f5dab4144254677de83a35285be1b8aba58b3861439ce4ba65875d0d5f3445a4a496daef63100ccf02b2dbc25bf58c6db84c9cb0b96d6435331e9d0a33b48541 languageName: node linkType: hard -"loupe@npm:^3.1.4": +"loupe@npm:^3.1.2, loupe@npm:^3.1.4": version: 3.2.1 resolution: "loupe@npm:3.2.1" checksum: 10c0/910c872cba291309664c2d094368d31a68907b6f5913e989d301b5c25f30e97d76d77f23ab3bf3b46d0f601ff0b6af8810c10c31b91d2c6b2f132809ca2cc705 @@ -3236,15 +2760,6 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:^3.3.8": - version: 3.3.8 - resolution: "nanoid@npm:3.3.8" - bin: - nanoid: bin/nanoid.cjs - checksum: 10c0/4b1bb29f6cfebf3be3bc4ad1f1296fb0a10a3043a79f34fbffe75d1621b4318319211cd420549459018ea3592f0d2f159247a6f874911d6d26eaaadda2478120 - languageName: node - linkType: hard - "nanomatch@npm:^1.2.9": version: 1.2.13 resolution: "nanomatch@npm:1.2.13" @@ -3449,6 +2964,13 @@ __metadata: languageName: node linkType: hard +"pathe@npm:^1.1.2": + version: 1.1.2 + resolution: "pathe@npm:1.1.2" + checksum: 10c0/64ee0a4e587fb0f208d9777a6c56e4f9050039268faaaaecd50e959ef01bf847b7872785c36483fa5cdcdbdfdb31fef2ff222684d4fc21c330ab60395c681897 + languageName: node + linkType: hard + "pathe@npm:^2.0.3": version: 2.0.3 resolution: "pathe@npm:2.0.3" @@ -3491,17 +3013,6 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.5.2": - version: 8.5.3 - resolution: "postcss@npm:8.5.3" - dependencies: - nanoid: "npm:^3.3.8" - picocolors: "npm:^1.1.1" - source-map-js: "npm:^1.2.1" - checksum: 10c0/b75510d7b28c3ab728c8733dd01538314a18c52af426f199a3c9177e63eb08602a3938bfb66b62dc01350b9aed62087eabbf229af97a1659eb8d3513cec823b3 - languageName: node - linkType: hard - "postcss@npm:^8.5.6": version: 8.5.6 resolution: "postcss@npm:8.5.6" @@ -3682,7 +3193,7 @@ __metadata: languageName: node linkType: hard -"rimraf@npm:^3.0.2": +"rimraf@npm:3.0.2": version: 3.0.2 resolution: "rimraf@npm:3.0.2" dependencies: @@ -3693,6 +3204,18 @@ __metadata: languageName: node linkType: hard +"rimraf@npm:6.0.1": + version: 6.0.1 + resolution: "rimraf@npm:6.0.1" + dependencies: + glob: "npm:^11.0.0" + package-json-from-dist: "npm:^1.0.0" + bin: + rimraf: dist/esm/bin.mjs + checksum: 10c0/b30b6b072771f0d1e73b4ca5f37bb2944ee09375be9db5f558fcd3310000d29dfcfa93cf7734d75295ad5a7486dc8e40f63089ced1722a664539ffc0c3ece8c6 + languageName: node + linkType: hard + "rimraf@npm:^5.0.5": version: 5.0.10 resolution: "rimraf@npm:5.0.10" @@ -3704,18 +3227,6 @@ __metadata: languageName: node linkType: hard -"rimraf@npm:^6.0.1": - version: 6.0.1 - resolution: "rimraf@npm:6.0.1" - dependencies: - glob: "npm:^11.0.0" - package-json-from-dist: "npm:^1.0.0" - bin: - rimraf: dist/esm/bin.mjs - checksum: 10c0/b30b6b072771f0d1e73b4ca5f37bb2944ee09375be9db5f558fcd3310000d29dfcfa93cf7734d75295ad5a7486dc8e40f63089ced1722a664539ffc0c3ece8c6 - languageName: node - linkType: hard - "rolldown@npm:1.0.0-beta.1": version: 1.0.0-beta.1 resolution: "rolldown@npm:1.0.0-beta.1" @@ -3769,78 +3280,6 @@ __metadata: languageName: node linkType: hard -"rollup@npm:^4.30.1": - version: 4.34.8 - resolution: "rollup@npm:4.34.8" - dependencies: - "@rollup/rollup-android-arm-eabi": "npm:4.34.8" - "@rollup/rollup-android-arm64": "npm:4.34.8" - "@rollup/rollup-darwin-arm64": "npm:4.34.8" - "@rollup/rollup-darwin-x64": "npm:4.34.8" - "@rollup/rollup-freebsd-arm64": "npm:4.34.8" - "@rollup/rollup-freebsd-x64": "npm:4.34.8" - "@rollup/rollup-linux-arm-gnueabihf": "npm:4.34.8" - "@rollup/rollup-linux-arm-musleabihf": "npm:4.34.8" - "@rollup/rollup-linux-arm64-gnu": "npm:4.34.8" - "@rollup/rollup-linux-arm64-musl": "npm:4.34.8" - "@rollup/rollup-linux-loongarch64-gnu": "npm:4.34.8" - "@rollup/rollup-linux-powerpc64le-gnu": "npm:4.34.8" - "@rollup/rollup-linux-riscv64-gnu": "npm:4.34.8" - "@rollup/rollup-linux-s390x-gnu": "npm:4.34.8" - "@rollup/rollup-linux-x64-gnu": "npm:4.34.8" - "@rollup/rollup-linux-x64-musl": "npm:4.34.8" - "@rollup/rollup-win32-arm64-msvc": "npm:4.34.8" - "@rollup/rollup-win32-ia32-msvc": "npm:4.34.8" - "@rollup/rollup-win32-x64-msvc": "npm:4.34.8" - "@types/estree": "npm:1.0.6" - fsevents: "npm:~2.3.2" - dependenciesMeta: - "@rollup/rollup-android-arm-eabi": - optional: true - "@rollup/rollup-android-arm64": - optional: true - "@rollup/rollup-darwin-arm64": - optional: true - "@rollup/rollup-darwin-x64": - optional: true - "@rollup/rollup-freebsd-arm64": - optional: true - "@rollup/rollup-freebsd-x64": - optional: true - "@rollup/rollup-linux-arm-gnueabihf": - optional: true - "@rollup/rollup-linux-arm-musleabihf": - optional: true - "@rollup/rollup-linux-arm64-gnu": - optional: true - "@rollup/rollup-linux-arm64-musl": - optional: true - "@rollup/rollup-linux-loongarch64-gnu": - optional: true - "@rollup/rollup-linux-powerpc64le-gnu": - optional: true - "@rollup/rollup-linux-riscv64-gnu": - optional: true - "@rollup/rollup-linux-s390x-gnu": - optional: true - "@rollup/rollup-linux-x64-gnu": - optional: true - "@rollup/rollup-linux-x64-musl": - optional: true - "@rollup/rollup-win32-arm64-msvc": - optional: true - "@rollup/rollup-win32-ia32-msvc": - optional: true - "@rollup/rollup-win32-x64-msvc": - optional: true - fsevents: - optional: true - bin: - rollup: dist/bin/rollup - checksum: 10c0/b9e711e33413112fbb761107c3fddc4561dfc74335c393542a829a85ccfb2763bfd17bf2422d84a2e9bee7646e5367018973e97005fdf64e49c2e209612f0eb6 - languageName: node - linkType: hard - "rollup@npm:^4.43.0": version: 4.50.1 resolution: "rollup@npm:4.50.1" @@ -3932,7 +3371,7 @@ __metadata: languageName: node linkType: hard -"run-script-os@npm:^1.1.6": +"run-script-os@npm:1.1.6": version: 1.1.6 resolution: "run-script-os@npm:1.1.6" bin: @@ -4048,7 +3487,7 @@ __metadata: languageName: node linkType: hard -"sirv@npm:^3.0.1": +"sirv@npm:^3.0.0": version: 3.0.2 resolution: "sirv@npm:3.0.2" dependencies: @@ -4206,13 +3645,6 @@ __metadata: languageName: node linkType: hard -"std-env@npm:^3.8.0": - version: 3.8.0 - resolution: "std-env@npm:3.8.0" - checksum: 10c0/f560a2902fd0fa3d648d7d0acecbd19d664006f7372c1fba197ed4c216b4c9e48db6e2769b5fe1616d42a9333c9f066c5011935035e85c59f45dc4f796272040 - languageName: node - linkType: hard - "std-env@npm:^3.9.0": version: 3.9.0 resolution: "std-env@npm:3.9.0" @@ -4345,7 +3777,7 @@ __metadata: languageName: node linkType: hard -"tinyglobby@npm:^0.2.14, tinyglobby@npm:^0.2.15": +"tinyglobby@npm:^0.2.10, tinyglobby@npm:^0.2.14, tinyglobby@npm:^0.2.15": version: 0.2.15 resolution: "tinyglobby@npm:0.2.15" dependencies: @@ -4355,13 +3787,6 @@ __metadata: languageName: node linkType: hard -"tinypool@npm:^1.0.2": - version: 1.0.2 - resolution: "tinypool@npm:1.0.2" - checksum: 10c0/31ac184c0ff1cf9a074741254fe9ea6de95026749eb2b8ec6fd2b9d8ca94abdccda731f8e102e7f32e72ed3b36d32c6975fd5f5523df3f1b6de6c3d8dfd95e63 - languageName: node - linkType: hard - "tinypool@npm:^1.1.1": version: 1.1.1 resolution: "tinypool@npm:1.1.1" @@ -4369,6 +3794,13 @@ __metadata: languageName: node linkType: hard +"tinyrainbow@npm:^1.2.0": + version: 1.2.0 + resolution: "tinyrainbow@npm:1.2.0" + checksum: 10c0/7f78a4b997e5ba0f5ecb75e7ed786f30bab9063716e7dff24dd84013fb338802e43d176cb21ed12480561f5649a82184cf31efb296601a29d38145b1cdb4c192 + languageName: node + linkType: hard + "tinyrainbow@npm:^2.0.0": version: 2.0.0 resolution: "tinyrainbow@npm:2.0.0" @@ -4376,13 +3808,6 @@ __metadata: languageName: node linkType: hard -"tinyspy@npm:^3.0.2": - version: 3.0.2 - resolution: "tinyspy@npm:3.0.2" - checksum: 10c0/55ffad24e346622b59292e097c2ee30a63919d5acb7ceca87fc0d1c223090089890587b426e20054733f97a58f20af2c349fb7cc193697203868ab7ba00bcea0 - languageName: node - linkType: hard - "tinyspy@npm:^4.0.3": version: 4.0.3 resolution: "tinyspy@npm:4.0.3" @@ -4506,13 +3931,13 @@ __metadata: languageName: node linkType: hard -"typescript@npm:^5.3.3, typescript@npm:^5.7.2": - version: 5.7.2 - resolution: "typescript@npm:5.7.2" +"typescript@npm:5.9.2": + version: 5.9.2 + resolution: "typescript@npm:5.9.2" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 10c0/a873118b5201b2ef332127ef5c63fb9d9c155e6fdbe211cbd9d8e65877283797cca76546bad742eea36ed7efbe3424a30376818f79c7318512064e8625d61622 + checksum: 10c0/cd635d50f02d6cf98ed42de2f76289701c1ec587a363369255f01ed15aaf22be0813226bff3c53e99d971f9b540e0b3cc7583dbe05faded49b1b0bed2f638a18 languageName: node linkType: hard @@ -4526,17 +3951,17 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@npm%3A^5.3.3#optional!builtin, typescript@patch:typescript@npm%3A^5.7.2#optional!builtin": - version: 5.7.2 - resolution: "typescript@patch:typescript@npm%3A5.7.2#optional!builtin::version=5.7.2&hash=5786d5" +"typescript@patch:typescript@npm%3A5.9.2#optional!builtin": + version: 5.9.2 + resolution: "typescript@patch:typescript@npm%3A5.9.2#optional!builtin::version=5.9.2&hash=5786d5" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 10c0/f3b8082c9d1d1629a215245c9087df56cb784f9fb6f27b5d55577a20e68afe2a889c040aacff6d27e35be165ecf9dca66e694c42eb9a50b3b2c451b36b5675cb + checksum: 10c0/34d2a8e23eb8e0d1875072064d5e1d9c102e0bdce56a10a25c0b917b8aa9001a9cf5c225df12497e99da107dc379360bc138163c66b55b95f5b105b50578067e languageName: node linkType: hard -"ulidx@npm:^2.3.0": +"ulidx@npm:2.4.1, ulidx@npm:^2.3.0": version: 2.4.1 resolution: "ulidx@npm:2.4.1" dependencies: @@ -4606,21 +4031,6 @@ __metadata: languageName: node linkType: hard -"vite-node@npm:3.0.6": - version: 3.0.6 - resolution: "vite-node@npm:3.0.6" - dependencies: - cac: "npm:^6.7.14" - debug: "npm:^4.4.0" - es-module-lexer: "npm:^1.6.0" - pathe: "npm:^2.0.3" - vite: "npm:^5.0.0 || ^6.0.0" - bin: - vite-node: vite-node.mjs - checksum: 10c0/bfef19ac659b453c31fc00b42f8d08b3f7539092f67b0b02504dc2f802af1fe9bcf3531a4ecd248bf8ce2f00b7f4b9a67e20cdd57c2e50d9ff8cea5ff941bedd - languageName: node - linkType: hard - "vite-node@npm:3.2.4": version: 3.2.4 resolution: "vite-node@npm:3.2.4" @@ -4636,58 +4046,6 @@ __metadata: languageName: node linkType: hard -"vite@npm:^5.0.0 || ^6.0.0": - version: 6.1.1 - resolution: "vite@npm:6.1.1" - dependencies: - esbuild: "npm:^0.24.2" - fsevents: "npm:~2.3.3" - postcss: "npm:^8.5.2" - rollup: "npm:^4.30.1" - peerDependencies: - "@types/node": ^18.0.0 || ^20.0.0 || >=22.0.0 - jiti: ">=1.21.0" - less: "*" - lightningcss: ^1.21.0 - sass: "*" - sass-embedded: "*" - stylus: "*" - sugarss: "*" - terser: ^5.16.0 - tsx: ^4.8.1 - yaml: ^2.4.2 - dependenciesMeta: - fsevents: - optional: true - peerDependenciesMeta: - "@types/node": - optional: true - jiti: - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - tsx: - optional: true - yaml: - optional: true - bin: - vite: bin/vite.js - checksum: 10c0/4ec5ddc9436951a68b213cd59c2a157663ef423658c387400774582ea33da40dcae18e55f3adb3b629173e2183b10d49db8370bc51a0aa89797e4ca5a34702a0 - languageName: node - linkType: hard - "vite@npm:^5.0.0 || ^6.0.0 || ^7.0.0-0": version: 7.1.5 resolution: "vite@npm:7.1.5" @@ -4743,60 +4101,7 @@ __metadata: languageName: node linkType: hard -"vitest@npm:^3.0.6": - version: 3.0.6 - resolution: "vitest@npm:3.0.6" - dependencies: - "@vitest/expect": "npm:3.0.6" - "@vitest/mocker": "npm:3.0.6" - "@vitest/pretty-format": "npm:^3.0.6" - "@vitest/runner": "npm:3.0.6" - "@vitest/snapshot": "npm:3.0.6" - "@vitest/spy": "npm:3.0.6" - "@vitest/utils": "npm:3.0.6" - chai: "npm:^5.2.0" - debug: "npm:^4.4.0" - expect-type: "npm:^1.1.0" - magic-string: "npm:^0.30.17" - pathe: "npm:^2.0.3" - std-env: "npm:^3.8.0" - tinybench: "npm:^2.9.0" - tinyexec: "npm:^0.3.2" - tinypool: "npm:^1.0.2" - tinyrainbow: "npm:^2.0.0" - vite: "npm:^5.0.0 || ^6.0.0" - vite-node: "npm:3.0.6" - why-is-node-running: "npm:^2.3.0" - peerDependencies: - "@edge-runtime/vm": "*" - "@types/debug": ^4.1.12 - "@types/node": ^18.0.0 || ^20.0.0 || >=22.0.0 - "@vitest/browser": 3.0.6 - "@vitest/ui": 3.0.6 - happy-dom: "*" - jsdom: "*" - peerDependenciesMeta: - "@edge-runtime/vm": - optional: true - "@types/debug": - optional: true - "@types/node": - optional: true - "@vitest/browser": - optional: true - "@vitest/ui": - optional: true - happy-dom: - optional: true - jsdom: - optional: true - bin: - vitest: vitest.mjs - checksum: 10c0/e50a08f8508a7dbda1ea985b2ba05483ab6f87e100a9388c6c4bc47ee76fcdebe89b33db320df177ea6d198fc50e98eb4b9650bb9d314dd8a7bfe885659b3d42 - languageName: node - linkType: hard - -"vitest@npm:^3.2.4": +"vitest@npm:3.2.4": version: 3.2.4 resolution: "vitest@npm:3.2.4" dependencies: diff --git a/mise.toml b/mise.toml deleted file mode 100644 index e52d230a8..000000000 --- a/mise.toml +++ /dev/null @@ -1,286 +0,0 @@ -[tools] -node = "20" -rust = "1.85.1" -sccache = "latest" - -[env] -_.path = ['./node_modules/.bin'] -RUSTC_WRAPPER="sccache" - - -# ============================================================================ -# CORE SETUP AND CONFIGURATION TASKS -# ============================================================================ - -[tasks.config-yarn] -description = "Configure yarn version and settings" -run = [ - "corepack enable", - "corepack prepare yarn@4.5.3 --activate", - "yarn --version", - "yarn config set -H enableImmutableInstalls false" -] - -[tasks.install] -description = "Install dependencies" -depends = ["config-yarn"] -run = "yarn install" -sources = ['package.json', 'yarn.lock'] -outputs = ['node_modules'] - -[tasks.build-tauri-plugin-api] -description = "Build Tauri plugin API" -depends = ["install"] -run = "yarn build:tauri:plugin:api" -sources = ['src-tauri/plugins/**/*'] -outputs = [ - 'src-tauri/plugins/tauri-plugin-hardware/dist-js', - 'src-tauri/plugins/tauri-plugin-llamacpp/dist-js', -] - -[tasks.build-core] -description = "Build core package" -depends = ["build-tauri-plugin-api"] -run = "yarn build:core" -sources = ['core/**/*'] -outputs = ['core/dist'] - -[tasks.build-extensions] -description = "Build extensions" -depends = ["build-core"] -run = "yarn build:extensions && yarn build:extensions-web" -sources = ['extensions/**/*'] -outputs = ['pre-install/*.tgz'] - -[tasks.install-and-build] -description = "Install dependencies and build core and extensions (matches Makefile)" -depends = ["build-extensions"] - -# ============================================================================ -# DEVELOPMENT TASKS -# ============================================================================ - -[tasks.dev] -description = "Start development server (matches Makefile)" -depends = ["install-and-build"] -run = [ - "yarn download:bin", - "yarn dev" -] - -[tasks.dev-tauri] -description = "Start development server with Tauri (DEPRECATED - matches Makefile)" -depends = ["install-and-build"] -run = [ - "yarn download:bin", - "yarn dev:tauri" -] - -# ============================================================================ -# WEB APPLICATION DEVELOPMENT TASKS -# ============================================================================ - -[tasks.dev-web-app] -description = "Start web application development server (matches Makefile)" -depends = ["build-core"] -run = "yarn dev:web-app" - -[tasks.build-web-app] -description = "Build web application (matches Makefile)" -depends = ["build-core"] -run = "yarn build:web-app" - -[tasks.serve-web-app] -description = "Serve built web application" -run = "yarn serve:web-app" - -[tasks.build-serve-web-app] -description = "Build and serve web application (matches Makefile)" -depends = ["build-web-app"] -run = "yarn serve:web-app" - -# ============================================================================ -# BUILD TASKS -# ============================================================================ - -[tasks.install-rust-targets] -description = "Install required Rust targets for MacOS universal builds" -run = ''' -#!/usr/bin/env bash -# Check if we're on macOS -if [[ "$OSTYPE" == "darwin"* ]]; then - echo "Detected macOS, installing universal build targets..." - rustup target add x86_64-apple-darwin - rustup target add aarch64-apple-darwin - echo "Rust targets installed successfully!" -fi -''' - -[tasks.build] -description = "Build complete application (matches Makefile)" -depends = ["install-rust-targets", "install-and-build"] -run = [ - "yarn download:bin", - "yarn build" -] - -# ============================================================================ -# QUALITY ASSURANCE TASKS -# ============================================================================ - -[tasks.lint] -description = "Run linting (matches Makefile)" -depends = ["build-extensions"] -run = "yarn lint" - -# ============================================================================ -# RUST TEST COMPONENTS -# ============================================================================ - -[tasks.test-rust-main] -description = "Test main src-tauri package" -run = "cargo test --manifest-path src-tauri/Cargo.toml --no-default-features --features test-tauri -- --test-threads=1" - -[tasks.test-rust-hardware] -description = "Test hardware plugin" -run = "cargo test --manifest-path src-tauri/plugins/tauri-plugin-hardware/Cargo.toml" - -[tasks.test-rust-llamacpp] -description = "Test llamacpp plugin" -run = "cargo test --manifest-path src-tauri/plugins/tauri-plugin-llamacpp/Cargo.toml" - -[tasks.test-rust-utils] -description = "Test utils package" -run = "cargo test --manifest-path src-tauri/utils/Cargo.toml" - -[tasks.test-rust] -description = "Run all Rust tests" -depends = ["test-rust-main", "test-rust-hardware", "test-rust-llamacpp", "test-rust-utils"] - -# ============================================================================ -# JS TEST COMPONENTS -# ============================================================================ - -[tasks.test-js-setup] -description = "Setup for JS tests" -run = [ - "yarn download:bin", - "yarn download:lib", - "yarn copy:assets:tauri", - "yarn build:icon" -] - -[tasks.test-js] -description = "Run JS tests" -depends = ["test-js-setup"] -run = "yarn test" - -# ============================================================================ -# COMBINED TEST TASKS -# ============================================================================ - -[tasks.test] -description = "Run complete test suite (matches Makefile)" -depends = ["lint", "test-js", "test-rust"] - -# ============================================================================ -# PARALLEL-FRIENDLY QUALITY ASSURANCE TASKS -# ============================================================================ - -[tasks.lint-only] -description = "Run linting only (parallel-friendly)" -depends = ["build-extensions"] -run = "yarn lint" -hide = true - -[tasks.test-only] -description = "Run tests only (parallel-friendly)" -depends = ["build-extensions", "test-js", "test-rust"] -hide = true - -[tasks.qa-parallel] -description = "Run linting and testing in parallel" -depends = ["lint-only", "test-only"] - -# ============================================================================ -# UTILITY TASKS -# ============================================================================ - -[tasks.clean] -description = "Clean all build artifacts and dependencies (cross-platform - matches Makefile)" -run = ''' -#!/usr/bin/env bash -echo "Cleaning build artifacts and dependencies..." - -# Platform detection and cleanup (matches Makefile exactly) -if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "win32" ]]; then - # Windows cleanup using PowerShell (matches Makefile) - powershell -Command "Get-ChildItem -Path . -Include node_modules, .next, dist, build, out, .turbo, .yarn -Recurse -Directory | Remove-Item -Recurse -Force" 2>/dev/null || true - powershell -Command "Get-ChildItem -Path . -Include package-lock.json, tsconfig.tsbuildinfo -Recurse -File | Remove-Item -Recurse -Force" 2>/dev/null || true - powershell -Command "Remove-Item -Recurse -Force ./pre-install/*.tgz" 2>/dev/null || true - powershell -Command "Remove-Item -Recurse -Force ./extensions/*/*.tgz" 2>/dev/null || true - powershell -Command "Remove-Item -Recurse -Force ./electron/pre-install/*.tgz" 2>/dev/null || true - powershell -Command "Remove-Item -Recurse -Force ./src-tauri/resources" 2>/dev/null || true - powershell -Command "Remove-Item -Recurse -Force ./src-tauri/target" 2>/dev/null || true - powershell -Command "if (Test-Path \"\$(\$env:USERPROFILE)\\jan\\extensions\\\") { Remove-Item -Path \"\$(\$env:USERPROFILE)\\jan\\extensions\" -Recurse -Force }" 2>/dev/null || true -elif [[ "$OSTYPE" == "linux-gnu"* ]]; then - # Linux cleanup (matches Makefile) - find . -name "node_modules" -type d -prune -exec rm -rf '{}' + 2>/dev/null || true - find . -name ".next" -type d -exec rm -rf '{}' + 2>/dev/null || true - find . -name "dist" -type d -exec rm -rf '{}' + 2>/dev/null || true - find . -name "build" -type d -exec rm -rf '{}' + 2>/dev/null || true - find . -name "out" -type d -exec rm -rf '{}' + 2>/dev/null || true - find . -name ".turbo" -type d -exec rm -rf '{}' + 2>/dev/null || true - find . -name ".yarn" -type d -exec rm -rf '{}' + 2>/dev/null || true - find . -name "package-lock.json" -type f -exec rm -rf '{}' + 2>/dev/null || true - rm -rf ./pre-install/*.tgz 2>/dev/null || true - rm -rf ./extensions/*/*.tgz 2>/dev/null || true - rm -rf ./electron/pre-install/*.tgz 2>/dev/null || true - rm -rf ./src-tauri/resources 2>/dev/null || true - rm -rf ./src-tauri/target 2>/dev/null || true - rm -rf ~/jan/extensions 2>/dev/null || true - rm -rf "~/.cache/jan*" 2>/dev/null || true - rm -rf "./.cache" 2>/dev/null || true -else - # macOS cleanup (matches Makefile) - find . -name "node_modules" -type d -prune -exec rm -rf '{}' + 2>/dev/null || true - find . -name ".next" -type d -exec rm -rf '{}' + 2>/dev/null || true - find . -name "dist" -type d -exec rm -rf '{}' + 2>/dev/null || true - find . -name "build" -type d -exec rm -rf '{}' + 2>/dev/null || true - find . -name "out" -type d -exec rm -rf '{}' + 2>/dev/null || true - find . -name ".turbo" -type d -exec rm -rf '{}' + 2>/dev/null || true - find . -name ".yarn" -type d -exec rm -rf '{}' + 2>/dev/null || true - find . -name "package-lock.json" -type f -exec rm -rf '{}' + 2>/dev/null || true - rm -rf ./pre-install/*.tgz 2>/dev/null || true - rm -rf ./extensions/*/*.tgz 2>/dev/null || true - rm -rf ./electron/pre-install/*.tgz 2>/dev/null || true - rm -rf ./src-tauri/resources 2>/dev/null || true - rm -rf ./src-tauri/target 2>/dev/null || true - rm -rf ~/jan/extensions 2>/dev/null || true - rm -rf ~/Library/Caches/jan* 2>/dev/null || true -fi - -echo "Clean completed!" -''' - -[tasks.all] -description = "Default target - shows available commands (matches Makefile)" -run = "echo 'Specify a target to run. Use: mise tasks'" - -# ============================================================================ -# DEVELOPMENT WORKFLOW SHORTCUTS -# ============================================================================ - -[tasks.setup] -description = "Complete development setup" -depends = ["install-and-build"] -alias = "init" - -[tasks.ci] -description = "Run CI pipeline (lint + test sequentially)" -depends = ["test"] - -[tasks.ci-parallel] -description = "Run CI pipeline (lint + test in parallel)" -depends = ["qa-parallel"] -alias = "ci-fast" diff --git a/package.json b/package.json index 5efd4db37..d191e9f44 100644 --- a/package.json +++ b/package.json @@ -36,8 +36,8 @@ "download:lib": "node ./scripts/download-lib.mjs", "download:bin": "node ./scripts/download-bin.mjs", "download:windows-installer": "node ./scripts/download-win-installer-deps.mjs", - "build:tauri:win32": "yarn download:bin && yarn download:lib && yarn download:windows-installer && yarn tauri build", - "build:tauri:linux": "yarn download:bin && yarn download:lib && NO_STRIP=1 ./src-tauri/build-utils/shim-linuxdeploy.sh yarn tauri build && ./src-tauri/build-utils/buildAppImage.sh", + "build:tauri:win32": "yarn download:bin && yarn download:windows-installer && yarn tauri build", + "build:tauri:linux": "yarn download:bin && NO_STRIP=1 ./src-tauri/build-utils/shim-linuxdeploy.sh yarn tauri build && ./src-tauri/build-utils/buildAppImage.sh", "build:tauri:darwin": "yarn download:bin && yarn tauri build --target universal-apple-darwin", "build:tauri": "yarn build:icon && yarn copy:assets:tauri && run-script-os", "build:tauri:plugin:api": "cd src-tauri/plugins && yarn install && yarn workspaces foreach -Apt run build", diff --git a/scripts/download-bin.mjs b/scripts/download-bin.mjs index 36e17b3f0..39eb9ae87 100644 --- a/scripts/download-bin.mjs +++ b/scripts/download-bin.mjs @@ -1,4 +1,3 @@ -console.log('Script is running') // scripts/download.js import https from 'https' import fs, { copyFile, mkdirSync } from 'fs' @@ -69,7 +68,10 @@ function getPlatformArch() { arch === 'arm64' ? 'aarch64-apple-darwin' : 'x86_64-apple-darwin' } else if (platform === 'linux') { bunPlatform = arch === 'arm64' ? 'linux-aarch64' : 'linux-x64' - uvPlatform = arch === 'arm64' ? 'aarch64-unknown-linux-gnu' : 'x86_64-unknown-linux-gnu' + uvPlatform = + arch === 'arm64' + ? 'aarch64-unknown-linux-gnu' + : 'x86_64-unknown-linux-gnu' } else if (platform === 'win32') { bunPlatform = 'windows-x64' // Bun has limited Windows support uvPlatform = 'x86_64-pc-windows-msvc' @@ -81,6 +83,10 @@ function getPlatformArch() { } async function main() { + if (process.env.SKIP_BINARIES) { + console.log('Skipping binaries download.') + process.exit(0) + } console.log('Starting main function') const platform = os.platform() const { bunPlatform, uvPlatform } = getPlatformArch() @@ -124,29 +130,45 @@ async function main() { if (err) { console.log('Add execution permission failed!', err) } - }); + }) if (platform === 'darwin') { - copyFile(path.join(binDir, 'bun'), path.join(binDir, 'bun-x86_64-apple-darwin'), (err) => { - if (err) { - console.log("Error Found:", err); - } - }) - copyFile(path.join(binDir, 'bun'), path.join(binDir, 'bun-aarch64-apple-darwin'), (err) => { - if (err) { - console.log("Error Found:", err); - } - }) - copyFile(path.join(binDir, 'bun'), path.join(binDir, 'bun-universal-apple-darwin'), (err) => { + copyFile( + path.join(binDir, 'bun'), + path.join(binDir, 'bun-x86_64-apple-darwin'), + (err) => { if (err) { - console.log("Error Found:", err); + console.log('Error Found:', err) } - }) - } else if (platform === 'linux') { - copyFile(path.join(binDir, 'bun'), path.join(binDir, 'bun-x86_64-unknown-linux-gnu'), (err) => { - if (err) { - console.log("Error Found:", err); } - }) + ) + copyFile( + path.join(binDir, 'bun'), + path.join(binDir, 'bun-aarch64-apple-darwin'), + (err) => { + if (err) { + console.log('Error Found:', err) + } + } + ) + copyFile( + path.join(binDir, 'bun'), + path.join(binDir, 'bun-universal-apple-darwin'), + (err) => { + if (err) { + console.log('Error Found:', err) + } + } + ) + } else if (platform === 'linux') { + copyFile( + path.join(binDir, 'bun'), + path.join(binDir, 'bun-x86_64-unknown-linux-gnu'), + (err) => { + if (err) { + console.log('Error Found:', err) + } + } + ) } } catch (err) { // Expect EEXIST error @@ -157,11 +179,15 @@ async function main() { path.join(binDir) ) if (platform === 'win32') { - copyFile(path.join(binDir, 'bun.exe'), path.join(binDir, 'bun-x86_64-pc-windows-msvc.exe'), (err) => { - if (err) { - console.log("Error Found:", err); + copyFile( + path.join(binDir, 'bun.exe'), + path.join(binDir, 'bun-x86_64-pc-windows-msvc.exe'), + (err) => { + if (err) { + console.log('Error Found:', err) + } } - }) + ) } } catch (err) { // Expect EEXIST error @@ -176,52 +202,66 @@ async function main() { await decompress(uvPath, tempBinDir) } try { - copySync( - path.join(tempBinDir, `uv-${uvPlatform}`, 'uv'), - path.join(binDir) - ) + copySync(path.join(tempBinDir, `uv-${uvPlatform}`, 'uv'), path.join(binDir)) fs.chmod(path.join(binDir, 'uv'), 0o755, (err) => { if (err) { console.log('Add execution permission failed!', err) } - }); + }) if (platform === 'darwin') { - copyFile(path.join(binDir, 'uv'), path.join(binDir, 'uv-x86_64-apple-darwin'), (err) => { - if (err) { - console.log("Error Found:", err); + copyFile( + path.join(binDir, 'uv'), + path.join(binDir, 'uv-x86_64-apple-darwin'), + (err) => { + if (err) { + console.log('Error Found:', err) + } } - }) - copyFile(path.join(binDir, 'uv'), path.join(binDir, 'uv-aarch64-apple-darwin'), (err) => { - if (err) { - console.log("Error Found:", err); + ) + copyFile( + path.join(binDir, 'uv'), + path.join(binDir, 'uv-aarch64-apple-darwin'), + (err) => { + if (err) { + console.log('Error Found:', err) + } } - }) - copyFile(path.join(binDir, 'uv'), path.join(binDir, 'uv-universal-apple-darwin'), (err) => { - if (err) { - console.log("Error Found:", err); + ) + copyFile( + path.join(binDir, 'uv'), + path.join(binDir, 'uv-universal-apple-darwin'), + (err) => { + if (err) { + console.log('Error Found:', err) + } } - }) + ) } else if (platform === 'linux') { - copyFile(path.join(binDir, 'uv'), path.join(binDir, 'uv-x86_64-unknown-linux-gnu'), (err) => { - if (err) { - console.log("Error Found:", err); + copyFile( + path.join(binDir, 'uv'), + path.join(binDir, 'uv-x86_64-unknown-linux-gnu'), + (err) => { + if (err) { + console.log('Error Found:', err) + } } - }) + ) } } catch (err) { // Expect EEXIST error } try { - copySync( - path.join(tempBinDir, 'uv.exe'), - path.join(binDir) - ) + copySync(path.join(tempBinDir, 'uv.exe'), path.join(binDir)) if (platform === 'win32') { - copyFile(path.join(binDir, 'uv.exe'), path.join(binDir, 'uv-x86_64-pc-windows-msvc.exe'), (err) => { - if (err) { - console.log("Error Found:", err); + copyFile( + path.join(binDir, 'uv.exe'), + path.join(binDir, 'uv-x86_64-pc-windows-msvc.exe'), + (err) => { + if (err) { + console.log('Error Found:', err) + } } - }) + ) } } catch (err) { // Expect EEXIST error diff --git a/scripts/download-lib.mjs b/scripts/download-lib.mjs deleted file mode 100644 index d2086b36e..000000000 --- a/scripts/download-lib.mjs +++ /dev/null @@ -1,86 +0,0 @@ -console.log('Script is running') -// scripts/download-lib.mjs -import https from 'https' -import fs, { mkdirSync } from 'fs' -import os from 'os' -import path from 'path' -import { copySync } from 'cpx' - -function download(url, dest) { - return new Promise((resolve, reject) => { - console.log(`Downloading ${url} to ${dest}`) - const file = fs.createWriteStream(dest) - https - .get(url, (response) => { - console.log(`Response status code: ${response.statusCode}`) - if ( - response.statusCode >= 300 && - response.statusCode < 400 && - response.headers.location - ) { - // Handle redirect - const redirectURL = response.headers.location - console.log(`Redirecting to ${redirectURL}`) - download(redirectURL, dest).then(resolve, reject) // Recursive call - return - } else if (response.statusCode !== 200) { - reject(`Failed to get '${url}' (${response.statusCode})`) - return - } - response.pipe(file) - file.on('finish', () => { - file.close(resolve) - }) - }) - .on('error', (err) => { - fs.unlink(dest, () => reject(err.message)) - }) - }) -} - -async function main() { - console.log('Starting main function') - const platform = os.platform() // 'darwin', 'linux', 'win32' - const arch = os.arch() // 'x64', 'arm64', etc. - - if (arch != 'x64') return - - let filename - if (platform == 'linux') - filename = 'libvulkan.so' - else if (platform == 'win32') - filename = 'vulkan-1.dll' - else - return - - const url = `https://catalog.jan.ai/${filename}` - - const libDir = 'src-tauri/resources/lib' - const tempDir = 'scripts/dist' - - try { - mkdirSync('scripts/dist') - } catch (err) { - // Expect EEXIST error if the directory already exists - } - - console.log(`Downloading libvulkan...`) - const savePath = path.join(tempDir, filename) - if (!fs.existsSync(savePath)) { - await download(url, savePath) - } - - // copy to tauri resources - try { - copySync(savePath, libDir) - } catch (err) { - // Expect EEXIST error - } - - console.log('Downloads completed.') -} - -main().catch((err) => { - console.error('Error:', err) - process.exit(1) -}) diff --git a/src-tauri/plugins/tauri-plugin-hardware/Cargo.toml b/src-tauri/plugins/tauri-plugin-hardware/Cargo.toml index eb74d32d1..7475fb353 100644 --- a/src-tauri/plugins/tauri-plugin-hardware/Cargo.toml +++ b/src-tauri/plugins/tauri-plugin-hardware/Cargo.toml @@ -11,7 +11,7 @@ exclude = ["/examples", "/dist-js", "/guest-js", "/node_modules"] links = "tauri-plugin-hardware" [dependencies] -ash = "0.38.0" +vulkano = "0.34" libc = "0.2" log = "0.4" nvml-wrapper = "0.10.0" diff --git a/src-tauri/plugins/tauri-plugin-hardware/src/commands.rs b/src-tauri/plugins/tauri-plugin-hardware/src/commands.rs index 56e78f1c1..ac13eb7f2 100644 --- a/src-tauri/plugins/tauri-plugin-hardware/src/commands.rs +++ b/src-tauri/plugins/tauri-plugin-hardware/src/commands.rs @@ -1,14 +1,12 @@ use crate::{ - helpers::get_jan_libvulkan_path, types::{CpuStaticInfo, SystemInfo, SystemUsage}, vendor::{nvidia, vulkan}, SYSTEM_INFO, }; use sysinfo::System; -use tauri::Runtime; #[tauri::command] -pub fn get_system_info(app: tauri::AppHandle) -> SystemInfo { +pub fn get_system_info() -> SystemInfo { SYSTEM_INFO .get_or_init(|| { let mut system = System::new(); @@ -19,15 +17,7 @@ pub fn get_system_info(app: tauri::AppHandle) -> SystemInfo { gpu_map.insert(gpu.uuid.clone(), gpu); } - // try system vulkan first - let paths = vec!["".to_string(), get_jan_libvulkan_path(app.clone())]; - let mut vulkan_gpus = vec![]; - for path in paths { - vulkan_gpus = vulkan::get_vulkan_gpus(&path); - if !vulkan_gpus.is_empty() { - break; - } - } + let vulkan_gpus = vulkan::get_vulkan_gpus(); for gpu in vulkan_gpus { match gpu_map.get_mut(&gpu.uuid) { @@ -64,7 +54,7 @@ pub fn get_system_info(app: tauri::AppHandle) -> SystemInfo { } #[tauri::command] -pub fn get_system_usage(app: tauri::AppHandle) -> SystemUsage { +pub fn get_system_usage() -> SystemUsage { let mut system = System::new(); system.refresh_memory(); @@ -81,7 +71,7 @@ pub fn get_system_usage(app: tauri::AppHandle) -> SystemUsage { cpu: cpu_usage, used_memory: system.used_memory() / 1024 / 1024, // bytes to MiB, total_memory: system.total_memory() / 1024 / 1024, // bytes to MiB, - gpus: get_system_info(app.clone()) + gpus: get_system_info() .gpus .iter() .map(|gpu| gpu.get_usage()) diff --git a/src-tauri/plugins/tauri-plugin-hardware/src/helpers.rs b/src-tauri/plugins/tauri-plugin-hardware/src/helpers.rs deleted file mode 100644 index 22bcc8669..000000000 --- a/src-tauri/plugins/tauri-plugin-hardware/src/helpers.rs +++ /dev/null @@ -1,20 +0,0 @@ -use tauri::{path::BaseDirectory, Manager, Runtime}; - -pub fn get_jan_libvulkan_path(app: tauri::AppHandle) -> String { - let lib_name = if cfg!(target_os = "windows") { - "vulkan-1.dll" - } else if cfg!(target_os = "linux") { - "libvulkan.so" - } else { - return "".to_string(); - }; - - // NOTE: this does not work in test mode (mock app) - match app.path().resolve( - format!("resources/lib/{}", lib_name), - BaseDirectory::Resource, - ) { - Ok(lib_path) => lib_path.to_string_lossy().to_string(), - Err(_) => "".to_string(), - } -} diff --git a/src-tauri/plugins/tauri-plugin-hardware/src/lib.rs b/src-tauri/plugins/tauri-plugin-hardware/src/lib.rs index 228a3731e..3a069892e 100644 --- a/src-tauri/plugins/tauri-plugin-hardware/src/lib.rs +++ b/src-tauri/plugins/tauri-plugin-hardware/src/lib.rs @@ -2,12 +2,10 @@ mod commands; mod constants; pub mod cpu; pub mod gpu; -mod helpers; mod types; pub mod vendor; pub use constants::*; -pub use helpers::*; pub use types::*; use std::sync::OnceLock; diff --git a/src-tauri/plugins/tauri-plugin-hardware/src/tests.rs b/src-tauri/plugins/tauri-plugin-hardware/src/tests.rs index 1d4975104..f27554579 100644 --- a/src-tauri/plugins/tauri-plugin-hardware/src/tests.rs +++ b/src-tauri/plugins/tauri-plugin-hardware/src/tests.rs @@ -4,15 +4,13 @@ use tauri::test::mock_app; #[test] fn test_system_info() { - let app = mock_app(); - let info = get_system_info(app.handle().clone()); + let info = get_system_info(); println!("System Static Info: {:?}", info); } #[test] fn test_system_usage() { - let app = mock_app(); - let usage = get_system_usage(app.handle().clone()); + let usage = get_system_usage(); println!("System Usage Info: {:?}", usage); } @@ -23,23 +21,23 @@ mod cpu_tests { #[test] fn test_cpu_static_info_new() { let cpu_info = CpuStaticInfo::new(); - + // Test that all fields are populated assert!(!cpu_info.name.is_empty()); assert_ne!(cpu_info.name, "unknown"); // Should have detected a CPU name assert!(cpu_info.core_count > 0); assert!(!cpu_info.arch.is_empty()); - + // Architecture should be one of the expected values assert!( - cpu_info.arch == "aarch64" || - cpu_info.arch == "arm64" || - cpu_info.arch == "x86_64" || - cpu_info.arch == std::env::consts::ARCH + cpu_info.arch == "aarch64" + || cpu_info.arch == "arm64" + || cpu_info.arch == "x86_64" + || cpu_info.arch == std::env::consts::ARCH ); - + // Extensions should be a valid list (can be empty on non-x86) - + println!("CPU Info: {:?}", cpu_info); } @@ -48,7 +46,7 @@ mod cpu_tests { // Test that multiple calls return consistent information let info1 = CpuStaticInfo::new(); let info2 = CpuStaticInfo::new(); - + assert_eq!(info1.name, info2.name); assert_eq!(info1.core_count, info2.core_count); assert_eq!(info1.arch, info2.arch); @@ -72,19 +70,41 @@ mod cpu_tests { #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] fn test_x86_extensions() { let cpu_info = CpuStaticInfo::new(); - + // On x86/x86_64, we should always have at least FPU assert!(cpu_info.extensions.contains(&"fpu".to_string())); - + // Check that all extensions are valid x86 feature names let valid_extensions = [ - "fpu", "mmx", "sse", "sse2", "sse3", "ssse3", "sse4_1", "sse4_2", - "pclmulqdq", "avx", "avx2", "avx512_f", "avx512_dq", "avx512_ifma", - "avx512_pf", "avx512_er", "avx512_cd", "avx512_bw", "avx512_vl", - "avx512_vbmi", "avx512_vbmi2", "avx512_vnni", "avx512_bitalg", - "avx512_vpopcntdq", "avx512_vp2intersect", "aes", "f16c" + "fpu", + "mmx", + "sse", + "sse2", + "sse3", + "ssse3", + "sse4_1", + "sse4_2", + "pclmulqdq", + "avx", + "avx2", + "avx512_f", + "avx512_dq", + "avx512_ifma", + "avx512_pf", + "avx512_er", + "avx512_cd", + "avx512_bw", + "avx512_vl", + "avx512_vbmi", + "avx512_vbmi2", + "avx512_vnni", + "avx512_bitalg", + "avx512_vpopcntdq", + "avx512_vp2intersect", + "aes", + "f16c", ]; - + for ext in &cpu_info.extensions { assert!( valid_extensions.contains(&ext.as_str()), @@ -98,7 +118,7 @@ mod cpu_tests { #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] fn test_non_x86_extensions() { let cpu_info = CpuStaticInfo::new(); - + // On non-x86 architectures, extensions should be empty assert!(cpu_info.extensions.is_empty()); } @@ -106,15 +126,15 @@ mod cpu_tests { #[test] fn test_arch_detection() { let cpu_info = CpuStaticInfo::new(); - + // Architecture should be a valid string assert!(!cpu_info.arch.is_empty()); - + // Should be one of the common architectures let common_archs = ["x86_64", "aarch64", "arm", "arm64", "x86"]; let is_common_arch = common_archs.iter().any(|&arch| cpu_info.arch == arch); let is_compile_time_arch = cpu_info.arch == std::env::consts::ARCH; - + assert!( is_common_arch || is_compile_time_arch, "Unexpected architecture: {}", @@ -125,11 +145,11 @@ mod cpu_tests { #[test] fn test_cpu_info_serialization() { let cpu_info = CpuStaticInfo::new(); - + // Test that the struct can be serialized (since it derives Serialize) let serialized = serde_json::to_string(&cpu_info); assert!(serialized.is_ok()); - + let json_str = serialized.unwrap(); assert!(json_str.contains("name")); assert!(json_str.contains("core_count")); diff --git a/src-tauri/plugins/tauri-plugin-hardware/src/vendor/tests.rs b/src-tauri/plugins/tauri-plugin-hardware/src/vendor/tests.rs index 0a641c089..d6213840b 100644 --- a/src-tauri/plugins/tauri-plugin-hardware/src/vendor/tests.rs +++ b/src-tauri/plugins/tauri-plugin-hardware/src/vendor/tests.rs @@ -12,7 +12,7 @@ fn test_get_nvidia_gpus() { #[test] fn test_get_vulkan_gpus() { - let gpus = vulkan::get_vulkan_gpus(""); + let gpus = vulkan::get_vulkan_gpus(); for (i, gpu) in gpus.iter().enumerate() { println!("GPU {}:", i); println!(" {:?}", gpu); diff --git a/src-tauri/plugins/tauri-plugin-llamacpp/src/gguf/commands.rs b/src-tauri/plugins/tauri-plugin-llamacpp/src/gguf/commands.rs index c636fa8bd..03e949eba 100644 --- a/src-tauri/plugins/tauri-plugin-llamacpp/src/gguf/commands.rs +++ b/src-tauri/plugins/tauri-plugin-llamacpp/src/gguf/commands.rs @@ -3,7 +3,6 @@ use super::utils::{estimate_kv_cache_internal, read_gguf_metadata_internal}; use crate::gguf::types::{KVCacheError, KVCacheEstimate, ModelSupportStatus}; use std::collections::HashMap; use std::fs; -use tauri::Runtime; use tauri_plugin_hardware::get_system_info; /// Read GGUF metadata from a model file #[tauri::command] @@ -49,16 +48,15 @@ pub async fn get_model_size(path: String) -> Result { } #[tauri::command] -pub async fn is_model_supported( +pub async fn is_model_supported( path: String, ctx_size: Option, - app_handle: tauri::AppHandle, ) -> Result { // Get model size let model_size = get_model_size(path.clone()).await?; // Get system info - let system_info = get_system_info(app_handle.clone()); + let system_info = get_system_info(); log::info!("modelSize: {}", model_size); diff --git a/src-tauri/plugins/tauri-plugin-llamacpp/src/gguf/model_planner.rs b/src-tauri/plugins/tauri-plugin-llamacpp/src/gguf/model_planner.rs index 118894871..14642af60 100644 --- a/src-tauri/plugins/tauri-plugin-llamacpp/src/gguf/model_planner.rs +++ b/src-tauri/plugins/tauri-plugin-llamacpp/src/gguf/model_planner.rs @@ -3,7 +3,6 @@ use crate::gguf::utils::estimate_kv_cache_internal; use crate::gguf::utils::read_gguf_metadata_internal; use serde::{Deserialize, Serialize}; use std::collections::HashMap; -use tauri::Runtime; use tauri_plugin_hardware::get_system_info; #[derive(Serialize, Deserialize, Clone, Debug)] @@ -27,15 +26,14 @@ pub enum ModelMode { } #[tauri::command] -pub async fn plan_model_load( +pub async fn plan_model_load( path: String, memory_mode: String, mmproj_path: Option, requested_ctx: Option, - app: tauri::AppHandle, ) -> Result { let model_size = get_model_size(path.clone()).await?; - let sys_info = get_system_info(app.clone()); + let sys_info = get_system_info(); let gguf = read_gguf_metadata_internal(path.clone()).await?; let mut mmproj_size: u64 = 0; diff --git a/src-tauri/src/core/downloads/helpers.rs b/src-tauri/src/core/downloads/helpers.rs index ab6979575..d3d8f6b7c 100644 --- a/src-tauri/src/core/downloads/helpers.rs +++ b/src-tauri/src/core/downloads/helpers.rs @@ -465,7 +465,11 @@ async fn download_single_file( .await .map_err(err_to_string)?; - log::info!("Started downloading: {}", item.url); + // Decode URL for better readability in logs + let decoded_url = url::Url::parse(&item.url) + .map(|u| u.to_string()) + .unwrap_or_else(|_| item.url.clone()); + log::info!("Started downloading: {}", decoded_url); let client = _get_client_for_item(item, &header_map).map_err(err_to_string)?; let mut download_delta = 0u64; let mut initial_progress = 0u64; @@ -584,7 +588,11 @@ async fn download_single_file( .await .map_err(err_to_string)?; - log::info!("Finished downloading: {}", item.url); + // Decode URL for better readability in logs + let decoded_url = url::Url::parse(&item.url) + .map(|u| u.to_string()) + .unwrap_or_else(|_| item.url.clone()); + log::info!("Finished downloading: {}", decoded_url); Ok(save_path.to_path_buf()) } diff --git a/src-tauri/src/core/filesystem/commands.rs b/src-tauri/src/core/filesystem/commands.rs index 389b3d1c9..fe44052b8 100644 --- a/src-tauri/src/core/filesystem/commands.rs +++ b/src-tauri/src/core/filesystem/commands.rs @@ -33,6 +33,22 @@ pub fn mkdir(app_handle: tauri::AppHandle, args: Vec) -> fs::create_dir_all(&path).map_err(|e| e.to_string()) } +#[tauri::command] +pub fn mv(app_handle: tauri::AppHandle, args: Vec) -> Result<(), String> { + if args.len() < 2 || args[0].is_empty() || args[1].is_empty() { + return Err("mv error: Invalid argument - source and destination required".to_string()); + } + + let source = resolve_path(app_handle.clone(), &args[0]); + let destination = resolve_path(app_handle, &args[1]); + + if !source.exists() { + return Err("mv error: Source path does not exist".to_string()); + } + + fs::rename(&source, &destination).map_err(|e| e.to_string()) +} + #[tauri::command] pub fn join_path( app_handle: tauri::AppHandle, diff --git a/src-tauri/src/core/mcp/helpers.rs b/src-tauri/src/core/mcp/helpers.rs index 80a8b5f86..7f8565e39 100644 --- a/src-tauri/src/core/mcp/helpers.rs +++ b/src-tauri/src/core/mcp/helpers.rs @@ -25,7 +25,7 @@ use crate::core::{ mcp::models::McpServerConfig, state::{AppState, RunningServiceEnum, SharedMcpServers}, }; -use jan_utils::can_override_npx; +use jan_utils::{can_override_npx, can_override_uvx}; /// Calculate exponential backoff delay with jitter /// @@ -627,19 +627,20 @@ async fn schedule_mcp_start_task( } } else { let mut cmd = Command::new(config_params.command.clone()); - if config_params.command.clone() == "npx" && can_override_npx() { + let bun_x_path = format!("{}/bun", bin_path.display()); + if config_params.command.clone() == "npx" && can_override_npx(bun_x_path.clone()) { let mut cache_dir = app_path.clone(); cache_dir.push(".npx"); - let bun_x_path = format!("{}/bun", bin_path.display()); cmd = Command::new(bun_x_path); cmd.arg("x"); cmd.env("BUN_INSTALL", cache_dir.to_str().unwrap().to_string()); } - if config_params.command.clone() == "uvx" { + + let uv_path = format!("{}/uv", bin_path.display()); + if config_params.command.clone() == "uvx" && can_override_uvx(uv_path.clone()) { let mut cache_dir = app_path.clone(); cache_dir.push(".uvx"); - let bun_x_path = format!("{}/uv", bin_path.display()); - cmd = Command::new(bun_x_path); + cmd = Command::new(uv_path); cmd.arg("tool"); cmd.arg("run"); cmd.env("UV_CACHE_DIR", cache_dir.to_str().unwrap().to_string()); diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 169ee5b19..d7ff7693c 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -51,6 +51,7 @@ pub fn run() { core::filesystem::commands::readdir_sync, core::filesystem::commands::read_file_sync, core::filesystem::commands::rm, + core::filesystem::commands::mv, core::filesystem::commands::file_stat, core::filesystem::commands::write_file_sync, core::filesystem::commands::write_yaml, @@ -141,8 +142,7 @@ pub fn run() { #[cfg(all(feature = "deep-link", any(windows, target_os = "linux")))] { use tauri_plugin_deep_link::DeepLinkExt; - // Register the deep-link scheme programmatically - app.deep_link().register("jan")?; + app.deep_link().register_all()?; } setup_mcp(app); Ok(()) diff --git a/src-tauri/tauri.linux.conf.json b/src-tauri/tauri.linux.conf.json index 552217384..55c11b1f8 100644 --- a/src-tauri/tauri.linux.conf.json +++ b/src-tauri/tauri.linux.conf.json @@ -10,13 +10,11 @@ "linux": { "appimage": { "bundleMediaFramework": false, - "files": { - } + "files": {} }, "deb": { "files": { - "usr/bin/bun": "resources/bin/bun", - "usr/lib/Jan/resources/lib/libvulkan.so": "resources/lib/libvulkan.so" + "usr/bin/bun": "resources/bin/bun" } } } diff --git a/src-tauri/tauri.windows.conf.json b/src-tauri/tauri.windows.conf.json index 1030563ee..a1438c385 100644 --- a/src-tauri/tauri.windows.conf.json +++ b/src-tauri/tauri.windows.conf.json @@ -7,7 +7,11 @@ "bundle": { "targets": ["nsis"], - "resources": ["resources/pre-install/**/*", "resources/lib/vulkan-1.dll", "resources/lib/vc_redist.x64.exe", "resources/LICENSE"], + "resources": [ + "resources/pre-install/**/*", + "resources/lib/vc_redist.x64.exe", + "resources/LICENSE" + ], "externalBin": ["resources/bin/bun", "resources/bin/uv"], "windows": { "nsis": { diff --git a/src-tauri/utils/src/system.rs b/src-tauri/utils/src/system.rs index d4ebc79af..cf281b3cb 100644 --- a/src-tauri/utils/src/system.rs +++ b/src-tauri/utils/src/system.rs @@ -1,5 +1,5 @@ -/// Checks AVX2 CPU support for npx override with bun binary -pub fn can_override_npx() -> bool { +/// Checks if npx can be overridden with bun binary +pub fn can_override_npx(bun_path: String) -> bool { // We need to check the CPU for the AVX2 instruction support if we are running under MacOS // with Intel CPU. We can override `npx` command with `bun` only if CPU is // supporting AVX2, otherwise we need to use default `npx` binary @@ -13,10 +13,31 @@ pub fn can_override_npx() -> bool { return false; // we cannot override npx with bun binary } } - + // Check if bun_path exists + if !std::path::Path::new(bun_path.as_str()).exists() { + #[cfg(feature = "logging")] + log::warn!( + "bun binary not found at '{}', default npx binary will be used", + bun_path + ); + return false; + } true // by default, we can override npx with bun binary } +/// Checks if uv_path exists and determines if uvx can be overridden with the uv binary +pub fn can_override_uvx(uv_path: String) -> bool { + if !std::path::Path::new(uv_path.as_str()).exists() { + #[cfg(feature = "logging")] + log::warn!( + "uv binary not found at '{}', default uvx binary will be used", + uv_path + ); + return false; + } + true // by default, we can override uvx with uv binary +} + /// Setup library paths for different operating systems pub fn setup_library_path(library_path: Option<&str>, command: &mut tokio::process::Command) { if let Some(lib_path) = library_path { diff --git a/web-app/package.json b/web-app/package.json index 79d5e7134..da7849f87 100644 --- a/web-app/package.json +++ b/web-app/package.json @@ -18,112 +18,112 @@ "build:serve:web": "yarn build:web && yarn serve:web" }, "dependencies": { - "@dnd-kit/core": "^6.3.1", - "@dnd-kit/modifiers": "^9.0.0", - "@dnd-kit/sortable": "^10.0.0", + "@dnd-kit/core": "6.3.1", + "@dnd-kit/modifiers": "9.0.0", + "@dnd-kit/sortable": "10.0.0", "@jan/extensions-web": "link:../extensions-web", "@janhq/core": "link:../core", - "@radix-ui/react-accordion": "^1.2.10", - "@radix-ui/react-avatar": "^1.1.10", - "@radix-ui/react-dialog": "^1.1.14", - "@radix-ui/react-dropdown-menu": "^2.1.15", - "@radix-ui/react-hover-card": "^1.1.14", - "@radix-ui/react-popover": "^1.1.13", - "@radix-ui/react-progress": "^1.1.4", - "@radix-ui/react-radio-group": "^1.3.7", - "@radix-ui/react-slider": "^1.3.2", - "@radix-ui/react-slot": "^1.2.0", - "@radix-ui/react-switch": "^1.2.2", - "@radix-ui/react-tooltip": "^1.2.4", - "@tabler/icons-react": "^3.33.0", - "@tailwindcss/vite": "^4.1.4", - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.121.34", - "@tanstack/react-virtual": "^3.13.12", - "@tauri-apps/api": "^2.8.0", + "@radix-ui/react-accordion": "1.2.11", + "@radix-ui/react-avatar": "1.1.10", + "@radix-ui/react-dialog": "1.1.15", + "@radix-ui/react-dropdown-menu": "2.1.16", + "@radix-ui/react-hover-card": "1.1.14", + "@radix-ui/react-popover": "1.1.14", + "@radix-ui/react-progress": "1.1.4", + "@radix-ui/react-radio-group": "1.3.8", + "@radix-ui/react-slider": "1.3.2", + "@radix-ui/react-slot": "1.2.0", + "@radix-ui/react-switch": "1.2.2", + "@radix-ui/react-tooltip": "1.2.4", + "@tabler/icons-react": "3.34.0", + "@tailwindcss/vite": "4.1.4", + "@tanstack/react-router": "1.117.0", + "@tanstack/react-router-devtools": "1.121.34", + "@tanstack/react-virtual": "3.13.12", + "@tauri-apps/api": "2.8.0", "@tauri-apps/plugin-deep-link": "2.4.3", - "@tauri-apps/plugin-dialog": "^2.2.1", - "@tauri-apps/plugin-http": "^2.2.1", - "@tauri-apps/plugin-opener": "^2.2.7", - "@tauri-apps/plugin-os": "^2.2.1", - "@tauri-apps/plugin-updater": "^2.7.1", - "@types/react-syntax-highlighter": "^15.5.13", - "@types/uuid": "^10.0.0", - "@uiw/react-textarea-code-editor": "^3.1.1", - "class-variance-authority": "^0.7.1", - "culori": "^4.0.1", - "emoji-picker-react": "^4.12.2", - "framer-motion": "^12.23.12", - "fuse.js": "^7.1.0", - "fzf": "^0.5.2", - "i18next": "^25.0.1", - "katex": "^0.16.22", - "lodash.clonedeep": "^4.5.0", - "lodash.debounce": "^4.0.8", - "lucide-react": "^0.536.0", - "motion": "^12.10.5", - "next-themes": "^0.4.6", - "posthog-js": "^1.246.0", - "react": "^19.0.0", - "react-colorful": "^5.6.1", - "react-dom": "^19.0.0", - "react-i18next": "^15.5.1", - "react-joyride": "^2.9.3", - "react-markdown": "^10.1.0", - "react-resizable-panels": "^3.0.3", - "react-syntax-highlighter": "^15.6.1", - "react-syntax-highlighter-virtualized-renderer": "^1.1.0", - "react-textarea-autosize": "^8.5.9", - "rehype-katex": "^7.0.1", - "rehype-raw": "^7.0.0", - "remark-breaks": "^4.0.0", - "remark-emoji": "^5.0.1", - "remark-gfm": "^4.0.1", - "remark-math": "^6.0.0", - "sonner": "^2.0.3", - "tailwindcss": "^4.1.4", + "@tauri-apps/plugin-dialog": "2.2.2", + "@tauri-apps/plugin-http": "2.5.0", + "@tauri-apps/plugin-opener": "2.3.0", + "@tauri-apps/plugin-os": "2.2.1", + "@tauri-apps/plugin-updater": "2.8.1", + "@types/react-syntax-highlighter": "15.5.13", + "@types/uuid": "10.0.0", + "@uiw/react-textarea-code-editor": "3.1.1", + "class-variance-authority": "0.7.1", + "culori": "4.0.1", + "emoji-picker-react": "4.12.2", + "framer-motion": "12.23.12", + "fuse.js": "7.1.0", + "fzf": "0.5.2", + "i18next": "25.0.2", + "katex": "0.16.22", + "lodash.clonedeep": "4.5.0", + "lodash.debounce": "4.0.8", + "lucide-react": "0.536.0", + "motion": "12.18.1", + "next-themes": "0.4.6", + "posthog-js": "1.255.1", + "react": "19.0.0", + "react-colorful": "5.6.1", + "react-dom": "19.0.0", + "react-i18next": "15.5.1", + "react-joyride": "2.9.3", + "react-markdown": "10.1.0", + "react-resizable-panels": "3.0.5", + "react-syntax-highlighter": "15.6.1", + "react-syntax-highlighter-virtualized-renderer": "1.1.0", + "react-textarea-autosize": "8.5.9", + "rehype-katex": "7.0.1", + "rehype-raw": "7.0.0", + "remark-breaks": "4.0.0", + "remark-emoji": "5.0.1", + "remark-gfm": "4.0.1", + "remark-math": "6.0.0", + "sonner": "2.0.5", + "tailwindcss": "4.1.4", "token.js": "npm:token.js-fork@0.7.27", - "tw-animate-css": "^1.2.7", - "ulidx": "^2.4.1", - "unified": "^11.0.5", - "uuid": "^11.1.0", - "vaul": "^1.1.2", - "zustand": "^5.0.3" + "tw-animate-css": "1.2.8", + "ulidx": "2.4.1", + "unified": "11.0.5", + "uuid": "11.1.0", + "vaul": "1.1.2", + "zustand": "5.0.3" }, "devDependencies": { - "@eslint/js": "^9.22.0", - "@tanstack/router-plugin": "^1.116.1", - "@testing-library/dom": "^10.4.0", - "@testing-library/jest-dom": "^6.6.3", - "@testing-library/react": "^16.3.0", - "@testing-library/user-event": "^14.6.1", - "@types/culori": "^2.1.1", - "@types/istanbul-lib-report": "^3", - "@types/istanbul-reports": "^3", - "@types/lodash.clonedeep": "^4", - "@types/lodash.debounce": "^4", - "@types/node": "^22.14.1", - "@types/react": "^19.0.10", - "@types/react-dom": "^19.0.4", - "@vitejs/plugin-react": "^4.3.4", + "@eslint/js": "8.57.0", + "@tanstack/router-plugin": "1.117.0", + "@testing-library/dom": "10.4.1", + "@testing-library/jest-dom": "6.8.0", + "@testing-library/react": "16.3.0", + "@testing-library/user-event": "14.6.1", + "@types/culori": "2.1.1", + "@types/istanbul-lib-report": "3.0.3", + "@types/istanbul-reports": "3.0.4", + "@types/lodash.clonedeep": "4.5.9", + "@types/lodash.debounce": "4.0.9", + "@types/node": "22.14.1", + "@types/react": "19.1.2", + "@types/react-dom": "19.1.2", + "@vitejs/plugin-react": "4.4.1", "@vitest/coverage-v8": "3.2.4", - "clsx": "^2.1.1", - "eslint": "^9.22.0", - "eslint-plugin-react-hooks": "^5.2.0", - "eslint-plugin-react-refresh": "^0.4.19", - "globals": "^16.0.0", - "istanbul-api": "^3.0.0", - "istanbul-lib-coverage": "^3.2.2", - "istanbul-lib-report": "^3.0.1", - "istanbul-reports": "^3.1.7", - "jsdom": "^26.1.0", - "serve": "^14.2.4", - "tailwind-merge": "^3.3.1", - "typescript": "~5.8.3", - "typescript-eslint": "^8.26.1", - "vite": "^6.3.0", - "vite-plugin-node-polyfills": "^0.23.0", - "vite-plugin-pwa": "^1.0.3", - "vitest": "^3.1.3" + "clsx": "2.1.1", + "eslint": "9.25.1", + "eslint-plugin-react-hooks": "5.2.0", + "eslint-plugin-react-refresh": "0.4.20", + "globals": "16.0.0", + "istanbul-api": "3.0.0", + "istanbul-lib-coverage": "2.0.5", + "istanbul-lib-report": "2.0.8", + "istanbul-reports": "3.1.7", + "jsdom": "26.1.0", + "serve": "14.2.5", + "tailwind-merge": "3.3.1", + "typescript": "5.9.2", + "typescript-eslint": "8.31.0", + "vite": "6.3.2", + "vite-plugin-node-polyfills": "0.23.0", + "vite-plugin-pwa": "1.0.3", + "vitest": "3.2.4" } } diff --git a/web-app/src/containers/DropdownModelProvider.tsx b/web-app/src/containers/DropdownModelProvider.tsx index 8f9ea35a8..a8614f89d 100644 --- a/web-app/src/containers/DropdownModelProvider.tsx +++ b/web-app/src/containers/DropdownModelProvider.tsx @@ -6,7 +6,7 @@ import { PopoverTrigger, } from '@/components/ui/popover' import { useModelProvider } from '@/hooks/useModelProvider' -import { cn, getProviderTitle } from '@/lib/utils' +import { cn, getProviderTitle, getModelDisplayName } from '@/lib/utils' import { highlightFzfMatch } from '@/utils/highlight' import Capabilities from './Capabilities' import { IconSettings, IconX } from '@tabler/icons-react' @@ -240,7 +240,7 @@ const DropdownModelProvider = ({ // Update display model when selection changes useEffect(() => { if (selectedProvider && selectedModel) { - setDisplayModel(selectedModel.id) + setDisplayModel(getModelDisplayName(selectedModel)) } else { setDisplayModel(t('common:selectAModel')) } @@ -326,7 +326,7 @@ const DropdownModelProvider = ({ // Create Fzf instance for fuzzy search const fzfInstance = useMemo(() => { return new Fzf(searchableItems, { - selector: (item) => item.model.id.toLowerCase(), + selector: (item) => `${getModelDisplayName(item.model)} ${item.model.id}`.toLowerCase(), }) }, [searchableItems]) @@ -390,7 +390,7 @@ const DropdownModelProvider = ({ const handleSelect = useCallback( async (searchableModel: SearchableModel) => { // Immediately update display to prevent double-click issues - setDisplayModel(searchableModel.model.id) + setDisplayModel(getModelDisplayName(searchableModel.model)) setSearchValue('') setOpen(false) @@ -576,7 +576,7 @@ const DropdownModelProvider = ({ />
    - {searchableModel.model.id} + {getModelDisplayName(searchableModel.model)}
    {capabilities.length > 0 && ( @@ -669,7 +669,7 @@ const DropdownModelProvider = ({ className="text-main-view-fg/80 text-sm" title={searchableModel.model.id} > - {searchableModel.model.id} + {getModelDisplayName(searchableModel.model)}
    {capabilities.length > 0 && ( diff --git a/web-app/src/containers/LeftPanel.tsx b/web-app/src/containers/LeftPanel.tsx index 43745d464..73c98dc09 100644 --- a/web-app/src/containers/LeftPanel.tsx +++ b/web-app/src/containers/LeftPanel.tsx @@ -432,9 +432,9 @@ const LeftPanel = () => { > - + {folder.name} diff --git a/web-app/src/containers/ModelSetting.tsx b/web-app/src/containers/ModelSetting.tsx index 9a3bfd814..079b735aa 100644 --- a/web-app/src/containers/ModelSetting.tsx +++ b/web-app/src/containers/ModelSetting.tsx @@ -14,7 +14,7 @@ import { Button } from '@/components/ui/button' import { DynamicControllerSetting } from '@/containers/dynamicControllerSetting' import { useModelProvider } from '@/hooks/useModelProvider' import { useServiceHub } from '@/hooks/useServiceHub' -import { cn } from '@/lib/utils' +import { cn, getModelDisplayName } from '@/lib/utils' import { useTranslation } from '@/i18n/react-i18next-compat' type ModelSettingProps = { @@ -261,7 +261,7 @@ export function ModelSetting({ - {t('common:modelSettings.title', { modelId: model.id })} + {t('common:modelSettings.title', { modelId: getModelDisplayName(model) })} {t('common:modelSettings.description')} diff --git a/web-app/src/containers/ScrollToBottom.tsx b/web-app/src/containers/ScrollToBottom.tsx index ac924df91..b1259480f 100644 --- a/web-app/src/containers/ScrollToBottom.tsx +++ b/web-app/src/containers/ScrollToBottom.tsx @@ -18,7 +18,7 @@ const ScrollToBottom = ({ }) => { const { t } = useTranslation() const appMainViewBgColor = useAppearance((state) => state.appMainViewBgColor) - const { showScrollToBottomBtn, scrollToBottom, setIsUserScrolling } = + const { showScrollToBottomBtn, scrollToBottom } = useThreadScrolling(threadId, scrollContainerRef) const { messages } = useMessages( useShallow((state) => ({ @@ -50,7 +50,6 @@ const ScrollToBottom = ({ className="bg-main-view-fg/10 px-2 border border-main-view-fg/5 flex items-center justify-center rounded-xl gap-x-2 cursor-pointer pointer-events-auto" onClick={() => { scrollToBottom(true) - setIsUserScrolling(false) }} >

    {t('scrollToBottom')}

    diff --git a/web-app/src/containers/__tests__/DropdownModelProvider.displayName.test.tsx b/web-app/src/containers/__tests__/DropdownModelProvider.displayName.test.tsx new file mode 100644 index 000000000..38783dfab --- /dev/null +++ b/web-app/src/containers/__tests__/DropdownModelProvider.displayName.test.tsx @@ -0,0 +1,277 @@ +import { describe, it, expect, beforeEach, vi } from 'vitest' +import { render, screen } from '@testing-library/react' +import '@testing-library/jest-dom' +import DropdownModelProvider from '../DropdownModelProvider' +import { getModelDisplayName } from '@/lib/utils' +import { useModelProvider } from '@/hooks/useModelProvider' + +// Define basic types to avoid missing declarations +type ModelProvider = { + provider: string + active: boolean + models: Array<{ + id: string + displayName?: string + capabilities: string[] + }> + settings: unknown[] +} + +type Model = { + id: string + displayName?: string + capabilities?: string[] +} + +type MockHookReturn = { + providers: ModelProvider[] + selectedProvider: string + selectedModel: Model + getProviderByName: (name: string) => ModelProvider | undefined + selectModelProvider: () => void + getModelBy: (id: string) => Model | undefined + updateProvider: () => void +} + +// Mock the dependencies +vi.mock('@/hooks/useModelProvider', () => ({ + useModelProvider: vi.fn(), +})) + +vi.mock('@/hooks/useThreads', () => ({ + useThreads: vi.fn(() => ({ + updateCurrentThreadModel: vi.fn(), + })), +})) + +vi.mock('@/hooks/useServiceHub', () => ({ + useServiceHub: vi.fn(() => ({ + models: () => ({ + checkMmprojExists: vi.fn(() => Promise.resolve(false)), + checkMmprojExistsAndUpdateOffloadMMprojSetting: vi.fn(() => Promise.resolve()), + }), + })), +})) + +vi.mock('@/i18n/react-i18next-compat', () => ({ + useTranslation: vi.fn(() => ({ + t: (key: string) => key, + })), +})) + +vi.mock('@tanstack/react-router', () => ({ + useNavigate: vi.fn(() => vi.fn()), +})) + +vi.mock('@/hooks/useFavoriteModel', () => ({ + useFavoriteModel: vi.fn(() => ({ + favoriteModels: [], + })), +})) + +vi.mock('@/lib/platform/const', () => ({ + PlatformFeatures: { + WEB_AUTO_MODEL_SELECTION: false, + MODEL_PROVIDER_SETTINGS: true, + }, +})) + +// Mock UI components +vi.mock('@/components/ui/popover', () => ({ + Popover: ({ children }: { children: React.ReactNode }) =>
    {children}
    , + PopoverTrigger: ({ children }: { children: React.ReactNode }) => ( +
    {children}
    + ), + PopoverContent: ({ children }: { children: React.ReactNode }) => ( +
    {children}
    + ), +})) + +vi.mock('../ProvidersAvatar', () => ({ + default: ({ provider }: { provider: any }) => ( +
    + ), +})) + +vi.mock('../Capabilities', () => ({ + default: ({ capabilities }: { capabilities: string[] }) => ( +
    {capabilities.join(',')}
    + ), +})) + +vi.mock('../ModelSetting', () => ({ + ModelSetting: () =>
    , +})) + +vi.mock('../ModelSupportStatus', () => ({ + ModelSupportStatus: () =>
    , +})) + +describe('DropdownModelProvider - Display Name Integration', () => { + const mockProviders: ModelProvider[] = [ + { + provider: 'llamacpp', + active: true, + models: [ + { + id: 'model1.gguf', + displayName: 'Custom Model 1', + capabilities: ['completion'], + }, + { + id: 'model2-very-long-filename.gguf', + displayName: 'Short Name', + capabilities: ['completion'], + }, + { + id: 'model3.gguf', + // No displayName - should fall back to ID + capabilities: ['completion'], + }, + ], + settings: [], + }, + ] + + const mockSelectedModel = { + id: 'model1.gguf', + displayName: 'Custom Model 1', + capabilities: ['completion'], + } + + beforeEach(() => { + vi.clearAllMocks() + + // Reset the mock for each test + vi.mocked(useModelProvider).mockReturnValue({ + providers: mockProviders, + selectedProvider: 'llamacpp', + selectedModel: mockSelectedModel, + getProviderByName: vi.fn((name: string) => + mockProviders.find((p: ModelProvider) => p.provider === name) + ), + selectModelProvider: vi.fn(), + getModelBy: vi.fn((id: string) => + mockProviders[0].models.find((m: Model) => m.id === id) + ), + updateProvider: vi.fn(), + } as MockHookReturn) + }) + + it('should display custom model name in the trigger button', () => { + render() + + // Should show the display name in both trigger and dropdown + expect(screen.getAllByText('Custom Model 1')).toHaveLength(2) // One in trigger, one in dropdown + // Model ID should not be visible as text (it's only in title attributes) + expect(screen.queryByDisplayValue('model1.gguf')).not.toBeInTheDocument() + }) + + it('should fall back to model ID when no displayName is set', () => { + vi.mocked(useModelProvider).mockReturnValue({ + providers: mockProviders, + selectedProvider: 'llamacpp', + selectedModel: mockProviders[0].models[2], // model3 without displayName + getProviderByName: vi.fn((name: string) => + mockProviders.find((p: ModelProvider) => p.provider === name) + ), + selectModelProvider: vi.fn(), + getModelBy: vi.fn((id: string) => + mockProviders[0].models.find((m: Model) => m.id === id) + ), + updateProvider: vi.fn(), + } as MockHookReturn) + + render() + + expect(screen.getAllByText('model3.gguf')).toHaveLength(2) // Trigger and dropdown + }) + + it('should show display names in the model list items', () => { + render() + + // Check if the display names are shown in the options + expect(screen.getAllByText('Custom Model 1')).toHaveLength(2) // Selected: Trigger + dropdown + expect(screen.getByText('Short Name')).toBeInTheDocument() // Only in dropdown + expect(screen.getByText('model3.gguf')).toBeInTheDocument() // Only in dropdown + }) + + it('should use getModelDisplayName utility correctly', () => { + // Test the utility function directly with different model scenarios + const modelWithDisplayName = { + id: 'long-model-name.gguf', + displayName: 'Short Name', + } as Model + + const modelWithoutDisplayName = { + id: 'model-without-display-name.gguf', + } as Model + + const modelWithEmptyDisplayName = { + id: 'model-with-empty.gguf', + displayName: '', + } as Model + + expect(getModelDisplayName(modelWithDisplayName)).toBe('Short Name') + expect(getModelDisplayName(modelWithoutDisplayName)).toBe('model-without-display-name.gguf') + expect(getModelDisplayName(modelWithEmptyDisplayName)).toBe('model-with-empty.gguf') + }) + + it('should maintain model ID for internal operations while showing display name', () => { + const mockSelectModelProvider = vi.fn() + + vi.mocked(useModelProvider).mockReturnValue({ + providers: mockProviders, + selectedProvider: 'llamacpp', + selectedModel: mockSelectedModel, + getProviderByName: vi.fn((name: string) => + mockProviders.find((p: ModelProvider) => p.provider === name) + ), + selectModelProvider: mockSelectModelProvider, + getModelBy: vi.fn((id: string) => + mockProviders[0].models.find((m: Model) => m.id === id) + ), + updateProvider: vi.fn(), + } as MockHookReturn) + + render() + + // Verify that display name is shown in UI + expect(screen.getAllByText('Custom Model 1')).toHaveLength(2) // Trigger + dropdown + + // The actual model ID should still be preserved for backend operations + // This would be tested in the click handlers, but that requires more complex mocking + expect(mockSelectedModel.id).toBe('model1.gguf') + }) + + it('should handle updating display model when selection changes', () => { + // Test that when a new model is selected, the trigger updates correctly + // First render with model1 selected + const { rerender } = render() + + // Check trigger shows Custom Model 1 + const triggerButton = screen.getByRole('button') + expect(triggerButton).toHaveTextContent('Custom Model 1') + + // Update to select model2 + vi.mocked(useModelProvider).mockReturnValue({ + providers: mockProviders, + selectedProvider: 'llamacpp', + selectedModel: mockProviders[0].models[1], // model2 + getProviderByName: vi.fn((name: string) => + mockProviders.find((p: ModelProvider) => p.provider === name) + ), + selectModelProvider: vi.fn(), + getModelBy: vi.fn((id: string) => + mockProviders[0].models.find((m: Model) => m.id === id) + ), + updateProvider: vi.fn(), + } as MockHookReturn) + + rerender() + // Check trigger now shows Short Name + expect(triggerButton).toHaveTextContent('Short Name') + // Both models are still visible in the dropdown, so we can't test for absence + expect(screen.getAllByText('Short Name')).toHaveLength(2) // trigger + dropdown + }) +}) \ No newline at end of file diff --git a/web-app/src/containers/__tests__/EditModel.test.tsx b/web-app/src/containers/__tests__/EditModel.test.tsx new file mode 100644 index 000000000..a02e72476 --- /dev/null +++ b/web-app/src/containers/__tests__/EditModel.test.tsx @@ -0,0 +1,184 @@ +import { describe, it, expect, beforeEach, vi } from 'vitest' +import { render, screen, fireEvent, waitFor } from '@testing-library/react' +import userEvent from '@testing-library/user-event' +import { DialogEditModel } from '../dialogs/EditModel' +import { useModelProvider } from '@/hooks/useModelProvider' +import '@testing-library/jest-dom' + +// Mock the dependencies +vi.mock('@/hooks/useModelProvider', () => ({ + useModelProvider: vi.fn(() => ({ + updateProvider: vi.fn(), + setProviders: vi.fn(), + })), +})) + +vi.mock('@/hooks/useServiceHub', () => ({ + useServiceHub: vi.fn(() => ({ + providers: () => ({ + getProviders: vi.fn(() => Promise.resolve([])), + }), + })), +})) + +vi.mock('@/i18n/react-i18next-compat', () => ({ + useTranslation: vi.fn(() => ({ + t: (key: string) => key, + })), +})) + +vi.mock('sonner', () => ({ + toast: { + success: vi.fn(), + error: vi.fn(), + }, +})) + +// Mock Dialog components +vi.mock('@/components/ui/dialog', () => ({ + Dialog: ({ children, open }: { children: React.ReactNode; open: boolean }) => + open ?
    {children}
    : null, + DialogContent: ({ children }: { children: React.ReactNode }) => ( +
    {children}
    + ), + DialogHeader: ({ children }: { children: React.ReactNode }) => ( +
    {children}
    + ), + DialogTitle: ({ children }: { children: React.ReactNode }) => ( +

    {children}

    + ), + DialogDescription: ({ children }: { children: React.ReactNode }) => ( +

    {children}

    + ), + DialogTrigger: ({ children }: { children: React.ReactNode }) => ( +
    {children}
    + ), +})) + +vi.mock('@/components/ui/input', () => ({ + Input: ({ value, onChange, ...props }: any) => ( + + ), +})) + +vi.mock('@/components/ui/button', () => ({ + Button: ({ children, onClick, ...props }: any) => ( + + ), +})) + +// Mock other UI components +vi.mock('@tabler/icons-react', () => ({ + IconPencil: () =>
    , + IconCheck: () =>
    , + IconX: () =>
    , + IconAlertTriangle: () =>
    , + IconEye: () =>
    , + IconTool: () =>
    , + IconLoader2: () =>
    , +})) + +describe('DialogEditModel - Basic Component Tests', () => { + const mockProvider = { + provider: 'llamacpp', + active: true, + models: [ + { + id: 'test-model.gguf', + displayName: 'My Custom Model', + capabilities: ['completion'], + }, + ], + settings: [], + } as any + + const mockUpdateProvider = vi.fn() + const mockSetProviders = vi.fn() + + beforeEach(() => { + vi.clearAllMocks() + + vi.mocked(useModelProvider).mockReturnValue({ + updateProvider: mockUpdateProvider, + setProviders: mockSetProviders, + } as any) + }) + + it('should render without errors', () => { + const { container } = render( + + ) + + // Component should render without throwing errors + expect(container).toBeInTheDocument() + }) + + it('should handle provider without models', () => { + const emptyProvider = { + ...mockProvider, + models: [], + } as any + + const { container } = render( + + ) + + // Component should handle empty models gracefully + expect(container).toBeInTheDocument() + }) + + it('should accept provider and modelId props', () => { + const { container } = render( + + ) + + expect(container).toBeInTheDocument() + }) + + it('should not crash with minimal props', () => { + const minimalProvider = { + provider: 'test', + active: false, + models: [], + settings: [], + } as any + + expect(() => { + render( + + ) + }).not.toThrow() + }) + + it('should have mocked dependencies available', () => { + render( + + ) + + // Verify our mocks are in place + expect(mockUpdateProvider).toBeDefined() + expect(mockSetProviders).toBeDefined() + }) +}) \ No newline at end of file diff --git a/web-app/src/containers/dialogs/EditModel.tsx b/web-app/src/containers/dialogs/EditModel.tsx index a07a5ae94..67576fbd6 100644 --- a/web-app/src/containers/dialogs/EditModel.tsx +++ b/web-app/src/containers/dialogs/EditModel.tsx @@ -7,6 +7,8 @@ import { DialogTrigger, } from '@/components/ui/dialog' import { Switch } from '@/components/ui/switch' +import { Input } from '@/components/ui/input' +import { Button } from '@/components/ui/button' import { useModelProvider } from '@/hooks/useModelProvider' import { @@ -14,12 +16,14 @@ import { IconEye, IconTool, IconAlertTriangle, + IconLoader2, // IconWorld, // IconAtom, // IconCodeCircle2, } from '@tabler/icons-react' import { useState, useEffect } from 'react' import { useTranslation } from '@/i18n/react-i18next-compat' +import { toast } from 'sonner' // No need to define our own interface, we'll use the existing Model type type DialogEditModelProps = { @@ -34,6 +38,13 @@ export const DialogEditModel = ({ const { t } = useTranslation() const { updateProvider } = useModelProvider() const [selectedModelId, setSelectedModelId] = useState('') + const [displayName, setDisplayName] = useState('') + const [originalDisplayName, setOriginalDisplayName] = useState('') + const [originalCapabilities, setOriginalCapabilities] = useState< + Record + >({}) + const [isOpen, setIsOpen] = useState(false) + const [isLoading, setIsLoading] = useState(false) const [capabilities, setCapabilities] = useState>({ completion: false, vision: false, @@ -45,20 +56,34 @@ export const DialogEditModel = ({ // Initialize with the provided model ID or the first model if available useEffect(() => { - if (modelId) { - setSelectedModelId(modelId) - } else if (provider.models && provider.models.length > 0) { - setSelectedModelId(provider.models[0].id) + // Only set the selected model ID if the dialog is not open to prevent switching during downloads + if (!isOpen) { + if (modelId) { + setSelectedModelId(modelId) + } else if (provider.models && provider.models.length > 0) { + setSelectedModelId(provider.models[0].id) + } } - }, [provider, modelId]) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [modelId, isOpen]) // Add isOpen dependency to prevent switching when dialog is open + + // Handle dialog opening - set the initial model selection + useEffect(() => { + if (isOpen && !selectedModelId) { + if (modelId) { + setSelectedModelId(modelId) + } else if (provider.models && provider.models.length > 0) { + setSelectedModelId(provider.models[0].id) + } + } + }, [isOpen, selectedModelId, modelId, provider.models]) // Get the currently selected model const selectedModel = provider.models.find( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (m: any) => m.id === selectedModelId + (m: Model) => m.id === selectedModelId ) - // Initialize capabilities from selected model + // Initialize capabilities and display name from selected model useEffect(() => { if (selectedModel) { const modelCapabilities = selectedModel.capabilities || [] @@ -70,69 +95,114 @@ export const DialogEditModel = ({ web_search: modelCapabilities.includes('web_search'), reasoning: modelCapabilities.includes('reasoning'), }) + // Use existing displayName if available, otherwise fall back to model ID + const displayNameValue = (selectedModel as Model & { displayName?: string }).displayName || selectedModel.id + setDisplayName(displayNameValue) + setOriginalDisplayName(displayNameValue) + + const originalCaps = { + completion: modelCapabilities.includes('completion'), + vision: modelCapabilities.includes('vision'), + tools: modelCapabilities.includes('tools'), + embeddings: modelCapabilities.includes('embeddings'), + web_search: modelCapabilities.includes('web_search'), + reasoning: modelCapabilities.includes('reasoning'), + } + setOriginalCapabilities(originalCaps) } }, [selectedModel]) - // Track if capabilities were updated by user action - const [capabilitiesUpdated, setCapabilitiesUpdated] = useState(false) - // Update model capabilities - only update local state const handleCapabilityChange = (capability: string, enabled: boolean) => { setCapabilities((prev) => ({ ...prev, [capability]: enabled, })) - // Mark that capabilities were updated by user action - setCapabilitiesUpdated(true) } - // Use effect to update the provider when capabilities are explicitly changed by user - useEffect(() => { - // Only run if capabilities were updated by user action and we have a selected model - if (!capabilitiesUpdated || !selectedModel) return + // Handle display name change + const handleDisplayNameChange = (newName: string) => { + setDisplayName(newName) + } - // Reset the flag - setCapabilitiesUpdated(false) + // Check if there are unsaved changes + const hasUnsavedChanges = () => { + const nameChanged = displayName !== originalDisplayName + const capabilitiesChanged = + JSON.stringify(capabilities) !== JSON.stringify(originalCapabilities) + return nameChanged || capabilitiesChanged + } - // Create updated capabilities array from the state - const updatedCapabilities = Object.entries(capabilities) - .filter(([, isEnabled]) => isEnabled) - .map(([capName]) => capName) + // Handle save changes + const handleSaveChanges = async () => { + if (!selectedModel?.id || isLoading) return - // Find and update the model in the provider - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const updatedModels = provider.models.map((m: any) => { - if (m.id === selectedModelId) { - return { - ...m, - capabilities: updatedCapabilities, - // Mark that user has manually configured capabilities - _userConfiguredCapabilities: true, - } + setIsLoading(true) + try { + let updatedModels = provider.models + + // Update display name if changed + if (displayName !== originalDisplayName) { + // Update the model in the provider models array with displayName + updatedModels = updatedModels.map((m: Model) => { + if (m.id === selectedModelId) { + return { + ...m, + displayName: displayName, + } + } + return m + }) + setOriginalDisplayName(displayName) } - return m - }) - // Update the provider with the updated models - updateProvider(provider.provider, { - ...provider, - models: updatedModels, - }) - }, [ - capabilitiesUpdated, - capabilities, - provider, - selectedModel, - selectedModelId, - updateProvider, - ]) + // Update capabilities if changed + if ( + JSON.stringify(capabilities) !== JSON.stringify(originalCapabilities) + ) { + const updatedCapabilities = Object.entries(capabilities) + .filter(([, isEnabled]) => isEnabled) + .map(([capName]) => capName) + + // Find and update the model in the provider + updatedModels = updatedModels.map((m: Model) => { + if (m.id === selectedModelId) { + return { + ...m, + capabilities: updatedCapabilities, + // Mark that user has manually configured capabilities + _userConfiguredCapabilities: true, + } + } + return m + }) + + setOriginalCapabilities(capabilities) + } + + // Update the provider with the updated models + updateProvider(provider.provider, { + ...provider, + models: updatedModels, + }) + + // Show success toast and close dialog + toast.success('Model updated successfully') + setIsOpen(false) + } catch (error) { + console.error('Failed to update model:', error) + toast.error('Failed to update model. Please try again.') + } finally { + setIsLoading(false) + } + } if (!selectedModel) { return null } return ( - +
    @@ -148,6 +218,27 @@ export const DialogEditModel = ({ + {/* Model Display Name Section */} +
    + + handleDisplayNameChange(e.target.value)} + placeholder="Enter display name" + className="w-full" + disabled={isLoading} + /> +

    + This is the name that will be shown in the interface. The original model file remains unchanged. +

    +
    + {/* Warning Banner */}
    @@ -181,6 +272,7 @@ export const DialogEditModel = ({ onCheckedChange={(checked) => handleCapabilityChange('tools', checked) } + disabled={isLoading} />
    @@ -197,6 +289,7 @@ export const DialogEditModel = ({ onCheckedChange={(checked) => handleCapabilityChange('vision', checked) } + disabled={isLoading} />
    @@ -253,6 +346,24 @@ export const DialogEditModel = ({
    */}
    + + {/* Save Button */} +
    + +
    ) diff --git a/web-app/src/hooks/__tests__/useModelProvider.test.ts b/web-app/src/hooks/__tests__/useModelProvider.test.ts new file mode 100644 index 000000000..88272cf57 --- /dev/null +++ b/web-app/src/hooks/__tests__/useModelProvider.test.ts @@ -0,0 +1,182 @@ +import { describe, it, expect, beforeEach, vi } from 'vitest' +import { act, renderHook } from '@testing-library/react' +import { useModelProvider } from '../useModelProvider' + +// Mock getServiceHub +vi.mock('@/hooks/useServiceHub', () => ({ + getServiceHub: vi.fn(() => ({ + path: () => ({ + sep: () => '/', + }), + })), +})) + +// Mock the localStorage key constants +vi.mock('@/constants/localStorage', () => ({ + localStorageKey: { + modelProvider: 'jan-model-provider', + }, +})) + +// Mock localStorage +const localStorageMock = { + getItem: vi.fn(), + setItem: vi.fn(), + removeItem: vi.fn(), + clear: vi.fn(), +} +Object.defineProperty(window, 'localStorage', { + value: localStorageMock, + writable: true, +}) + +describe('useModelProvider - displayName functionality', () => { + beforeEach(() => { + vi.clearAllMocks() + localStorageMock.getItem.mockReturnValue(null) + + // Reset Zustand store to default state + act(() => { + useModelProvider.setState({ + providers: [], + selectedProvider: 'llamacpp', + selectedModel: null, + deletedModels: [], + }) + }) + }) + + it('should handle models without displayName property', () => { + const { result } = renderHook(() => useModelProvider()) + + const provider = { + provider: 'llamacpp', + active: true, + models: [ + { + id: 'test-model.gguf', + capabilities: ['completion'], + }, + ], + settings: [], + } as any + + // First add the provider, then update it (since updateProvider only updates existing providers) + act(() => { + result.current.addProvider(provider) + }) + + const updatedProvider = result.current.getProviderByName('llamacpp') + expect(updatedProvider?.models[0].displayName).toBeUndefined() + expect(updatedProvider?.models[0].id).toBe('test-model.gguf') + }) + + it('should preserve displayName when merging providers in setProviders', () => { + const { result } = renderHook(() => useModelProvider()) + + // First, set up initial state with displayName via direct state manipulation + // This simulates the scenario where a user has already customized a display name + act(() => { + useModelProvider.setState({ + providers: [ + { + provider: 'llamacpp', + active: true, + models: [ + { + id: 'test-model.gguf', + displayName: 'My Custom Model', + capabilities: ['completion'], + }, + ], + settings: [], + }, + ] as any, + selectedProvider: 'llamacpp', + selectedModel: null, + deletedModels: [], + }) + }) + + // Now simulate setProviders with fresh data (like from server refresh) + const freshProviders = [ + { + provider: 'llamacpp', + active: true, + persist: true, + models: [ + { + id: 'test-model.gguf', + capabilities: ['completion'], + // Note: no displayName in fresh data + }, + ], + settings: [], + }, + ] as any + + act(() => { + result.current.setProviders(freshProviders) + }) + + // The displayName should be preserved from existing state + const provider = result.current.getProviderByName('llamacpp') + expect(provider?.models[0].displayName).toBe('My Custom Model') + }) + + it('should provide basic functionality without breaking existing behavior', () => { + const { result } = renderHook(() => useModelProvider()) + + // Test that basic provider operations work + expect(result.current.providers).toEqual([]) + expect(result.current.selectedProvider).toBe('llamacpp') + expect(result.current.selectedModel).toBeNull() + + // Test addProvider functionality + const provider = { + provider: 'openai', + active: true, + models: [], + settings: [], + } as any + + act(() => { + result.current.addProvider(provider) + }) + + expect(result.current.providers).toHaveLength(1) + expect(result.current.getProviderByName('openai')).toBeDefined() + }) + + it('should handle provider operations with models that have displayName', () => { + const { result } = renderHook(() => useModelProvider()) + + // Test that we can at least get and set providers with displayName models + const providerWithDisplayName = { + provider: 'llamacpp', + active: true, + models: [ + { + id: 'test-model.gguf', + displayName: 'Custom Model Name', + capabilities: ['completion'], + }, + ], + settings: [], + } as any + + // Set the state directly (simulating what would happen in real usage) + act(() => { + useModelProvider.setState({ + providers: [providerWithDisplayName], + selectedProvider: 'llamacpp', + selectedModel: null, + deletedModels: [], + }) + }) + + const provider = result.current.getProviderByName('llamacpp') + expect(provider?.models[0].displayName).toBe('Custom Model Name') + expect(provider?.models[0].id).toBe('test-model.gguf') + }) +}) \ No newline at end of file diff --git a/web-app/src/hooks/useClickOutside.ts b/web-app/src/hooks/useClickOutside.ts index 237b9dff1..9a4f82f3a 100644 --- a/web-app/src/hooks/useClickOutside.ts +++ b/web-app/src/hooks/useClickOutside.ts @@ -32,7 +32,7 @@ export function useClickOutside( ) return () => { - ;(events || DEFAULT_EVENTS).forEach((fn) => + (events || DEFAULT_EVENTS).forEach((fn) => document.removeEventListener(fn, listener) ) } diff --git a/web-app/src/hooks/useModelProvider.ts b/web-app/src/hooks/useModelProvider.ts index bd3dbc49b..a0b5a96ce 100644 --- a/web-app/src/hooks/useModelProvider.ts +++ b/web-app/src/hooks/useModelProvider.ts @@ -104,6 +104,7 @@ export const useModelProvider = create()( ...model, settings: settings, capabilities: existingModel?.capabilities || model.capabilities, + displayName: existingModel?.displayName || model.displayName, } }) diff --git a/web-app/src/hooks/useThreadScrolling.tsx b/web-app/src/hooks/useThreadScrolling.tsx index 9dfbeefb7..41362db61 100644 --- a/web-app/src/hooks/useThreadScrolling.tsx +++ b/web-app/src/hooks/useThreadScrolling.tsx @@ -1,8 +1,10 @@ -import { useCallback, useEffect, useMemo, useRef, useState } from 'react' +import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useAppState } from './useAppState' import { useMessages } from './useMessages' -import { useShallow } from 'zustand/react/shallow' -import debounce from 'lodash.debounce' + +const VIEWPORT_PADDING = 40 // Offset from viewport bottom for user message positioning +const MAX_DOM_RETRY_ATTEMPTS = 5 // Maximum attempts to find DOM elements before giving up +const DOM_RETRY_DELAY = 100 // Delay in ms between DOM element retry attempts export const useThreadScrolling = ( threadId: string, @@ -10,18 +12,36 @@ export const useThreadScrolling = ( ) => { const streamingContent = useAppState((state) => state.streamingContent) const isFirstRender = useRef(true) - const { messages } = useMessages( - useShallow((state) => ({ - messages: state.messages[threadId], - })) - ) const wasStreamingRef = useRef(false) const userIntendedPositionRef = useRef(null) - const [isUserScrolling, setIsUserScrolling] = useState(false) const [isAtBottom, setIsAtBottom] = useState(true) const [hasScrollbar, setHasScrollbar] = useState(false) const lastScrollTopRef = useRef(0) - const messagesCount = useMemo(() => messages?.length ?? 0, [messages]) + const lastAssistantMessageRef = useRef(null) + + const messageCount = useMessages((state) => state.messages[threadId]?.length ?? 0) + const lastMessageRole = useMessages((state) => { + const msgs = state.messages[threadId] + return msgs && msgs.length > 0 ? msgs[msgs.length - 1].role : null + }) + + const [paddingHeight, setPaddingHeightInternal] = useState(0) + const setPaddingHeight = setPaddingHeightInternal + const originalPaddingRef = useRef(0) + + const getDOMElements = useCallback(() => { + const scrollContainer = scrollContainerRef.current + if (!scrollContainer) return null + + const userMessages = scrollContainer.querySelectorAll('[data-message-author-role="user"]') + const assistantMessages = scrollContainer.querySelectorAll('[data-message-author-role="assistant"]') + return { + scrollContainer, + lastUserMessage: userMessages[userMessages.length - 1] as HTMLElement, + lastAssistantMessage: assistantMessages[assistantMessages.length - 1] as HTMLElement, + } + }, [scrollContainerRef]) + const showScrollToBottomBtn = !isAtBottom && hasScrollbar @@ -32,20 +52,16 @@ export const useThreadScrolling = ( ...(smooth ? { behavior: 'smooth' } : {}), }) } - }, []) + }, [scrollContainerRef]) + const handleScroll = useCallback((e: Event) => { const target = e.target as HTMLDivElement const { scrollTop, scrollHeight, clientHeight } = target - // Use a small tolerance to better detect when we're at the bottom const isBottom = Math.abs(scrollHeight - scrollTop - clientHeight) < 10 const hasScroll = scrollHeight > clientHeight - // Detect if this is a user-initiated scroll if (Math.abs(scrollTop - lastScrollTopRef.current) > 10) { - setIsUserScrolling(!isBottom) - - // If user scrolls during streaming and moves away from bottom, record their intended position if (streamingContent && !isBottom) { userIntendedPositionRef.current = scrollTop } @@ -76,117 +92,129 @@ export const useThreadScrolling = ( setHasScrollbar(hasScroll) }, []) - // Single useEffect for all auto-scrolling logic useEffect(() => { - // Track streaming state changes - const isCurrentlyStreaming = !!streamingContent - const justFinishedStreaming = - wasStreamingRef.current && !isCurrentlyStreaming - wasStreamingRef.current = isCurrentlyStreaming - - // If streaming just finished and user had an intended position, restore it - if (justFinishedStreaming && userIntendedPositionRef.current !== null) { - // Small delay to ensure DOM has updated - setTimeout(() => { - if ( - scrollContainerRef.current && - userIntendedPositionRef.current !== null - ) { - scrollContainerRef.current.scrollTo({ - top: userIntendedPositionRef.current, - behavior: 'smooth', - }) - userIntendedPositionRef.current = null - setIsUserScrolling(false) - } - }, 100) - return - } - // Clear intended position when streaming starts fresh - if (isCurrentlyStreaming && !wasStreamingRef.current) { - userIntendedPositionRef.current = null - } - - // Only auto-scroll when the user is not actively scrolling - // AND either at the bottom OR there's streaming content - if (!isUserScrolling && (streamingContent || isAtBottom) && messagesCount) { - // Use non-smooth scrolling for auto-scroll to prevent jank - scrollToBottom(false) - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [streamingContent, isUserScrolling, messagesCount]) - - useEffect(() => { - if (streamingContent) { - const interval = setInterval(checkScrollState, 100) - return () => clearInterval(interval) - } - }, [streamingContent, checkScrollState]) - - // Auto-scroll to bottom when component mounts or thread content changes - useEffect(() => { - const scrollContainer = scrollContainerRef.current - if (!scrollContainer) return - - // Always scroll to bottom on first render or when thread changes + if (!scrollContainerRef.current) return if (isFirstRender.current) { isFirstRender.current = false - scrollToBottom() - setIsAtBottom(true) - setIsUserScrolling(false) userIntendedPositionRef.current = null wasStreamingRef.current = false + scrollToBottom(false) checkScrollState() - return } }, [checkScrollState, scrollToBottom]) - const handleDOMScroll = (e: Event) => { - const target = e.target as HTMLDivElement - const { scrollTop, scrollHeight, clientHeight } = target - // Use a small tolerance to better detect when we're at the bottom - const isBottom = Math.abs(scrollHeight - scrollTop - clientHeight) < 10 - const hasScroll = scrollHeight > clientHeight - // Detect if this is a user-initiated scroll - if (Math.abs(scrollTop - lastScrollTopRef.current) > 10) { - setIsUserScrolling(!isBottom) + const prevCountRef = useRef(messageCount) + useEffect(() => { + const prevCount = prevCountRef.current + const becameLonger = messageCount > prevCount + const isUserMessage = lastMessageRole === 'user' - // If user scrolls during streaming and moves away from bottom, record their intended position - if (streamingContent && !isBottom) { - userIntendedPositionRef.current = scrollTop + if (becameLonger && messageCount > 0 && isUserMessage) { + const calculatePadding = () => { + const elements = getDOMElements() + if (!elements?.lastUserMessage) return + + const viewableHeight = elements.scrollContainer.clientHeight + const userMessageHeight = elements.lastUserMessage.offsetHeight + const calculatedPadding = Math.max(0, viewableHeight - VIEWPORT_PADDING - userMessageHeight) + + setPaddingHeight(calculatedPadding) + originalPaddingRef.current = calculatedPadding + + // Scroll after padding is applied to the DOM + requestAnimationFrame(() => { + elements.scrollContainer.scrollTo({ + top: elements.scrollContainer.scrollHeight, + behavior: 'smooth', + }) + }) } + + let retryCount = 0 + + const tryCalculatePadding = () => { + if (getDOMElements()?.lastUserMessage) { + calculatePadding() + } else if (retryCount < MAX_DOM_RETRY_ATTEMPTS) { + retryCount++ + setTimeout(tryCalculatePadding, DOM_RETRY_DELAY) + } + } + + tryCalculatePadding() } - setIsAtBottom(isBottom) - setHasScrollbar(hasScroll) - lastScrollTopRef.current = scrollTop - } - // Use a shorter debounce time for more responsive scrolling - const debouncedScroll = debounce(handleDOMScroll) + + prevCountRef.current = messageCount + }, [messageCount, lastMessageRole]) useEffect(() => { - const chatHistoryElement = scrollContainerRef.current - if (chatHistoryElement) { - chatHistoryElement.addEventListener('scroll', debouncedScroll) - return () => - chatHistoryElement.removeEventListener('scroll', debouncedScroll) - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []) + const previouslyStreaming = wasStreamingRef.current + const currentlyStreaming = !!streamingContent && streamingContent.thread_id === threadId + + const streamingStarted = !previouslyStreaming && currentlyStreaming + const streamingEnded = previouslyStreaming && !currentlyStreaming + const hasPaddingToAdjust = originalPaddingRef.current > 0 + + // Store the current assistant message when streaming starts + if (streamingStarted) { + const elements = getDOMElements() + lastAssistantMessageRef.current = elements?.lastAssistantMessage || null + } + + if (streamingEnded && hasPaddingToAdjust) { + let retryCount = 0 + + const adjustPaddingWhenReady = () => { + const elements = getDOMElements() + const currentAssistantMessage = elements?.lastAssistantMessage + + // Check if a new assistant message has appeared (different from the one before streaming) + const hasNewAssistantMessage = currentAssistantMessage && + currentAssistantMessage !== lastAssistantMessageRef.current + + if (hasNewAssistantMessage && elements?.lastUserMessage) { + const userRect = elements.lastUserMessage.getBoundingClientRect() + const assistantRect = currentAssistantMessage.getBoundingClientRect() + const actualSpacing = assistantRect.top - userRect.bottom + const totalAssistantHeight = currentAssistantMessage.offsetHeight + actualSpacing + const newPadding = Math.max(0, originalPaddingRef.current - totalAssistantHeight) + + setPaddingHeight(newPadding) + originalPaddingRef.current = newPadding + lastAssistantMessageRef.current = currentAssistantMessage + } else if (retryCount < MAX_DOM_RETRY_ATTEMPTS) { + retryCount++ + setTimeout(adjustPaddingWhenReady, DOM_RETRY_DELAY) + } else { + // Max retries hit - remove padding as fallback + setPaddingHeight(0) + originalPaddingRef.current = 0 + } + } + + adjustPaddingWhenReady() + } + + wasStreamingRef.current = currentlyStreaming + }, [streamingContent, threadId]) - // Reset scroll state when thread changes useEffect(() => { - isFirstRender.current = true - scrollToBottom() - setIsAtBottom(true) - setIsUserScrolling(false) userIntendedPositionRef.current = null wasStreamingRef.current = false + setPaddingHeight(0) + originalPaddingRef.current = 0 + prevCountRef.current = messageCount + scrollToBottom(false) checkScrollState() - }, [threadId, checkScrollState, scrollToBottom]) + }, [threadId]) return useMemo( - () => ({ showScrollToBottomBtn, scrollToBottom, setIsUserScrolling }), - [showScrollToBottomBtn, scrollToBottom, setIsUserScrolling] + () => ({ + showScrollToBottomBtn, + scrollToBottom, + paddingHeight + }), + [showScrollToBottomBtn, scrollToBottom, paddingHeight] ) } diff --git a/web-app/src/lib/__tests__/utils.test.ts b/web-app/src/lib/__tests__/utils.test.ts index 25bc91334..33c51447e 100644 --- a/web-app/src/lib/__tests__/utils.test.ts +++ b/web-app/src/lib/__tests__/utils.test.ts @@ -6,6 +6,7 @@ import { toGigabytes, formatMegaBytes, formatDuration, + getModelDisplayName, } from '../utils' describe('getProviderLogo', () => { @@ -200,3 +201,52 @@ describe('formatDuration', () => { expect(formatDuration(start, 86400000)).toBe('1d 0h 0m 0s') // exactly 1 day }) }) + +describe('getModelDisplayName', () => { + it('returns displayName when it exists', () => { + const model = { + id: 'llama-3.2-1b-instruct-q4_k_m.gguf', + displayName: 'My Custom Model', + } as Model + expect(getModelDisplayName(model)).toBe('My Custom Model') + }) + + it('returns model.id when displayName is undefined', () => { + const model = { + id: 'llama-3.2-1b-instruct-q4_k_m.gguf', + } as Model + expect(getModelDisplayName(model)).toBe('llama-3.2-1b-instruct-q4_k_m.gguf') + }) + + it('returns model.id when displayName is empty string', () => { + const model = { + id: 'llama-3.2-1b-instruct-q4_k_m.gguf', + displayName: '', + } as Model + expect(getModelDisplayName(model)).toBe('llama-3.2-1b-instruct-q4_k_m.gguf') + }) + + it('returns model.id when displayName is null', () => { + const model = { + id: 'llama-3.2-1b-instruct-q4_k_m.gguf', + displayName: null as any, + } as Model + expect(getModelDisplayName(model)).toBe('llama-3.2-1b-instruct-q4_k_m.gguf') + }) + + it('handles models with complex display names', () => { + const model = { + id: 'very-long-model-file-name-with-lots-of-details.gguf', + displayName: 'Short Name 🤖', + } as Model + expect(getModelDisplayName(model)).toBe('Short Name 🤖') + }) + + it('handles models with special characters in displayName', () => { + const model = { + id: 'model.gguf', + displayName: 'Model (Version 2.0) - Fine-tuned', + } as Model + expect(getModelDisplayName(model)).toBe('Model (Version 2.0) - Fine-tuned') + }) +}) diff --git a/web-app/src/lib/utils.ts b/web-app/src/lib/utils.ts index 60a055720..663a5051b 100644 --- a/web-app/src/lib/utils.ts +++ b/web-app/src/lib/utils.ts @@ -1,11 +1,34 @@ import { type ClassValue, clsx } from 'clsx' import { twMerge } from 'tailwind-merge' import { ExtensionManager } from './extension' +import path from "path" export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) } +export function basenameNoExt(filePath: string): string { + const base = path.basename(filePath); + const VALID_EXTENSIONS = [".tar.gz", ".zip"]; + + // handle VALID extensions first + for (const ext of VALID_EXTENSIONS) { + if (base.toLowerCase().endsWith(ext)) { + return base.slice(0, -ext.length); + } + } + + // fallback: remove only the last extension + return base.slice(0, -path.extname(base).length); +} + +/** + * Get the display name for a model, falling back to the model ID if no display name is set + */ +export function getModelDisplayName(model: Model): string { + return model.displayName || model.id +} + export function getProviderLogo(provider: string) { switch (provider) { case 'jan': diff --git a/web-app/src/providers/ToasterProvider.tsx b/web-app/src/providers/ToasterProvider.tsx index 0c46d9339..f0a178f67 100644 --- a/web-app/src/providers/ToasterProvider.tsx +++ b/web-app/src/providers/ToasterProvider.tsx @@ -13,11 +13,15 @@ export function ToasterProvider() { alignItems: 'start', borderColor: 'color-mix(in oklch, var(--app-main-view) 5%, transparent)', + userSelect: 'none', + WebkitUserSelect: 'none', + MozUserSelect: 'none', + msUserSelect: 'none', }, classNames: { - toast: 'toast', - title: '!text-main-view/90', - description: '!text-main-view/70', + toast: 'toast select-none', + title: '!text-main-view/90 select-none', + description: '!text-main-view/70 select-none', }, }} /> diff --git a/web-app/src/routes/project/index.tsx b/web-app/src/routes/project/index.tsx index fa8e1cf3a..5ab24bb39 100644 --- a/web-app/src/routes/project/index.tsx +++ b/web-app/src/routes/project/index.tsx @@ -134,25 +134,22 @@ function ProjectContent() { className="bg-main-view-fg/3 py-2 px-4 rounded-lg" key={folder.id} > -
    -
    +
    +
    -
    -
    -

    +
    +
    +

    {folder.name}

    - - {projectThreads.length}{' '} - {projectThreads.length === 1 - ? t('projects.thread') - : t('projects.threads')} -

    {t('projects.updated')}{' '} @@ -161,6 +158,12 @@ function ProjectContent() {

    + + {projectThreads.length}{' '} + {projectThreads.length === 1 + ? t('projects.thread') + : t('projects.threads')} + {projectThreads.length > 0 && (
    diff --git a/web-app/src/routes/threads/$threadId.tsx b/web-app/src/routes/threads/$threadId.tsx index 57b09de0a..93e27d640 100644 --- a/web-app/src/routes/threads/$threadId.tsx +++ b/web-app/src/routes/threads/$threadId.tsx @@ -22,6 +22,7 @@ import { PlatformFeatures } from '@/lib/platform/const' import { PlatformFeature } from '@/lib/platform/types' import ScrollToBottom from '@/containers/ScrollToBottom' import { PromptProgress } from '@/components/PromptProgress' +import { useThreadScrolling } from '@/hooks/useThreadScrolling' // as route.threadsDetail export const Route = createFileRoute('/threads/$threadId')({ @@ -51,6 +52,9 @@ function ThreadDetail() { const thread = useThreads(useShallow((state) => state.threads[threadId])) const scrollContainerRef = useRef(null) + // Get padding height for ChatGPT-style message positioning + const { paddingHeight } = useThreadScrolling(threadId, scrollContainerRef) + useEffect(() => { setCurrentThreadId(threadId) const assistant = assistants.find( @@ -194,6 +198,12 @@ function ThreadDetail() { threadId={threadId} data-test-id="thread-content-text" /> + {/* Persistent padding element for ChatGPT-style message positioning */} +
    ({ @@ -26,6 +26,7 @@ describe('DefaultModelsService', () => { const mockEngine = { list: vi.fn(), updateSettings: vi.fn(), + update: vi.fn(), import: vi.fn(), abortImport: vi.fn(), delete: vi.fn(), @@ -108,22 +109,41 @@ describe('DefaultModelsService', () => { describe('updateModel', () => { it('should update model settings', async () => { + const modelId = 'model1' const model = { id: 'model1', settings: [{ key: 'temperature', value: 0.7 }], } - await modelsService.updateModel(model as any) + await modelsService.updateModel(modelId, model as any) expect(mockEngine.updateSettings).toHaveBeenCalledWith(model.settings) + expect(mockEngine.update).not.toHaveBeenCalled() }) it('should handle model without settings', async () => { + const modelId = 'model1' const model = { id: 'model1' } - await modelsService.updateModel(model) + await modelsService.updateModel(modelId, model) expect(mockEngine.updateSettings).not.toHaveBeenCalled() + expect(mockEngine.update).not.toHaveBeenCalled() + }) + + it('should handle model when modelId differs from model.id', async () => { + const modelId = 'old-model-id' + const model = { + id: 'new-model-id', + settings: [{ key: 'temperature', value: 0.7 }], + } + + await modelsService.updateModel(modelId, model as any) + + expect(mockEngine.updateSettings).toHaveBeenCalledWith(model.settings) + // Note: Model ID updates are now handled at the provider level in the frontend + // The engine no longer has an update method for model metadata + expect(mockEngine.update).not.toHaveBeenCalled() }) }) diff --git a/web-app/src/services/dialog/tauri.ts b/web-app/src/services/dialog/tauri.ts index faafbb3c8..1b4efad28 100644 --- a/web-app/src/services/dialog/tauri.ts +++ b/web-app/src/services/dialog/tauri.ts @@ -9,7 +9,16 @@ import { DefaultDialogService } from './default' export class TauriDialogService extends DefaultDialogService { async open(options?: DialogOpenOptions): Promise { try { - return await open(options) + console.log('TauriDialogService: Opening dialog with options:', options) + if (options?.filters) { + console.log('TauriDialogService: File filters:', options.filters) + options.filters.forEach((filter, index) => { + console.log(`TauriDialogService: Filter ${index} - Name: "${filter.name}", Extensions:`, filter.extensions) + }) + } + const result = await open(options) + console.log('TauriDialogService: Dialog result:', result) + return result } catch (error) { console.error('Error opening dialog in Tauri:', error) return null diff --git a/web-app/src/services/dialog/web.ts b/web-app/src/services/dialog/web.ts index bb24024f1..c735cbf41 100644 --- a/web-app/src/services/dialog/web.ts +++ b/web-app/src/services/dialog/web.ts @@ -19,10 +19,14 @@ export class WebDialogService implements DialogService { } if (options?.filters) { + console.log('WebDialogService: Processing file filters:', options.filters) const extensions = options.filters.flatMap(filter => filter.extensions.map(ext => `.${ext}`) ) - input.accept = extensions.join(',') + console.log('WebDialogService: Generated extensions with dots:', extensions) + const acceptString = extensions.join(',') + console.log('WebDialogService: Final accept attribute:', acceptString) + input.accept = acceptString } input.onchange = (e) => { diff --git a/web-app/src/services/models/default.ts b/web-app/src/services/models/default.ts index 5d18e2985..746f869d1 100644 --- a/web-app/src/services/models/default.ts +++ b/web-app/src/services/models/default.ts @@ -162,11 +162,15 @@ export class DefaultModelsService implements ModelsService { } } - async updateModel(model: Partial): Promise { - if (model.settings) + async updateModel(modelId: string, model: Partial): Promise { + if (model.settings) { this.getEngine()?.updateSettings( model.settings as SettingComponentProps[] ) + } + // Note: Model name/ID updates are handled at the provider level in the frontend + // The engine doesn't have an update method for model metadata + console.log('Model update request processed for modelId:', modelId) } async pullModel( diff --git a/web-app/src/services/models/types.ts b/web-app/src/services/models/types.ts index 6248e82ac..4f7ef638f 100644 --- a/web-app/src/services/models/types.ts +++ b/web-app/src/services/models/types.ts @@ -99,7 +99,7 @@ export interface ModelsService { hfToken?: string ): Promise convertHfRepoToCatalogModel(repo: HuggingFaceRepo): CatalogModel - updateModel(model: Partial): Promise + updateModel(modelId: string, model: Partial): Promise pullModel( id: string, modelPath: string, diff --git a/web-app/src/types/modelProviders.d.ts b/web-app/src/types/modelProviders.d.ts index eb035e471..93cdd0df2 100644 --- a/web-app/src/types/modelProviders.d.ts +++ b/web-app/src/types/modelProviders.d.ts @@ -28,6 +28,7 @@ type Model = { id: string model?: string name?: string + displayName?: string version?: number | string description?: string format?: string diff --git a/yarn.lock b/yarn.lock index b12b0ef4f..963824f9c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1186,7 +1186,7 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.23.7": +"@babel/core@npm:^7.23.7, @babel/core@npm:^7.26.10, @babel/core@npm:^7.26.8": version: 7.26.10 resolution: "@babel/core@npm:7.26.10" dependencies: @@ -1209,7 +1209,7 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.24.4, @babel/core@npm:^7.27.4, @babel/core@npm:^7.27.7, @babel/core@npm:^7.28.0": +"@babel/core@npm:^7.24.4": version: 7.28.4 resolution: "@babel/core@npm:7.28.4" dependencies: @@ -1232,7 +1232,7 @@ __metadata: languageName: node linkType: hard -"@babel/generator@npm:^7.26.10, @babel/generator@npm:^7.27.0": +"@babel/generator@npm:^7.26.10, @babel/generator@npm:^7.26.8, @babel/generator@npm:^7.27.0": version: 7.27.0 resolution: "@babel/generator@npm:7.27.0" dependencies: @@ -1436,7 +1436,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-plugin-utils@npm:^7.0.0": +"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.25.9": version: 7.26.5 resolution: "@babel/helper-plugin-utils@npm:7.26.5" checksum: 10c0/cdaba71d4b891aa6a8dfbe5bac2f94effb13e5fa4c2c487667fdbaa04eae059b78b28d85a885071f45f7205aeb56d16759e1bed9c118b94b16e4720ef1ab0f65 @@ -1570,7 +1570,7 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.23.6, @babel/parser@npm:^7.26.10, @babel/parser@npm:^7.27.0": +"@babel/parser@npm:^7.23.6, @babel/parser@npm:^7.26.10, @babel/parser@npm:^7.26.8, @babel/parser@npm:^7.27.0": version: 7.27.0 resolution: "@babel/parser@npm:7.27.0" dependencies: @@ -1592,7 +1592,7 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.27.2, @babel/parser@npm:^7.27.5, @babel/parser@npm:^7.27.7": +"@babel/parser@npm:^7.27.2, @babel/parser@npm:^7.27.7": version: 7.27.7 resolution: "@babel/parser@npm:7.27.7" dependencies: @@ -1704,25 +1704,25 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-jsx@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-syntax-jsx@npm:7.27.1" +"@babel/plugin-syntax-jsx@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-syntax-jsx@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/bc5afe6a458d5f0492c02a54ad98c5756a0c13bd6d20609aae65acd560a9e141b0876da5f358dce34ea136f271c1016df58b461184d7ae9c4321e0f98588bc84 + checksum: 10c0/d56597aff4df39d3decda50193b6dfbe596ca53f437ff2934622ce19a743bf7f43492d3fb3308b0289f5cee2b825d99ceb56526a2b9e7b68bf04901546c5618c languageName: node linkType: hard -"@babel/plugin-syntax-typescript@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-syntax-typescript@npm:7.27.1" +"@babel/plugin-syntax-typescript@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-syntax-typescript@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/11589b4c89c66ef02d57bf56c6246267851ec0c361f58929327dc3e070b0dab644be625bbe7fb4c4df30c3634bfdfe31244e1f517be397d2def1487dbbe3c37d + checksum: 10c0/5192ebe11bd46aea68b7a60fd9555465c59af7e279e71126788e59121b86e00b505816685ab4782abe159232b0f73854e804b54449820b0d950b397ee158caa2 languageName: node linkType: hard @@ -2202,25 +2202,25 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-react-jsx-self@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-react-jsx-self@npm:7.27.1" +"@babel/plugin-transform-react-jsx-self@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-react-jsx-self@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/00a4f917b70a608f9aca2fb39aabe04a60aa33165a7e0105fd44b3a8531630eb85bf5572e9f242f51e6ad2fa38c2e7e780902176c863556c58b5ba6f6e164031 + checksum: 10c0/ce0e289f6af93d7c4dc6b385512199c5bb138ae61507b4d5117ba88b6a6b5092f704f1bdf80080b7d69b1b8c36649f2a0b250e8198667d4d30c08bbb1546bd99 languageName: node linkType: hard -"@babel/plugin-transform-react-jsx-source@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-react-jsx-source@npm:7.27.1" +"@babel/plugin-transform-react-jsx-source@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-react-jsx-source@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/5e67b56c39c4d03e59e03ba80692b24c5a921472079b63af711b1d250fc37c1733a17069b63537f750f3e937ec44a42b1ee6a46cd23b1a0df5163b17f741f7f2 + checksum: 10c0/fc9ee08efc9be7cbd2cc6788bbf92579adf3cab37912481f1b915221be3d22b0613b5b36a721df5f4c0ab65efe8582fcf8673caab83e6e1ce4cc04ceebf57dfa languageName: node linkType: hard @@ -2314,21 +2314,6 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-typescript@npm:^7.27.1": - version: 7.28.0 - resolution: "@babel/plugin-transform-typescript@npm:7.28.0" - dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.27.3" - "@babel/helper-create-class-features-plugin": "npm:^7.27.1" - "@babel/helper-plugin-utils": "npm:^7.27.1" - "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.27.1" - "@babel/plugin-syntax-typescript": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/049c2bd3407bbf5041d8c95805a4fadee6d176e034f6b94ce7967b92a846f1e00f323cf7dfbb2d06c93485f241fb8cf4c10520e30096a6059d251b94e80386e9 - languageName: node - linkType: hard - "@babel/plugin-transform-unicode-escapes@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-transform-unicode-escapes@npm:7.27.1" @@ -2469,22 +2454,7 @@ __metadata: languageName: node linkType: hard -"@babel/preset-typescript@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/preset-typescript@npm:7.27.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - "@babel/helper-validator-option": "npm:^7.27.1" - "@babel/plugin-syntax-jsx": "npm:^7.27.1" - "@babel/plugin-transform-modules-commonjs": "npm:^7.27.1" - "@babel/plugin-transform-typescript": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/cba6ca793d915f8aff9fe2f13b0dfbf5fd3f2e9a17f17478ec9878e9af0d206dcfe93154b9fd353727f16c1dca7c7a3ceb4943f8d28b216235f106bc0fbbcaa3 - languageName: node - linkType: hard - -"@babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.27.6": +"@babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.5": version: 7.28.4 resolution: "@babel/runtime@npm:7.28.4" checksum: 10c0/792ce7af9750fb9b93879cc9d1db175701c4689da890e6ced242ea0207c9da411ccf16dc04e689cc01158b28d7898c40d75598f4559109f761c12ce01e959bf7 @@ -2507,13 +2477,24 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.8.7": +"@babel/runtime@npm:^7.25.0, @babel/runtime@npm:^7.26.10, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.8.7": version: 7.27.1 resolution: "@babel/runtime@npm:7.27.1" checksum: 10c0/530a7332f86ac5a7442250456823a930906911d895c0b743bf1852efc88a20a016ed4cd26d442d0ca40ae6d5448111e02a08dd638a4f1064b47d080e2875dc05 languageName: node linkType: hard +"@babel/template@npm:^7.26.8, @babel/template@npm:^7.27.0": + version: 7.27.0 + resolution: "@babel/template@npm:7.27.0" + dependencies: + "@babel/code-frame": "npm:^7.26.2" + "@babel/parser": "npm:^7.27.0" + "@babel/types": "npm:^7.27.0" + checksum: 10c0/13af543756127edb5f62bf121f9b093c09a2b6fe108373887ccffc701465cfbcb17e07cf48aa7f440415b263f6ec006e9415c79dfc2e8e6010b069435f81f340 + languageName: node + linkType: hard + "@babel/template@npm:^7.26.9": version: 7.26.9 resolution: "@babel/template@npm:7.26.9" @@ -2525,17 +2506,6 @@ __metadata: languageName: node linkType: hard -"@babel/template@npm:^7.27.0": - version: 7.27.0 - resolution: "@babel/template@npm:7.27.0" - dependencies: - "@babel/code-frame": "npm:^7.26.2" - "@babel/parser": "npm:^7.27.0" - "@babel/types": "npm:^7.27.0" - checksum: 10c0/13af543756127edb5f62bf121f9b093c09a2b6fe108373887ccffc701465cfbcb17e07cf48aa7f440415b263f6ec006e9415c79dfc2e8e6010b069435f81f340 - languageName: node - linkType: hard - "@babel/template@npm:^7.27.1, @babel/template@npm:^7.27.2, @babel/template@npm:^7.4.0": version: 7.27.2 resolution: "@babel/template@npm:7.27.2" @@ -2547,7 +2517,7 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.23.7, @babel/traverse@npm:^7.27.7, @babel/traverse@npm:^7.28.0, @babel/traverse@npm:^7.28.3, @babel/traverse@npm:^7.28.4": +"@babel/traverse@npm:^7.23.7, @babel/traverse@npm:^7.28.0, @babel/traverse@npm:^7.28.3, @babel/traverse@npm:^7.28.4": version: 7.28.4 resolution: "@babel/traverse@npm:7.28.4" dependencies: @@ -2577,7 +2547,7 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.26.10": +"@babel/traverse@npm:^7.26.10, @babel/traverse@npm:^7.26.8": version: 7.27.0 resolution: "@babel/traverse@npm:7.27.0" dependencies: @@ -2632,7 +2602,7 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.23.6, @babel/types@npm:^7.26.10, @babel/types@npm:^7.27.0": +"@babel/types@npm:^7.23.6, @babel/types@npm:^7.26.10, @babel/types@npm:^7.26.8, @babel/types@npm:^7.27.0": version: 7.27.0 resolution: "@babel/types@npm:7.27.0" dependencies: @@ -2743,7 +2713,7 @@ __metadata: languageName: node linkType: hard -"@dnd-kit/core@npm:^6.3.1": +"@dnd-kit/core@npm:6.3.1": version: 6.3.1 resolution: "@dnd-kit/core@npm:6.3.1" dependencies: @@ -2757,7 +2727,7 @@ __metadata: languageName: node linkType: hard -"@dnd-kit/modifiers@npm:^9.0.0": +"@dnd-kit/modifiers@npm:9.0.0": version: 9.0.0 resolution: "@dnd-kit/modifiers@npm:9.0.0" dependencies: @@ -2770,7 +2740,7 @@ __metadata: languageName: node linkType: hard -"@dnd-kit/sortable@npm:^10.0.0": +"@dnd-kit/sortable@npm:10.0.0": version: 10.0.0 resolution: "@dnd-kit/sortable@npm:10.0.0" dependencies: @@ -2804,13 +2774,13 @@ __metadata: languageName: node linkType: hard -"@emnapi/core@npm:^1.4.3, @emnapi/core@npm:^1.4.5": - version: 1.5.0 - resolution: "@emnapi/core@npm:1.5.0" +"@emnapi/core@npm:^1.4.0": + version: 1.4.3 + resolution: "@emnapi/core@npm:1.4.3" dependencies: - "@emnapi/wasi-threads": "npm:1.1.0" + "@emnapi/wasi-threads": "npm:1.0.2" tslib: "npm:^2.4.0" - checksum: 10c0/52ba3485277706d92fa27d92b37e5b4f6ef0742c03ed68f8096f294c6bfa30f0752c82d4c2bfa14bff4dc30d63c9f71a8f9fb64a92743d00807d9e468fafd5ff + checksum: 10c0/e30101d16d37ef3283538a35cad60e22095aff2403fb9226a35330b932eb6740b81364d525537a94eb4fb51355e48ae9b10d779c0dd1cdcd55d71461fe4b45c7 languageName: node linkType: hard @@ -2823,12 +2793,12 @@ __metadata: languageName: node linkType: hard -"@emnapi/runtime@npm:^1.4.3, @emnapi/runtime@npm:^1.4.5": - version: 1.5.0 - resolution: "@emnapi/runtime@npm:1.5.0" +"@emnapi/runtime@npm:^1.4.0": + version: 1.4.3 + resolution: "@emnapi/runtime@npm:1.4.3" dependencies: tslib: "npm:^2.4.0" - checksum: 10c0/a85c9fc4e3af49cbe41e5437e5be2551392a931910cd0a5b5d3572532786927810c9cc1db11b232ec8f9657b33d4e6f7c4f985f1a052917d7cd703b5b2a20faa + checksum: 10c0/3b7ab72d21cb4e034f07df80165265f85f445ef3f581d1bc87b67e5239428baa00200b68a7d5e37a0425c3a78320b541b07f76c5530f6f6f95336a6294ebf30b languageName: node linkType: hard @@ -2841,12 +2811,12 @@ __metadata: languageName: node linkType: hard -"@emnapi/wasi-threads@npm:1.1.0, @emnapi/wasi-threads@npm:^1.0.4": - version: 1.1.0 - resolution: "@emnapi/wasi-threads@npm:1.1.0" +"@emnapi/wasi-threads@npm:1.0.2, @emnapi/wasi-threads@npm:^1.0.1": + version: 1.0.2 + resolution: "@emnapi/wasi-threads@npm:1.0.2" dependencies: tslib: "npm:^2.4.0" - checksum: 10c0/e6d54bf2b1e64cdd83d2916411e44e579b6ae35d5def0dea61a3c452d9921373044dff32a8b8473ae60c80692bdc39323e98b96a3f3d87ba6886b24dd0ef7ca1 + checksum: 10c0/f0621b1fc715221bd2d8332c0ca922617bcd77cdb3050eae50a124eb8923c54fa425d23982dc8f29d505c8798a62d1049bace8b0686098ff9dd82270e06d772e languageName: node linkType: hard @@ -3193,7 +3163,7 @@ __metadata: languageName: node linkType: hard -"@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.7.0, @eslint-community/eslint-utils@npm:^4.8.0": +"@eslint-community/eslint-utils@npm:^4.2.0": version: 4.9.0 resolution: "@eslint-community/eslint-utils@npm:4.9.0" dependencies: @@ -3204,6 +3174,17 @@ __metadata: languageName: node linkType: hard +"@eslint-community/eslint-utils@npm:^4.4.0": + version: 4.4.1 + resolution: "@eslint-community/eslint-utils@npm:4.4.1" + dependencies: + eslint-visitor-keys: "npm:^3.4.3" + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + checksum: 10c0/2aa0ac2fc50ff3f234408b10900ed4f1a0b19352f21346ad4cc3d83a1271481bdda11097baa45d484dd564c895e0762a27a8240be7a256b3ad47129e96528252 + languageName: node + linkType: hard + "@eslint-community/regexpp@npm:^4.10.0, @eslint-community/regexpp@npm:^4.12.1, @eslint-community/regexpp@npm:^4.6.1": version: 4.12.1 resolution: "@eslint-community/regexpp@npm:4.12.1" @@ -3211,30 +3192,30 @@ __metadata: languageName: node linkType: hard -"@eslint/config-array@npm:^0.21.0": - version: 0.21.0 - resolution: "@eslint/config-array@npm:0.21.0" +"@eslint/config-array@npm:^0.20.0": + version: 0.20.0 + resolution: "@eslint/config-array@npm:0.20.0" dependencies: "@eslint/object-schema": "npm:^2.1.6" debug: "npm:^4.3.1" minimatch: "npm:^3.1.2" - checksum: 10c0/0ea801139166c4aa56465b309af512ef9b2d3c68f9198751bbc3e21894fe70f25fbf26e1b0e9fffff41857bc21bfddeee58649ae6d79aadcd747db0c5dca771f + checksum: 10c0/94bc5d0abb96dc5295ff559925242ff75a54eacfb3576677e95917e42f7175e1c4b87bf039aa2a872f949b4852ad9724bf2f7529aaea6b98f28bb3fca7f1d659 languageName: node linkType: hard -"@eslint/config-helpers@npm:^0.3.1": - version: 0.3.1 - resolution: "@eslint/config-helpers@npm:0.3.1" - checksum: 10c0/f6c5b3a0b76a0d7d84cc93e310c259e6c3e0792ddd0a62c5fc0027796ffae44183432cb74b2c2b1162801ee1b1b34a6beb5d90a151632b4df7349f994146a856 +"@eslint/config-helpers@npm:^0.2.1": + version: 0.2.1 + resolution: "@eslint/config-helpers@npm:0.2.1" + checksum: 10c0/3e829a78b0bb4f7c44384ba1df3986e5de24b7f440ad5c6bb3cfc366ded773a869ca9ee8d212b5a563ae94596c5940dea6fd2ea1ee53a84c6241ac953dcb8bb7 languageName: node linkType: hard -"@eslint/core@npm:^0.15.2": - version: 0.15.2 - resolution: "@eslint/core@npm:0.15.2" +"@eslint/core@npm:^0.13.0": + version: 0.13.0 + resolution: "@eslint/core@npm:0.13.0" dependencies: "@types/json-schema": "npm:^7.0.15" - checksum: 10c0/c17a6dc4f5a6006ecb60165cc38bcd21fefb4a10c7a2578a0cfe5813bbd442531a87ed741da5adab5eb678e8e693fda2e2b14555b035355537e32bcec367ea17 + checksum: 10c0/ba724a7df7ed9dab387481f11d0d0f708180f40be93acce2c21dacca625c5867de3528760c42f1c457ccefe6a669d525ff87b779017eabc0d33479a36300797b languageName: node linkType: hard @@ -3279,10 +3260,10 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:9.35.0, @eslint/js@npm:^9.22.0": - version: 9.35.0 - resolution: "@eslint/js@npm:9.35.0" - checksum: 10c0/d40fe38724bc76c085c0b753cdf937fa35c0d6807ae76b2632e3f5f66c3040c91adcf1aff2ce70b4f45752e60629fadc415eeec9af3be3c274bae1cac54b9840 +"@eslint/js@npm:9.25.1": + version: 9.25.1 + resolution: "@eslint/js@npm:9.25.1" + checksum: 10c0/87d86b512ab109bfd3b9317ced3220ea3d444ac3bfa7abd853ca7f724d72c36e213062f9def16a632365d97dc29e0094312e3682a9767590ee6f43b3d5d873fd languageName: node linkType: hard @@ -3293,13 +3274,13 @@ __metadata: languageName: node linkType: hard -"@eslint/plugin-kit@npm:^0.3.5": - version: 0.3.5 - resolution: "@eslint/plugin-kit@npm:0.3.5" +"@eslint/plugin-kit@npm:^0.2.8": + version: 0.2.8 + resolution: "@eslint/plugin-kit@npm:0.2.8" dependencies: - "@eslint/core": "npm:^0.15.2" + "@eslint/core": "npm:^0.13.0" levn: "npm:^0.4.1" - checksum: 10c0/c178c1b58c574200c0fd125af3e4bc775daba7ce434ba6d1eeaf9bcb64b2e9fea75efabffb3ed3ab28858e55a016a5efa95f509994ee4341b341199ca630b89e + checksum: 10c0/554847c8f2b6bfe0e634f317fc43d0b54771eea0015c4f844f75915fdb9e6170c830c004291bad57db949d61771732e459f36ed059f45cf750af223f77357c5c languageName: node linkType: hard @@ -3490,14 +3471,14 @@ __metadata: resolution: "@jan/extensions-web@workspace:extensions-web" dependencies: "@janhq/core": "workspace:*" - "@modelcontextprotocol/sdk": "npm:^1.17.5" - typescript: "npm:^5.3.3" - vite: "npm:^5.0.0" - vitest: "npm:^2.0.0" - zustand: "npm:^5.0.8" + "@modelcontextprotocol/sdk": "npm:1.17.5" + typescript: "npm:5.9.2" + vite: "npm:5.4.20" + vitest: "npm:2.1.9" + zustand: "npm:5.0.8" peerDependencies: "@janhq/core": "*" - zustand: ^5.0.0 + zustand: 5.0.3 languageName: unknown linkType: soft @@ -3534,111 +3515,111 @@ __metadata: version: 0.0.0-use.local resolution: "@janhq/web-app@workspace:web-app" dependencies: - "@dnd-kit/core": "npm:^6.3.1" - "@dnd-kit/modifiers": "npm:^9.0.0" - "@dnd-kit/sortable": "npm:^10.0.0" - "@eslint/js": "npm:^9.22.0" + "@dnd-kit/core": "npm:6.3.1" + "@dnd-kit/modifiers": "npm:9.0.0" + "@dnd-kit/sortable": "npm:10.0.0" + "@eslint/js": "npm:8.57.0" "@jan/extensions-web": "link:../extensions-web" "@janhq/core": "link:../core" - "@radix-ui/react-accordion": "npm:^1.2.10" - "@radix-ui/react-avatar": "npm:^1.1.10" - "@radix-ui/react-dialog": "npm:^1.1.14" - "@radix-ui/react-dropdown-menu": "npm:^2.1.15" - "@radix-ui/react-hover-card": "npm:^1.1.14" - "@radix-ui/react-popover": "npm:^1.1.13" - "@radix-ui/react-progress": "npm:^1.1.4" - "@radix-ui/react-radio-group": "npm:^1.3.7" - "@radix-ui/react-slider": "npm:^1.3.2" - "@radix-ui/react-slot": "npm:^1.2.0" - "@radix-ui/react-switch": "npm:^1.2.2" - "@radix-ui/react-tooltip": "npm:^1.2.4" - "@tabler/icons-react": "npm:^3.33.0" - "@tailwindcss/vite": "npm:^4.1.4" - "@tanstack/react-router": "npm:^1.116.0" - "@tanstack/react-router-devtools": "npm:^1.121.34" - "@tanstack/react-virtual": "npm:^3.13.12" - "@tanstack/router-plugin": "npm:^1.116.1" - "@tauri-apps/api": "npm:^2.8.0" + "@radix-ui/react-accordion": "npm:1.2.11" + "@radix-ui/react-avatar": "npm:1.1.10" + "@radix-ui/react-dialog": "npm:1.1.15" + "@radix-ui/react-dropdown-menu": "npm:2.1.16" + "@radix-ui/react-hover-card": "npm:1.1.14" + "@radix-ui/react-popover": "npm:1.1.14" + "@radix-ui/react-progress": "npm:1.1.4" + "@radix-ui/react-radio-group": "npm:1.3.8" + "@radix-ui/react-slider": "npm:1.3.2" + "@radix-ui/react-slot": "npm:1.2.0" + "@radix-ui/react-switch": "npm:1.2.2" + "@radix-ui/react-tooltip": "npm:1.2.4" + "@tabler/icons-react": "npm:3.34.0" + "@tailwindcss/vite": "npm:4.1.4" + "@tanstack/react-router": "npm:1.117.0" + "@tanstack/react-router-devtools": "npm:1.121.34" + "@tanstack/react-virtual": "npm:3.13.12" + "@tanstack/router-plugin": "npm:1.117.0" + "@tauri-apps/api": "npm:2.8.0" "@tauri-apps/plugin-deep-link": "npm:2.4.3" - "@tauri-apps/plugin-dialog": "npm:^2.2.1" - "@tauri-apps/plugin-http": "npm:^2.2.1" - "@tauri-apps/plugin-opener": "npm:^2.2.7" - "@tauri-apps/plugin-os": "npm:^2.2.1" - "@tauri-apps/plugin-updater": "npm:^2.7.1" - "@testing-library/dom": "npm:^10.4.0" - "@testing-library/jest-dom": "npm:^6.6.3" - "@testing-library/react": "npm:^16.3.0" - "@testing-library/user-event": "npm:^14.6.1" - "@types/culori": "npm:^2.1.1" - "@types/istanbul-lib-report": "npm:^3" - "@types/istanbul-reports": "npm:^3" - "@types/lodash.clonedeep": "npm:^4" - "@types/lodash.debounce": "npm:^4" - "@types/node": "npm:^22.14.1" - "@types/react": "npm:^19.0.10" - "@types/react-dom": "npm:^19.0.4" - "@types/react-syntax-highlighter": "npm:^15.5.13" - "@types/uuid": "npm:^10.0.0" - "@uiw/react-textarea-code-editor": "npm:^3.1.1" - "@vitejs/plugin-react": "npm:^4.3.4" + "@tauri-apps/plugin-dialog": "npm:2.2.2" + "@tauri-apps/plugin-http": "npm:2.5.0" + "@tauri-apps/plugin-opener": "npm:2.3.0" + "@tauri-apps/plugin-os": "npm:2.2.1" + "@tauri-apps/plugin-updater": "npm:2.8.1" + "@testing-library/dom": "npm:10.4.1" + "@testing-library/jest-dom": "npm:6.8.0" + "@testing-library/react": "npm:16.3.0" + "@testing-library/user-event": "npm:14.6.1" + "@types/culori": "npm:2.1.1" + "@types/istanbul-lib-report": "npm:3.0.3" + "@types/istanbul-reports": "npm:3.0.4" + "@types/lodash.clonedeep": "npm:4.5.9" + "@types/lodash.debounce": "npm:4.0.9" + "@types/node": "npm:22.14.1" + "@types/react": "npm:19.1.2" + "@types/react-dom": "npm:19.1.2" + "@types/react-syntax-highlighter": "npm:15.5.13" + "@types/uuid": "npm:10.0.0" + "@uiw/react-textarea-code-editor": "npm:3.1.1" + "@vitejs/plugin-react": "npm:4.4.1" "@vitest/coverage-v8": "npm:3.2.4" - class-variance-authority: "npm:^0.7.1" - clsx: "npm:^2.1.1" - culori: "npm:^4.0.1" - emoji-picker-react: "npm:^4.12.2" - eslint: "npm:^9.22.0" - eslint-plugin-react-hooks: "npm:^5.2.0" - eslint-plugin-react-refresh: "npm:^0.4.19" - framer-motion: "npm:^12.23.12" - fuse.js: "npm:^7.1.0" - fzf: "npm:^0.5.2" - globals: "npm:^16.0.0" - i18next: "npm:^25.0.1" - istanbul-api: "npm:^3.0.0" - istanbul-lib-coverage: "npm:^3.2.2" - istanbul-lib-report: "npm:^3.0.1" - istanbul-reports: "npm:^3.1.7" - jsdom: "npm:^26.1.0" - katex: "npm:^0.16.22" - lodash.clonedeep: "npm:^4.5.0" - lodash.debounce: "npm:^4.0.8" - lucide-react: "npm:^0.536.0" - motion: "npm:^12.10.5" - next-themes: "npm:^0.4.6" - posthog-js: "npm:^1.246.0" - react: "npm:^19.0.0" - react-colorful: "npm:^5.6.1" - react-dom: "npm:^19.0.0" - react-i18next: "npm:^15.5.1" - react-joyride: "npm:^2.9.3" - react-markdown: "npm:^10.1.0" - react-resizable-panels: "npm:^3.0.3" - react-syntax-highlighter: "npm:^15.6.1" - react-syntax-highlighter-virtualized-renderer: "npm:^1.1.0" - react-textarea-autosize: "npm:^8.5.9" - rehype-katex: "npm:^7.0.1" - rehype-raw: "npm:^7.0.0" - remark-breaks: "npm:^4.0.0" - remark-emoji: "npm:^5.0.1" - remark-gfm: "npm:^4.0.1" - remark-math: "npm:^6.0.0" - serve: "npm:^14.2.4" - sonner: "npm:^2.0.3" - tailwind-merge: "npm:^3.3.1" - tailwindcss: "npm:^4.1.4" + class-variance-authority: "npm:0.7.1" + clsx: "npm:2.1.1" + culori: "npm:4.0.1" + emoji-picker-react: "npm:4.12.2" + eslint: "npm:9.25.1" + eslint-plugin-react-hooks: "npm:5.2.0" + eslint-plugin-react-refresh: "npm:0.4.20" + framer-motion: "npm:12.23.12" + fuse.js: "npm:7.1.0" + fzf: "npm:0.5.2" + globals: "npm:16.0.0" + i18next: "npm:25.0.2" + istanbul-api: "npm:3.0.0" + istanbul-lib-coverage: "npm:2.0.5" + istanbul-lib-report: "npm:2.0.8" + istanbul-reports: "npm:3.1.7" + jsdom: "npm:26.1.0" + katex: "npm:0.16.22" + lodash.clonedeep: "npm:4.5.0" + lodash.debounce: "npm:4.0.8" + lucide-react: "npm:0.536.0" + motion: "npm:12.18.1" + next-themes: "npm:0.4.6" + posthog-js: "npm:1.255.1" + react: "npm:19.0.0" + react-colorful: "npm:5.6.1" + react-dom: "npm:19.0.0" + react-i18next: "npm:15.5.1" + react-joyride: "npm:2.9.3" + react-markdown: "npm:10.1.0" + react-resizable-panels: "npm:3.0.5" + react-syntax-highlighter: "npm:15.6.1" + react-syntax-highlighter-virtualized-renderer: "npm:1.1.0" + react-textarea-autosize: "npm:8.5.9" + rehype-katex: "npm:7.0.1" + rehype-raw: "npm:7.0.0" + remark-breaks: "npm:4.0.0" + remark-emoji: "npm:5.0.1" + remark-gfm: "npm:4.0.1" + remark-math: "npm:6.0.0" + serve: "npm:14.2.5" + sonner: "npm:2.0.5" + tailwind-merge: "npm:3.3.1" + tailwindcss: "npm:4.1.4" token.js: "npm:token.js-fork@0.7.27" - tw-animate-css: "npm:^1.2.7" - typescript: "npm:~5.8.3" - typescript-eslint: "npm:^8.26.1" - ulidx: "npm:^2.4.1" - unified: "npm:^11.0.5" - uuid: "npm:^11.1.0" - vaul: "npm:^1.1.2" - vite: "npm:^6.3.0" - vite-plugin-node-polyfills: "npm:^0.23.0" - vite-plugin-pwa: "npm:^1.0.3" - vitest: "npm:^3.1.3" - zustand: "npm:^5.0.3" + tw-animate-css: "npm:1.2.8" + typescript: "npm:5.9.2" + typescript-eslint: "npm:8.31.0" + ulidx: "npm:2.4.1" + unified: "npm:11.0.5" + uuid: "npm:11.1.0" + vaul: "npm:1.1.2" + vite: "npm:6.3.2" + vite-plugin-node-polyfills: "npm:0.23.0" + vite-plugin-pwa: "npm:1.0.3" + vitest: "npm:3.2.4" + zustand: "npm:5.0.3" languageName: unknown linkType: soft @@ -3663,7 +3644,7 @@ __metadata: languageName: node linkType: hard -"@jridgewell/remapping@npm:^2.3.4, @jridgewell/remapping@npm:^2.3.5": +"@jridgewell/remapping@npm:^2.3.5": version: 2.3.5 resolution: "@jridgewell/remapping@npm:2.3.5" dependencies: @@ -3750,9 +3731,9 @@ __metadata: languageName: node linkType: hard -"@modelcontextprotocol/sdk@npm:^1.17.5": - version: 1.18.0 - resolution: "@modelcontextprotocol/sdk@npm:1.18.0" +"@modelcontextprotocol/sdk@npm:1.17.5": + version: 1.17.5 + resolution: "@modelcontextprotocol/sdk@npm:1.17.5" dependencies: ajv: "npm:^6.12.6" content-type: "npm:^1.0.5" @@ -3766,18 +3747,7 @@ __metadata: raw-body: "npm:^3.0.0" zod: "npm:^3.23.8" zod-to-json-schema: "npm:^3.24.1" - checksum: 10c0/73ee91a2f72bdbb9cb9ed1a20f0c35d8ba7439d34b0fb5143814834504b6b244462a5789f30ebe72568c07b4a2cf0ac5a3c15009832f5d0e9a644178f3b8f2ca - languageName: node - linkType: hard - -"@napi-rs/wasm-runtime@npm:^0.2.12": - version: 0.2.12 - resolution: "@napi-rs/wasm-runtime@npm:0.2.12" - dependencies: - "@emnapi/core": "npm:^1.4.3" - "@emnapi/runtime": "npm:^1.4.3" - "@tybys/wasm-util": "npm:^0.10.0" - checksum: 10c0/6d07922c0613aab30c6a497f4df297ca7c54e5b480e00035e0209b872d5c6aab7162fc49477267556109c2c7ed1eb9c65a174e27e9b87568106a87b0a6e3ca7d + checksum: 10c0/182b92b5e7c07da428fd23c6de22021c4f9a91f799c02a8ef15def07e4f9361d0fc22303548658fec2a700623535fd44a9dc4d010fb5d803a8f80e3c6c64a45e languageName: node linkType: hard @@ -3792,6 +3762,17 @@ __metadata: languageName: node linkType: hard +"@napi-rs/wasm-runtime@npm:^0.2.8": + version: 0.2.9 + resolution: "@napi-rs/wasm-runtime@npm:0.2.9" + dependencies: + "@emnapi/core": "npm:^1.4.0" + "@emnapi/runtime": "npm:^1.4.0" + "@tybys/wasm-util": "npm:^0.9.0" + checksum: 10c0/1cc40b854b255f84e12ade634456ba489f6bf90659ef8164a16823c515c294024c96ee2bb81ab51f35493ba9496f62842b960f915dbdcdc1791f221f989e9e59 + languageName: node + linkType: hard + "@nodelib/fs.scandir@npm:2.1.5": version: 2.1.5 resolution: "@nodelib/fs.scandir@npm:2.1.5" @@ -4124,13 +4105,6 @@ __metadata: languageName: node linkType: hard -"@posthog/core@npm:1.0.2": - version: 1.0.2 - resolution: "@posthog/core@npm:1.0.2" - checksum: 10c0/b6cb66df077230c5cbd0de15b708b7e6fa47dac20a1bcfe5308d5c1b1ec487e57c923e22a51d6f8d45acea8239562fa9546c528d5c2bef1487419c70d3a76a43 - languageName: node - linkType: hard - "@radix-ui/number@npm:1.1.1": version: 1.1.1 resolution: "@radix-ui/number@npm:1.1.1" @@ -4138,6 +4112,13 @@ __metadata: languageName: node linkType: hard +"@radix-ui/primitive@npm:1.1.2": + version: 1.1.2 + resolution: "@radix-ui/primitive@npm:1.1.2" + checksum: 10c0/5e2d2528d2fe37c16865e77b0beaac2b415a817ad13d8178db6e8187b2a092672568a64ee0041510abfde3034490a5cadd3057049bb15789020c06892047597c + languageName: node + linkType: hard + "@radix-ui/primitive@npm:1.1.3": version: 1.1.3 resolution: "@radix-ui/primitive@npm:1.1.3" @@ -4145,12 +4126,12 @@ __metadata: languageName: node linkType: hard -"@radix-ui/react-accordion@npm:^1.2.10": - version: 1.2.12 - resolution: "@radix-ui/react-accordion@npm:1.2.12" +"@radix-ui/react-accordion@npm:1.2.11": + version: 1.2.11 + resolution: "@radix-ui/react-accordion@npm:1.2.11" dependencies: - "@radix-ui/primitive": "npm:1.1.3" - "@radix-ui/react-collapsible": "npm:1.1.12" + "@radix-ui/primitive": "npm:1.1.2" + "@radix-ui/react-collapsible": "npm:1.1.11" "@radix-ui/react-collection": "npm:1.1.7" "@radix-ui/react-compose-refs": "npm:1.1.2" "@radix-ui/react-context": "npm:1.1.2" @@ -4168,7 +4149,26 @@ __metadata: optional: true "@types/react-dom": optional: true - checksum: 10c0/c64a53ce766a1ef529cf6413ed7382598c94f78879b3a83ceda27cb1894ed6eb6e8ad61f6a550ca3c7fa813657045dadfc7328dbf1d736a37e1cf3c446db43de + checksum: 10c0/40c5f09380c86e61d8c24ec596be4099cf4b26533f7de7c7f1da8c2e558dfaca93298011484e0697cb9b7fd9949b21c755d67dbc649accec877c02aac3b48a36 + languageName: node + linkType: hard + +"@radix-ui/react-arrow@npm:1.1.4": + version: 1.1.4 + resolution: "@radix-ui/react-arrow@npm:1.1.4" + dependencies: + "@radix-ui/react-primitive": "npm:2.1.0" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/ce93c35e6c85661d9ba90d235164dcbe9a1bd477dd9096763526c71348378d959f3642a017eb32fb4e72952043fddd8e100b17c67d5552250d60c8fc11551323 languageName: node linkType: hard @@ -4191,7 +4191,7 @@ __metadata: languageName: node linkType: hard -"@radix-ui/react-avatar@npm:^1.1.10": +"@radix-ui/react-avatar@npm:1.1.10": version: 1.1.10 resolution: "@radix-ui/react-avatar@npm:1.1.10" dependencies: @@ -4214,15 +4214,15 @@ __metadata: languageName: node linkType: hard -"@radix-ui/react-collapsible@npm:1.1.12": - version: 1.1.12 - resolution: "@radix-ui/react-collapsible@npm:1.1.12" +"@radix-ui/react-collapsible@npm:1.1.11": + version: 1.1.11 + resolution: "@radix-ui/react-collapsible@npm:1.1.11" dependencies: - "@radix-ui/primitive": "npm:1.1.3" + "@radix-ui/primitive": "npm:1.1.2" "@radix-ui/react-compose-refs": "npm:1.1.2" "@radix-ui/react-context": "npm:1.1.2" "@radix-ui/react-id": "npm:1.1.1" - "@radix-ui/react-presence": "npm:1.1.5" + "@radix-ui/react-presence": "npm:1.1.4" "@radix-ui/react-primitive": "npm:2.1.3" "@radix-ui/react-use-controllable-state": "npm:1.2.2" "@radix-ui/react-use-layout-effect": "npm:1.1.1" @@ -4236,7 +4236,29 @@ __metadata: optional: true "@types/react-dom": optional: true - checksum: 10c0/777cced73fbbec9cfafe6325aa5605e90f49d889af2778f4c4a6be101c07cacd69ae817d0b41cc27e3181f49392e2c06db7f32d6b084db047a51805ec70729b3 + checksum: 10c0/fa2de539ef06e2b2d18acebb12a34ce1534ca88bd484b7359aac05534d1e551fe83eaafbf60915c00161bb370f0dc9fc303903133510dea0a59fd018155b7db5 + languageName: node + linkType: hard + +"@radix-ui/react-collection@npm:1.1.4": + version: 1.1.4 + resolution: "@radix-ui/react-collection@npm:1.1.4" + dependencies: + "@radix-ui/react-compose-refs": "npm:1.1.2" + "@radix-ui/react-context": "npm:1.1.2" + "@radix-ui/react-primitive": "npm:2.1.0" + "@radix-ui/react-slot": "npm:1.2.0" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/fc03f1964789226161f2cea2a97c909feaf0e09ba5bb849a9471fb19c1e161e4d8c64588d14fba80ac869eb06c752538c0eaa328c3608ef5dddb033a2ad87770 languageName: node linkType: hard @@ -4288,7 +4310,7 @@ __metadata: languageName: node linkType: hard -"@radix-ui/react-dialog@npm:^1.1.1, @radix-ui/react-dialog@npm:^1.1.14": +"@radix-ui/react-dialog@npm:1.1.15, @radix-ui/react-dialog@npm:^1.1.1": version: 1.1.15 resolution: "@radix-ui/react-dialog@npm:1.1.15" dependencies: @@ -4333,6 +4355,29 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-dismissable-layer@npm:1.1.10": + version: 1.1.10 + resolution: "@radix-ui/react-dismissable-layer@npm:1.1.10" + dependencies: + "@radix-ui/primitive": "npm:1.1.2" + "@radix-ui/react-compose-refs": "npm:1.1.2" + "@radix-ui/react-primitive": "npm:2.1.3" + "@radix-ui/react-use-callback-ref": "npm:1.1.1" + "@radix-ui/react-use-escape-keydown": "npm:1.1.1" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/21a2d03689f5e06586135b6a735937ef14f2571fdf6044a3019bc3f9fa368a9400b5a9b631f43e8ad3682693449e369ffa7cc8642764246ce18ebe7359a45faf + languageName: node + linkType: hard + "@radix-ui/react-dismissable-layer@npm:1.1.11": version: 1.1.11 resolution: "@radix-ui/react-dismissable-layer@npm:1.1.11" @@ -4356,7 +4401,30 @@ __metadata: languageName: node linkType: hard -"@radix-ui/react-dropdown-menu@npm:^2.1.15": +"@radix-ui/react-dismissable-layer@npm:1.1.7": + version: 1.1.7 + resolution: "@radix-ui/react-dismissable-layer@npm:1.1.7" + dependencies: + "@radix-ui/primitive": "npm:1.1.2" + "@radix-ui/react-compose-refs": "npm:1.1.2" + "@radix-ui/react-primitive": "npm:2.1.0" + "@radix-ui/react-use-callback-ref": "npm:1.1.1" + "@radix-ui/react-use-escape-keydown": "npm:1.1.1" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/bb93b821ab1e24da86f4a4e74e251d9bc53c021a8a2cb4be5273af6cfe94fcd95807058a789b74bd5ca256bcb8be6dfaec3a0768f8323009dd2b2a9161964d7a + languageName: node + linkType: hard + +"@radix-ui/react-dropdown-menu@npm:2.1.16": version: 2.1.16 resolution: "@radix-ui/react-dropdown-menu@npm:2.1.16" dependencies: @@ -4381,6 +4449,19 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-focus-guards@npm:1.1.2": + version: 1.1.2 + resolution: "@radix-ui/react-focus-guards@npm:1.1.2" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10c0/8d6fa55752b9b6e55d1eebb643178e38a824e8ba418eb29031b2979077a12c4e3922892de9f984dd326f77071a14960cd81e99a960beea07598b8c80da618dc5 + languageName: node + linkType: hard + "@radix-ui/react-focus-guards@npm:1.1.3": version: 1.1.3 resolution: "@radix-ui/react-focus-guards@npm:1.1.3" @@ -4415,17 +4496,17 @@ __metadata: languageName: node linkType: hard -"@radix-ui/react-hover-card@npm:^1.1.14": - version: 1.1.15 - resolution: "@radix-ui/react-hover-card@npm:1.1.15" +"@radix-ui/react-hover-card@npm:1.1.14": + version: 1.1.14 + resolution: "@radix-ui/react-hover-card@npm:1.1.14" dependencies: - "@radix-ui/primitive": "npm:1.1.3" + "@radix-ui/primitive": "npm:1.1.2" "@radix-ui/react-compose-refs": "npm:1.1.2" "@radix-ui/react-context": "npm:1.1.2" - "@radix-ui/react-dismissable-layer": "npm:1.1.11" - "@radix-ui/react-popper": "npm:1.2.8" + "@radix-ui/react-dismissable-layer": "npm:1.1.10" + "@radix-ui/react-popper": "npm:1.2.7" "@radix-ui/react-portal": "npm:1.1.9" - "@radix-ui/react-presence": "npm:1.1.5" + "@radix-ui/react-presence": "npm:1.1.4" "@radix-ui/react-primitive": "npm:2.1.3" "@radix-ui/react-use-controllable-state": "npm:1.2.2" peerDependencies: @@ -4438,7 +4519,7 @@ __metadata: optional: true "@types/react-dom": optional: true - checksum: 10c0/c44ab88b0c62a3c1bf274b72e5cc3f5a6aea571a52bf2fcb2d471e1336738adabdbd10c26c8e72071cad444704ac28fcf2679d43132b69279564ad689839cf4e + checksum: 10c0/f352bab22dd81ac2ef1140ca1a8426913010851becd03df9d8b8476bdf6ef7001f0559f6a61c4f98ff8033d6cedacd4c86ad47e4c391385254430e266329a2a0 languageName: node linkType: hard @@ -4493,20 +4574,20 @@ __metadata: languageName: node linkType: hard -"@radix-ui/react-popover@npm:^1.1.13": - version: 1.1.15 - resolution: "@radix-ui/react-popover@npm:1.1.15" +"@radix-ui/react-popover@npm:1.1.14": + version: 1.1.14 + resolution: "@radix-ui/react-popover@npm:1.1.14" dependencies: - "@radix-ui/primitive": "npm:1.1.3" + "@radix-ui/primitive": "npm:1.1.2" "@radix-ui/react-compose-refs": "npm:1.1.2" "@radix-ui/react-context": "npm:1.1.2" - "@radix-ui/react-dismissable-layer": "npm:1.1.11" - "@radix-ui/react-focus-guards": "npm:1.1.3" + "@radix-ui/react-dismissable-layer": "npm:1.1.10" + "@radix-ui/react-focus-guards": "npm:1.1.2" "@radix-ui/react-focus-scope": "npm:1.1.7" "@radix-ui/react-id": "npm:1.1.1" - "@radix-ui/react-popper": "npm:1.2.8" + "@radix-ui/react-popper": "npm:1.2.7" "@radix-ui/react-portal": "npm:1.1.9" - "@radix-ui/react-presence": "npm:1.1.5" + "@radix-ui/react-presence": "npm:1.1.4" "@radix-ui/react-primitive": "npm:2.1.3" "@radix-ui/react-slot": "npm:1.2.3" "@radix-ui/react-use-controllable-state": "npm:1.2.2" @@ -4522,7 +4603,63 @@ __metadata: optional: true "@types/react-dom": optional: true - checksum: 10c0/c1c76b5e5985b128d03b621424fb453f769931d497759a1977734d303007da9f970570cf3ea1f6968ab609ab4a97f384168bff056197bd2d3d422abea0e3614b + checksum: 10c0/04e557bfcaab4887694d119555b101e16b8a4e99595541ff2cbe805c551be853cb02882a2ada04e6507ffc45bc092bc2b89704b7b79f5025251767d0b4f3230a + languageName: node + linkType: hard + +"@radix-ui/react-popper@npm:1.2.4": + version: 1.2.4 + resolution: "@radix-ui/react-popper@npm:1.2.4" + dependencies: + "@floating-ui/react-dom": "npm:^2.0.0" + "@radix-ui/react-arrow": "npm:1.1.4" + "@radix-ui/react-compose-refs": "npm:1.1.2" + "@radix-ui/react-context": "npm:1.1.2" + "@radix-ui/react-primitive": "npm:2.1.0" + "@radix-ui/react-use-callback-ref": "npm:1.1.1" + "@radix-ui/react-use-layout-effect": "npm:1.1.1" + "@radix-ui/react-use-rect": "npm:1.1.1" + "@radix-ui/react-use-size": "npm:1.1.1" + "@radix-ui/rect": "npm:1.1.1" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/3c0b1dac6f3e25700604424c11f0e3a29aacb430f4cf5ed78ea3acb059481c7dc6907fbb9538f068415583c03b2ba7ebb2a270e5dfd156421e4112b42ae70168 + languageName: node + linkType: hard + +"@radix-ui/react-popper@npm:1.2.7": + version: 1.2.7 + resolution: "@radix-ui/react-popper@npm:1.2.7" + dependencies: + "@floating-ui/react-dom": "npm:^2.0.0" + "@radix-ui/react-arrow": "npm:1.1.7" + "@radix-ui/react-compose-refs": "npm:1.1.2" + "@radix-ui/react-context": "npm:1.1.2" + "@radix-ui/react-primitive": "npm:2.1.3" + "@radix-ui/react-use-callback-ref": "npm:1.1.1" + "@radix-ui/react-use-layout-effect": "npm:1.1.1" + "@radix-ui/react-use-rect": "npm:1.1.1" + "@radix-ui/react-use-size": "npm:1.1.1" + "@radix-ui/rect": "npm:1.1.1" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/fb901329df5432225b0be08778a89faaa25c40e8042f0f181218e385cae26811420b6e4b1effc70955393e09d83cd462d1b0eb6ca6d33282d76692972b602ad8 languageName: node linkType: hard @@ -4554,6 +4691,26 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-portal@npm:1.1.6": + version: 1.1.6 + resolution: "@radix-ui/react-portal@npm:1.1.6" + dependencies: + "@radix-ui/react-primitive": "npm:2.1.0" + "@radix-ui/react-use-layout-effect": "npm:1.1.1" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/46bc998794848289665fc5a31c14827a56406bc5ad104fc1ba829cc52506b38989301fe5405e3960d4ac504f5176549cf5ef42e80a5e3844ce53148b4f86f31b + languageName: node + linkType: hard + "@radix-ui/react-portal@npm:1.1.9": version: 1.1.9 resolution: "@radix-ui/react-portal@npm:1.1.9" @@ -4574,6 +4731,26 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-presence@npm:1.1.4": + version: 1.1.4 + resolution: "@radix-ui/react-presence@npm:1.1.4" + dependencies: + "@radix-ui/react-compose-refs": "npm:1.1.2" + "@radix-ui/react-use-layout-effect": "npm:1.1.1" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/8202647139d6f5097b0abcc43dfba471c00b69da95ca336afe3ea23a165e05ca21992f40fc801760fe442f3e064e54e2f2cbcb9ad758c4b07ef6c69a5b6777bd + languageName: node + linkType: hard + "@radix-ui/react-presence@npm:1.1.5": version: 1.1.5 resolution: "@radix-ui/react-presence@npm:1.1.5" @@ -4594,6 +4771,25 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-primitive@npm:2.1.0": + version: 2.1.0 + resolution: "@radix-ui/react-primitive@npm:2.1.0" + dependencies: + "@radix-ui/react-slot": "npm:1.2.0" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/b436280dbd705b8b32f66b2a36a6432d90db579191fd283697d5d6a4b661ac4ee86b0f6a05e223806ce0802b2652dd8d95c6f7e0ce3c0a5567b2b1e2c3a3fcfe + languageName: node + linkType: hard + "@radix-ui/react-primitive@npm:2.1.3": version: 2.1.3 resolution: "@radix-ui/react-primitive@npm:2.1.3" @@ -4613,12 +4809,12 @@ __metadata: languageName: node linkType: hard -"@radix-ui/react-progress@npm:^1.1.4": - version: 1.1.7 - resolution: "@radix-ui/react-progress@npm:1.1.7" +"@radix-ui/react-progress@npm:1.1.4": + version: 1.1.4 + resolution: "@radix-ui/react-progress@npm:1.1.4" dependencies: "@radix-ui/react-context": "npm:1.1.2" - "@radix-ui/react-primitive": "npm:2.1.3" + "@radix-ui/react-primitive": "npm:2.1.0" peerDependencies: "@types/react": "*" "@types/react-dom": "*" @@ -4629,11 +4825,11 @@ __metadata: optional: true "@types/react-dom": optional: true - checksum: 10c0/bed5349682a75db02d362c07ac99fefddbbdc0152c4d5035719498223b9d490ebd834e2d9f64d498424048eb3da7eb7e55ba696e202cd0a048d6e319390e69d3 + checksum: 10c0/36c518c336c59dcf0629b0e9f5358ff646ac7cc110d7def7365fbe250b151b6e67c68b3581b9b39448d4116d79472d3683058b229ad2d1f11dcb4467a58cb2d3 languageName: node linkType: hard -"@radix-ui/react-radio-group@npm:^1.3.7": +"@radix-ui/react-radio-group@npm:1.3.8": version: 1.3.8 resolution: "@radix-ui/react-radio-group@npm:1.3.8" dependencies: @@ -4688,17 +4884,17 @@ __metadata: languageName: node linkType: hard -"@radix-ui/react-slider@npm:^1.3.2": - version: 1.3.6 - resolution: "@radix-ui/react-slider@npm:1.3.6" +"@radix-ui/react-slider@npm:1.3.2": + version: 1.3.2 + resolution: "@radix-ui/react-slider@npm:1.3.2" dependencies: "@radix-ui/number": "npm:1.1.1" - "@radix-ui/primitive": "npm:1.1.3" - "@radix-ui/react-collection": "npm:1.1.7" + "@radix-ui/primitive": "npm:1.1.2" + "@radix-ui/react-collection": "npm:1.1.4" "@radix-ui/react-compose-refs": "npm:1.1.2" "@radix-ui/react-context": "npm:1.1.2" "@radix-ui/react-direction": "npm:1.1.1" - "@radix-ui/react-primitive": "npm:2.1.3" + "@radix-ui/react-primitive": "npm:2.1.0" "@radix-ui/react-use-controllable-state": "npm:1.2.2" "@radix-ui/react-use-layout-effect": "npm:1.1.1" "@radix-ui/react-use-previous": "npm:1.1.1" @@ -4713,11 +4909,26 @@ __metadata: optional: true "@types/react-dom": optional: true - checksum: 10c0/a53d7854e28c5ef3d29b76c8d04cc3c723b982b643152cd5a8fefc7a8359180f8fd21753e5a08302a290bc837e7be04f2efad9d308b7a4a23326df6a6b1ac882 + checksum: 10c0/9e177aee6306397ecf6b0775f72e553df935b7049c2178e220d3582eb4d3542ed66aa4b07b5cc4bdc765641307f9d9b63dce97b905686da8b73d3025b2efd7fd languageName: node linkType: hard -"@radix-ui/react-slot@npm:1.2.3, @radix-ui/react-slot@npm:^1.2.0": +"@radix-ui/react-slot@npm:1.2.0": + version: 1.2.0 + resolution: "@radix-ui/react-slot@npm:1.2.0" + dependencies: + "@radix-ui/react-compose-refs": "npm:1.1.2" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10c0/f1455f36479e87a0a2254fc2e2b2aba6740d1fbcada949071210bf2a009a031ad508ac01b544bce96337bcca82f49531b46c71615141a5985aaa11ae69b967b1 + languageName: node + linkType: hard + +"@radix-ui/react-slot@npm:1.2.3": version: 1.2.3 resolution: "@radix-ui/react-slot@npm:1.2.3" dependencies: @@ -4732,14 +4943,14 @@ __metadata: languageName: node linkType: hard -"@radix-ui/react-switch@npm:^1.2.2": - version: 1.2.6 - resolution: "@radix-ui/react-switch@npm:1.2.6" +"@radix-ui/react-switch@npm:1.2.2": + version: 1.2.2 + resolution: "@radix-ui/react-switch@npm:1.2.2" dependencies: - "@radix-ui/primitive": "npm:1.1.3" + "@radix-ui/primitive": "npm:1.1.2" "@radix-ui/react-compose-refs": "npm:1.1.2" "@radix-ui/react-context": "npm:1.1.2" - "@radix-ui/react-primitive": "npm:2.1.3" + "@radix-ui/react-primitive": "npm:2.1.0" "@radix-ui/react-use-controllable-state": "npm:1.2.2" "@radix-ui/react-use-previous": "npm:1.1.1" "@radix-ui/react-use-size": "npm:1.1.1" @@ -4753,26 +4964,26 @@ __metadata: optional: true "@types/react-dom": optional: true - checksum: 10c0/888303cbeb0e69ebba5676b225f9ea0f00f61453c6b8a6b66384b5c5c4c7fb0ccc53493c1eb14ec6d436e5b867b302aadd6af51a1f2e6c04581c583fd9be65be + checksum: 10c0/0cae52e27fd65fc68dea5078312985c8b9f4c98447ddde9d0b913c2d31d79c1054975f2f6c52485d64c5804aa638a2e5b0877f7ea58e2cc46bfc60aaa442df2f languageName: node linkType: hard -"@radix-ui/react-tooltip@npm:^1.2.4": - version: 1.2.8 - resolution: "@radix-ui/react-tooltip@npm:1.2.8" +"@radix-ui/react-tooltip@npm:1.2.4": + version: 1.2.4 + resolution: "@radix-ui/react-tooltip@npm:1.2.4" dependencies: - "@radix-ui/primitive": "npm:1.1.3" + "@radix-ui/primitive": "npm:1.1.2" "@radix-ui/react-compose-refs": "npm:1.1.2" "@radix-ui/react-context": "npm:1.1.2" - "@radix-ui/react-dismissable-layer": "npm:1.1.11" + "@radix-ui/react-dismissable-layer": "npm:1.1.7" "@radix-ui/react-id": "npm:1.1.1" - "@radix-ui/react-popper": "npm:1.2.8" - "@radix-ui/react-portal": "npm:1.1.9" - "@radix-ui/react-presence": "npm:1.1.5" - "@radix-ui/react-primitive": "npm:2.1.3" - "@radix-ui/react-slot": "npm:1.2.3" + "@radix-ui/react-popper": "npm:1.2.4" + "@radix-ui/react-portal": "npm:1.1.6" + "@radix-ui/react-presence": "npm:1.1.4" + "@radix-ui/react-primitive": "npm:2.1.0" + "@radix-ui/react-slot": "npm:1.2.0" "@radix-ui/react-use-controllable-state": "npm:1.2.2" - "@radix-ui/react-visually-hidden": "npm:1.2.3" + "@radix-ui/react-visually-hidden": "npm:1.2.0" peerDependencies: "@types/react": "*" "@types/react-dom": "*" @@ -4783,7 +4994,7 @@ __metadata: optional: true "@types/react-dom": optional: true - checksum: 10c0/de0cbae9c571a00671f160928d819e59502f59be8749f536ab4b180181d9d70aee3925a5b2555f8f32d0bea622bc35f65b70ca7ff0449e4844f891302310cc48 + checksum: 10c0/da07e538f26a309edac954bf6bd04835209e96ec79c6812cebd656f94513b4b6667501a610aeb85f3858310be2d6c4acb3a279857bafd2578be36f30962ebee6 languageName: node linkType: hard @@ -4917,11 +5128,11 @@ __metadata: languageName: node linkType: hard -"@radix-ui/react-visually-hidden@npm:1.2.3": - version: 1.2.3 - resolution: "@radix-ui/react-visually-hidden@npm:1.2.3" +"@radix-ui/react-visually-hidden@npm:1.2.0": + version: 1.2.0 + resolution: "@radix-ui/react-visually-hidden@npm:1.2.0" dependencies: - "@radix-ui/react-primitive": "npm:2.1.3" + "@radix-ui/react-primitive": "npm:2.1.0" peerDependencies: "@types/react": "*" "@types/react-dom": "*" @@ -4932,7 +5143,7 @@ __metadata: optional: true "@types/react-dom": optional: true - checksum: 10c0/cf86a37f1cbee50a964056f3dc4f6bb1ee79c76daa321f913aa20ff3e1ccdfafbf2b114d7bb616aeefc7c4b895e6ca898523fdb67710d89bd5d8edb739a0d9b6 + checksum: 10c0/58d9dc7b39078b3da609e51d0cb0f5fa80b547ba94f8794d20616e34d5c1724b8908d6cc253797f78983eed7e29d04a092e4810161658c0d890389743cdd34c1 languageName: node linkType: hard @@ -5029,13 +5240,6 @@ __metadata: languageName: node linkType: hard -"@rolldown/pluginutils@npm:1.0.0-beta.27": - version: 1.0.0-beta.27 - resolution: "@rolldown/pluginutils@npm:1.0.0-beta.27" - checksum: 10c0/9658f235b345201d4f6bfb1f32da9754ca164f892d1cb68154fe5f53c1df42bd675ecd409836dff46884a7847d6c00bdc38af870f7c81e05bba5c2645eb4ab9c - languageName: node - linkType: hard - "@rollup/plugin-babel@npm:^5.2.0": version: 5.3.1 resolution: "@rollup/plugin-babel@npm:5.3.1" @@ -6677,148 +6881,143 @@ __metadata: languageName: node linkType: hard -"@tabler/icons-react@npm:^3.33.0": - version: 3.34.1 - resolution: "@tabler/icons-react@npm:3.34.1" +"@tabler/icons-react@npm:3.34.0": + version: 3.34.0 + resolution: "@tabler/icons-react@npm:3.34.0" dependencies: - "@tabler/icons": "npm:3.34.1" + "@tabler/icons": "npm:3.34.0" peerDependencies: react: ">= 16" - checksum: 10c0/35b6943156ee72a1362c34dec1d85f64d2f7dca5c6d19911850fa54e902b0807760b6f3f5b0e3007cbba0ea78b6330403e38d8129259b10e1d6ac5fd64a98589 + checksum: 10c0/b2d094c6ae02fc157d9a059e06c65b1dd49a96c7fc77a57bc9acf289899df66504bcab533e7a22d9ec3ca7c3952176c6c916e84aff827b24d2c69ecc7bfc737d languageName: node linkType: hard -"@tabler/icons@npm:3.34.1": - version: 3.34.1 - resolution: "@tabler/icons@npm:3.34.1" - checksum: 10c0/e5568f1f8a2446f71e6b027a7f844f263086a73c033b6e8bb1011e6662aa23eb6420f693b7a220fc4f7376867b5f1b2190ac2597c0dd3b9adcf1166875e12439 +"@tabler/icons@npm:3.34.0": + version: 3.34.0 + resolution: "@tabler/icons@npm:3.34.0" + checksum: 10c0/7b4bb937e051ece9258ab4321363f284a4c1d53fbe0211c6976bff41d0ca031e8196156595bb30fa2bfb963f1771814d1438aa01a4422df9a6e21a46ebe6cc9b languageName: node linkType: hard -"@tailwindcss/node@npm:4.1.13": - version: 4.1.13 - resolution: "@tailwindcss/node@npm:4.1.13" +"@tailwindcss/node@npm:4.1.4": + version: 4.1.4 + resolution: "@tailwindcss/node@npm:4.1.4" dependencies: - "@jridgewell/remapping": "npm:^2.3.4" - enhanced-resolve: "npm:^5.18.3" - jiti: "npm:^2.5.1" - lightningcss: "npm:1.30.1" - magic-string: "npm:^0.30.18" - source-map-js: "npm:^1.2.1" - tailwindcss: "npm:4.1.13" - checksum: 10c0/969b2eaefced271655fdf53a07737103736115c6b55fa1559c78147d17871da988c165ab2236bf4da8cdbde1e50a5116b8df2225e20f63de981d43da5b69e3f1 + enhanced-resolve: "npm:^5.18.1" + jiti: "npm:^2.4.2" + lightningcss: "npm:1.29.2" + tailwindcss: "npm:4.1.4" + checksum: 10c0/0369c89a1f3588ac4d24a156e1e0e089fc596adc82e13f88cc8817bd507876110e7be081335ab25379bce2a2d8e9e693236cde0a6e81cc4fc545211d1a32de11 languageName: node linkType: hard -"@tailwindcss/oxide-android-arm64@npm:4.1.13": - version: 4.1.13 - resolution: "@tailwindcss/oxide-android-arm64@npm:4.1.13" +"@tailwindcss/oxide-android-arm64@npm:4.1.4": + version: 4.1.4 + resolution: "@tailwindcss/oxide-android-arm64@npm:4.1.4" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@tailwindcss/oxide-darwin-arm64@npm:4.1.13": - version: 4.1.13 - resolution: "@tailwindcss/oxide-darwin-arm64@npm:4.1.13" +"@tailwindcss/oxide-darwin-arm64@npm:4.1.4": + version: 4.1.4 + resolution: "@tailwindcss/oxide-darwin-arm64@npm:4.1.4" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@tailwindcss/oxide-darwin-x64@npm:4.1.13": - version: 4.1.13 - resolution: "@tailwindcss/oxide-darwin-x64@npm:4.1.13" +"@tailwindcss/oxide-darwin-x64@npm:4.1.4": + version: 4.1.4 + resolution: "@tailwindcss/oxide-darwin-x64@npm:4.1.4" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@tailwindcss/oxide-freebsd-x64@npm:4.1.13": - version: 4.1.13 - resolution: "@tailwindcss/oxide-freebsd-x64@npm:4.1.13" +"@tailwindcss/oxide-freebsd-x64@npm:4.1.4": + version: 4.1.4 + resolution: "@tailwindcss/oxide-freebsd-x64@npm:4.1.4" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@tailwindcss/oxide-linux-arm-gnueabihf@npm:4.1.13": - version: 4.1.13 - resolution: "@tailwindcss/oxide-linux-arm-gnueabihf@npm:4.1.13" +"@tailwindcss/oxide-linux-arm-gnueabihf@npm:4.1.4": + version: 4.1.4 + resolution: "@tailwindcss/oxide-linux-arm-gnueabihf@npm:4.1.4" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@tailwindcss/oxide-linux-arm64-gnu@npm:4.1.13": - version: 4.1.13 - resolution: "@tailwindcss/oxide-linux-arm64-gnu@npm:4.1.13" +"@tailwindcss/oxide-linux-arm64-gnu@npm:4.1.4": + version: 4.1.4 + resolution: "@tailwindcss/oxide-linux-arm64-gnu@npm:4.1.4" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@tailwindcss/oxide-linux-arm64-musl@npm:4.1.13": - version: 4.1.13 - resolution: "@tailwindcss/oxide-linux-arm64-musl@npm:4.1.13" +"@tailwindcss/oxide-linux-arm64-musl@npm:4.1.4": + version: 4.1.4 + resolution: "@tailwindcss/oxide-linux-arm64-musl@npm:4.1.4" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@tailwindcss/oxide-linux-x64-gnu@npm:4.1.13": - version: 4.1.13 - resolution: "@tailwindcss/oxide-linux-x64-gnu@npm:4.1.13" +"@tailwindcss/oxide-linux-x64-gnu@npm:4.1.4": + version: 4.1.4 + resolution: "@tailwindcss/oxide-linux-x64-gnu@npm:4.1.4" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@tailwindcss/oxide-linux-x64-musl@npm:4.1.13": - version: 4.1.13 - resolution: "@tailwindcss/oxide-linux-x64-musl@npm:4.1.13" +"@tailwindcss/oxide-linux-x64-musl@npm:4.1.4": + version: 4.1.4 + resolution: "@tailwindcss/oxide-linux-x64-musl@npm:4.1.4" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@tailwindcss/oxide-wasm32-wasi@npm:4.1.13": - version: 4.1.13 - resolution: "@tailwindcss/oxide-wasm32-wasi@npm:4.1.13" +"@tailwindcss/oxide-wasm32-wasi@npm:4.1.4": + version: 4.1.4 + resolution: "@tailwindcss/oxide-wasm32-wasi@npm:4.1.4" dependencies: - "@emnapi/core": "npm:^1.4.5" - "@emnapi/runtime": "npm:^1.4.5" - "@emnapi/wasi-threads": "npm:^1.0.4" - "@napi-rs/wasm-runtime": "npm:^0.2.12" - "@tybys/wasm-util": "npm:^0.10.0" + "@emnapi/core": "npm:^1.4.0" + "@emnapi/runtime": "npm:^1.4.0" + "@emnapi/wasi-threads": "npm:^1.0.1" + "@napi-rs/wasm-runtime": "npm:^0.2.8" + "@tybys/wasm-util": "npm:^0.9.0" tslib: "npm:^2.8.0" conditions: cpu=wasm32 languageName: node linkType: hard -"@tailwindcss/oxide-win32-arm64-msvc@npm:4.1.13": - version: 4.1.13 - resolution: "@tailwindcss/oxide-win32-arm64-msvc@npm:4.1.13" +"@tailwindcss/oxide-win32-arm64-msvc@npm:4.1.4": + version: 4.1.4 + resolution: "@tailwindcss/oxide-win32-arm64-msvc@npm:4.1.4" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@tailwindcss/oxide-win32-x64-msvc@npm:4.1.13": - version: 4.1.13 - resolution: "@tailwindcss/oxide-win32-x64-msvc@npm:4.1.13" +"@tailwindcss/oxide-win32-x64-msvc@npm:4.1.4": + version: 4.1.4 + resolution: "@tailwindcss/oxide-win32-x64-msvc@npm:4.1.4" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"@tailwindcss/oxide@npm:4.1.13": - version: 4.1.13 - resolution: "@tailwindcss/oxide@npm:4.1.13" +"@tailwindcss/oxide@npm:4.1.4": + version: 4.1.4 + resolution: "@tailwindcss/oxide@npm:4.1.4" dependencies: - "@tailwindcss/oxide-android-arm64": "npm:4.1.13" - "@tailwindcss/oxide-darwin-arm64": "npm:4.1.13" - "@tailwindcss/oxide-darwin-x64": "npm:4.1.13" - "@tailwindcss/oxide-freebsd-x64": "npm:4.1.13" - "@tailwindcss/oxide-linux-arm-gnueabihf": "npm:4.1.13" - "@tailwindcss/oxide-linux-arm64-gnu": "npm:4.1.13" - "@tailwindcss/oxide-linux-arm64-musl": "npm:4.1.13" - "@tailwindcss/oxide-linux-x64-gnu": "npm:4.1.13" - "@tailwindcss/oxide-linux-x64-musl": "npm:4.1.13" - "@tailwindcss/oxide-wasm32-wasi": "npm:4.1.13" - "@tailwindcss/oxide-win32-arm64-msvc": "npm:4.1.13" - "@tailwindcss/oxide-win32-x64-msvc": "npm:4.1.13" - detect-libc: "npm:^2.0.4" - tar: "npm:^7.4.3" + "@tailwindcss/oxide-android-arm64": "npm:4.1.4" + "@tailwindcss/oxide-darwin-arm64": "npm:4.1.4" + "@tailwindcss/oxide-darwin-x64": "npm:4.1.4" + "@tailwindcss/oxide-freebsd-x64": "npm:4.1.4" + "@tailwindcss/oxide-linux-arm-gnueabihf": "npm:4.1.4" + "@tailwindcss/oxide-linux-arm64-gnu": "npm:4.1.4" + "@tailwindcss/oxide-linux-arm64-musl": "npm:4.1.4" + "@tailwindcss/oxide-linux-x64-gnu": "npm:4.1.4" + "@tailwindcss/oxide-linux-x64-musl": "npm:4.1.4" + "@tailwindcss/oxide-wasm32-wasi": "npm:4.1.4" + "@tailwindcss/oxide-win32-arm64-msvc": "npm:4.1.4" + "@tailwindcss/oxide-win32-x64-msvc": "npm:4.1.4" dependenciesMeta: "@tailwindcss/oxide-android-arm64": optional: true @@ -6844,57 +7043,57 @@ __metadata: optional: true "@tailwindcss/oxide-win32-x64-msvc": optional: true - checksum: 10c0/7cc64827b0c854724a3b371a7f1484535db5cca9f53dda359631bce9c42b043f2822db6c5359f7ed9f1c8adbc48ecb52c414454f9330ffd25a9a679686d2a83e + checksum: 10c0/1e01157774265587cdc7209f4c248a21463b0dde1672e49ff3667b6b8918bdbdc48ebb4bdf228489170dc221c5dec54492a9cdf699244562d8966ae8c6cdd508 languageName: node linkType: hard -"@tailwindcss/vite@npm:^4.1.4": - version: 4.1.13 - resolution: "@tailwindcss/vite@npm:4.1.13" +"@tailwindcss/vite@npm:4.1.4": + version: 4.1.4 + resolution: "@tailwindcss/vite@npm:4.1.4" dependencies: - "@tailwindcss/node": "npm:4.1.13" - "@tailwindcss/oxide": "npm:4.1.13" - tailwindcss: "npm:4.1.13" + "@tailwindcss/node": "npm:4.1.4" + "@tailwindcss/oxide": "npm:4.1.4" + tailwindcss: "npm:4.1.4" peerDependencies: - vite: ^5.2.0 || ^6 || ^7 - checksum: 10c0/4e9b1d54a64655b775f26816a7be52236d4716a35f88af6b835fcb4f7f466db3c9cbb6c052e5550a97b3e5cff821f337cd6d9ddefd480e71db21a2844719b20e + vite: ^5.2.0 || ^6 + checksum: 10c0/21cbc6d3069923bbbcca9fb9f851c32abde47f124eefcfb246e3870d73d3e56909118b3fdf1619b7f74fa8d45c562811a22237409b24d083b4d02a98bcafc3b1 languageName: node linkType: hard -"@tanstack/history@npm:1.131.2": - version: 1.131.2 - resolution: "@tanstack/history@npm:1.131.2" - checksum: 10c0/61760b5e705a7e590b7137476f1a462c744d249fdc417920a898f9109456bb5bab0daacc8cb7751ca67a9b1df399cd4aa50853954ee3c8f8ef282d5bd06a942b +"@tanstack/history@npm:1.115.0": + version: 1.115.0 + resolution: "@tanstack/history@npm:1.115.0" + checksum: 10c0/d9daa348a81a03478c95727cb68002a9b70a5871089d4d3a111cea9b2647f6c159b8f04b13dcd302fafa7077ec28cc1ec878e1daf23d38e72534d649d5db7fd5 languageName: node linkType: hard -"@tanstack/react-router-devtools@npm:^1.121.34": - version: 1.131.44 - resolution: "@tanstack/react-router-devtools@npm:1.131.44" +"@tanstack/react-router-devtools@npm:1.121.34": + version: 1.121.34 + resolution: "@tanstack/react-router-devtools@npm:1.121.34" dependencies: - "@tanstack/router-devtools-core": "npm:1.131.44" + "@tanstack/router-devtools-core": "npm:^1.121.34" peerDependencies: - "@tanstack/react-router": ^1.131.44 + "@tanstack/react-router": ^1.121.34 react: ">=18.0.0 || >=19.0.0" react-dom: ">=18.0.0 || >=19.0.0" - checksum: 10c0/825db6702892f69bf3e24204a9a64676505d4b34cdb184baf0928d93bc3b135e14594b37188286369e1ba169ffc84f2f448cd4c138bbb9b5d64aa0b83d01c8a3 + checksum: 10c0/815b32eafde6755a6f6f36d28590abd72db50530433b94ee864a5f37e61497b4c5b143943d1ce96786528b20e066708f8f441bf306c8b97bbc5217c65a4c12be languageName: node linkType: hard -"@tanstack/react-router@npm:^1.116.0": - version: 1.131.44 - resolution: "@tanstack/react-router@npm:1.131.44" +"@tanstack/react-router@npm:1.117.0": + version: 1.117.0 + resolution: "@tanstack/react-router@npm:1.117.0" dependencies: - "@tanstack/history": "npm:1.131.2" + "@tanstack/history": "npm:1.115.0" "@tanstack/react-store": "npm:^0.7.0" - "@tanstack/router-core": "npm:1.131.44" - isbot: "npm:^5.1.22" + "@tanstack/router-core": "npm:1.117.0" + jsesc: "npm:^3.1.0" tiny-invariant: "npm:^1.3.3" tiny-warning: "npm:^1.0.3" peerDependencies: react: ">=18.0.0 || >=19.0.0" react-dom: ">=18.0.0 || >=19.0.0" - checksum: 10c0/9766f7fb25b3ed02c24d6417064f41c74984d7b0cb2d284fc43b25be4cca981d5f3f752d4b7f6ca419ddf3fbfdc4790fbfbe3af1c432edf9827898d2e820d288 + checksum: 10c0/743d9ddcb57e48cc877e0fa2b1f7440891792c3866260dff70c76141f945c985499fa872b2a235fa775a4ca52ce74257afae9a7afa5228b8426e6eeb71c5e67c languageName: node linkType: hard @@ -6911,7 +7110,7 @@ __metadata: languageName: node linkType: hard -"@tanstack/react-virtual@npm:^3.13.12": +"@tanstack/react-virtual@npm:3.13.12": version: 3.13.12 resolution: "@tanstack/react-virtual@npm:3.13.12" dependencies: @@ -6923,77 +7122,77 @@ __metadata: languageName: node linkType: hard -"@tanstack/router-core@npm:1.131.44": - version: 1.131.44 - resolution: "@tanstack/router-core@npm:1.131.44" +"@tanstack/router-core@npm:1.117.0, @tanstack/router-core@npm:^1.117.0": + version: 1.117.0 + resolution: "@tanstack/router-core@npm:1.117.0" dependencies: - "@tanstack/history": "npm:1.131.2" + "@tanstack/history": "npm:1.115.0" "@tanstack/store": "npm:^0.7.0" - cookie-es: "npm:^1.2.2" - seroval: "npm:^1.3.2" - seroval-plugins: "npm:^1.3.2" tiny-invariant: "npm:^1.3.3" - tiny-warning: "npm:^1.0.3" - checksum: 10c0/4f6d89c4a57053e9711c925baeb80d9ebd2f29d97c13076b2706017987af7d4490ac0568b038601d3a57adbf9c0206b7ea1dc277353ac74bab44cd8f436fe886 + checksum: 10c0/ff2229bc4f36611ffaecaafe8563bd3b0fb0d4af32ef4893a512ae87280ea083d7769df3b7b11441f73c46f94f4619d67afb47e1b4b859b87e8d5b640ae5aa15 languageName: node linkType: hard -"@tanstack/router-devtools-core@npm:1.131.44": - version: 1.131.44 - resolution: "@tanstack/router-devtools-core@npm:1.131.44" +"@tanstack/router-devtools-core@npm:^1.121.34": + version: 1.121.34 + resolution: "@tanstack/router-devtools-core@npm:1.121.34" dependencies: clsx: "npm:^2.1.1" goober: "npm:^2.1.16" solid-js: "npm:^1.9.5" peerDependencies: - "@tanstack/router-core": ^1.131.44 + "@tanstack/router-core": ^1.121.34 csstype: ^3.0.10 solid-js: ">=1.9.5" tiny-invariant: ^1.3.3 peerDependenciesMeta: csstype: optional: true - checksum: 10c0/5fe2c76c3011b3d89c444f4d4bdde81ca8be064952c52294ad4e9fb9a3a35a6efd7504d34bc5671d9aa20ec21a3fc8049be43c43cf9fbd82656a4d38ba977025 + checksum: 10c0/3cdc0ee4827e4ab37a979700d062c318538a13b982ed80bb23b5235eea6fa5992940b406cc9c4e03737742a45f3ab8397aefe52a1b7913cdc48a470702a00f24 languageName: node linkType: hard -"@tanstack/router-generator@npm:1.131.44": - version: 1.131.44 - resolution: "@tanstack/router-generator@npm:1.131.44" +"@tanstack/router-generator@npm:^1.117.0": + version: 1.117.0 + resolution: "@tanstack/router-generator@npm:1.117.0" dependencies: - "@tanstack/router-core": "npm:1.131.44" - "@tanstack/router-utils": "npm:1.131.2" - "@tanstack/virtual-file-routes": "npm:1.131.2" + "@tanstack/virtual-file-routes": "npm:^1.115.0" prettier: "npm:^3.5.0" - recast: "npm:^0.23.11" - source-map: "npm:^0.7.4" tsx: "npm:^4.19.2" zod: "npm:^3.24.2" - checksum: 10c0/f85bf3154e4e0b6a6d1ef581be4c926263717f91cb340eb761a6f29eefa9a68f678c28b14c4b765331f79e10953b026188fa7590db1e60d11250a792d1e21905 + peerDependencies: + "@tanstack/react-router": ^1.117.0 + peerDependenciesMeta: + "@tanstack/react-router": + optional: true + checksum: 10c0/b251946d302566dcfa715721e5d7bf3ab06ef2860cc95c6ada513a35e5d0a9bd42425bb887cd32be39afcd898b5f644cf9363777824f82dc74cbf0c191e52bea languageName: node linkType: hard -"@tanstack/router-plugin@npm:^1.116.1": - version: 1.131.44 - resolution: "@tanstack/router-plugin@npm:1.131.44" +"@tanstack/router-plugin@npm:1.117.0": + version: 1.117.0 + resolution: "@tanstack/router-plugin@npm:1.117.0" dependencies: - "@babel/core": "npm:^7.27.7" - "@babel/plugin-syntax-jsx": "npm:^7.27.1" - "@babel/plugin-syntax-typescript": "npm:^7.27.1" - "@babel/template": "npm:^7.27.2" - "@babel/traverse": "npm:^7.27.7" - "@babel/types": "npm:^7.27.7" - "@tanstack/router-core": "npm:1.131.44" - "@tanstack/router-generator": "npm:1.131.44" - "@tanstack/router-utils": "npm:1.131.2" - "@tanstack/virtual-file-routes": "npm:1.131.2" + "@babel/core": "npm:^7.26.8" + "@babel/plugin-syntax-jsx": "npm:^7.25.9" + "@babel/plugin-syntax-typescript": "npm:^7.25.9" + "@babel/template": "npm:^7.26.8" + "@babel/traverse": "npm:^7.26.8" + "@babel/types": "npm:^7.26.8" + "@tanstack/router-core": "npm:^1.117.0" + "@tanstack/router-generator": "npm:^1.117.0" + "@tanstack/router-utils": "npm:^1.115.0" + "@tanstack/virtual-file-routes": "npm:^1.115.0" + "@types/babel__core": "npm:^7.20.5" + "@types/babel__template": "npm:^7.4.4" + "@types/babel__traverse": "npm:^7.20.6" babel-dead-code-elimination: "npm:^1.0.10" chokidar: "npm:^3.6.0" unplugin: "npm:^2.1.2" zod: "npm:^3.24.2" peerDependencies: "@rsbuild/core": ">=1.0.2" - "@tanstack/react-router": ^1.131.44 + "@tanstack/react-router": ^1.117.0 vite: ">=5.0.0 || >=6.0.0" vite-plugin-solid: ^2.11.2 webpack: ">=5.92.0" @@ -7008,21 +7207,19 @@ __metadata: optional: true webpack: optional: true - checksum: 10c0/41a8f684227d952a0060fa217717fc2e73f2838daa52a700b93fb1824a0e805a383eab4cab58ac7e697f8dee57c920de45dd60864353436ae70b4207adba3b23 + checksum: 10c0/d69b3bc66edf5f2f24dca6c00f9888c0386a58b4f549815e7886064dd76d9043797f0b5a3f93fdfbbc36ff1b9fe9d48389bbd911dd56bf0f614226932313b4c8 languageName: node linkType: hard -"@tanstack/router-utils@npm:1.131.2": - version: 1.131.2 - resolution: "@tanstack/router-utils@npm:1.131.2" +"@tanstack/router-utils@npm:^1.115.0": + version: 1.115.0 + resolution: "@tanstack/router-utils@npm:1.115.0" dependencies: - "@babel/core": "npm:^7.27.4" - "@babel/generator": "npm:^7.27.5" - "@babel/parser": "npm:^7.27.5" - "@babel/preset-typescript": "npm:^7.27.1" - ansis: "npm:^4.1.0" - diff: "npm:^8.0.2" - checksum: 10c0/15affaed0fac4323d7c785420c31dc75d58ffc1eb9e0910d96b4ad94260b5704195fcb88a56af09e31e8ff3f0609cc47b448305ac117af37e295b9f36832a229 + "@babel/generator": "npm:^7.26.8" + "@babel/parser": "npm:^7.26.8" + ansis: "npm:^3.11.0" + diff: "npm:^7.0.0" + checksum: 10c0/e4ed11346e1e61ddd2f0b16222783fa360f270078d3039efe11dc726abf56f137db68a8fc83fd47e62cbd823221a4c07cd233bc12739d35a9a82a2118ab5adfe languageName: node linkType: hard @@ -7040,10 +7237,24 @@ __metadata: languageName: node linkType: hard -"@tanstack/virtual-file-routes@npm:1.131.2": - version: 1.131.2 - resolution: "@tanstack/virtual-file-routes@npm:1.131.2" - checksum: 10c0/2c6f86c75d4532d84aeb97b3988f073826f6507afe59af3cafbc1b8f065a96f9a3143e443e6d83045d43ac2deea0c37b6142816790a4ae45d667243cd504a8fc +"@tanstack/virtual-file-routes@npm:^1.115.0": + version: 1.115.0 + resolution: "@tanstack/virtual-file-routes@npm:1.115.0" + checksum: 10c0/4df85dbffb1d15cda655644202e15f55769181e7b64949ec19740e49e9dc2f5af5353f5891619749973f3307df34d7f223a0477cbe206d3889e41b934496c6a9 + languageName: node + linkType: hard + +"@tauri-apps/api@npm:2.8.0, @tauri-apps/api@npm:^2.8.0": + version: 2.8.0 + resolution: "@tauri-apps/api@npm:2.8.0" + checksum: 10c0/fb111e4d7572372997b440ebe6879543fa8c4765151878e3fddfbfe809b18da29eed142ce83061d14a9ca6d896b3266dc8a4927c642d71cdc0b4277dc7e3aabf + languageName: node + linkType: hard + +"@tauri-apps/api@npm:^2.0.0": + version: 2.5.0 + resolution: "@tauri-apps/api@npm:2.5.0" + checksum: 10c0/8eeb28049d48f5f89a5419cdf313bb159305204b193a5f27ebddbe0704ff43037c8b2e78518de831d7393e00178f0c0ac66cef1a57b99c632de71eca29f562c0 languageName: node linkType: hard @@ -7054,13 +7265,6 @@ __metadata: languageName: node linkType: hard -"@tauri-apps/api@npm:^2.8.0": - version: 2.8.0 - resolution: "@tauri-apps/api@npm:2.8.0" - checksum: 10c0/fb111e4d7572372997b440ebe6879543fa8c4765151878e3fddfbfe809b18da29eed142ce83061d14a9ca6d896b3266dc8a4927c642d71cdc0b4277dc7e3aabf - languageName: node - linkType: hard - "@tauri-apps/cli-darwin-arm64@npm:2.8.4": version: 2.8.4 resolution: "@tauri-apps/cli-darwin-arm64@npm:2.8.4" @@ -7191,52 +7395,52 @@ __metadata: languageName: node linkType: hard -"@tauri-apps/plugin-dialog@npm:^2.2.1": - version: 2.4.0 - resolution: "@tauri-apps/plugin-dialog@npm:2.4.0" +"@tauri-apps/plugin-dialog@npm:2.2.2": + version: 2.2.2 + resolution: "@tauri-apps/plugin-dialog@npm:2.2.2" dependencies: - "@tauri-apps/api": "npm:^2.8.0" - checksum: 10c0/6c75bc0cfc3a2c0bc1298ff9ef19c5afe9273b1f24c224110ae9b37384e4d9efe8645fefeb4031cbbbba0dab1a0b0f301ac4f773349de2fd8a22bcd228b297c5 + "@tauri-apps/api": "npm:^2.0.0" + checksum: 10c0/d08a30c35d93bb99ac9f8a33c98d8e4bab83308346b8db0ecf54ad8dffc798623fc4db16fb4c40167b905d894012e04577106b96b2fcccb53960d5a9544e8ccd languageName: node linkType: hard -"@tauri-apps/plugin-http@npm:^2.2.1": - version: 2.5.2 - resolution: "@tauri-apps/plugin-http@npm:2.5.2" - dependencies: - "@tauri-apps/api": "npm:^2.8.0" - checksum: 10c0/14ca96a1f3cca03a7f391bc04e3d4cb693bd56595ce01b9ce037342733b428c4ca781aa573968352332361fe7c3a438be7603db4d03f681db90b890daaa3e152 - languageName: node - linkType: hard - -"@tauri-apps/plugin-opener@npm:^2.2.7": +"@tauri-apps/plugin-http@npm:2.5.0": version: 2.5.0 - resolution: "@tauri-apps/plugin-opener@npm:2.5.0" - dependencies: - "@tauri-apps/api": "npm:^2.8.0" - checksum: 10c0/31503644c64678e5f5d1d995c0db145a3dabeb1bef1b9f7cfef84a83e4188c169f630207705fc6484f9e1934be6bd59de50676e4b9f1e2f628d1b54e38f00dbd - languageName: node - linkType: hard - -"@tauri-apps/plugin-os@npm:^2.2.1": - version: 2.3.1 - resolution: "@tauri-apps/plugin-os@npm:2.3.1" - dependencies: - "@tauri-apps/api": "npm:^2.8.0" - checksum: 10c0/fc40d3becbea0ac9e868bbc442bd34d0994b60a70e4c414b71e8724b731b63e2149a9b995ff11c9944880f86de4a9db48f72a2f6054b3b515b79e66bc7ecdbfa - languageName: node - linkType: hard - -"@tauri-apps/plugin-updater@npm:^2.7.1": - version: 2.9.0 - resolution: "@tauri-apps/plugin-updater@npm:2.9.0" + resolution: "@tauri-apps/plugin-http@npm:2.5.0" dependencies: "@tauri-apps/api": "npm:^2.6.0" - checksum: 10c0/72ce83d1c241308a13b9929f0900e4d33453875877009166e3998e3e75a1003ac48c3641086b4d3230f0f18c64f475ad6c3556d1603fc641ca50dc9c18d61866 + checksum: 10c0/eed47bb2adf012cde4409c4decae30e6b759f5828cb959cf43fc34c5fdfe68e6670f14f1134c8c4c941bc3fdb00e312772ebd72ec94e15c56ed1b7fbd47dd91c languageName: node linkType: hard -"@testing-library/dom@npm:^10.4.0": +"@tauri-apps/plugin-opener@npm:2.3.0": + version: 2.3.0 + resolution: "@tauri-apps/plugin-opener@npm:2.3.0" + dependencies: + "@tauri-apps/api": "npm:^2.0.0" + checksum: 10c0/6b4e9cd572eb17e528e41814356bd2ea0c2ec5a5858e8087ba19f9e2bb769c513d4f262b222e4347555ec3ddc5289f11bc4e62e6860f2525840570789c45bf27 + languageName: node + linkType: hard + +"@tauri-apps/plugin-os@npm:2.2.1": + version: 2.2.1 + resolution: "@tauri-apps/plugin-os@npm:2.2.1" + dependencies: + "@tauri-apps/api": "npm:^2.0.0" + checksum: 10c0/bfd3e213f420cf56c8f4e569dcdf69c9b3d1ca5655b5f642926d5bf5a00855d6b088df2aef6a0ac99421bf5d321f1477f8a1adfa532a8e48d7bd08303cb45a4e + languageName: node + linkType: hard + +"@tauri-apps/plugin-updater@npm:2.8.1": + version: 2.8.1 + resolution: "@tauri-apps/plugin-updater@npm:2.8.1" + dependencies: + "@tauri-apps/api": "npm:^2.0.0" + checksum: 10c0/0f36fd7a2461ec793f2ee1b82b453c67f9d054db0236556f0cbfd256d6ca13bd19a7824db08aa8a45f47a9f015cb3aad1f193cb5cbf05347d8757410cbc27090 + languageName: node + linkType: hard + +"@testing-library/dom@npm:10.4.1": version: 10.4.1 resolution: "@testing-library/dom@npm:10.4.1" dependencies: @@ -7252,7 +7456,7 @@ __metadata: languageName: node linkType: hard -"@testing-library/jest-dom@npm:^6.6.3": +"@testing-library/jest-dom@npm:6.8.0": version: 6.8.0 resolution: "@testing-library/jest-dom@npm:6.8.0" dependencies: @@ -7266,7 +7470,7 @@ __metadata: languageName: node linkType: hard -"@testing-library/react@npm:^16.3.0": +"@testing-library/react@npm:16.3.0": version: 16.3.0 resolution: "@testing-library/react@npm:16.3.0" dependencies: @@ -7286,7 +7490,7 @@ __metadata: languageName: node linkType: hard -"@testing-library/user-event@npm:^14.6.1": +"@testing-library/user-event@npm:14.6.1": version: 14.6.1 resolution: "@testing-library/user-event@npm:14.6.1" peerDependencies: @@ -7322,15 +7526,6 @@ __metadata: languageName: node linkType: hard -"@tybys/wasm-util@npm:^0.10.0": - version: 0.10.1 - resolution: "@tybys/wasm-util@npm:0.10.1" - dependencies: - tslib: "npm:^2.4.0" - checksum: 10c0/b255094f293794c6d2289300c5fbcafbb5532a3aed3a5ffd2f8dc1828e639b88d75f6a376dd8f94347a44813fd7a7149d8463477a9a49525c8b2dcaa38c2d1e8 - languageName: node - linkType: hard - "@tybys/wasm-util@npm:^0.9.0": version: 0.9.0 resolution: "@tybys/wasm-util@npm:0.9.0" @@ -7369,7 +7564,7 @@ __metadata: languageName: node linkType: hard -"@types/babel__template@npm:*": +"@types/babel__template@npm:*, @types/babel__template@npm:^7.4.4": version: 7.4.4 resolution: "@types/babel__template@npm:7.4.4" dependencies: @@ -7388,6 +7583,15 @@ __metadata: languageName: node linkType: hard +"@types/babel__traverse@npm:^7.20.6": + version: 7.20.7 + resolution: "@types/babel__traverse@npm:7.20.7" + dependencies: + "@babel/types": "npm:^7.20.7" + checksum: 10c0/5386f0af44f8746b063b87418f06129a814e16bb2686965a575e9d7376b360b088b89177778d8c426012abc43dd1a2d8ec3218bfc382280c898682746ce2ffbd + languageName: node + linkType: hard + "@types/chai@npm:^5.2.2": version: 5.2.2 resolution: "@types/chai@npm:5.2.2" @@ -7397,7 +7601,7 @@ __metadata: languageName: node linkType: hard -"@types/culori@npm:^2.1.1": +"@types/culori@npm:2.1.1": version: 2.1.1 resolution: "@types/culori@npm:2.1.1" checksum: 10c0/75b0c1de1e6f23ae8e6efa78f15fcb13e069ffdbe7334c0e6aa728b43338faf5dbfbc2a4f23b5d7d5feaafcc020889da93b0e4daff4721001311a9155464d969 @@ -7482,7 +7686,7 @@ __metadata: languageName: node linkType: hard -"@types/istanbul-lib-report@npm:*, @types/istanbul-lib-report@npm:^3": +"@types/istanbul-lib-report@npm:*, @types/istanbul-lib-report@npm:3.0.3": version: 3.0.3 resolution: "@types/istanbul-lib-report@npm:3.0.3" dependencies: @@ -7491,7 +7695,7 @@ __metadata: languageName: node linkType: hard -"@types/istanbul-reports@npm:^3": +"@types/istanbul-reports@npm:3.0.4": version: 3.0.4 resolution: "@types/istanbul-reports@npm:3.0.4" dependencies: @@ -7514,7 +7718,7 @@ __metadata: languageName: node linkType: hard -"@types/lodash.clonedeep@npm:^4": +"@types/lodash.clonedeep@npm:4.5.9": version: 4.5.9 resolution: "@types/lodash.clonedeep@npm:4.5.9" dependencies: @@ -7523,7 +7727,7 @@ __metadata: languageName: node linkType: hard -"@types/lodash.debounce@npm:^4": +"@types/lodash.debounce@npm:4.0.9": version: 4.0.9 resolution: "@types/lodash.debounce@npm:4.0.9" dependencies: @@ -7574,6 +7778,15 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:22.14.1": + version: 22.14.1 + resolution: "@types/node@npm:22.14.1" + dependencies: + undici-types: "npm:~6.21.0" + checksum: 10c0/d49c4d00403b1c2348cf0701b505fd636d80aabe18102105998dc62fdd36dcaf911e73c7a868c48c21c1022b825c67b475b65b1222d84b704d8244d152bb7f86 + languageName: node + linkType: hard + "@types/node@npm:^18.11.18": version: 18.19.124 resolution: "@types/node@npm:18.19.124" @@ -7592,15 +7805,6 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^22.14.1": - version: 22.14.1 - resolution: "@types/node@npm:22.14.1" - dependencies: - undici-types: "npm:~6.21.0" - checksum: 10c0/d49c4d00403b1c2348cf0701b505fd636d80aabe18102105998dc62fdd36dcaf911e73c7a868c48c21c1022b825c67b475b65b1222d84b704d8244d152bb7f86 - languageName: node - linkType: hard - "@types/prismjs@npm:^1.0.0": version: 1.26.5 resolution: "@types/prismjs@npm:1.26.5" @@ -7608,16 +7812,16 @@ __metadata: languageName: node linkType: hard -"@types/react-dom@npm:^19.0.4": - version: 19.1.9 - resolution: "@types/react-dom@npm:19.1.9" +"@types/react-dom@npm:19.1.2": + version: 19.1.2 + resolution: "@types/react-dom@npm:19.1.2" peerDependencies: "@types/react": ^19.0.0 - checksum: 10c0/34c8dda86c1590b3ef0e7ecd38f9663a66ba2dd69113ba74fb0adc36b83bbfb8c94c1487a2505282a5f7e5e000d2ebf36f4c0fd41b3b672f5178fd1d4f1f8f58 + checksum: 10c0/100c341cacba9ec8ae1d47ee051072a3450e9573bf8eeb7262490e341cb246ea0f95a07a1f2077e61cf92648f812a0324c602fcd811bd87b7ce41db2811510cd languageName: node linkType: hard -"@types/react-syntax-highlighter@npm:^15.5.13": +"@types/react-syntax-highlighter@npm:15.5.13": version: 15.5.13 resolution: "@types/react-syntax-highlighter@npm:15.5.13" dependencies: @@ -7635,7 +7839,7 @@ __metadata: languageName: node linkType: hard -"@types/react@npm:^19.0.10": +"@types/react@npm:19.1.2": version: 19.1.2 resolution: "@types/react@npm:19.1.2" dependencies: @@ -7672,7 +7876,7 @@ __metadata: languageName: node linkType: hard -"@types/uuid@npm:^10.0.0": +"@types/uuid@npm:10.0.0": version: 10.0.0 resolution: "@types/uuid@npm:10.0.0" checksum: 10c0/9a1404bf287164481cb9b97f6bb638f78f955be57c40c6513b7655160beb29df6f84c915aaf4089a1559c216557dc4d2f79b48d978742d3ae10b937420ddac60 @@ -7686,144 +7890,119 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:8.43.0": - version: 8.43.0 - resolution: "@typescript-eslint/eslint-plugin@npm:8.43.0" +"@typescript-eslint/eslint-plugin@npm:8.31.0": + version: 8.31.0 + resolution: "@typescript-eslint/eslint-plugin@npm:8.31.0" dependencies: "@eslint-community/regexpp": "npm:^4.10.0" - "@typescript-eslint/scope-manager": "npm:8.43.0" - "@typescript-eslint/type-utils": "npm:8.43.0" - "@typescript-eslint/utils": "npm:8.43.0" - "@typescript-eslint/visitor-keys": "npm:8.43.0" + "@typescript-eslint/scope-manager": "npm:8.31.0" + "@typescript-eslint/type-utils": "npm:8.31.0" + "@typescript-eslint/utils": "npm:8.31.0" + "@typescript-eslint/visitor-keys": "npm:8.31.0" graphemer: "npm:^1.4.0" - ignore: "npm:^7.0.0" + ignore: "npm:^5.3.1" natural-compare: "npm:^1.4.0" - ts-api-utils: "npm:^2.1.0" + ts-api-utils: "npm:^2.0.1" peerDependencies: - "@typescript-eslint/parser": ^8.43.0 + "@typescript-eslint/parser": ^8.0.0 || ^8.0.0-alpha.0 eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/9823f6e917d16f95a87fb1fd6c224f361a9f17386453ac97d7d457774cf2ea7bdbcfad37ad063b71ec01a4292127a8bfe69d1987b948e85def2410de8fe353dd + typescript: ">=4.8.4 <5.9.0" + checksum: 10c0/7d78e0cdcc967742752d49d2d38986ee38d0b7ca64af247e5fe0816cea9ae5f1bfa5c126154acc0846af515c4fb1c52c96926ee25c73b4c3f7e6fd73cb6d2b0e languageName: node linkType: hard -"@typescript-eslint/parser@npm:8.43.0": - version: 8.43.0 - resolution: "@typescript-eslint/parser@npm:8.43.0" +"@typescript-eslint/parser@npm:8.31.0": + version: 8.31.0 + resolution: "@typescript-eslint/parser@npm:8.31.0" dependencies: - "@typescript-eslint/scope-manager": "npm:8.43.0" - "@typescript-eslint/types": "npm:8.43.0" - "@typescript-eslint/typescript-estree": "npm:8.43.0" - "@typescript-eslint/visitor-keys": "npm:8.43.0" + "@typescript-eslint/scope-manager": "npm:8.31.0" + "@typescript-eslint/types": "npm:8.31.0" + "@typescript-eslint/typescript-estree": "npm:8.31.0" + "@typescript-eslint/visitor-keys": "npm:8.31.0" debug: "npm:^4.3.4" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/b8296d3fac08f6e03c931843264a4219469a6a7d5c4d269fb14fe4c1547477a0dd1c259e6929c749efa043fb4e272436adfc94afdf07039d3b1d9e6956a6a0ea + typescript: ">=4.8.4 <5.9.0" + checksum: 10c0/9bd903b3ea4e24bfeb444d7a5c2ed82e591ef5cffc0874c609de854c05d34935cd85543e66678ecdb8e0e3eae2cda2df5c1ba66eb72010632cb9f8779031d56d languageName: node linkType: hard -"@typescript-eslint/project-service@npm:8.43.0": - version: 8.43.0 - resolution: "@typescript-eslint/project-service@npm:8.43.0" +"@typescript-eslint/scope-manager@npm:8.31.0": + version: 8.31.0 + resolution: "@typescript-eslint/scope-manager@npm:8.31.0" dependencies: - "@typescript-eslint/tsconfig-utils": "npm:^8.43.0" - "@typescript-eslint/types": "npm:^8.43.0" + "@typescript-eslint/types": "npm:8.31.0" + "@typescript-eslint/visitor-keys": "npm:8.31.0" + checksum: 10c0/eae758a24cc578fa351b8bf0c30c50de384292c0b05a58762f9b632d65a009bd5d902d806eccb6b678cc0b09686289fb4f1fd67da7f12d59ad43ff033b35cc4f + languageName: node + linkType: hard + +"@typescript-eslint/type-utils@npm:8.31.0": + version: 8.31.0 + resolution: "@typescript-eslint/type-utils@npm:8.31.0" + dependencies: + "@typescript-eslint/typescript-estree": "npm:8.31.0" + "@typescript-eslint/utils": "npm:8.31.0" debug: "npm:^4.3.4" - peerDependencies: - typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/c9058b5fbf9642c35a303641e4ff2d0df1ddac337275bab84b56167f1019fbcb7e69959239fed82e53c747f58d6ee4c1859cf5b018803cba1b1aab430439d728 - languageName: node - linkType: hard - -"@typescript-eslint/scope-manager@npm:8.43.0": - version: 8.43.0 - resolution: "@typescript-eslint/scope-manager@npm:8.43.0" - dependencies: - "@typescript-eslint/types": "npm:8.43.0" - "@typescript-eslint/visitor-keys": "npm:8.43.0" - checksum: 10c0/f87b3c3a5d3ad18326945288fa5b9b9fa662d87f466dc159e1514e00e359e830b80557f213acb3d23d5d600826b4cc4cfa5d2d479f8aba1b9834df19a640a779 - languageName: node - linkType: hard - -"@typescript-eslint/tsconfig-utils@npm:8.43.0, @typescript-eslint/tsconfig-utils@npm:^8.43.0": - version: 8.43.0 - resolution: "@typescript-eslint/tsconfig-utils@npm:8.43.0" - peerDependencies: - typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/b3a472368ad31e31e58ef019f6afec7387f5885e3fd423c71f3910b6d6b767324fde8bd60bec2e7505cc130317ece7fbc91314c44cdfea74ff76b5039bf26d52 - languageName: node - linkType: hard - -"@typescript-eslint/type-utils@npm:8.43.0": - version: 8.43.0 - resolution: "@typescript-eslint/type-utils@npm:8.43.0" - dependencies: - "@typescript-eslint/types": "npm:8.43.0" - "@typescript-eslint/typescript-estree": "npm:8.43.0" - "@typescript-eslint/utils": "npm:8.43.0" - debug: "npm:^4.3.4" - ts-api-utils: "npm:^2.1.0" + ts-api-utils: "npm:^2.0.1" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/70e61233fd586c4545b0ee11871001ba603816fccb69b9fe883a653b32aa049e957a97f208f522b58480a4f4e1c6322b9a3ef60a389925eaefba94abcd44ff7e + typescript: ">=4.8.4 <5.9.0" + checksum: 10c0/f6938413a583430468b259f6823bb2ab1b5cd77cd6d4e21e1803df70e329046b9579aed5bdc9bdcf4046c8091615a911ac3990859db78d00210bb867915ba37f languageName: node linkType: hard -"@typescript-eslint/types@npm:8.43.0, @typescript-eslint/types@npm:^8.43.0": - version: 8.43.0 - resolution: "@typescript-eslint/types@npm:8.43.0" - checksum: 10c0/60d19b695affce128fe1076ebe4cff7e05d38dd50155d653fc9e995eafa56c299fd49ad4d9d2997f118a75fb57e3ca18001623bc3ef3fa0111f863079203e4b2 +"@typescript-eslint/types@npm:8.31.0": + version: 8.31.0 + resolution: "@typescript-eslint/types@npm:8.31.0" + checksum: 10c0/04130a30aac477d36d6a155399b27773457aeb9b485ef8fb56fee05725b6e36768c9fac7e4d1f073fd16988de0eb7dffc743c3f834ae907cf918cabb075e5cd8 languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:8.43.0": - version: 8.43.0 - resolution: "@typescript-eslint/typescript-estree@npm:8.43.0" +"@typescript-eslint/typescript-estree@npm:8.31.0": + version: 8.31.0 + resolution: "@typescript-eslint/typescript-estree@npm:8.31.0" dependencies: - "@typescript-eslint/project-service": "npm:8.43.0" - "@typescript-eslint/tsconfig-utils": "npm:8.43.0" - "@typescript-eslint/types": "npm:8.43.0" - "@typescript-eslint/visitor-keys": "npm:8.43.0" + "@typescript-eslint/types": "npm:8.31.0" + "@typescript-eslint/visitor-keys": "npm:8.31.0" debug: "npm:^4.3.4" fast-glob: "npm:^3.3.2" is-glob: "npm:^4.0.3" minimatch: "npm:^9.0.4" semver: "npm:^7.6.0" - ts-api-utils: "npm:^2.1.0" + ts-api-utils: "npm:^2.0.1" peerDependencies: - typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/184ba925067d7fbcb377450195a89511f030a49d080e27058fa78078a069d86c1936b1a82ce6f19ff24c30c4de8b779deb050c36b06db5372c95fc7e5be7115a + typescript: ">=4.8.4 <5.9.0" + checksum: 10c0/0ec074b2b9c49f80fafea716aa0cc4b05085e65730a3ef7c7d2d39db1657a40b38abe83f22bbe15ac4f6fdf576692f47d2d057347242e6cef5be81d070f55064 languageName: node linkType: hard -"@typescript-eslint/utils@npm:8.43.0": - version: 8.43.0 - resolution: "@typescript-eslint/utils@npm:8.43.0" +"@typescript-eslint/utils@npm:8.31.0": + version: 8.31.0 + resolution: "@typescript-eslint/utils@npm:8.31.0" dependencies: - "@eslint-community/eslint-utils": "npm:^4.7.0" - "@typescript-eslint/scope-manager": "npm:8.43.0" - "@typescript-eslint/types": "npm:8.43.0" - "@typescript-eslint/typescript-estree": "npm:8.43.0" + "@eslint-community/eslint-utils": "npm:^4.4.0" + "@typescript-eslint/scope-manager": "npm:8.31.0" + "@typescript-eslint/types": "npm:8.31.0" + "@typescript-eslint/typescript-estree": "npm:8.31.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/42fc8c60551361d80b5c53b303ba8cd20cf914665168416ad0a278cd44aae587311af9e4461f92ed28b5f36091d275a0e9974482d5e9ba95fc00108a537cdd36 + typescript: ">=4.8.4 <5.9.0" + checksum: 10c0/1fd4f62e16a44a5be2de501f70ba4b2d64479e014370bde7bbc6de6897cf1699766a8b7be4deb9b0328e74c2b4171839336ede4e3c60fec6ac8378b623a75275 languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:8.43.0": - version: 8.43.0 - resolution: "@typescript-eslint/visitor-keys@npm:8.43.0" +"@typescript-eslint/visitor-keys@npm:8.31.0": + version: 8.31.0 + resolution: "@typescript-eslint/visitor-keys@npm:8.31.0" dependencies: - "@typescript-eslint/types": "npm:8.43.0" - eslint-visitor-keys: "npm:^4.2.1" - checksum: 10c0/5d576eaf7bea41933ba726f4b24410bd3fc2521ef286967c3dc630c6a90fabff2a2d7c4d12cb841d3f946d2e5e6fb2605e7edd84e3360308fe379dbf2b8dc2fa + "@typescript-eslint/types": "npm:8.31.0" + eslint-visitor-keys: "npm:^4.2.0" + checksum: 10c0/e41e2a9e287d11232cda6126377d1df4de69c6e9dc2a14058819cff15280ec654a3877886a6806728196f299766cfbb0b299eb021c2ce168eb15dff5eb07b51b languageName: node linkType: hard -"@uiw/react-textarea-code-editor@npm:^3.1.1": +"@uiw/react-textarea-code-editor@npm:3.1.1": version: 3.1.1 resolution: "@uiw/react-textarea-code-editor@npm:3.1.1" dependencies: @@ -7845,19 +8024,18 @@ __metadata: languageName: node linkType: hard -"@vitejs/plugin-react@npm:^4.3.4": - version: 4.7.0 - resolution: "@vitejs/plugin-react@npm:4.7.0" +"@vitejs/plugin-react@npm:4.4.1": + version: 4.4.1 + resolution: "@vitejs/plugin-react@npm:4.4.1" dependencies: - "@babel/core": "npm:^7.28.0" - "@babel/plugin-transform-react-jsx-self": "npm:^7.27.1" - "@babel/plugin-transform-react-jsx-source": "npm:^7.27.1" - "@rolldown/pluginutils": "npm:1.0.0-beta.27" + "@babel/core": "npm:^7.26.10" + "@babel/plugin-transform-react-jsx-self": "npm:^7.25.9" + "@babel/plugin-transform-react-jsx-source": "npm:^7.25.9" "@types/babel__core": "npm:^7.20.5" react-refresh: "npm:^0.17.0" peerDependencies: - vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 - checksum: 10c0/692f23960972879485d647713663ec299c478222c96567d60285acf7c7dc5c178e71abfe9d2eefddef1eeb01514dacbc2ed68aad84628debf9c7116134734253 + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 + checksum: 10c0/0eda45f2026cdfff4b172b1b2148824e5ac41ce65f1f1ce108f3ce4de2f0024caf79c811c1305a782168a269b0b1bc58d4cf8eaf164e4ef19954f05428ba7077 languageName: node linkType: hard @@ -8144,6 +8322,15 @@ __metadata: languageName: node linkType: hard +"acorn@npm:^8.14.0": + version: 8.14.1 + resolution: "acorn@npm:8.14.1" + bin: + acorn: bin/acorn + checksum: 10c0/dbd36c1ed1d2fa3550140000371fcf721578095b18777b85a79df231ca093b08edc6858d75d6e48c73e431c174dcf9214edbd7e6fa5911b93bd8abfa54e47123 + languageName: node + linkType: hard + "acorn@npm:^8.15.0": version: 8.15.0 resolution: "acorn@npm:8.15.0" @@ -8270,10 +8457,10 @@ __metadata: languageName: node linkType: hard -"ansis@npm:^4.1.0": - version: 4.1.0 - resolution: "ansis@npm:4.1.0" - checksum: 10c0/df62d017a7791babdaf45b93f930d2cfd6d1dab5568b610735c11434c9a5ef8f513740e7cfd80bcbc3530fc8bd892b88f8476f26621efc251230e53cbd1a2c24 +"ansis@npm:^3.11.0": + version: 3.17.0 + resolution: "ansis@npm:3.17.0" + checksum: 10c0/d8fa94ca7bb91e7e5f8a7d323756aa075facce07c5d02ca883673e128b2873d16f93e0dec782f98f1eeb1f2b3b4b7b60dcf0ad98fb442e75054fe857988cc5cb languageName: node linkType: hard @@ -8484,15 +8671,6 @@ __metadata: languageName: node linkType: hard -"ast-types@npm:^0.16.1": - version: 0.16.1 - resolution: "ast-types@npm:0.16.1" - dependencies: - tslib: "npm:^2.0.1" - checksum: 10c0/abcc49e42eb921a7ebc013d5bec1154651fb6dbc3f497541d488859e681256901b2990b954d530ba0da4d0851271d484f7057d5eff5e07cb73e8b10909f711bf - languageName: node - linkType: hard - "ast-v8-to-istanbul@npm:^0.3.3": version: 0.3.5 resolution: "ast-v8-to-istanbul@npm:0.3.5" @@ -9388,7 +9566,7 @@ __metadata: languageName: node linkType: hard -"class-variance-authority@npm:^0.7.1": +"class-variance-authority@npm:0.7.1": version: 0.7.1 resolution: "class-variance-authority@npm:0.7.1" dependencies: @@ -9422,6 +9600,13 @@ __metadata: languageName: node linkType: hard +"clsx@npm:2.1.1, clsx@npm:^2.1.1": + version: 2.1.1 + resolution: "clsx@npm:2.1.1" + checksum: 10c0/c4c8eb865f8c82baab07e71bfa8897c73454881c4f99d6bc81585aecd7c441746c1399d08363dc096c550cceaf97bd4ce1e8854e1771e9998d9f94c4fe075839 + languageName: node + linkType: hard + "clsx@npm:^1.0.4": version: 1.2.1 resolution: "clsx@npm:1.2.1" @@ -9429,13 +9614,6 @@ __metadata: languageName: node linkType: hard -"clsx@npm:^2.1.1": - version: 2.1.1 - resolution: "clsx@npm:2.1.1" - checksum: 10c0/c4c8eb865f8c82baab07e71bfa8897c73454881c4f99d6bc81585aecd7c441746c1399d08363dc096c550cceaf97bd4ce1e8854e1771e9998d9f94c4fe075839 - languageName: node - linkType: hard - "cmd-shim@npm:^6.0.0": version: 6.0.3 resolution: "cmd-shim@npm:6.0.3" @@ -9629,13 +9807,6 @@ __metadata: languageName: node linkType: hard -"cookie-es@npm:^1.2.2": - version: 1.2.2 - resolution: "cookie-es@npm:1.2.2" - checksum: 10c0/210eb67cd40a53986fda99d6f47118cfc45a69c4abc03490d15ab1b83ac978d5518356aecdd7a7a4969292445e3063c2302deda4c73706a67edc008127608638 - languageName: node - linkType: hard - "cookie-signature@npm:^1.2.1": version: 1.2.2 resolution: "cookie-signature@npm:1.2.2" @@ -9864,10 +10035,10 @@ __metadata: languageName: node linkType: hard -"culori@npm:^4.0.1": - version: 4.0.2 - resolution: "culori@npm:4.0.2" - checksum: 10c0/5d3c952b947ac5915409bab513e1d2e8bd813caa491af8ded0c769fdc1186a5ff61fb3c59fc8edf5393237d92074dbc54a492e6e99cb039dd6535d5d96106bfe +"culori@npm:4.0.1": + version: 4.0.1 + resolution: "culori@npm:4.0.1" + checksum: 10c0/4efc4a41151c5c2660913a8276f6d9bc82be63c76a56251d0a975e04196b5fde63e37f2f9e4ecb5a69029c6b34320a3a0f92225dd0ed03a3503dea3e9e2b8999 languageName: node linkType: hard @@ -10104,7 +10275,7 @@ __metadata: languageName: node linkType: hard -"detect-libc@npm:^2.0.3, detect-libc@npm:^2.0.4": +"detect-libc@npm:^2.0.3": version: 2.1.0 resolution: "detect-libc@npm:2.1.0" checksum: 10c0/4d0d36c77fdcb1d3221779d8dfc7d5808dd52530d49db67193fb3cd8149e2d499a1eeb87bb830ad7c442294929992c12e971f88ae492965549f8f83e5336eba6 @@ -10127,10 +10298,10 @@ __metadata: languageName: node linkType: hard -"diff@npm:^8.0.2": - version: 8.0.2 - resolution: "diff@npm:8.0.2" - checksum: 10c0/abfb387f033e089df3ec3be960205d17b54df8abf0924d982a7ced3a94c557a4e6cbff2e78b121f216b85f466b3d8d041673a386177c311aaea41459286cc9bc +"diff@npm:^7.0.0": + version: 7.0.0 + resolution: "diff@npm:7.0.0" + checksum: 10c0/251fd15f85ffdf814cfc35a728d526b8d2ad3de338dcbd011ac6e57c461417090766b28995f8ff733135b5fbc3699c392db1d5e27711ac4e00244768cd1d577b languageName: node linkType: hard @@ -10285,14 +10456,14 @@ __metadata: languageName: node linkType: hard -"emoji-picker-react@npm:^4.12.2": - version: 4.13.3 - resolution: "emoji-picker-react@npm:4.13.3" +"emoji-picker-react@npm:4.12.2": + version: 4.12.2 + resolution: "emoji-picker-react@npm:4.12.2" dependencies: flairup: "npm:1.0.0" peerDependencies: react: ">=16" - checksum: 10c0/897d7369609a0d0d66acd9f57d9a7c18cbaa733ac10d1aae16d127b120933eb740e8baf50f73797a755a38a8270f85593c1012b442324fdff0f31badfc5c6f08 + checksum: 10c0/52f024672b0bc7eda90adc0ecf36695491e59471b354390ed744839119be4f22e075bc6d282192b98d71c3246159833da69f2123f4a71ccddc609f87f3189008 languageName: node linkType: hard @@ -10340,13 +10511,13 @@ __metadata: languageName: node linkType: hard -"enhanced-resolve@npm:^5.18.3": - version: 5.18.3 - resolution: "enhanced-resolve@npm:5.18.3" +"enhanced-resolve@npm:^5.18.1": + version: 5.18.1 + resolution: "enhanced-resolve@npm:5.18.1" dependencies: graceful-fs: "npm:^4.2.4" tapable: "npm:^2.2.0" - checksum: 10c0/d413c23c2d494e4c1c9c9ac7d60b812083dc6d446699ed495e69c920988af0a3c66bf3f8d0e7a45cb1686c2d4c1df9f4e7352d973f5b56fe63d8d711dd0ccc54 + checksum: 10c0/4cffd9b125225184e2abed9fdf0ed3dbd2224c873b165d0838fd066cde32e0918626cba2f1f4bf6860762f13a7e2364fd89a82b99566be2873d813573ac71846 languageName: node linkType: hard @@ -10690,7 +10861,7 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-react-hooks@npm:^5.2.0": +"eslint-plugin-react-hooks@npm:5.2.0": version: 5.2.0 resolution: "eslint-plugin-react-hooks@npm:5.2.0" peerDependencies: @@ -10699,7 +10870,7 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-react-refresh@npm:^0.4.19": +"eslint-plugin-react-refresh@npm:0.4.20": version: 0.4.20 resolution: "eslint-plugin-react-refresh@npm:0.4.20" peerDependencies: @@ -10718,13 +10889,13 @@ __metadata: languageName: node linkType: hard -"eslint-scope@npm:^8.4.0": - version: 8.4.0 - resolution: "eslint-scope@npm:8.4.0" +"eslint-scope@npm:^8.3.0": + version: 8.3.0 + resolution: "eslint-scope@npm:8.3.0" dependencies: esrecurse: "npm:^4.3.0" estraverse: "npm:^5.2.0" - checksum: 10c0/407f6c600204d0f3705bd557f81bd0189e69cd7996f408f8971ab5779c0af733d1af2f1412066b40ee1588b085874fc37a2333986c6521669cdbdd36ca5058e0 + checksum: 10c0/23bf54345573201fdf06d29efa345ab508b355492f6c6cc9e2b9f6d02b896f369b6dd5315205be94b8853809776c4d13353b85c6b531997b164ff6c3328ecf5b languageName: node linkType: hard @@ -10735,6 +10906,13 @@ __metadata: languageName: node linkType: hard +"eslint-visitor-keys@npm:^4.2.0": + version: 4.2.0 + resolution: "eslint-visitor-keys@npm:4.2.0" + checksum: 10c0/2ed81c663b147ca6f578312919483eb040295bbab759e5a371953456c636c5b49a559883e2677112453728d66293c0a4c90ab11cab3428cf02a0236d2e738269 + languageName: node + linkType: hard + "eslint-visitor-keys@npm:^4.2.1": version: 4.2.1 resolution: "eslint-visitor-keys@npm:4.2.1" @@ -10790,18 +10968,18 @@ __metadata: languageName: node linkType: hard -"eslint@npm:^9.22.0": - version: 9.35.0 - resolution: "eslint@npm:9.35.0" +"eslint@npm:9.25.1": + version: 9.25.1 + resolution: "eslint@npm:9.25.1" dependencies: - "@eslint-community/eslint-utils": "npm:^4.8.0" + "@eslint-community/eslint-utils": "npm:^4.2.0" "@eslint-community/regexpp": "npm:^4.12.1" - "@eslint/config-array": "npm:^0.21.0" - "@eslint/config-helpers": "npm:^0.3.1" - "@eslint/core": "npm:^0.15.2" + "@eslint/config-array": "npm:^0.20.0" + "@eslint/config-helpers": "npm:^0.2.1" + "@eslint/core": "npm:^0.13.0" "@eslint/eslintrc": "npm:^3.3.1" - "@eslint/js": "npm:9.35.0" - "@eslint/plugin-kit": "npm:^0.3.5" + "@eslint/js": "npm:9.25.1" + "@eslint/plugin-kit": "npm:^0.2.8" "@humanfs/node": "npm:^0.16.6" "@humanwhocodes/module-importer": "npm:^1.0.1" "@humanwhocodes/retry": "npm:^0.4.2" @@ -10812,9 +10990,9 @@ __metadata: cross-spawn: "npm:^7.0.6" debug: "npm:^4.3.2" escape-string-regexp: "npm:^4.0.0" - eslint-scope: "npm:^8.4.0" - eslint-visitor-keys: "npm:^4.2.1" - espree: "npm:^10.4.0" + eslint-scope: "npm:^8.3.0" + eslint-visitor-keys: "npm:^4.2.0" + espree: "npm:^10.3.0" esquery: "npm:^1.5.0" esutils: "npm:^2.0.2" fast-deep-equal: "npm:^3.1.3" @@ -10836,11 +11014,11 @@ __metadata: optional: true bin: eslint: bin/eslint.js - checksum: 10c0/798c527520ccf62106f8cd210bd1db1f8eb1b0e7a56feb0a8b322bf3a1e6a0bc6dc3a414542c22b1b393d58d5e3cd0252c44c023049de9067b836450503a2f03 + checksum: 10c0/3bb1997ae994253d441e56aba2fc64a71b3b8dce32756de3dedae5e85416ba33eb07e19ede94a6fa8ce7ef3a0a3b0dd8b6836f41be46a3ab52e5345ad59a553f languageName: node linkType: hard -"espree@npm:^10.0.1, espree@npm:^10.4.0": +"espree@npm:^10.0.1": version: 10.4.0 resolution: "espree@npm:10.4.0" dependencies: @@ -10851,6 +11029,17 @@ __metadata: languageName: node linkType: hard +"espree@npm:^10.3.0": + version: 10.3.0 + resolution: "espree@npm:10.3.0" + dependencies: + acorn: "npm:^8.14.0" + acorn-jsx: "npm:^5.3.2" + eslint-visitor-keys: "npm:^4.2.0" + checksum: 10c0/272beeaca70d0a1a047d61baff64db04664a33d7cfb5d144f84bc8a5c6194c6c8ebe9cc594093ca53add88baa23e59b01e69e8a0160ab32eac570482e165c462 + languageName: node + linkType: hard + "espree@npm:^9.6.0, espree@npm:^9.6.1": version: 9.6.1 resolution: "espree@npm:9.6.1" @@ -10862,7 +11051,7 @@ __metadata: languageName: node linkType: hard -"esprima@npm:^4.0.0, esprima@npm:~4.0.0": +"esprima@npm:^4.0.0": version: 4.0.1 resolution: "esprima@npm:4.0.1" bin: @@ -11563,7 +11752,7 @@ __metadata: languageName: node linkType: hard -"framer-motion@npm:^12.23.12": +"framer-motion@npm:12.23.12": version: 12.23.12 resolution: "framer-motion@npm:12.23.12" dependencies: @@ -11585,6 +11774,28 @@ __metadata: languageName: node linkType: hard +"framer-motion@npm:^12.18.1": + version: 12.18.1 + resolution: "framer-motion@npm:12.18.1" + dependencies: + motion-dom: "npm:^12.18.1" + motion-utils: "npm:^12.18.1" + tslib: "npm:^2.4.0" + peerDependencies: + "@emotion/is-prop-valid": "*" + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + "@emotion/is-prop-valid": + optional: true + react: + optional: true + react-dom: + optional: true + checksum: 10c0/13aa6030fb619a482cb7d3fdb375a2ced54adcc11d23abf7e42b9dc8a40bc47d32fb3492dbb450e75c465c8469da72db21376719316d945829700f663af18c20 + languageName: node + linkType: hard + "fresh@npm:^2.0.0": version: 2.0.0 resolution: "fresh@npm:2.0.0" @@ -11717,14 +11928,14 @@ __metadata: languageName: node linkType: hard -"fuse.js@npm:^7.1.0": +"fuse.js@npm:7.1.0": version: 7.1.0 resolution: "fuse.js@npm:7.1.0" checksum: 10c0/c0d1b1d192a4bdf3eade897453ddd28aff96b70bf3e49161a45880f9845ebaee97265595db633776700a5bcf8942223c752754a848d70c508c3c9fd997faad1e languageName: node linkType: hard -"fzf@npm:^0.5.2": +"fzf@npm:0.5.2": version: 0.5.2 resolution: "fzf@npm:0.5.2" checksum: 10c0/5b1f945b289855891c4e3cb03db35381f8d85464dceb15b6d32f0fc74e43d7d2b9a13554cf78a86760ba762de39134d40644ccb54e60668a4bc5b15c4765d36e @@ -11939,6 +12150,13 @@ __metadata: languageName: node linkType: hard +"globals@npm:16.0.0": + version: 16.0.0 + resolution: "globals@npm:16.0.0" + checksum: 10c0/8906d5f01838df64a81d6c2a7b7214312e2216cf65c5ed1546dc9a7d0febddf55ffa906cf04efd5b01eec2534d6f14859a89535d1a68241832810e41ef3fd5bb + languageName: node + linkType: hard + "globals@npm:^11.1.0": version: 11.12.0 resolution: "globals@npm:11.12.0" @@ -11962,13 +12180,6 @@ __metadata: languageName: node linkType: hard -"globals@npm:^16.0.0": - version: 16.4.0 - resolution: "globals@npm:16.4.0" - checksum: 10c0/a14b447a78b664b42f6d324e8675fcae6fe5e57924fecc1f6328dce08af9b2ca3a3138501e1b1f244a49814a732dc60cfc1aa24e714e0b64ac8bd18910bfac90 - languageName: node - linkType: hard - "globalthis@npm:^1.0.4": version: 1.0.4 resolution: "globalthis@npm:1.0.4" @@ -12626,17 +12837,17 @@ __metadata: languageName: node linkType: hard -"i18next@npm:^25.0.1": - version: 25.5.2 - resolution: "i18next@npm:25.5.2" +"i18next@npm:25.0.2": + version: 25.0.2 + resolution: "i18next@npm:25.0.2" dependencies: - "@babel/runtime": "npm:^7.27.6" + "@babel/runtime": "npm:^7.26.10" peerDependencies: typescript: ^5 peerDependenciesMeta: typescript: optional: true - checksum: 10c0/25db34d17e8f11f0cd52d9ddc9c2e5942800aaaa20d0f40563aa1c50e958abd553d82ab3acf2b50ed46530c8d5cf0d5d5ccaf4d75df660c96083f78c83553438 + checksum: 10c0/1f09bce7fa620c26e107c42a356c7e968fedd1f4df948ab5b9c885b3b5abf52113aba4b0042c00e2fadd0ce732ee3e25d994d595215e874136343684c78ce608 languageName: node linkType: hard @@ -12690,20 +12901,13 @@ __metadata: languageName: node linkType: hard -"ignore@npm:^5.2.0": +"ignore@npm:^5.2.0, ignore@npm:^5.3.1": version: 5.3.2 resolution: "ignore@npm:5.3.2" checksum: 10c0/f9f652c957983634ded1e7f02da3b559a0d4cc210fca3792cb67f1b153623c9c42efdc1c4121af171e295444459fc4a9201101fb041b1104a3c000bccb188337 languageName: node linkType: hard -"ignore@npm:^7.0.0": - version: 7.0.5 - resolution: "ignore@npm:7.0.5" - checksum: 10c0/ae00db89fe873064a093b8999fe4cc284b13ef2a178636211842cceb650b9c3e390d3339191acb145d81ed5379d2074840cf0c33a20bdbd6f32821f79eb4ad5d - languageName: node - linkType: hard - "import-fresh@npm:^3.2.1": version: 3.3.1 resolution: "import-fresh@npm:3.3.1" @@ -13408,13 +13612,6 @@ __metadata: languageName: node linkType: hard -"isbot@npm:^5.1.22": - version: 5.1.30 - resolution: "isbot@npm:5.1.30" - checksum: 10c0/00a34842c0573669830ef17fc8b0ce8e3a947835179c13e10da737899310b33d1644fbab8042a8963d581010cce6ae46cd6ee947bd5e79465e29b9cbead44113 - languageName: node - linkType: hard - "isexe@npm:^2.0.0": version: 2.0.0 resolution: "isexe@npm:2.0.0" @@ -13459,7 +13656,7 @@ __metadata: languageName: node linkType: hard -"istanbul-api@npm:^3.0.0": +"istanbul-api@npm:3.0.0": version: 3.0.0 resolution: "istanbul-api@npm:3.0.0" dependencies: @@ -13481,7 +13678,7 @@ __metadata: languageName: node linkType: hard -"istanbul-lib-coverage@npm:^2.0.5": +"istanbul-lib-coverage@npm:2.0.5, istanbul-lib-coverage@npm:^2.0.5": version: 2.0.5 resolution: "istanbul-lib-coverage@npm:2.0.5" checksum: 10c0/370bd6940532ea2737a85532870f3024b113774ce3e637438cccfaf979a7598aa29d342f4adcc3d73e306155c907b519bc1c5c6887a29234f605a1a472747821 @@ -13519,7 +13716,7 @@ __metadata: languageName: node linkType: hard -"istanbul-lib-report@npm:^2.0.8": +"istanbul-lib-report@npm:2.0.8, istanbul-lib-report@npm:^2.0.8": version: 2.0.8 resolution: "istanbul-lib-report@npm:2.0.8" dependencies: @@ -13565,6 +13762,16 @@ __metadata: languageName: node linkType: hard +"istanbul-reports@npm:3.1.7": + version: 3.1.7 + resolution: "istanbul-reports@npm:3.1.7" + dependencies: + html-escaper: "npm:^2.0.0" + istanbul-lib-report: "npm:^3.0.0" + checksum: 10c0/a379fadf9cf8dc5dfe25568115721d4a7eb82fbd50b005a6672aff9c6989b20cc9312d7865814e0859cd8df58cbf664482e1d3604be0afde1f7fc3ccc1394a51 + languageName: node + linkType: hard + "istanbul-reports@npm:^2.2.5": version: 2.2.7 resolution: "istanbul-reports@npm:2.2.7" @@ -13637,12 +13844,12 @@ __metadata: languageName: unknown linkType: soft -"jiti@npm:^2.5.1": - version: 2.5.1 - resolution: "jiti@npm:2.5.1" +"jiti@npm:^2.4.2": + version: 2.4.2 + resolution: "jiti@npm:2.4.2" bin: jiti: lib/jiti-cli.mjs - checksum: 10c0/f0a38d7d8842cb35ffe883038166aa2d52ffd21f1a4fc839ae4076ea7301c22a1f11373f8fc52e2667de7acde8f3e092835620dd6f72a0fbe9296b268b0874bb + checksum: 10c0/4ceac133a08c8faff7eac84aabb917e85e8257f5ad659e843004ce76e981c457c390a220881748ac67ba1b940b9b729b30fb85cbaf6e7989f04b6002c94da331 languageName: node linkType: hard @@ -13697,7 +13904,7 @@ __metadata: languageName: node linkType: hard -"jsdom@npm:^26.1.0": +"jsdom@npm:26.1.0, jsdom@npm:^26.1.0": version: 26.1.0 resolution: "jsdom@npm:26.1.0" dependencies: @@ -13730,7 +13937,7 @@ __metadata: languageName: node linkType: hard -"jsesc@npm:^3.0.2": +"jsesc@npm:^3.0.2, jsesc@npm:^3.1.0": version: 3.1.0 resolution: "jsesc@npm:3.1.0" bin: @@ -13903,7 +14110,7 @@ __metadata: languageName: node linkType: hard -"katex@npm:^0.16.0, katex@npm:^0.16.22": +"katex@npm:0.16.22, katex@npm:^0.16.0": version: 0.16.22 resolution: "katex@npm:0.16.22" dependencies: @@ -13972,91 +14179,91 @@ __metadata: languageName: node linkType: hard -"lightningcss-darwin-arm64@npm:1.30.1": - version: 1.30.1 - resolution: "lightningcss-darwin-arm64@npm:1.30.1" +"lightningcss-darwin-arm64@npm:1.29.2": + version: 1.29.2 + resolution: "lightningcss-darwin-arm64@npm:1.29.2" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"lightningcss-darwin-x64@npm:1.30.1": - version: 1.30.1 - resolution: "lightningcss-darwin-x64@npm:1.30.1" +"lightningcss-darwin-x64@npm:1.29.2": + version: 1.29.2 + resolution: "lightningcss-darwin-x64@npm:1.29.2" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"lightningcss-freebsd-x64@npm:1.30.1": - version: 1.30.1 - resolution: "lightningcss-freebsd-x64@npm:1.30.1" +"lightningcss-freebsd-x64@npm:1.29.2": + version: 1.29.2 + resolution: "lightningcss-freebsd-x64@npm:1.29.2" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"lightningcss-linux-arm-gnueabihf@npm:1.30.1": - version: 1.30.1 - resolution: "lightningcss-linux-arm-gnueabihf@npm:1.30.1" +"lightningcss-linux-arm-gnueabihf@npm:1.29.2": + version: 1.29.2 + resolution: "lightningcss-linux-arm-gnueabihf@npm:1.29.2" conditions: os=linux & cpu=arm languageName: node linkType: hard -"lightningcss-linux-arm64-gnu@npm:1.30.1": - version: 1.30.1 - resolution: "lightningcss-linux-arm64-gnu@npm:1.30.1" +"lightningcss-linux-arm64-gnu@npm:1.29.2": + version: 1.29.2 + resolution: "lightningcss-linux-arm64-gnu@npm:1.29.2" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"lightningcss-linux-arm64-musl@npm:1.30.1": - version: 1.30.1 - resolution: "lightningcss-linux-arm64-musl@npm:1.30.1" +"lightningcss-linux-arm64-musl@npm:1.29.2": + version: 1.29.2 + resolution: "lightningcss-linux-arm64-musl@npm:1.29.2" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"lightningcss-linux-x64-gnu@npm:1.30.1": - version: 1.30.1 - resolution: "lightningcss-linux-x64-gnu@npm:1.30.1" +"lightningcss-linux-x64-gnu@npm:1.29.2": + version: 1.29.2 + resolution: "lightningcss-linux-x64-gnu@npm:1.29.2" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"lightningcss-linux-x64-musl@npm:1.30.1": - version: 1.30.1 - resolution: "lightningcss-linux-x64-musl@npm:1.30.1" +"lightningcss-linux-x64-musl@npm:1.29.2": + version: 1.29.2 + resolution: "lightningcss-linux-x64-musl@npm:1.29.2" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"lightningcss-win32-arm64-msvc@npm:1.30.1": - version: 1.30.1 - resolution: "lightningcss-win32-arm64-msvc@npm:1.30.1" +"lightningcss-win32-arm64-msvc@npm:1.29.2": + version: 1.29.2 + resolution: "lightningcss-win32-arm64-msvc@npm:1.29.2" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"lightningcss-win32-x64-msvc@npm:1.30.1": - version: 1.30.1 - resolution: "lightningcss-win32-x64-msvc@npm:1.30.1" +"lightningcss-win32-x64-msvc@npm:1.29.2": + version: 1.29.2 + resolution: "lightningcss-win32-x64-msvc@npm:1.29.2" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"lightningcss@npm:1.30.1": - version: 1.30.1 - resolution: "lightningcss@npm:1.30.1" +"lightningcss@npm:1.29.2": + version: 1.29.2 + resolution: "lightningcss@npm:1.29.2" dependencies: detect-libc: "npm:^2.0.3" - lightningcss-darwin-arm64: "npm:1.30.1" - lightningcss-darwin-x64: "npm:1.30.1" - lightningcss-freebsd-x64: "npm:1.30.1" - lightningcss-linux-arm-gnueabihf: "npm:1.30.1" - lightningcss-linux-arm64-gnu: "npm:1.30.1" - lightningcss-linux-arm64-musl: "npm:1.30.1" - lightningcss-linux-x64-gnu: "npm:1.30.1" - lightningcss-linux-x64-musl: "npm:1.30.1" - lightningcss-win32-arm64-msvc: "npm:1.30.1" - lightningcss-win32-x64-msvc: "npm:1.30.1" + lightningcss-darwin-arm64: "npm:1.29.2" + lightningcss-darwin-x64: "npm:1.29.2" + lightningcss-freebsd-x64: "npm:1.29.2" + lightningcss-linux-arm-gnueabihf: "npm:1.29.2" + lightningcss-linux-arm64-gnu: "npm:1.29.2" + lightningcss-linux-arm64-musl: "npm:1.29.2" + lightningcss-linux-x64-gnu: "npm:1.29.2" + lightningcss-linux-x64-musl: "npm:1.29.2" + lightningcss-win32-arm64-msvc: "npm:1.29.2" + lightningcss-win32-x64-msvc: "npm:1.29.2" dependenciesMeta: lightningcss-darwin-arm64: optional: true @@ -14078,7 +14285,7 @@ __metadata: optional: true lightningcss-win32-x64-msvc: optional: true - checksum: 10c0/1e1ad908f3c68bf39d964a6735435a8dd5474fb2765076732d64a7b6aa2af1f084da65a9462443a9adfebf7dcfb02fb532fce1d78697f2a9de29c8f40f09aee3 + checksum: 10c0/e06bb99c98e9f56cfcf37b5ce0e0198cdeeac2993ef2e5b878b6b0934fff54c7528f38bf8875e7bd71e64c9b20b29c0cada222d1e0089c8f94c1159bbb5d611f languageName: node linkType: hard @@ -14091,14 +14298,14 @@ __metadata: languageName: node linkType: hard -"lodash.clonedeep@npm:^4.5.0": +"lodash.clonedeep@npm:4.5.0": version: 4.5.0 resolution: "lodash.clonedeep@npm:4.5.0" checksum: 10c0/2caf0e4808f319d761d2939ee0642fa6867a4bbf2cfce43276698828380756b99d4c4fa226d881655e6ac298dd453fe12a5ec8ba49861777759494c534936985 languageName: node linkType: hard -"lodash.debounce@npm:^4.0.8": +"lodash.debounce@npm:4.0.8, lodash.debounce@npm:^4.0.8": version: 4.0.8 resolution: "lodash.debounce@npm:4.0.8" checksum: 10c0/762998a63e095412b6099b8290903e0a8ddcb353ac6e2e0f2d7e7d03abd4275fe3c689d88960eb90b0dde4f177554d51a690f22a343932ecbc50a5d111849987 @@ -14201,7 +14408,7 @@ __metadata: languageName: node linkType: hard -"lucide-react@npm:^0.536.0": +"lucide-react@npm:0.536.0": version: 0.536.0 resolution: "lucide-react@npm:0.536.0" peerDependencies: @@ -14228,7 +14435,7 @@ __metadata: languageName: node linkType: hard -"magic-string@npm:^0.30.12, magic-string@npm:^0.30.18": +"magic-string@npm:^0.30.12": version: 0.30.19 resolution: "magic-string@npm:0.30.19" dependencies: @@ -15338,6 +15545,15 @@ __metadata: languageName: node linkType: hard +"motion-dom@npm:^12.18.1": + version: 12.18.1 + resolution: "motion-dom@npm:12.18.1" + dependencies: + motion-utils: "npm:^12.18.1" + checksum: 10c0/33914f174fc8ff27e65b579d70cb6ae2af320eb3f85d12a29c05fe046dd5966844844fbac59b9e7e98f8a325e7529666173fca7fe5e4a3aff59b9bd1eb1b3266 + languageName: node + linkType: hard + "motion-dom@npm:^12.23.12": version: 12.23.12 resolution: "motion-dom@npm:12.23.12" @@ -15347,6 +15563,13 @@ __metadata: languageName: node linkType: hard +"motion-utils@npm:^12.18.1": + version: 12.18.1 + resolution: "motion-utils@npm:12.18.1" + checksum: 10c0/703702d9a82db223f4b0e0437e7c00b9e3f347bf7bffb20b0b7ad171d937db823b2420dbd8bf0764def885ba6c8aac659cc3595bcd8ecd56b5e63a990a1fae07 + languageName: node + linkType: hard + "motion-utils@npm:^12.23.6": version: 12.23.6 resolution: "motion-utils@npm:12.23.6" @@ -15354,11 +15577,11 @@ __metadata: languageName: node linkType: hard -"motion@npm:^12.10.5": - version: 12.23.12 - resolution: "motion@npm:12.23.12" +"motion@npm:12.18.1": + version: 12.18.1 + resolution: "motion@npm:12.18.1" dependencies: - framer-motion: "npm:^12.23.12" + framer-motion: "npm:^12.18.1" tslib: "npm:^2.4.0" peerDependencies: "@emotion/is-prop-valid": "*" @@ -15371,7 +15594,7 @@ __metadata: optional: true react-dom: optional: true - checksum: 10c0/48137c82b4fc8e55e06031f17219b2eb4385f028e77717aa6b2e87238c1e42d4222fb4b59b6527ebb66f98ea5f1234edd17c15682985e690b8cf48a5f3e44e67 + checksum: 10c0/f90c533af3c7636ac28b819ea192b971650e672033808942eacc0bf2a7ba5e802d164763948f71faf374e07de6a069e902fe7f3cec1bc3f66064c516c3385e7b languageName: node linkType: hard @@ -15472,7 +15695,7 @@ __metadata: languageName: node linkType: hard -"next-themes@npm:^0.4.6": +"next-themes@npm:0.4.6": version: 0.4.6 resolution: "next-themes@npm:0.4.6" peerDependencies: @@ -16440,11 +16663,10 @@ __metadata: languageName: node linkType: hard -"posthog-js@npm:^1.246.0": - version: 1.266.0 - resolution: "posthog-js@npm:1.266.0" +"posthog-js@npm:1.255.1": + version: 1.255.1 + resolution: "posthog-js@npm:1.255.1" dependencies: - "@posthog/core": "npm:1.0.2" core-js: "npm:^3.38.1" fflate: "npm:^0.4.8" preact: "npm:^10.19.3" @@ -16457,7 +16679,7 @@ __metadata: optional: true rrweb-snapshot: optional: true - checksum: 10c0/8bba7a74404cd02cc4296c5b18e8bcf451a99ba446764f1e38fbcc09bd8030cbcbee55387c10ed2cd7e4f2d55239f3769b22123fdb76870804e6378132287c0a + checksum: 10c0/313c9df0cabbc2025db4a7aa9bffdd1006e29c2f04331a9176c7237035a5d64ae8f40541fd8e322abbf09bf84470f067dbfd6329684e0644f03fcd099cd1ef13 languageName: node linkType: hard @@ -16516,7 +16738,7 @@ __metadata: languageName: node linkType: hard -"prismjs@npm:^1.30.0": +"prismjs@npm:^1.27.0": version: 1.30.0 resolution: "prismjs@npm:1.30.0" checksum: 10c0/f56205bfd58ef71ccfcbcb691fd0eb84adc96c6ff21b0b69fc6fdcf02be42d6ef972ba4aed60466310de3d67733f6a746f89f2fb79c00bf217406d465b3e8f23 @@ -16786,7 +17008,7 @@ __metadata: languageName: node linkType: hard -"react-colorful@npm:^5.6.1": +"react-colorful@npm:5.6.1": version: 5.6.1 resolution: "react-colorful@npm:5.6.1" peerDependencies: @@ -16796,14 +17018,14 @@ __metadata: languageName: node linkType: hard -"react-dom@npm:^19.0.0": - version: 19.1.1 - resolution: "react-dom@npm:19.1.1" +"react-dom@npm:19.0.0": + version: 19.0.0 + resolution: "react-dom@npm:19.0.0" dependencies: - scheduler: "npm:^0.26.0" + scheduler: "npm:^0.25.0" peerDependencies: - react: ^19.1.1 - checksum: 10c0/8c91198510521299c56e4e8d5e3a4508b2734fb5e52f29eeac33811de64e76fe586ad32c32182e2e84e070d98df67125da346c3360013357228172dbcd20bcdd + react: ^19.0.0 + checksum: 10c0/a36ce7ab507b237ae2759c984cdaad4af4096d8199fb65b3815c16825e5cfeb7293da790a3fc2184b52bfba7ba3ff31c058c01947aff6fd1a3701632aabaa6a9 languageName: node linkType: hard @@ -16823,14 +17045,14 @@ __metadata: languageName: node linkType: hard -"react-i18next@npm:^15.5.1": - version: 15.7.3 - resolution: "react-i18next@npm:15.7.3" +"react-i18next@npm:15.5.1": + version: 15.5.1 + resolution: "react-i18next@npm:15.5.1" dependencies: - "@babel/runtime": "npm:^7.27.6" + "@babel/runtime": "npm:^7.25.0" html-parse-stringify: "npm:^3.0.1" peerDependencies: - i18next: ">= 25.4.1" + i18next: ">= 23.2.3" react: ">= 16.8.0" typescript: ^5 peerDependenciesMeta: @@ -16840,7 +17062,7 @@ __metadata: optional: true typescript: optional: true - checksum: 10c0/dc3ca1da9accb47f63b2049c94ff7a94ba92d76bad586aca7c2aa3b7a01c2d4e69d4363ff0cfa898cef22b109f2dd49864d6ac94cd9afbac485d44e70ed5a4d6 + checksum: 10c0/448e190beb3338e5e6e48936c82b5e8610fdb54d0b3dafc14c2af76115a6c931eff601c3e4aee00b3d3c1b78d4d7061bbac443fc9bcff786d131e695c79f5822 languageName: node linkType: hard @@ -16868,7 +17090,7 @@ __metadata: languageName: node linkType: hard -"react-joyride@npm:^2.9.3": +"react-joyride@npm:2.9.3": version: 2.9.3 resolution: "react-joyride@npm:2.9.3" dependencies: @@ -16897,7 +17119,7 @@ __metadata: languageName: node linkType: hard -"react-markdown@npm:^10.1.0": +"react-markdown@npm:10.1.0": version: 10.1.0 resolution: "react-markdown@npm:10.1.0" dependencies: @@ -16961,13 +17183,13 @@ __metadata: languageName: node linkType: hard -"react-resizable-panels@npm:^3.0.3": - version: 3.0.6 - resolution: "react-resizable-panels@npm:3.0.6" +"react-resizable-panels@npm:3.0.5": + version: 3.0.5 + resolution: "react-resizable-panels@npm:3.0.5" peerDependencies: react: ^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc - checksum: 10c0/e6a6a2a7f438aaf3d4411c39626c1cab5c23af6f25d5ff1fdb8446916388fec549be63d65c47fe17bcc82522b1b5fc7fffa77a550ca9d0b8d21e340d83bdb3c0 + checksum: 10c0/c6f18dcd3e24410084a8075ffd17c95940322e4a2a51362a0acd2fd2a875a052eac9b3ee589c41e43b603ac614c4cd1d8196ff6fc5f6a72aad837ddea499f816 languageName: node linkType: hard @@ -16987,7 +17209,7 @@ __metadata: languageName: node linkType: hard -"react-syntax-highlighter-virtualized-renderer@npm:^1.1.0": +"react-syntax-highlighter-virtualized-renderer@npm:1.1.0": version: 1.1.0 resolution: "react-syntax-highlighter-virtualized-renderer@npm:1.1.0" dependencies: @@ -17000,19 +17222,19 @@ __metadata: languageName: node linkType: hard -"react-syntax-highlighter@npm:^15.6.1": - version: 15.6.6 - resolution: "react-syntax-highlighter@npm:15.6.6" +"react-syntax-highlighter@npm:15.6.1": + version: 15.6.1 + resolution: "react-syntax-highlighter@npm:15.6.1" dependencies: "@babel/runtime": "npm:^7.3.1" highlight.js: "npm:^10.4.1" highlightjs-vue: "npm:^1.0.0" lowlight: "npm:^1.17.0" - prismjs: "npm:^1.30.0" + prismjs: "npm:^1.27.0" refractor: "npm:^3.6.0" peerDependencies: react: ">= 0.14.0" - checksum: 10c0/894f8b7c79ed40866c0fc542ad0a2040128a8c7e6e6decfd06ef092d8af9c63788ecdd911ea9b2b433e361a4a33a14f721bcec81fd59f1e7394442ade4e7ea46 + checksum: 10c0/4a4cf4695c45d7a6b25078970fb79ae5a85edeba5be0a2508766ee18e8aee1c0c4cdd97bf54f5055e4af671fe7e5e71348e81cafe09a0eb07a763ae876b7f073 languageName: node linkType: hard @@ -17029,7 +17251,7 @@ __metadata: languageName: node linkType: hard -"react-textarea-autosize@npm:^8.5.9": +"react-textarea-autosize@npm:8.5.9": version: 8.5.9 resolution: "react-textarea-autosize@npm:8.5.9" dependencies: @@ -17059,10 +17281,10 @@ __metadata: languageName: node linkType: hard -"react@npm:^19.0.0": - version: 19.1.1 - resolution: "react@npm:19.1.1" - checksum: 10c0/8c9769a2dfd02e603af6445058325e6c8a24b47b185d0e461f66a6454765ddcaecb3f0a90184836c68bb509f3c38248359edbc42f0d07c23eb500a5c30c87b4e +"react@npm:19.0.0": + version: 19.0.0 + resolution: "react@npm:19.0.0" + checksum: 10c0/9cad8f103e8e3a16d15cb18a0d8115d8bd9f9e1ce3420310aea381eb42aa0a4f812cf047bb5441349257a05fba8a291515691e3cb51267279b2d2c3253f38471 languageName: node linkType: hard @@ -17142,19 +17364,6 @@ __metadata: languageName: node linkType: hard -"recast@npm:^0.23.11": - version: 0.23.11 - resolution: "recast@npm:0.23.11" - dependencies: - ast-types: "npm:^0.16.1" - esprima: "npm:~4.0.0" - source-map: "npm:~0.6.1" - tiny-invariant: "npm:^1.3.3" - tslib: "npm:^2.0.1" - checksum: 10c0/45b520a8f0868a5a24ecde495be9de3c48e69a54295d82a7331106554b75cfba75d16c909959d056e9ceed47a1be5e061e2db8b9ecbcd6ba44c2f3ef9a47bd18 - languageName: node - linkType: hard - "redent@npm:^3.0.0": version: 3.0.0 resolution: "redent@npm:3.0.0" @@ -17318,7 +17527,7 @@ __metadata: languageName: node linkType: hard -"rehype-katex@npm:^7.0.1": +"rehype-katex@npm:7.0.1": version: 7.0.1 resolution: "rehype-katex@npm:7.0.1" dependencies: @@ -17358,7 +17567,7 @@ __metadata: languageName: node linkType: hard -"rehype-raw@npm:^7.0.0": +"rehype-raw@npm:7.0.0": version: 7.0.0 resolution: "rehype-raw@npm:7.0.0" dependencies: @@ -17392,7 +17601,7 @@ __metadata: languageName: node linkType: hard -"remark-breaks@npm:^4.0.0": +"remark-breaks@npm:4.0.0": version: 4.0.0 resolution: "remark-breaks@npm:4.0.0" dependencies: @@ -17403,20 +17612,20 @@ __metadata: languageName: node linkType: hard -"remark-emoji@npm:^5.0.1": - version: 5.0.2 - resolution: "remark-emoji@npm:5.0.2" +"remark-emoji@npm:5.0.1": + version: 5.0.1 + resolution: "remark-emoji@npm:5.0.1" dependencies: "@types/mdast": "npm:^4.0.4" emoticon: "npm:^4.0.1" mdast-util-find-and-replace: "npm:^3.0.1" node-emoji: "npm:^2.1.3" unified: "npm:^11.0.4" - checksum: 10c0/fdf133428c862da510b82e17cb25ce4b9128dafa1a344e61a74aaaab5503b4f668b2cf41b5445b5b06148f5a99f46ab216dc035a68d55e26fabbd1ffb8eb7fd9 + checksum: 10c0/d4b330a06c1d42b97b9e9a03e486426f462d50a66b68c70443abb224ba576e2008c38faef19c654cd3e95749b5783cc3a64e7b997a279057fb7f5b8fd912b6b5 languageName: node linkType: hard -"remark-gfm@npm:^4.0.1": +"remark-gfm@npm:4.0.1": version: 4.0.1 resolution: "remark-gfm@npm:4.0.1" dependencies: @@ -17430,7 +17639,7 @@ __metadata: languageName: node linkType: hard -"remark-math@npm:^6.0.0": +"remark-math@npm:6.0.0": version: 6.0.0 resolution: "remark-math@npm:6.0.0" dependencies: @@ -18006,10 +18215,10 @@ __metadata: languageName: node linkType: hard -"scheduler@npm:^0.26.0": - version: 0.26.0 - resolution: "scheduler@npm:0.26.0" - checksum: 10c0/5b8d5bfddaae3513410eda54f2268e98a376a429931921a81b5c3a2873aab7ca4d775a8caac5498f8cbc7d0daeab947cf923dbd8e215d61671f9f4e392d34356 +"scheduler@npm:^0.25.0": + version: 0.25.0 + resolution: "scheduler@npm:0.25.0" + checksum: 10c0/a4bb1da406b613ce72c1299db43759526058fdcc413999c3c3e0db8956df7633acf395cb20eb2303b6a65d658d66b6585d344460abaee8080b4aa931f10eaafe languageName: node linkType: hard @@ -18082,7 +18291,7 @@ __metadata: languageName: node linkType: hard -"seroval-plugins@npm:^1.3.2, seroval-plugins@npm:~1.3.0": +"seroval-plugins@npm:~1.3.0": version: 1.3.3 resolution: "seroval-plugins@npm:1.3.3" peerDependencies: @@ -18091,7 +18300,7 @@ __metadata: languageName: node linkType: hard -"seroval@npm:^1.3.2, seroval@npm:~1.3.0": +"seroval@npm:~1.3.0": version: 1.3.2 resolution: "seroval@npm:1.3.2" checksum: 10c0/19e74825643786d22e5c58054bd28065238de0156545afba82f9a7d3ee70ea4f0249b427f317bc6bf983849dde8e4190264728d90c84620aa163bfbc5971f1bc @@ -18125,7 +18334,7 @@ __metadata: languageName: node linkType: hard -"serve@npm:^14.2.4": +"serve@npm:14.2.5": version: 14.2.5 resolution: "serve@npm:14.2.5" dependencies: @@ -18444,13 +18653,13 @@ __metadata: languageName: node linkType: hard -"sonner@npm:^2.0.3": - version: 2.0.7 - resolution: "sonner@npm:2.0.7" +"sonner@npm:2.0.5": + version: 2.0.5 + resolution: "sonner@npm:2.0.5" peerDependencies: react: ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-rc - checksum: 10c0/6966ab5e892ed6aab579a175e4a24f3b48747f0fc21cb68c3e33cb41caa7a0eebeb098c210545395e47a18d585eb8734ae7dd12d2bd18c8a3294a1ee73f997d9 + checksum: 10c0/38ec98e2f5d7e086825307f737a90bdc8639182d184e002719c2368bf3a9259c340f41afda731716d2b78c40e5e3aa9165058375be42f6a93bda0876b9b433ba languageName: node linkType: hard @@ -18498,20 +18707,13 @@ __metadata: languageName: node linkType: hard -"source-map@npm:^0.6.0, source-map@npm:^0.6.1, source-map@npm:~0.6.1": +"source-map@npm:^0.6.0, source-map@npm:^0.6.1": version: 0.6.1 resolution: "source-map@npm:0.6.1" checksum: 10c0/ab55398007c5e5532957cb0beee2368529618ac0ab372d789806f5718123cc4367d57de3904b4e6a4170eb5a0b0f41373066d02ca0735a0c4d75c7d328d3e011 languageName: node linkType: hard -"source-map@npm:^0.7.4": - version: 0.7.6 - resolution: "source-map@npm:0.7.6" - checksum: 10c0/59f6f05538539b274ba771d2e9e32f6c65451982510564438e048bc1352f019c6efcdc6dd07909b1968144941c14015c2c7d4369fb7c4d7d53ae769716dcc16c - languageName: node - linkType: hard - "source-map@npm:^0.8.0-beta.0": version: 0.8.0-beta.0 resolution: "source-map@npm:0.8.0-beta.0" @@ -18965,21 +19167,14 @@ __metadata: languageName: node linkType: hard -"tailwind-merge@npm:^3.3.1": +"tailwind-merge@npm:3.3.1": version: 3.3.1 resolution: "tailwind-merge@npm:3.3.1" checksum: 10c0/b84c6a78d4669fa12bf5ab8f0cdc4400a3ce0a7c006511af4af4be70bb664a27466dbe13ee9e3b31f50ddf6c51d380e8192ce0ec9effce23ca729d71a9f63818 languageName: node linkType: hard -"tailwindcss@npm:4.1.13": - version: 4.1.13 - resolution: "tailwindcss@npm:4.1.13" - checksum: 10c0/2b80b4b11463818fd16063b7cc13fd0f6e18d7e3c3e54bbdc98742981be807884addb1dd657bc6816cb4085197b7d583f5064f619e1039a54221ffa36b7ed4c0 - languageName: node - linkType: hard - -"tailwindcss@npm:^4.1.4": +"tailwindcss@npm:4.1.4": version: 4.1.4 resolution: "tailwindcss@npm:4.1.4" checksum: 10c0/4927653b740861f0279b6b465c87e188652d3c0e311c633b4efe5d72bbb4dce12b9dddc674a386a3d0454ef4dd4951aac6fd7346dcd9b2b2b06952e431c1835d @@ -19131,7 +19326,7 @@ __metadata: languageName: node linkType: hard -"tinyglobby@npm:^0.2.10, tinyglobby@npm:^0.2.13, tinyglobby@npm:^0.2.15": +"tinyglobby@npm:^0.2.10, tinyglobby@npm:^0.2.15": version: 0.2.15 resolution: "tinyglobby@npm:0.2.15" dependencies: @@ -19381,7 +19576,7 @@ __metadata: languageName: node linkType: hard -"ts-api-utils@npm:^2.1.0": +"ts-api-utils@npm:^2.0.1": version: 2.1.0 resolution: "ts-api-utils@npm:2.1.0" peerDependencies: @@ -19397,7 +19592,7 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.0.0, tslib@npm:^2.0.1, tslib@npm:^2.1.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.5.0, tslib@npm:^2.6.2, tslib@npm:^2.8.0": +"tslib@npm:^2.0.0, tslib@npm:^2.1.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.5.0, tslib@npm:^2.6.2, tslib@npm:^2.8.0": version: 2.8.1 resolution: "tslib@npm:2.8.1" checksum: 10c0/9c4759110a19c53f992d9aae23aac5ced636e99887b51b9e61def52611732872ff7668757d4e4c61f19691e36f4da981cd9485e869b4a7408d689f6bf1f14e62 @@ -19458,10 +19653,10 @@ __metadata: languageName: node linkType: hard -"tw-animate-css@npm:^1.2.7": - version: 1.3.8 - resolution: "tw-animate-css@npm:1.3.8" - checksum: 10c0/8b905ec319447e80444d88b475beb9d4bbe8f783ee4fa0f90e63c01aed3a77ab2585b25c2741ff2e741b7b9098a82268c2d30dc36f9716a9e83edfa4081be544 +"tw-animate-css@npm:1.2.8": + version: 1.2.8 + resolution: "tw-animate-css@npm:1.2.8" + checksum: 10c0/395b0a10e6f9a0e3522e5c065d20af20bdf1eddebc6502dbde7ffd4123117c8015ebb91c4e18887282b44e4f5c3c8a9dc087802ee44569ef81e6e1e6d0fabfdb languageName: node linkType: hard @@ -19573,22 +19768,21 @@ __metadata: languageName: node linkType: hard -"typescript-eslint@npm:^8.26.1": - version: 8.43.0 - resolution: "typescript-eslint@npm:8.43.0" +"typescript-eslint@npm:8.31.0": + version: 8.31.0 + resolution: "typescript-eslint@npm:8.31.0" dependencies: - "@typescript-eslint/eslint-plugin": "npm:8.43.0" - "@typescript-eslint/parser": "npm:8.43.0" - "@typescript-eslint/typescript-estree": "npm:8.43.0" - "@typescript-eslint/utils": "npm:8.43.0" + "@typescript-eslint/eslint-plugin": "npm:8.31.0" + "@typescript-eslint/parser": "npm:8.31.0" + "@typescript-eslint/utils": "npm:8.31.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/ee8429b16a5b7678136b8b2688bec03d11b5f1590895523ba9b8c6920c7a0876c9bf3bf0ff415df79e57c10ed48955cf183b727394b1c228ca75b5168fb466a1 + typescript: ">=4.8.4 <5.9.0" + checksum: 10c0/8545887f70c4f40c4aee51d224326368f67ef5f770ba5ae9e67bfd36f4d9ab5f3414569ffaaec311893a312539934ea367a68135c6f2b0a3e175c3de59507338 languageName: node linkType: hard -"typescript@npm:^5.3.3": +"typescript@npm:5.9.2": version: 5.9.2 resolution: "typescript@npm:5.9.2" bin: @@ -19598,7 +19792,7 @@ __metadata: languageName: node linkType: hard -"typescript@npm:^5.8.3, typescript@npm:~5.8.3": +"typescript@npm:^5.8.3": version: 5.8.3 resolution: "typescript@npm:5.8.3" bin: @@ -19608,7 +19802,7 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@npm%3A^5.3.3#optional!builtin": +"typescript@patch:typescript@npm%3A5.9.2#optional!builtin": version: 5.9.2 resolution: "typescript@patch:typescript@npm%3A5.9.2#optional!builtin::version=5.9.2&hash=5786d5" bin: @@ -19618,7 +19812,7 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@npm%3A^5.8.3#optional!builtin, typescript@patch:typescript@npm%3A~5.8.3#optional!builtin": +"typescript@patch:typescript@npm%3A^5.8.3#optional!builtin": version: 5.8.3 resolution: "typescript@patch:typescript@npm%3A5.8.3#optional!builtin::version=5.8.3&hash=5786d5" bin: @@ -19628,7 +19822,7 @@ __metadata: languageName: node linkType: hard -"ulidx@npm:^2.3.0, ulidx@npm:^2.4.1": +"ulidx@npm:2.4.1, ulidx@npm:^2.3.0": version: 2.4.1 resolution: "ulidx@npm:2.4.1" dependencies: @@ -19708,7 +19902,7 @@ __metadata: languageName: node linkType: hard -"unified@npm:^11.0.0, unified@npm:^11.0.4, unified@npm:^11.0.5": +"unified@npm:11.0.5, unified@npm:^11.0.0, unified@npm:^11.0.4": version: 11.0.5 resolution: "unified@npm:11.0.5" dependencies: @@ -20077,7 +20271,7 @@ __metadata: languageName: node linkType: hard -"uuid@npm:^11.1.0": +"uuid@npm:11.1.0": version: 11.1.0 resolution: "uuid@npm:11.1.0" bin: @@ -20135,7 +20329,7 @@ __metadata: languageName: node linkType: hard -"vaul@npm:^1.1.2": +"vaul@npm:1.1.2": version: 1.1.2 resolution: "vaul@npm:1.1.2" dependencies: @@ -20218,7 +20412,7 @@ __metadata: languageName: node linkType: hard -"vite-plugin-node-polyfills@npm:^0.23.0": +"vite-plugin-node-polyfills@npm:0.23.0": version: 0.23.0 resolution: "vite-plugin-node-polyfills@npm:0.23.0" dependencies: @@ -20230,7 +20424,7 @@ __metadata: languageName: node linkType: hard -"vite-plugin-pwa@npm:^1.0.3": +"vite-plugin-pwa@npm:1.0.3": version: 1.0.3 resolution: "vite-plugin-pwa@npm:1.0.3" dependencies: @@ -20251,7 +20445,7 @@ __metadata: languageName: node linkType: hard -"vite@npm:^5.0.0": +"vite@npm:5.4.20, vite@npm:^5.0.0": version: 5.4.20 resolution: "vite@npm:5.4.20" dependencies: @@ -20294,6 +20488,61 @@ __metadata: languageName: node linkType: hard +"vite@npm:6.3.2": + version: 6.3.2 + resolution: "vite@npm:6.3.2" + dependencies: + esbuild: "npm:^0.25.0" + fdir: "npm:^6.4.3" + fsevents: "npm:~2.3.3" + picomatch: "npm:^4.0.2" + postcss: "npm:^8.5.3" + rollup: "npm:^4.34.9" + tinyglobby: "npm:^0.2.12" + peerDependencies: + "@types/node": ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: ">=1.21.0" + less: "*" + lightningcss: ^1.21.0 + sass: "*" + sass-embedded: "*" + stylus: "*" + sugarss: "*" + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + dependenciesMeta: + fsevents: + optional: true + peerDependenciesMeta: + "@types/node": + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + bin: + vite: bin/vite.js + checksum: 10c0/08681e83e8338f3915cee729d8296bb9cfd53f71d6796816445d58cd84a8387396a3f5f3e179c52b09e98ccf7247ec3fabb50b95b0e7f3289a619ef8bf71bd8a + languageName: node + linkType: hard + "vite@npm:^5.0.0 || ^6.0.0 || ^7.0.0-0": version: 7.1.5 resolution: "vite@npm:7.1.5" @@ -20349,62 +20598,7 @@ __metadata: languageName: node linkType: hard -"vite@npm:^6.3.0": - version: 6.3.6 - resolution: "vite@npm:6.3.6" - dependencies: - esbuild: "npm:^0.25.0" - fdir: "npm:^6.4.4" - fsevents: "npm:~2.3.3" - picomatch: "npm:^4.0.2" - postcss: "npm:^8.5.3" - rollup: "npm:^4.34.9" - tinyglobby: "npm:^0.2.13" - peerDependencies: - "@types/node": ^18.0.0 || ^20.0.0 || >=22.0.0 - jiti: ">=1.21.0" - less: "*" - lightningcss: ^1.21.0 - sass: "*" - sass-embedded: "*" - stylus: "*" - sugarss: "*" - terser: ^5.16.0 - tsx: ^4.8.1 - yaml: ^2.4.2 - dependenciesMeta: - fsevents: - optional: true - peerDependenciesMeta: - "@types/node": - optional: true - jiti: - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - tsx: - optional: true - yaml: - optional: true - bin: - vite: bin/vite.js - checksum: 10c0/add701f1e72596c002275782e38d0389ab400c1be330c93a3009804d62db68097a936ca1c53c3301df3aaacfe5e328eab547060f31ef9c49a277ae50df6ad4fb - languageName: node - linkType: hard - -"vitest@npm:^2.0.0, vitest@npm:^2.1.8": +"vitest@npm:2.1.9, vitest@npm:^2.1.8": version: 2.1.9 resolution: "vitest@npm:2.1.9" dependencies: @@ -20454,7 +20648,7 @@ __metadata: languageName: node linkType: hard -"vitest@npm:^3.1.3": +"vitest@npm:3.2.4, vitest@npm:^3.1.3": version: 3.2.4 resolution: "vitest@npm:3.2.4" dependencies: @@ -21074,7 +21268,28 @@ __metadata: languageName: node linkType: hard -"zustand@npm:^5.0.3, zustand@npm:^5.0.8": +"zustand@npm:5.0.3": + version: 5.0.3 + resolution: "zustand@npm:5.0.3" + peerDependencies: + "@types/react": ">=18.0.0" + immer: ">=9.0.6" + react: ">=18.0.0" + use-sync-external-store: ">=1.2.0" + peerDependenciesMeta: + "@types/react": + optional: true + immer: + optional: true + react: + optional: true + use-sync-external-store: + optional: true + checksum: 10c0/dad96c6c123fda088c583d5df6692e9245cd207583078dc15f93d255a67b0f346bad4535545c98852ecde93d254812a0c799579dfde2ab595016b99fbe20e4d5 + languageName: node + linkType: hard + +"zustand@npm:5.0.8": version: 5.0.8 resolution: "zustand@npm:5.0.8" peerDependencies: