diff --git a/.github/workflows/desktop.yml b/.github/workflows/desktop.yml new file mode 100644 index 00000000..2f957b23 --- /dev/null +++ b/.github/workflows/desktop.yml @@ -0,0 +1,131 @@ +name: Desktop build + +# Builds the OpenKB desktop app (Tauri shell + frozen openkb-api sidecar) for +# every platform, and — on a `desktop-v*` tag — attaches the installers to a +# GitHub Release. +# +# Neither half cross-compiles — PyInstaller freezes for the host OS/arch and +# Tauri links the platform WebView — so each target is its own runner. macOS +# arm64/x86_64 are separate runners (native builds; no --target needed). +# +# Ordering within a job matters: build the web UI FIRST (npm run build → +# openkb/web), THEN freeze the sidecar (build_sidecar.sh bundles openkb/web), +# THEN `tauri build` (bundles the sidecar dir as a resource). + +on: + workflow_dispatch: + push: + tags: + - "desktop-v*" + +permissions: + contents: read + +concurrency: + group: desktop-${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-22.04 + target: linux + - os: windows-latest + target: windows + - os: macos-14 # Apple Silicon + target: macos-arm64 + - os: macos-13 # Intel + target: macos-intel + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + with: + persist-credentials: false + + # Tauri's Linux WebView + bundler dependencies. Windows (WebView2) and + # macOS (WebKit) ship theirs with the OS, so this is Linux-only. + - name: Install Linux WebView deps + if: matrix.target == 'linux' + run: | + sudo apt-get update + sudo apt-get install -y \ + libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev \ + build-essential curl wget file libxdo-dev libssl-dev + + - uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0 + with: + python-version: "3.12" + + # openkb.api (the sidecar) + PyInstaller. PyInstaller is a build tool, not + # a runtime dep, so it's installed ad-hoc rather than pinned in pyproject. + - name: Install openkb + build tools + run: pip install -e ".[api]" pyinstaller + + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + with: + node-version: "20" + + # MUST run before the sidecar freeze — build_sidecar.sh bundles openkb/web. + - name: Build web UI + working-directory: frontend + run: | + npm ci + npm run build + + # `shell: bash` so the same script runs on Windows (git-bash) too. + # PyInstaller emits openkb-api-sidecar(.exe) for the host OS/arch. + - name: Freeze API sidecar + shell: bash + run: PYTHON=python bash desktop/packaging/build_sidecar.sh + + # ubuntu/macos/windows runners ship a stable Rust toolchain. tauri-cli is + # installed from crates.io (locked) rather than via a third-party action, + # to keep the supply chain explicit. + - name: Install tauri-cli + run: cargo install tauri-cli --version "^2" --locked + + - name: Build Tauri bundle + working-directory: desktop/src-tauri + run: cargo tauri build + + # TODO: pin actions/upload-artifact to a SHA to match the repo policy. + - name: Upload installers + uses: actions/upload-artifact@v4 + with: + name: openkb-desktop-${{ matrix.target }} + path: | + desktop/src-tauri/target/release/bundle/**/*.AppImage + desktop/src-tauri/target/release/bundle/**/*.deb + desktop/src-tauri/target/release/bundle/**/*.rpm + desktop/src-tauri/target/release/bundle/**/*.dmg + desktop/src-tauri/target/release/bundle/**/*.msi + desktop/src-tauri/target/release/bundle/**/*.exe + if-no-files-found: warn + + # Attach every platform's installers to a GitHub Release, but only for a + # `desktop-v*` tag. Signing/notarization (macOS Gatekeeper, Windows + # SmartScreen) is not configured yet — these are unsigned artifacts. + release: + if: startsWith(github.ref, 'refs/tags/desktop-v') + needs: build + runs-on: ubuntu-latest + permissions: + contents: write + steps: + # TODO: pin actions/download-artifact to a SHA to match the repo policy. + - name: Download all installers + uses: actions/download-artifact@v4 + with: + path: installers + merge-multiple: true + + - name: Create / update the release + uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0 + with: + tag_name: ${{ github.ref_name }} + name: ${{ github.ref_name }} + generate_release_notes: true + files: installers/**/* diff --git a/desktop/.gitignore b/desktop/.gitignore new file mode 100644 index 00000000..970032a7 --- /dev/null +++ b/desktop/.gitignore @@ -0,0 +1,8 @@ +# PyInstaller sidecar build artifacts +packaging/build/ +packaging/dist/ +packaging/*.spec + +# Tauri / Rust build artifacts +src-tauri/target/ +src-tauri/gen/ diff --git a/desktop/README.md b/desktop/README.md new file mode 100644 index 00000000..91a01dfa --- /dev/null +++ b/desktop/README.md @@ -0,0 +1,103 @@ +# OpenKB Desktop (Tauri) + +A desktop app that wraps OpenKB for non-technical users: no `pip`, no terminal. +It is a thin [Tauri](https://tauri.app) (Rust) shell around two things OpenKB +already produces: + +1. **The API sidecar** — `openkb-api` (the FastAPI server from the Knowledge + Workbench, `openkb.api:main`) frozen into a self-contained binary with + PyInstaller. It serves both the JSON/SSE API and the built web UI. +2. **The web UI** — the `frontend/` Vite SPA, served by the sidecar at `/`. + +``` +┌─────────────────────────────────────────────┐ +│ Tauri shell (Rust + system WebView) │ +│ │ +│ spawns ──▶ openkb-api-sidecar (frozen) │ +│ ├─ FastAPI /api/v1/* │ +│ └─ web UI / │ +│ WebView ──▶ http://127.0.0.1:/ │ +└─────────────────────────────────────────────┘ +``` + +The user double-clicks the app; the Rust shell starts the sidecar on a +localhost port, waits until it answers, then points the WebView at it. No +browser, no port, no "server" ever surfaces to the user. + +## Why this shape + +- OpenKB's capability lives in a heavy Python stack (litellm, pageindex, + markitdown, pymupdf). Rust can't replace that, so the Python runs as a frozen + sidecar. The Rust shell is glue: window, WebView, process lifecycle, updater. +- Tauri (vs Electron) ships no Chromium — smaller download, less memory — at the + cost of using each platform's system WebView. + +## Layout + +``` +desktop/ + packaging/ # freeze the Python API into a slim sidecar binary + build_sidecar.sh # PyInstaller recipe (slim: no magika/onnxruntime) + sidecar_entry.py # frozen entry -> openkb.api:main + pyi_rthook_magika.py# runtime hook: stub magika (drops onnxruntime) + prune_litellm_proxy.py # post-build: delete the unused LiteLLM proxy server + src-tauri/ # Tauri (Rust) shell — spawns the sidecar, opens the window +``` + +## Build pipeline + +```bash +# 1. Python env with API + PyInstaller +python -m venv .venv && . .venv/bin/activate +pip install -e ".[api]" pyinstaller + +# 2. Build the web UI (its output is what the sidecar serves) +cd frontend && npm install && npm run build && cd .. + +# 3. Freeze the slim API sidecar -> desktop/packaging/dist/openkb-api-sidecar/ +PYTHON=.venv/bin/python desktop/packaging/build_sidecar.sh + +# 4. Build the Tauri app (bundles the sidecar + opens the WebView) +cd desktop/src-tauri && cargo tauri build +``` + +## Slimming (measured, x86_64 Linux) + +The sidecar reuses the packaging work from the CLI slimming (see PR #186 for the +lazy-markitdown source change that makes it possible): + +| stage | compressed | +|---|---| +| full PyInstaller freeze | 147 MB | +| − magika / onnxruntime (stub hook) | 140 MB | +| − LiteLLM proxy server | 133 MB | + +The frozen **API sidecar** (adds FastAPI + uvicorn over the CLI baseline) +measures **≈134 MB compressed / 338 MB on disk**, verified booting uvicorn and +serving `GET /api/v1/kbs` → 200. + +`pymupdf` (PDF engine) and `pandas`/`numpy` (Excel support) are kept +deliberately — they are load-bearing for OpenKB's document formats. + +## Toolchain / status + +Full builds need, per platform: Rust + Cargo, Node + npm, a Python 3.10+ env, +and on **Linux `webkit2gtk`** (`libwebkit2gtk-4.1-dev`) for the WebView. + +CI: `.github/workflows/desktop.yml` runs this pipeline on `workflow_dispatch` +and `desktop-v*` tags (Linux only for now; the matrix has commented Windows / +macOS entries). + +**Status:** +- **API sidecar** (`packaging/`) — implemented and verified: the frozen slim + binary boots uvicorn and serves both `GET /api/v1/kbs` and the web UI at `/`. +- **Web UI** — builds (`npm run build` → `openkb/web/`), is bundled into the + sidecar freeze, and renders end-to-end (verified via headless Chromium). +- **Tauri shell** (`src-tauri/`) — compiles and runs: verified under `xvfb` + (WebKitGTK) navigating to the sidecar and rendering the desktop TitleBar + (`window.__OPENKB_DESKTOP__` is injected by the shell). +- **Installers** — `cargo tauri build` produces a Linux `.deb` and `.rpm` + (verified locally; each ~175 MB, bundling the app + frozen sidecar). The + `.AppImage` target additionally downloads `appimagetool` at build time, so it + needs unrestricted network (fine on GitHub runners; blocked in a locked-down + sandbox). Windows/macOS installers build once their matrix runners are added. diff --git a/desktop/packaging/build_sidecar.sh b/desktop/packaging/build_sidecar.sh new file mode 100755 index 00000000..23bc315a --- /dev/null +++ b/desktop/packaging/build_sidecar.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +# +# Build the OpenKB API sidecar: a self-contained, slimmed PyInstaller binary +# that the Tauri desktop shell spawns and talks to over localhost HTTP. +# +# Slimming (see ../README.md for measured sizes): +# - exclude magika + onnxruntime; a runtime hook stubs magika so markitdown +# still converts Office/HTML by file extension. +# - post-build prune of the unused LiteLLM Proxy Server. +# +# Prerequisites: a Python env with `pip install -e ".[api]"` and `pyinstaller`. +# Set PYTHON to that env's interpreter (default: python3). +# +# Usage: PYTHON=/path/to/venv/bin/python desktop/packaging/build_sidecar.sh +# Output: desktop/packaging/dist/openkb-api-sidecar/ +set -euo pipefail + +HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PYTHON="${PYTHON:-python3}" +cd "$HERE" + +rm -rf build dist openkb-api-sidecar.spec + +# `openkb` is collected whole so PyInstaller bundles (a) its data files — +# crucially the built web UI at openkb/web that the API serves at `/`, plus +# prompt/template assets — and (b) submodules reached only via lazy/dynamic +# imports (e.g. the deferred `from openkb.converter import ...`). The web UI +# must be built (npm run build → openkb/web) BEFORE this script runs. +COLLECT=(openkb litellm markitdown pageindex tiktoken agents openai tiktoken_ext uvicorn fastapi) +EXCLUDE=(magika onnxruntime) + +ARGS=(--onedir --name openkb-api-sidecar --noconfirm --clean --log-level=WARN) +ARGS+=(--runtime-hook "$HERE/pyi_rthook_magika.py") +for pkg in "${COLLECT[@]}"; do ARGS+=(--collect-all "$pkg"); done +for pkg in "${EXCLUDE[@]}"; do ARGS+=(--exclude-module "$pkg"); done + +echo ">>> freezing openkb-api sidecar (slim: no magika/onnxruntime)" +"$PYTHON" -m PyInstaller "${ARGS[@]}" sidecar_entry.py + +echo ">>> pruning unused litellm proxy server" +"$PYTHON" prune_litellm_proxy.py "dist/openkb-api-sidecar" + +echo ">>> done: dist/openkb-api-sidecar/openkb-api-sidecar" diff --git a/desktop/packaging/prune_litellm_proxy.py b/desktop/packaging/prune_litellm_proxy.py new file mode 100644 index 00000000..a3f1055b --- /dev/null +++ b/desktop/packaging/prune_litellm_proxy.py @@ -0,0 +1,51 @@ +"""Prune the unused LiteLLM Proxy Server from a frozen build. + +`--collect-all litellm` pulls litellm's entire *Proxy Server* (~44 MB: a +FastAPI gateway with an admin UI, swagger assets and OpenAPI snapshots), but +OpenKB only uses litellm as a client. `import litellm` loads a handful of small +proxy submodules; none of the static/data assets below are reached by any +client code path (verified: not in sys.modules after `import litellm` plus a +completion call). Deleting them from the frozen tree is safe; the sidecar smoke +test (`GET /api/v1/kbs` returns 200) confirms the client path stays intact. + +Usage: python prune_litellm_proxy.py +The frozen app dir is PyInstaller's onedir output (contains `_internal/`). +""" + +from __future__ import annotations + +import sys +from pathlib import Path + +# Static/data dead weight — never imported by a litellm *client*. +_PRUNE_DIRS = ("_experimental", "swagger") +_PRUNE_GLOBS = ("*.jpg", "*.json", "*.yaml", "*.txt", "README.md") + + +def _dir_size_mb(path: Path) -> int: + return sum(f.stat().st_size for f in path.rglob("*") if f.is_file()) // (1024 * 1024) + + +def prune(app_dir: Path) -> None: + proxy = app_dir / "_internal" / "litellm" / "proxy" + if not proxy.is_dir(): + print(f"prune_litellm_proxy: no proxy dir at {proxy}; nothing to do") + return + before = _dir_size_mb(proxy) + import shutil + + for name in _PRUNE_DIRS: + target = proxy / name + if target.exists(): + shutil.rmtree(target) + for pattern in _PRUNE_GLOBS: + for f in proxy.glob(pattern): + f.unlink() + after = _dir_size_mb(proxy) + print(f"prune_litellm_proxy: {before}M -> {after}M") + + +if __name__ == "__main__": + if len(sys.argv) != 2: + raise SystemExit("usage: python prune_litellm_proxy.py ") + prune(Path(sys.argv[1])) diff --git a/desktop/packaging/pyi_rthook_magika.py b/desktop/packaging/pyi_rthook_magika.py new file mode 100644 index 00000000..a47ba9ee --- /dev/null +++ b/desktop/packaging/pyi_rthook_magika.py @@ -0,0 +1,39 @@ +"""PyInstaller runtime hook: stub `magika` so markitdown runs without onnxruntime. + +markitdown hard-depends on magika, which loads an ONNX model via onnxruntime +(tens of MB) purely to sniff a file's type from its content. OpenKB only ever +converts real files with correct extensions, so markitdown's extension/mimetype +based stream-info guessing is sufficient and magika's content sniffing is +redundant. This hook installs a lightweight in-memory `magika` module before +markitdown imports it; `identify_stream` returns a non-"ok" status, which makes +markitdown fall back to the extension guess. Paired with +`--exclude-module magika --exclude-module onnxruntime` at build time, this drops +onnxruntime (and magika's model) from the packaged sidecar entirely. +""" + +import sys +import types + + +class _Result: + # Any status other than "ok" makes markitdown use its extension-based guess. + status = "stub" + + +class Magika: + def __init__(self, *args, **kwargs): + pass + + def identify_stream(self, *args, **kwargs): + return _Result() + + def identify_bytes(self, *args, **kwargs): + return _Result() + + def identify_path(self, *args, **kwargs): + return _Result() + + +_stub = types.ModuleType("magika") +_stub.Magika = Magika +sys.modules.setdefault("magika", _stub) diff --git a/desktop/packaging/sidecar_entry.py b/desktop/packaging/sidecar_entry.py new file mode 100644 index 00000000..13fb11c7 --- /dev/null +++ b/desktop/packaging/sidecar_entry.py @@ -0,0 +1,11 @@ +"""Frozen entry point for the OpenKB API sidecar. + +Mirrors the `openkb-api = openkb.api:main` console script. The Tauri shell +spawns the frozen binary as `openkb-api-sidecar --host 127.0.0.1 --port `; +argparse in `openkb.api.main` reads those args from sys.argv unchanged. +""" + +from openkb.api import main + +if __name__ == "__main__": + main() diff --git a/desktop/src-tauri/Cargo.lock b/desktop/src-tauri/Cargo.lock new file mode 100644 index 00000000..0616e37a --- /dev/null +++ b/desktop/src-tauri/Cargo.lock @@ -0,0 +1,4492 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e76a019e91224d279006ff972f1e984179a6e9feb050adba6ce8274aef23195" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" + +[[package]] +name = "atk" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "241b621213072e993be4f6f3a9e4b45f65b7e6faad43001be957184b7bb1824b" +dependencies = [ + "atk-sys", + "glib", + "libc", +] + +[[package]] +name = "atk-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e48b684b0ca77d2bbadeef17424c2ea3c897d44d566a1617e7e8f30614d086" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" +dependencies = [ + "serde_core", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2", +] + +[[package]] +name = "brotli" +version = "8.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc91aac060a7a1e25823bdccbfb6af1875b88f17c6daac97894eed8207166b3" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "5.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a32acac15fe1967bc3986b2a6347dffc965602354ea6f450ad07e8bfd253583" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + +[[package]] +name = "bytemuck" +version = "1.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6aedf8ae72766347502cf3cb4f41cf5e9cc37d28bee90f1fdaaae15f9cf9424" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" +dependencies = [ + "serde", +] + +[[package]] +name = "cairo-rs" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" +dependencies = [ + "bitflags 2.13.1", + "cairo-sys-rs", + "glib", + "libc", + "once_cell", + "thiserror 1.0.69", +] + +[[package]] +name = "cairo-sys-rs" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "camino" +version = "1.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f2d30e4173c4026932d51d31d6b0613b1fd3014bf3f9f8943d4ba139c437ba0" +dependencies = [ + "serde_core", +] + +[[package]] +name = "cargo-platform" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror 2.0.18", +] + +[[package]] +name = "cargo_toml" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "374b7c592d9c00c1f4972ea58390ac6b18cbb6ab79011f3bdc90a0b82ca06b77" +dependencies = [ + "serde", + "toml 0.9.12+spec-1.1.0", +] + +[[package]] +name = "cc" +version = "1.2.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17dd265a7d0f31ef544e1b20e03add05d3b45b491b633b10d67145d2acc1a38" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cfb" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38f2da7a0a2c4ccf0065be06397cc26a81f4e528be095826eee9d4adbb8c60f" +dependencies = [ + "byteorder", + "fnv", + "uuid", +] + +[[package]] +name = "cfg-expr" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +dependencies = [ + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "chrono" +version = "0.4.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" +dependencies = [ + "iana-time-zone", + "num-traits", + "serde", + "windows-link 0.2.1", +] + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "cookie" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" +dependencies = [ + "time", + "version_check", +] + +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "core-graphics" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97" +dependencies = [ + "bitflags 2.13.1", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" +dependencies = [ + "bitflags 2.13.1", + "core-foundation", + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d85363c37faeca707aef026efa9f3b34d077bce547e48f770770625c6013679e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "cssparser" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dae61cf9c0abb83bd659dab65b7e4e38d8236824c85f0f804f173567bda257d2" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "phf", + "smallvec", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn 2.0.119", +] + +[[package]] +name = "ctor" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "352d39c2f7bef1d6ad73db6f5160efcaed66d94ef8c6c573a8410c00bf909a98" +dependencies = [ + "ctor-proc-macro", + "dtor", +] + +[[package]] +name = "ctor-proc-macro" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52560adf09603e58c9a7ee1fe1dcb95a16927b17c127f0ac02d6e768a0e25bc1" + +[[package]] +name = "darling" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" +dependencies = [ + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.119", +] + +[[package]] +name = "darling_macro" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "dbus" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ab69f03cc8c4340c9c8e315114e1658e6775a9b16a04357973aa21cec22b32e" +dependencies = [ + "libc", + "libdbus-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "serde_core", +] + +[[package]] +name = "derive_more" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.119", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dirs" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.61.2", +] + +[[package]] +name = "dispatch2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" +dependencies = [ + "bitflags 2.13.1", + "block2", + "libc", + "objc2", +] + +[[package]] +name = "displaydoc" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "dlopen2" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e2c5bd4158e66d1e215c49b837e11d62f3267b30c92f1d171c4d3105e3dc4d4" +dependencies = [ + "dlopen2_derive", + "libc", + "once_cell", + "winapi", +] + +[[package]] +name = "dlopen2_derive" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fbbb781877580993a8707ec48672673ec7b81eeba04cfd2310bd28c08e47c8f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "dom_query" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521e380c0c8afb8d9a1e83a1822ee03556fc3e3e7dbc1fd30be14e37f9cb3f89" +dependencies = [ + "bit-set", + "cssparser", + "foldhash", + "html5ever", + "precomputed-hash", + "selectors", + "tendril", +] + +[[package]] +name = "dpi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" +dependencies = [ + "serde", +] + +[[package]] +name = "dtoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c3cf4824e2d5f025c7b531afcb2325364084a16806f6d47fbc1f5fbd9960590" + +[[package]] +name = "dtoa-short" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +dependencies = [ + "dtoa", +] + +[[package]] +name = "dtor" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1057d6c64987086ff8ed0fd3fbf377a6b7d205cc7715868cd401705f715cbe4" +dependencies = [ + "dtor-proc-macro", +] + +[[package]] +name = "dtor-proc-macro" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5" + +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + +[[package]] +name = "embed-resource" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbfdaacccebec3b28e4866b8973543c7647797db5ada1bdab552e48fe665fbbd" +dependencies = [ + "cc", + "memchr", + "rustc_version", + "toml 1.1.3+spec-1.1.0", + "vswhom", + "winreg", +] + +[[package]] +name = "embed_plist" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "erased-serde" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2add8a07dd6a8d93ff627029c51de145e12686fbc36ecb298ac22e74cf02dec" +dependencies = [ + "serde", + "serde_core", + "typeid", +] + +[[package]] +name = "fastrand" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "field-offset" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" +dependencies = [ + "memoffset", + "rustc_version", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-executor" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-macro" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + +[[package]] +name = "gdk" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9f245958c627ac99d8e529166f9823fb3b838d1d41fd2b297af3075093c2691" +dependencies = [ + "cairo-rs", + "gdk-pixbuf", + "gdk-sys", + "gio", + "glib", + "libc", + "pango", +] + +[[package]] +name = "gdk-pixbuf" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50e1f5f1b0bfb830d6ccc8066d18db35c487b1b2b1e8589b5dfe9f07e8defaec" +dependencies = [ + "gdk-pixbuf-sys", + "gio", + "glib", + "libc", + "once_cell", +] + +[[package]] +name = "gdk-pixbuf-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9839ea644ed9c97a34d129ad56d38a25e6756f99f3a88e15cd39c20629caf7" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gdk-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c2d13f38594ac1e66619e188c6d5a1adb98d11b2fcf7894fc416ad76aa2f3f7" +dependencies = [ + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "pkg-config", + "system-deps", +] + +[[package]] +name = "gdkwayland-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "140071d506d223f7572b9f09b5e155afbd77428cd5cc7af8f2694c41d98dfe69" +dependencies = [ + "gdk-sys", + "glib-sys", + "gobject-sys", + "libc", + "pkg-config", + "system-deps", +] + +[[package]] +name = "gdkx11" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3caa00e14351bebbc8183b3c36690327eb77c49abc2268dd4bd36b856db3fbfe" +dependencies = [ + "gdk", + "gdkx11-sys", + "gio", + "glib", + "libc", + "x11", +] + +[[package]] +name = "gdkx11-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e7445fe01ac26f11601db260dd8608fe172514eb63b3b5e261ea6b0f4428d" +dependencies = [ + "gdk-sys", + "glib-sys", + "libc", + "system-deps", + "x11", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi 5.3.0", + "wasip2", +] + +[[package]] +name = "getrandom" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", +] + +[[package]] +name = "gio" +version = "0.18.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fc8f532f87b79cbc51a79748f16a6828fb784be93145a322fa14d06d354c73" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "gio-sys", + "glib", + "libc", + "once_cell", + "pin-project-lite", + "smallvec", + "thiserror 1.0.69", +] + +[[package]] +name = "gio-sys" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", + "winapi", +] + +[[package]] +name = "glib" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" +dependencies = [ + "bitflags 2.13.1", + "futures-channel", + "futures-core", + "futures-executor", + "futures-task", + "futures-util", + "gio-sys", + "glib-macros", + "glib-sys", + "gobject-sys", + "libc", + "memchr", + "once_cell", + "smallvec", + "thiserror 1.0.69", +] + +[[package]] +name = "glib-macros" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc" +dependencies = [ + "heck 0.4.1", + "proc-macro-crate 2.0.2", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "glib-sys" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898" +dependencies = [ + "libc", + "system-deps", +] + +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "gobject-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gtk" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd56fb197bfc42bd5d2751f4f017d44ff59fbb58140c6b49f9b3b2bdab08506a" +dependencies = [ + "atk", + "cairo-rs", + "field-offset", + "futures-channel", + "gdk", + "gdk-pixbuf", + "gio", + "glib", + "gtk-sys", + "gtk3-macros", + "libc", + "pango", + "pkg-config", +] + +[[package]] +name = "gtk-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f29a1c21c59553eb7dd40e918be54dccd60c52b049b75119d5d96ce6b624414" +dependencies = [ + "atk-sys", + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "system-deps", +] + +[[package]] +name = "gtk3-macros" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ff3c5b21f14f0736fed6dcfc0bfb4225ebf5725f3c0209edeec181e4d73e9d" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "html5ever" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1054432bae2f14e0061e33d23402fbaa67a921d319d56adc6bcf887ddad1cbc2" +dependencies = [ + "log", + "markup5ever", +] + +[[package]] +name = "http" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9f41fd6a08e4d4ec69df65976da761afd5ad5e58a9d4acb46bd1c953a9e3ff2" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "hyper" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-util" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core 0.62.2", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ico" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e795dff5605e0f04bff85ca41b51a96b83e80b281e96231bcaaf1ac35103371" +dependencies = [ + "byteorder", + "png 0.17.16", +] + +[[package]] +name = "icu_collections" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" +dependencies = [ + "displaydoc", + "potential_utf", + "utf8_iter", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" + +[[package]] +name = "icu_properties" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" + +[[package]] +name = "icu_provider" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.1", + "serde", + "serde_core", +] + +[[package]] +name = "infer" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a588916bfdfd92e71cacef98a63d9b1f0d74d6599980d11894290e7ddefffcf7" +dependencies = [ + "cfb", +] + +[[package]] +name = "ipnet" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "javascriptcore-rs" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca5671e9ffce8ffba57afc24070e906da7fc4b1ba66f2cabebf61bf2ea257fcc" +dependencies = [ + "bitflags 1.3.2", + "glib", + "javascriptcore-rs-sys", +] + +[[package]] +name = "javascriptcore-rs-sys" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1be78d14ffa4b75b66df31840478fef72b51f8c2465d4ca7c194da9f7a5124" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys 0.3.1", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.119", +] + +[[package]] +name = "js-sys" +version = "0.3.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" +dependencies = [ + "cfg-if", + "futures-util", + "wasm-bindgen", +] + +[[package]] +name = "json-patch" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "863726d7afb6bc2590eeff7135d923545e5e964f004c2ccf8716c25e70a86f08" +dependencies = [ + "jsonptr", + "serde", + "serde_json", + "thiserror 1.0.69", +] + +[[package]] +name = "jsonptr" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dea2b27dd239b2556ed7a25ba842fe47fd602e7fc7433c2a8d6106d4d9edd70" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "keyboard-types" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" +dependencies = [ + "bitflags 2.13.1", + "serde", + "unicode-segmentation", +] + +[[package]] +name = "libappindicator" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03589b9607c868cc7ae54c0b2a22c8dc03dd41692d48f2d7df73615c6a95dc0a" +dependencies = [ + "glib", + "gtk", + "gtk-sys", + "libappindicator-sys", + "log", +] + +[[package]] +name = "libappindicator-sys" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e9ec52138abedcc58dc17a7c6c0c00a2bdb4f3427c7f63fa97fd0d859155caf" +dependencies = [ + "gtk-sys", + "libloading", + "once_cell", +] + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "libdbus-sys" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "328c4789d42200f1eeec05bd86c9c13c7f091d2ba9a6ea35acdf51f31bc0f043" +dependencies = [ + "pkg-config", +] + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "libredox" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" +dependencies = [ + "libc", +] + +[[package]] +name = "litemap" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" + +[[package]] +name = "markup5ever" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8983d30f2915feeaaab2d6babdd6bc7e9ed1a00b66b5e6d74df19aa9c0e91862" +dependencies = [ + "log", + "tendril", + "web_atoms", +] + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "muda" +version = "0.19.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd04e60bc0b07438a6771710ee1698f98f6ebbc7f89b61264af1563b8aeb878" +dependencies = [ + "crossbeam-channel", + "dpi", + "gtk", + "keyboard-types", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", + "once_cell", + "png 0.18.1", + "serde", + "thiserror 2.0.18", + "windows-sys 0.61.2", +] + +[[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags 2.13.1", + "jni-sys 0.3.1", + "log", + "ndk-sys", + "num_enum", + "raw-window-handle", + "thiserror 1.0.69", +] + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys 0.3.1", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "num-conv" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_enum" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" +dependencies = [ + "proc-macro-crate 3.5.0", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "objc2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" +dependencies = [ + "objc2-encode", + "objc2-exception-helper", +] + +[[package]] +name = "objc2-app-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" +dependencies = [ + "bitflags 2.13.1", + "block2", + "objc2", + "objc2-core-foundation", + "objc2-foundation", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" +dependencies = [ + "bitflags 2.13.1", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-data" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.13.1", + "dispatch2", + "objc2", +] + +[[package]] +name = "objc2-core-graphics" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" +dependencies = [ + "bitflags 2.13.1", + "dispatch2", + "objc2", + "objc2-core-foundation", + "objc2-io-surface", +] + +[[package]] +name = "objc2-core-image" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-location" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca347214e24bc973fc025fd0d36ebb179ff30536ed1f80252706db19ee452009" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-text" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" +dependencies = [ + "bitflags 2.13.1", + "objc2", + "objc2-core-foundation", + "objc2-core-graphics", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-exception-helper" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7a1c5fbb72d7735b076bb47b578523aedc40f3c439bea6dfd595c089d79d98a" +dependencies = [ + "cc", +] + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags 2.13.1", + "block2", + "objc2", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-io-surface" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" +dependencies = [ + "bitflags 2.13.1", + "objc2", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" +dependencies = [ + "bitflags 2.13.1", + "objc2", + "objc2-core-foundation", + "objc2-foundation", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" +dependencies = [ + "bitflags 2.13.1", + "block2", + "objc2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-image", + "objc2-core-location", + "objc2-core-text", + "objc2-foundation", + "objc2-quartz-core", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9df9128cbbfef73cda168416ccf7f837b62737d748333bfe9ab71c245d76613e" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-web-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2e5aaab980c433cf470df9d7af96a7b46a9d892d521a2cbbb2f8a4c16751e7f" +dependencies = [ + "bitflags 2.13.1", + "block2", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "openkb-desktop" +version = "0.1.0" +dependencies = [ + "tauri", + "tauri-build", + "ureq", +] + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "pango" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4" +dependencies = [ + "gio", + "glib", + "libc", + "once_cell", + "pango-sys", +] + +[[package]] +name = "pango-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436737e391a843e5933d6d9aa102cb126d501e815b83601365a948a518555dc5" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link 0.2.1", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "phf" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" +dependencies = [ + "phf_macros", + "phf_shared", + "serde", +] + +[[package]] +name = "phf_codegen" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49aa7f9d80421bca176ca8dbfebe668cc7a2684708594ec9f3c0db0805d5d6e1" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" +dependencies = [ + "fastrand", + "phf_shared", +] + +[[package]] +name = "phf_macros" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "phf_shared" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "pkg-config" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" + +[[package]] +name = "plist" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da1d65da6dd5d1e44199ac0f58712d241c0f439f80adea8924d832384087f85" +dependencies = [ + "base64 0.22.1", + "indexmap 2.14.0", + "quick-xml", + "serde", + "time", +] + +[[package]] +name = "png" +version = "0.17.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "png" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" +dependencies = [ + "bitflags 2.13.1", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "potential_utf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" +dependencies = [ + "zerovec", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-crate" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" +dependencies = [ + "toml_datetime 0.6.3", + "toml_edit 0.20.2", +] + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit 0.25.13+spec-1.1.0", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quick-xml" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1" +dependencies = [ + "memchr", +] + +[[package]] +name = "quote" +version = "1.0.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.13.1", +] + +[[package]] +name = "redox_users" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" +dependencies = [ + "getrandom 0.2.17", + "libredox", + "thiserror 2.0.18", +] + +[[package]] +name = "ref-cast" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "regex" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fcfdb36bda0c880c5931cdc7a2bcdc8ba4556847b9d912bca70bc94708711ad" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + +[[package]] +name = "reqwest" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "sync_wrapper", + "tokio", + "tokio-util", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.17", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustc-hash" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustls" +version = "0.23.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c54fcab019b409d04215d3a17cb438fd7fbf192ee61461f20f4fe18704bc138" +dependencies = [ + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "764899a24af3980067ee14bc143654f297b22eaebfe3c7b6b211920a5a59b046" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schemars" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615" +dependencies = [ + "dyn-clone", + "indexmap 1.9.3", + "schemars_derive", + "serde", + "serde_json", + "url", + "uuid", +] + +[[package]] +name = "schemars" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 2.0.119", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "selectors" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5d9c0c92a92d33f08817311cf3f2c29a3538a8240e94a6a3c622ce652d7e00c" +dependencies = [ + "bitflags 2.13.1", + "cssparser", + "derive_more", + "log", + "new_debug_unreachable", + "phf", + "phf_codegen", + "precomputed-hash", + "rustc-hash", + "servo_arc", + "smallvec", +] + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde-untagged" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9faf48a4a2d2693be24c6289dbe26552776eb7737074e6722891fadbe6c5058" +dependencies = [ + "erased-serde", + "serde", + "serde_core", + "typeid", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "serde_json" +version = "1.0.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_repr" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_spanned" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_with" +version = "3.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a5c54c7310e7b8b9577c286d7e399ddd876c3e12b3ed917a8aabc4b96e9e8c" +dependencies = [ + "base64 0.22.1", + "bs58", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.14.0", + "schemars 0.9.0", + "schemars 1.2.1", + "serde_core", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84d57bc0c8b9a17920c178daa6bb924850d54a9c97ab45194bb8c17ad66bb660" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "serialize-to-javascript" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04f3666a07a197cdb77cdf306c32be9b7f598d7060d50cfd4d5aa04bfd92f6c5" +dependencies = [ + "serde", + "serde_json", + "serialize-to-javascript-impl", +] + +[[package]] +name = "serialize-to-javascript-impl" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "772ee033c0916d670af7860b6e1ef7d658a4629a6d0b4c8c3e67f09b3765b75d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "servo_arc" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "170fb83ab34de17dc69aa7c67482b22218ddb85da56546f9bd6b929e32a05930" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] +name = "simd-adler32" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" + +[[package]] +name = "siphasher" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" + +[[package]] +name = "socket2" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "softbuffer" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aac18da81ebbf05109ab275b157c22a653bb3c12cf884450179942f81bcbf6c3" +dependencies = [ + "bytemuck", + "js-sys", + "ndk", + "objc2", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation", + "objc2-quartz-core", + "raw-window-handle", + "redox_syscall", + "tracing", + "wasm-bindgen", + "web-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "soup3" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "471f924a40f31251afc77450e781cb26d55c0b650842efafc9c6cbd2f7cc4f9f" +dependencies = [ + "futures-channel", + "gio", + "glib", + "libc", + "soup3-sys", +] + +[[package]] +name = "soup3-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebe8950a680a12f24f15ebe1bf70db7af98ad242d9db43596ad3108aab86c27" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "string_cache" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18596f8c785a729f2819c0f6a7eae6ebeebdfffbfe4214ae6b087f690e31901" +dependencies = [ + "new_debug_unreachable", + "parking_lot", + "phf_shared", + "precomputed-hash", +] + +[[package]] +name = "string_cache_codegen" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585635e46db231059f76c5849798146164652513eb9e8ab2685939dd90f29b69" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "swift-rs" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4057c98e2e852d51fdcfca832aac7b571f6b351ad159f9eda5db1655f8d0c4d7" +dependencies = [ + "base64 0.21.7", + "serde", + "serde_json", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "system-deps" +version = "6.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +dependencies = [ + "cfg-expr", + "heck 0.5.0", + "pkg-config", + "toml 0.8.2", + "version-compare", +] + +[[package]] +name = "tao" +version = "0.35.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1c93047acf68669466a34690ac58cca7010bd1b201e1ec86f1fd0a75d3dd4a9" +dependencies = [ + "bitflags 2.13.1", + "block2", + "core-foundation", + "core-graphics", + "crossbeam-channel", + "dbus", + "dispatch2", + "dlopen2", + "dpi", + "gdkwayland-sys", + "gdkx11-sys", + "gtk", + "jni", + "libc", + "log", + "ndk", + "ndk-sys", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "objc2-ui-kit", + "once_cell", + "parking_lot", + "percent-encoding", + "raw-window-handle", + "tao-macros", + "unicode-segmentation", + "url", + "windows", + "windows-core 0.61.2", + "windows-version", + "x11-dl", +] + +[[package]] +name = "tao-macros" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + +[[package]] +name = "tauri" +version = "2.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "667b20e2726d572dea2de7370da16e188eb06008faf9a92fab7cdc46791190b5" +dependencies = [ + "anyhow", + "bytes", + "cookie", + "dirs", + "dunce", + "embed_plist", + "getrandom 0.3.4", + "glob", + "gtk", + "heck 0.5.0", + "http", + "jni", + "libc", + "log", + "mime", + "muda", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "objc2-ui-kit", + "objc2-web-kit", + "percent-encoding", + "plist", + "raw-window-handle", + "reqwest", + "serde", + "serde_json", + "serde_repr", + "serialize-to-javascript", + "swift-rs", + "tauri-build", + "tauri-macros", + "tauri-runtime", + "tauri-runtime-wry", + "tauri-utils", + "thiserror 2.0.18", + "tokio", + "tray-icon", + "url", + "webkit2gtk", + "webview2-com", + "window-vibrancy", + "windows", +] + +[[package]] +name = "tauri-build" +version = "2.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc9ce40b16101cb6ea63d3e221567affd1c3a9205f95d7bc574941a10636b632" +dependencies = [ + "anyhow", + "cargo_toml", + "dirs", + "glob", + "heck 0.5.0", + "json-patch", + "schemars 0.8.22", + "semver", + "serde", + "serde_json", + "tauri-utils", + "tauri-winres", + "walkdir", +] + +[[package]] +name = "tauri-codegen" +version = "2.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08279169ff42f8fc45a1dbc9dcae888893ba95288142e5880c59b93a26d2cfc5" +dependencies = [ + "base64 0.22.1", + "brotli", + "ico", + "json-patch", + "plist", + "png 0.17.16", + "proc-macro2", + "quote", + "semver", + "serde", + "serde_json", + "sha2", + "syn 2.0.119", + "tauri-utils", + "thiserror 2.0.18", + "time", + "url", + "uuid", + "walkdir", +] + +[[package]] +name = "tauri-macros" +version = "2.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8b394794f399a421811d06966343e7933fcae92d59f5180b9388d1174497a45" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.119", + "tauri-codegen", + "tauri-utils", +] + +[[package]] +name = "tauri-runtime" +version = "2.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0b4bc95aed361b0019067d189a1174a603d460d0f6c72606512d59fc9c12ec8" +dependencies = [ + "cookie", + "dpi", + "gtk", + "http", + "jni", + "objc2", + "objc2-ui-kit", + "objc2-web-kit", + "raw-window-handle", + "serde", + "serde_json", + "tauri-utils", + "thiserror 2.0.18", + "url", + "webkit2gtk", + "webview2-com", + "windows", +] + +[[package]] +name = "tauri-runtime-wry" +version = "2.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e6fac707727b7a2f48e4ded90976324267371073edbb415ffb73bb0458d203f" +dependencies = [ + "gtk", + "http", + "jni", + "log", + "objc2", + "objc2-app-kit", + "once_cell", + "percent-encoding", + "raw-window-handle", + "softbuffer", + "tao", + "tauri-runtime", + "tauri-utils", + "url", + "webkit2gtk", + "webview2-com", + "windows", + "wry", +] + +[[package]] +name = "tauri-utils" +version = "2.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e176a18e67764923c4f1ce66f25ae4abe5f688384d5eb1a0fa6c77f3d90f887" +dependencies = [ + "anyhow", + "brotli", + "cargo_metadata", + "ctor", + "dom_query", + "dunce", + "glob", + "http", + "infer", + "json-patch", + "log", + "memchr", + "phf", + "plist", + "proc-macro2", + "quote", + "regex", + "schemars 0.8.22", + "semver", + "serde", + "serde-untagged", + "serde_json", + "serde_with", + "swift-rs", + "thiserror 2.0.18", + "toml 1.1.3+spec-1.1.0", + "url", + "urlpattern", + "uuid", + "walkdir", +] + +[[package]] +name = "tauri-winres" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc65d45c68858bfe420dd29e834b5d15dbecf8a07a8a16cf4d532c7b1f69d4b6" +dependencies = [ + "dunce", + "embed-resource", + "toml 1.1.3+spec-1.1.0", +] + +[[package]] +name = "tendril" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fed54709c5b3a53d09bb1c113ea4f5ceafd1e772ddcb0030a82e1d56c087b08" +dependencies = [ + "new_debug_unreachable", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "time" +version = "0.3.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18dfaaeddcb932337b5e7866ee7d0ce9b76d2fd092997146f187ec09b4558a50" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" + +[[package]] +name = "time-macros" +version = "0.2.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c431b87111666e491a90baa837f914fb45cd5dc3c268591b0220ff5057f2085f" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinystr" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d988bcd52dbe076d3d46903332f58c912b87a2c49b1428419a5845154762ffee" +dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-util" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" +dependencies = [ + "serde", + "serde_spanned 0.6.9", + "toml_datetime 0.6.3", + "toml_edit 0.20.2", +] + +[[package]] +name = "toml" +version = "0.9.12+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" +dependencies = [ + "indexmap 2.14.0", + "serde_core", + "serde_spanned 1.1.1", + "toml_datetime 0.7.5+spec-1.1.0", + "toml_parser", + "toml_writer", + "winnow 0.7.15", +] + +[[package]] +name = "toml" +version = "1.1.3+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53c96ecdfa941c8fc4fcaed14f99ada8ebed502eef533015095a07e3301d4c3c" +dependencies = [ + "indexmap 2.14.0", + "serde_core", + "serde_spanned 1.1.1", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "toml_writer", + "winnow 1.0.4", +] + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_datetime" +version = "0.7.5+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.14.0", + "toml_datetime 0.6.3", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap 2.14.0", + "serde", + "serde_spanned 0.6.9", + "toml_datetime 0.6.3", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.25.13+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6975367e4d2ef766d86af01ffad14b622fecc8d4357a998fbc4deb6e9bacaf9b" +dependencies = [ + "indexmap 2.14.0", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "winnow 1.0.4", +] + +[[package]] +name = "toml_parser" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ + "winnow 1.0.4", +] + +[[package]] +name = "toml_writer" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" + +[[package]] +name = "tower" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" +dependencies = [ + "bitflags 2.13.1", + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", + "url", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "tray-icon" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65ba1e5f6b9ef9fd87e21b9c6f351554dbd717960089168fcfdef854686961dc" +dependencies = [ + "crossbeam-channel", + "dirs", + "libappindicator", + "muda", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation", + "once_cell", + "png 0.18.1", + "serde", + "thiserror 2.0.18", + "windows-sys 0.61.2", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typeid" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" + +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + +[[package]] +name = "unic-char-property" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" +dependencies = [ + "unic-char-range", +] + +[[package]] +name = "unic-char-range" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" + +[[package]] +name = "unic-common" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" + +[[package]] +name = "unic-ucd-ident" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e230a37c0381caa9219d67cf063aa3a375ffed5bf541a452db16e744bdab6987" +dependencies = [ + "unic-char-property", + "unic-char-range", + "unic-ucd-version", +] + +[[package]] +name = "unic-ucd-version" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" +dependencies = [ + "unic-common", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-segmentation" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "ureq" +version = "2.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d" +dependencies = [ + "base64 0.22.1", + "flate2", + "log", + "once_cell", + "rustls", + "rustls-pki-types", + "url", + "webpki-roots 0.26.11", +] + +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", + "serde_derive", +] + +[[package]] +name = "urlpattern" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70acd30e3aa1450bc2eece896ce2ad0d178e9c079493819301573dae3c37ba6d" +dependencies = [ + "regex", + "serde", + "unic-ucd-ident", + "url", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "uuid" +version = "1.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf3923a6f5c4c6382e0b653c4117f48d631ea17f38ed86e2a828e6f7412f5239" +dependencies = [ + "getrandom 0.4.3", + "js-sys", + "serde_core", + "wasm-bindgen", +] + +[[package]] +name = "version-compare" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "vswhom" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be979b7f07507105799e854203b470ff7c78a1639e330a58f183b5fea574608b" +dependencies = [ + "libc", + "vswhom-sys", +] + +[[package]] +name = "vswhom-sys" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb067e4cbd1ff067d1df46c9194b5de0e98efd2810bbc95c5d5e5f25a3231150" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.4+wasi-0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.119", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-streams" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "web-sys" +version = "0.3.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web_atoms" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "075474b12bcb3d2e3d4546580e9de478eeeead668a1761e2a8860c836b7ef297" +dependencies = [ + "phf", + "phf_codegen", + "string_cache", + "string_cache_codegen", +] + +[[package]] +name = "webkit2gtk" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1027150013530fb2eaf806408df88461ae4815a45c541c8975e61d6f2fc4793" +dependencies = [ + "bitflags 1.3.2", + "cairo-rs", + "gdk", + "gdk-sys", + "gio", + "gio-sys", + "glib", + "glib-sys", + "gobject-sys", + "gtk", + "gtk-sys", + "javascriptcore-rs", + "libc", + "once_cell", + "soup3", + "webkit2gtk-sys", +] + +[[package]] +name = "webkit2gtk-sys" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "916a5f65c2ef0dfe12fff695960a2ec3d4565359fdbb2e9943c974e06c734ea5" +dependencies = [ + "bitflags 1.3.2", + "cairo-sys-rs", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "gtk-sys", + "javascriptcore-rs-sys", + "libc", + "pkg-config", + "soup3-sys", + "system-deps", +] + +[[package]] +name = "webpki-roots" +version = "0.26.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" +dependencies = [ + "webpki-roots 1.0.8", +] + +[[package]] +name = "webpki-roots" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf85cb06032201fa7c6f829d7db5a7e5aa45bcc0655327713065f6f0576731bf" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "webview2-com" +version = "0.38.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7130243a7a5b33c54a444e54842e6a9e133de08b5ad7b5861cd8ed9a6a5bc96a" +dependencies = [ + "webview2-com-macros", + "webview2-com-sys", + "windows", + "windows-core 0.61.2", + "windows-implement", + "windows-interface", +] + +[[package]] +name = "webview2-com-macros" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a921c1b6914c367b2b823cd4cde6f96beec77d30a939c8199bb377cf9b9b54" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "webview2-com-sys" +version = "0.38.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "381336cfffd772377d291702245447a5251a2ffa5bad679c99e61bc48bacbf9c" +dependencies = [ + "thiserror 2.0.18", + "windows", + "windows-core 0.61.2", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "window-vibrancy" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9bec5a31f3f9362f2258fd0e9c9dd61a9ca432e7306cc78c444258f0dce9a9c" +dependencies = [ + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", + "raw-window-handle", + "windows-sys 0.59.0", + "windows-version", +] + +[[package]] +name = "windows" +version = "0.61.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +dependencies = [ + "windows-collections", + "windows-core 0.61.2", + "windows-future", + "windows-link 0.1.3", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +dependencies = [ + "windows-core 0.61.2", +] + +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", +] + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-threading" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-version" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4060a1da109b9d0326b7262c8e12c84df67cc0dbc9e33cf49e01ccc2eb63631" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" + +[[package]] +name = "winnow" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.55.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb5a765337c50e9ec252c2069be9bf91c7df47afb103b642ba3a53bf8101be97" +dependencies = [ + "cfg-if", + "windows-sys 0.59.0", +] + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "writeable" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" + +[[package]] +name = "wry" +version = "0.55.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186f9871daa55fd9c016578b810d149de58367113db7fb72b462d2323ce19514" +dependencies = [ + "base64 0.22.1", + "block2", + "cookie", + "crossbeam-channel", + "dirs", + "dom_query", + "dpi", + "dunce", + "gdkx11", + "gtk", + "http", + "javascriptcore-rs", + "jni", + "libc", + "ndk", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", + "objc2-ui-kit", + "objc2-web-kit", + "once_cell", + "percent-encoding", + "raw-window-handle", + "sha2", + "soup3", + "tao-macros", + "thiserror 2.0.18", + "url", + "webkit2gtk", + "webkit2gtk-sys", + "webview2-com", + "windows", + "windows-core 0.61.2", + "windows-version", + "x11-dl", +] + +[[package]] +name = "x11" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "502da5464ccd04011667b11c435cb992822c2c0dbde1770c988480d312a0db2e" +dependencies = [ + "libc", + "pkg-config", +] + +[[package]] +name = "x11-dl" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + +[[package]] +name = "yoke" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", + "synstructure", +] + +[[package]] +name = "zerofrom" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" + +[[package]] +name = "zerotrie" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/desktop/src-tauri/Cargo.toml b/desktop/src-tauri/Cargo.toml new file mode 100644 index 00000000..eb093ed1 --- /dev/null +++ b/desktop/src-tauri/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "openkb-desktop" +version = "0.1.0" +edition = "2021" +description = "OpenKB desktop shell (Tauri) — wraps the frozen openkb-api sidecar" +license = "Apache-2.0" + +[build-dependencies] +tauri-build = { version = "2", features = [] } + +[dependencies] +tauri = { version = "2", features = [] } +# ureq is a tiny blocking HTTP client used only to poll the sidecar's health +# endpoint during startup. Swap for anything you prefer. +ureq = "2" diff --git a/desktop/src-tauri/build.rs b/desktop/src-tauri/build.rs new file mode 100644 index 00000000..d860e1e6 --- /dev/null +++ b/desktop/src-tauri/build.rs @@ -0,0 +1,3 @@ +fn main() { + tauri_build::build() +} diff --git a/desktop/src-tauri/icons/128x128.png b/desktop/src-tauri/icons/128x128.png new file mode 100644 index 00000000..b2922cab Binary files /dev/null and b/desktop/src-tauri/icons/128x128.png differ diff --git a/desktop/src-tauri/icons/256x256.png b/desktop/src-tauri/icons/256x256.png new file mode 100644 index 00000000..39379bd6 Binary files /dev/null and b/desktop/src-tauri/icons/256x256.png differ diff --git a/desktop/src-tauri/icons/32x32.png b/desktop/src-tauri/icons/32x32.png new file mode 100644 index 00000000..33b29cde Binary files /dev/null and b/desktop/src-tauri/icons/32x32.png differ diff --git a/desktop/src-tauri/icons/icon.ico b/desktop/src-tauri/icons/icon.ico new file mode 100644 index 00000000..de62a5da Binary files /dev/null and b/desktop/src-tauri/icons/icon.ico differ diff --git a/desktop/src-tauri/icons/icon.png b/desktop/src-tauri/icons/icon.png new file mode 100644 index 00000000..215db640 Binary files /dev/null and b/desktop/src-tauri/icons/icon.png differ diff --git a/desktop/src-tauri/splash/index.html b/desktop/src-tauri/splash/index.html new file mode 100644 index 00000000..3ec9ee56 --- /dev/null +++ b/desktop/src-tauri/splash/index.html @@ -0,0 +1,32 @@ + + + + + + OpenKB + + + +
+

OpenKB

+

Starting your knowledge base

+
+ + diff --git a/desktop/src-tauri/src/main.rs b/desktop/src-tauri/src/main.rs new file mode 100644 index 00000000..33a251bb --- /dev/null +++ b/desktop/src-tauri/src/main.rs @@ -0,0 +1,121 @@ +// OpenKB desktop shell. +// +// Reference skeleton (Tauri v2). On launch it: (1) spawns the frozen +// openkb-api sidecar on a localhost port, (2) shows a splash window while +// polling the sidecar's health, (3) navigates the WebView to the sidecar once +// it answers, and (4) kills the sidecar on exit. +// +// NOTE: not compiled in the container used so far (no webkit2gtk). Build on a +// machine with the platform WebView libraries. Treat exact Tauri-v2 API details +// (navigate signature, resource path) as things to confirm against your Tauri +// version. +#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] + +use std::process::{Child, Command}; +use std::sync::Mutex; +use std::time::{Duration, Instant}; + +use tauri::{Manager, RunEvent, Url}; + +/// Held in Tauri state so the sidecar can be killed when the app exits. +struct Sidecar(Mutex>); + +const HOST: &str = "127.0.0.1"; +const PORT: u16 = 8765; + +/// Spawn the bundled PyInstaller onedir sidecar. +/// +/// The sidecar is bundled as a resource *directory* named `sidecar` (see +/// `tauri.conf.json` `bundle.resources`), because PyInstaller onedir output is +/// a folder, not a single executable — so this can't use Tauri's `externalBin` +/// mechanism. +fn spawn_sidecar(app: &tauri::App) -> std::io::Result { + let resource_dir = app + .path() + .resource_dir() + .expect("resource dir should resolve"); + let exe_name = if cfg!(windows) { + "openkb-api-sidecar.exe" + } else { + "openkb-api-sidecar" + }; + let exe = resource_dir + .join("sidecar") + .join("openkb-api-sidecar") + .join(exe_name); + Command::new(exe) + .args(["--host", HOST, "--port", &PORT.to_string()]) + .spawn() +} + +/// Poll `url` until it answers or `timeout` elapses. +fn wait_until_ready(url: &str, timeout: Duration) -> bool { + let deadline = Instant::now() + timeout; + while Instant::now() < deadline { + if ureq::get(url) + .timeout(Duration::from_millis(500)) + .call() + .is_ok() + { + return true; + } + std::thread::sleep(Duration::from_millis(200)); + } + false +} + +fn main() { + tauri::Builder::default() + .manage(Sidecar(Mutex::new(None))) + .setup(|app| { + // Create the main window programmatically so we can inject the + // desktop-shell flag the frontend checks (window.__OPENKB_DESKTOP__). + // It gates the in-app TitleBar and other desktop-only chrome. An + // initialization script runs before page scripts on every + // navigation, so the flag is present on the splash AND after we + // navigate to the sidecar's served UI. + tauri::WebviewWindowBuilder::new( + app, + "main", + tauri::WebviewUrl::App("index.html".into()), + ) + .title("OpenKB") + .inner_size(1200.0, 800.0) + .initialization_script("window.__OPENKB_DESKTOP__ = true;") + .build()?; + + // Non-fatal: if the sidecar can't start (missing binary, port in + // use), keep the window up on the splash rather than crashing the + // app. In `cargo run` dev the bundled sidecar isn't present, so + // this lets the shell attach to an externally-run `openkb-api`. + match spawn_sidecar(app) { + Ok(child) => { + app.state::().0.lock().unwrap().replace(child); + } + Err(e) => eprintln!("openkb: could not spawn sidecar: {e}"), + } + + let url = format!("http://{HOST}:{PORT}/"); + let handle = app.handle().clone(); + // Poll off the main thread so the splash window can paint. + std::thread::spawn(move || { + if wait_until_ready(&url, Duration::from_secs(30)) { + if let (Some(win), Ok(parsed)) = + (handle.get_webview_window("main"), Url::parse(&url)) + { + let _ = win.navigate(parsed); + } + } + }); + Ok(()) + }) + .build(tauri::generate_context!()) + .expect("error while building tauri app") + .run(|app_handle, event| { + if let RunEvent::Exit = event { + if let Some(mut child) = app_handle.state::().0.lock().unwrap().take() { + let _ = child.kill(); + } + } + }); +} diff --git a/desktop/src-tauri/tauri.conf.json b/desktop/src-tauri/tauri.conf.json new file mode 100644 index 00000000..b9d4e0cc --- /dev/null +++ b/desktop/src-tauri/tauri.conf.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://schema.tauri.app/config/2", + "productName": "OpenKB", + "version": "0.1.0", + "identifier": "ai.pageindex.openkb", + "build": { + "frontendDist": "splash" + }, + "app": { + "windows": [], + "security": { + "csp": null + } + }, + "bundle": { + "active": true, + "targets": "all", + "resources": { + "../packaging/dist/openkb-api-sidecar": "sidecar" + } + } +} diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index ff8dbbba..330b4deb 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -19,6 +19,8 @@ import { } from "@/components/ui/dialog" import { Button } from "@/components/ui/button" import { getApiBase, getToken, onUnauthorized, setConnection } from "@/api/client" +import { getGlobalConfig } from "@/api/config" +import Onboarding from "@/components/Onboarding" import Home from "@/pages/Home" import ChatSession from "@/pages/ChatSession" import KbList from "@/pages/KbList" @@ -126,6 +128,7 @@ function ConnectionDialog({ export default function App() { const [authOpen, setAuthOpen] = useState(false) + const [onboardOpen, setOnboardOpen] = useState(false) const isDesktopShell = typeof (window as { __OPENKB_DESKTOP__?: unknown }).__OPENKB_DESKTOP__ !== "undefined" @@ -136,6 +139,14 @@ export default function App() { onUnauthorized(() => setAuthOpen(true)) }, []) + // First-launch onboarding: open the setup wizard when no LLM key is + // configured yet. Silent on failure (e.g. a 401 handles its own prompt). + useEffect(() => { + getGlobalConfig() + .then((c) => setOnboardOpen(!c.has_api_key)) + .catch(() => {}) + }, []) + return (
@@ -180,6 +191,7 @@ export default function App() {
+ setOnboardOpen(false)} />
diff --git a/frontend/src/components/Onboarding.tsx b/frontend/src/components/Onboarding.tsx new file mode 100644 index 00000000..8b656da9 --- /dev/null +++ b/frontend/src/components/Onboarding.tsx @@ -0,0 +1,197 @@ +import { useState } from "react" +import { useNavigate } from "react-router" +import { useTranslation } from "react-i18next" +import { toast } from "sonner" +import { Sparkles, KeyRound, FolderPlus, Loader2 } from "lucide-react" +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogDescription, + DialogFooter, +} from "@/components/ui/dialog" +import { Button } from "@/components/ui/button" +import { UnLanguageDatalist, UN_LANG_LIST_ID } from "@/components/UnLanguageDatalist" +import { patchGlobalConfig, type GlobalConfigPatch } from "@/api/config" +import { createKb } from "@/api/kb" + +const inputCls = + "mt-1.5 w-full h-9 rounded-md border border-input bg-transparent px-3 text-[13px] font-mono2 outline-none focus-visible:ring-2 focus-visible:ring-ring focus:border-accent-brand" + +/** + * First-launch setup: welcome → connect the model (patchGlobalConfig) → create + * the first knowledge base (createKb). Shown when the global config has no API + * key configured yet. "Skip for now" dismisses it. + */ +export default function Onboarding({ open, onClose }: { open: boolean; onClose: () => void }) { + const { t } = useTranslation("common") + const navigate = useNavigate() + const [step, setStep] = useState(1) + const [model, setModel] = useState("gpt-5.4") + const [language, setLanguage] = useState("") + const [apiKey, setApiKey] = useState("") + const [baseUrl, setBaseUrl] = useState("") + const [kbName, setKbName] = useState("my-kb") + const [busy, setBusy] = useState(false) + + const errText = (e: unknown) => (e instanceof Error ? e.message : String(e)) + + const saveConfig = async () => { + setBusy(true) + try { + const patch: GlobalConfigPatch = { config: { model: model.trim() } } + if (language.trim()) patch.config!.language = language.trim() + if (apiKey.trim()) patch.api_key = apiKey.trim() + if (baseUrl.trim()) patch.openai_api_base = baseUrl.trim() + await patchGlobalConfig(patch) + setStep(3) + } catch (e) { + toast.error(errText(e)) + } finally { + setBusy(false) + } + } + + const createFirstKb = async () => { + const name = kbName.trim() + if (!name) return + setBusy(true) + try { + await createKb({ kb: name }) + toast.success(t("onboarding.createdToast", { name })) + onClose() + navigate(`/kb/${encodeURIComponent(name)}`) + } catch (e) { + toast.error(errText(e)) + } finally { + setBusy(false) + } + } + + return ( + { + if (!v) onClose() + }} + > + + {step === 1 && ( + <> + + + + {t("onboarding.welcomeTitle")} + + {t("onboarding.welcomeBody")} + + + + + + + )} + + {step === 2 && ( + <> + + + + {t("onboarding.configTitle")} + + {t("onboarding.configBody")} + +
+
+ + setModel(e.target.value)} className={inputCls} /> +
+
+ + setLanguage(e.target.value)} + list={UN_LANG_LIST_ID} + placeholder="English" + className={inputCls} + /> + +
+
+ + setApiKey(e.target.value)} + placeholder={t("onboarding.apiKeyPlaceholder")} + className={inputCls} + /> +
+
+ + setBaseUrl(e.target.value)} + placeholder={t("onboarding.baseUrlPlaceholder")} + className={inputCls} + /> +
+
+ + + + + + )} + + {step === 3 && ( + <> + + + + {t("onboarding.kbTitle")} + + {t("onboarding.kbBody")} + +
+ + setKbName(e.target.value)} + placeholder="my-kb" + className={inputCls} + /> +
+ + + + + + )} +
+
+ ) +} diff --git a/frontend/src/lib/i18n.ts b/frontend/src/lib/i18n.ts index 43ced157..e62cdfc7 100644 --- a/frontend/src/lib/i18n.ts +++ b/frontend/src/lib/i18n.ts @@ -2,7 +2,7 @@ import i18n from "i18next" import { initReactI18next } from "react-i18next" import resourcesToBackend from "i18next-resources-to-backend" -export const SUPPORTED_LANGUAGES = ["zh", "en"] as const +export const SUPPORTED_LANGUAGES = ["zh", "en", "fr", "es", "ru", "ja"] as const export type Language = (typeof SUPPORTED_LANGUAGES)[number] /** All namespaces. Only `common` is preloaded (see `ns` below); every other diff --git a/frontend/src/lib/language.tsx b/frontend/src/lib/language.tsx index 51da2d34..d0eaaba5 100644 --- a/frontend/src/lib/language.tsx +++ b/frontend/src/lib/language.tsx @@ -1,7 +1,14 @@ import { createContext, useContext, useState, type ReactNode } from "react" import { Languages } from "lucide-react" import { useTranslation } from "react-i18next" -import i18n, { type Language } from "@/lib/i18n" +import i18n, { type Language, SUPPORTED_LANGUAGES } from "@/lib/i18n" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuRadioGroup, + DropdownMenuRadioItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu" const KEY = "openkb_lang" @@ -14,11 +21,14 @@ const LanguageCtx = createContext<{ * "zh" → zh, else en — `en` is the only non-Chinese bucket for the 2-locale * scope); else the zh fallback. Detection only picks the INITIAL value. */ function detectInitial(): Language { + const supported = SUPPORTED_LANGUAGES as readonly string[] const stored = localStorage.getItem(KEY) - if (stored === "zh" || stored === "en") return stored + if (stored && supported.includes(stored)) return stored as Language + // Match the browser/OS language by its base subtag ("fr-CA" → "fr"). const nav = (navigator.languages?.[0] ?? navigator.language ?? "").toLowerCase() - if (nav.startsWith("zh")) return "zh" - return nav ? "en" : "zh" + const code = nav.split("-")[0] + if (supported.includes(code)) return code as Language + return "en" } export function LanguageProvider({ children }: { children: ReactNode }) { @@ -43,21 +53,36 @@ export function useLanguage() { return ctx } -/** Language toggle icon button (toggles between zh and en). Same `h-8 w-8` - * shape as ThemeToggle; slots into App.tsx's top-right chrome pill next to it. */ +/** Language menu button. A dropdown of every supported language (shown by its + * own autonym); same `h-8 w-8` shape as ThemeToggle, slots into App.tsx's + * top-right chrome pill next to it. */ export function LanguageToggle({ className }: { className?: string }) { const { language, setLanguage } = useLanguage() const { t } = useTranslation("common") - const next: Language = language === "zh" ? "en" : "zh" - const label = language === "zh" ? t("language.zh") : t("language.en") + const label = t(`language.${language}`) return ( - + + + + + + setLanguage(v as Language)} + > + {SUPPORTED_LANGUAGES.map((lng) => ( + + {t(`language.${lng}`)} + + ))} + + + ) } diff --git a/frontend/src/locales/en/common.json b/frontend/src/locales/en/common.json index 88cc7561..3e3aaad5 100644 --- a/frontend/src/locales/en/common.json +++ b/frontend/src/locales/en/common.json @@ -37,7 +37,11 @@ "language": { "zh": "中文", "en": "English", - "toggleTitle": "Language: {{label}} (click to switch)", + "fr": "Français", + "es": "Español", + "ru": "Русский", + "ja": "日本語", + "toggleTitle": "Language: {{label}}", "toggleAria": "Language: {{label}}" }, "auth": { @@ -50,5 +54,27 @@ "connector": { "tooltip": "Cloud sync is in development · vote for it on GitHub", "vote": "Want it? Vote" + }, + "onboarding": { + "welcomeTitle": "Welcome to OpenKB", + "welcomeBody": "Turn your documents into an interlinked, always-current knowledge base. Two quick steps and you're ready.", + "getStarted": "Get started", + "skip": "Skip for now", + "configTitle": "Connect your model", + "configBody": "OpenKB uses an LLM to compile and answer. Paste an API key — it is stored locally and never leaves your machine.", + "modelLabel": "LLM model", + "langLabel": "Wiki language", + "apiKeyLabel": "LLM API key", + "apiKeyPlaceholder": "Paste your API key", + "baseUrlLabel": "Custom base URL (optional)", + "baseUrlPlaceholder": "e.g. http://localhost:11434 (Ollama, LM Studio)", + "continue": "Continue", + "back": "Back", + "kbTitle": "Create your first knowledge base", + "kbBody": "A knowledge base holds your documents and the compiled wiki. You can add more later.", + "kbNameLabel": "Knowledge base name", + "createFinish": "Create & finish", + "saving": "Saving…", + "createdToast": "Created {{name}}" } } diff --git a/frontend/src/locales/es/artifacts.json b/frontend/src/locales/es/artifacts.json new file mode 100644 index 00000000..81b67d8f --- /dev/null +++ b/frontend/src/locales/es/artifacts.json @@ -0,0 +1,35 @@ +{ + "card": { + "done": "Generado", + "open": "Abrir" + }, + "deck": { + "subtitle": "Deck HTML · {{name}}" + }, + "file": { + "subtitle": "Archivo HTML · {{name}}" + }, + "graph": { + "label": "Grafo de conocimiento", + "empty": "Aún no hay grafo de conceptos que visualizar", + "subtitle_one": "{{count}} concepto · {{edges}} enlaces", + "subtitle_other": "{{count}} conceptos · {{edges}} enlaces", + "subtitleWithTypes_one": "{{count}} concepto · {{edges}} enlaces · {{types}} tipos", + "subtitleWithTypes_other": "{{count}} conceptos · {{edges}} enlaces · {{types}} tipos" + }, + "skill": { + "downloadError": "No se pudo descargar el paquete de la habilidad: {{error}}", + "body": "La habilidad se ha generado como un directorio instalable. Descarga el <0>.zip, descomprímelo en la carpeta de habilidades de tu agente (Claude Code / Codex / Gemini CLI) y estará lista para usar.", + "download": "Descargar paquete de habilidad (.zip)" + }, + "unknown": "Artefacto desconocido", + "previewUnsupported": "Este tipo de artefacto no se puede previsualizar", + "loadError": "No se pudo cargar el artefacto: {{error}}", + "openError": "Error al abrir: {{error}}", + "downloadError": "Error al descargar: {{error}}", + "panel": { + "resize": "Arrastra para cambiar el ancho", + "openTab": "Abrir en una pestaña nueva", + "download": "Descargar" + } +} diff --git a/frontend/src/locales/es/chat.json b/frontend/src/locales/es/chat.json new file mode 100644 index 00000000..44ef0061 --- /dev/null +++ b/frontend/src/locales/es/chat.json @@ -0,0 +1,63 @@ +{ + "phase": { + "generating": "Generando (llamada al LLM, puede tardar unos minutos)…", + "done": "Listo", + "preparing": "Preparando…", + "buildingGraph": "Construyendo el grafo de conceptos…" + }, + "artifact": { + "failed": "Error en la generación" + }, + "sources": { + "heading": "Fuentes", + "pageTip": "Haz clic para ver esta página del wiki", + "internalTip": "Contenido interno de un documento largo (PageIndex); no hay página independiente que abrir" + }, + "reading": { + "page": "Leyendo <0>{{label}}", + "doc": "Leyendo el documento largo <0>{{label}}", + "thinking": "Pensando…" + }, + "step": { + "read": "Leído <0>{{path}}" + }, + "requestError": "La solicitud falló: {{error}}", + "savedTo": "Guardado en {{path}}", + "usage": { + "deck": "Uso: /deck , p. ej. «retrieval-intro presentar la recuperación sin vectores a ingenieros»", + "skill": "Uso: /skill , p. ej. «pageindex-expert experto en preguntas y respuestas sobre recuperación de documentos largos»" + }, + "genErrorToast": "Error en la generación: {{error}}", + "requestErrorToast": "La solicitud falló: {{error}}", + "errors": { + "noKb": "No se pudo determinar a qué base de conocimiento pertenece esta sesión; entra desde la página de inicio", + "loadSession": "No se pudo cargar la sesión: {{error}}", + "openSource": "No se pudo abrir la fuente {{path}}: {{error}}" + }, + "newSession": "Nueva sesión", + "inputPlaceholder": "Haz una pregunta de seguimiento, o escribe / para ver comandos…", + "commands": { + "paletteHeading": "Comandos · generadores", + "deck": { + "label": "Generar diapositivas", + "desc": "Compilar el conocimiento en un deck HTML de un solo archivo" + }, + "skill": { + "label": "Destilar una habilidad", + "desc": "Generar una Agent Skill instalable" + }, + "visualize": { + "label": "Grafo de conocimiento", + "desc": "Generar un grafo de conceptos interactivo" + } + }, + "input": { + "cmdPlaceholder": "{{label}}: describe tu intención…", + "defaultPlaceholder": "Pregunta a tu base de conocimiento, o escribe / para ver comandos…", + "selectKb": "Selecciona una base de conocimiento", + "noKbs": "Aún no hay bases de conocimiento", + "current": "Actual", + "stop": "Detener", + "hint": "Escribe <0>/ para ver comandos" + } +} diff --git a/frontend/src/locales/es/common.json b/frontend/src/locales/es/common.json new file mode 100644 index 00000000..b59432c0 --- /dev/null +++ b/frontend/src/locales/es/common.json @@ -0,0 +1,79 @@ +{ + "loading": "Cargando…", + "pageLoadError": "No se pudo cargar la página: {{error}}", + "noChanges": "No hay cambios que guardar", + "saveError": "Error al guardar: {{error}}", + "configLoadError": "No se pudo cargar la configuración: {{error}}", + "actions": { + "newKb": "Nueva base de conocimiento", + "close": "Cerrar", + "refresh": "Actualizar" + }, + "fields": { + "model": "Modelo", + "wikiLanguage": "Idioma de salida del wiki", + "threshold": "Umbral de PageIndex (páginas)" + }, + "errors": { + "requestFailed": "La solicitud falló", + "uploadFailed": "Error al subir: {{detail}}" + }, + "nav": { + "home": "Inicio", + "kbs": "Bases de conocimiento", + "settings": "Ajustes" + }, + "titlebar": { + "chat": "Chat", + "local": "Local" + }, + "theme": { + "light": "Claro", + "dark": "Oscuro", + "system": "Sistema", + "toggleTitle": "Tema: {{label}} (clic para cambiar)", + "toggleAria": "Tema: {{label}}" + }, + "language": { + "zh": "中文", + "en": "English", + "fr": "Français", + "es": "Español", + "ru": "Русский", + "toggleTitle": "Idioma: {{label}}", + "toggleAria": "Idioma: {{label}}" + }, + "auth": { + "title": "Se requiere un token de acceso", + "description": "Este servidor tiene un token de acceso configurado (OPENKB_API_TOKEN). Introduce el token para continuar; se almacena solo en este navegador.", + "tokenLabel": "Token de acceso", + "baseLabel": "Dirección de la API (opcional; déjalo en blanco para usar el origen actual)", + "connect": "Conectar" + }, + "connector": { + "tooltip": "La sincronización en la nube está en desarrollo · vótala en GitHub", + "vote": "¿La quieres? Vota" + }, + "onboarding": { + "welcomeTitle": "Te damos la bienvenida a OpenKB", + "welcomeBody": "Convierte tus documentos en una base de conocimiento interconectada y siempre actualizada. Dos pasos rápidos y listo.", + "getStarted": "Empezar", + "skip": "Omitir por ahora", + "configTitle": "Conecta tu modelo", + "configBody": "OpenKB usa un LLM para compilar y responder. Pega una clave de API — se almacena localmente y nunca sale de tu equipo.", + "modelLabel": "Modelo LLM", + "langLabel": "Idioma del wiki", + "apiKeyLabel": "Clave de API del LLM", + "apiKeyPlaceholder": "Pega tu clave de API", + "baseUrlLabel": "URL base personalizada (opcional)", + "baseUrlPlaceholder": "p. ej. http://localhost:11434 (Ollama, LM Studio)", + "continue": "Continuar", + "back": "Atrás", + "kbTitle": "Crea tu primera base de conocimiento", + "kbBody": "Una base de conocimiento contiene tus documentos y el wiki compilado. Podrás añadir más después.", + "kbNameLabel": "Nombre de la base de conocimiento", + "createFinish": "Crear y finalizar", + "saving": "Guardando…", + "createdToast": "{{name}} creada" + } +} diff --git a/frontend/src/locales/es/home.json b/frontend/src/locales/es/home.json new file mode 100644 index 00000000..e2b01cde --- /dev/null +++ b/frontend/src/locales/es/home.json @@ -0,0 +1,7 @@ +{ + "greeting": "¿Qué te gustaría preguntar?", + "ready": "Conocimiento compilado · <0>{{docs}} docs · <1>{{kbs}} bases", + "recentSessions": "Sesiones recientes", + "untitledSession": "Sesión sin título", + "tagline": "Con la tecnología de OpenKB · tu conocimiento siempre en Markdown puro, y siempre tuyo" +} diff --git a/frontend/src/locales/es/kb.json b/frontend/src/locales/es/kb.json new file mode 100644 index 00000000..db16fd1c --- /dev/null +++ b/frontend/src/locales/es/kb.json @@ -0,0 +1,84 @@ +{ + "settingsButton": "Ajustes de la base de conocimiento", + "loadError": "Error al cargar: {{error}}", + "wikiNote": "wiki/ es una carpeta de Markdown puro en este equipo — tus datos siempre son tuyos", + "reader": { + "empty": "Esta base de conocimiento aún no tiene páginas compiladas", + "selectPage": "Selecciona una página a la izquierda para ver su contenido" + }, + "upload": { + "added": "{{count}} añadido(s)", + "skipped": "{{count}} omitido(s)", + "failed": "{{count}} con error", + "errorToast": "Error al subir: {{summary}}", + "reasonSuffix": " ({{reason}})", + "partialToast": "Éxito parcial: {{summary}}", + "successToast": "Subida completada: {{summary}}", + "existsToast": "Los documentos ya existen, no se añadió nada: {{summary}}", + "incompleteToast": "Subida interrumpida: no se recibió señal de finalización; actualiza para comprobar los resultados", + "note": "Los documentos subidos van a la carpeta local raw/ y se compilan automáticamente en la base; los archivos permanecen en este equipo", + "inProgress": "Subiendo y compilando…", + "dropzone": "Suelta archivos aquí, o haz clic para elegir", + "dropzoneHint": "PDF / Word / Markdown / texto y más; se admite selección múltiple", + "progressHeading": "Progreso de la subida · {{count}}", + "fileStatus": { + "pending": "En espera", + "processing": "Compilando…", + "added": "Añadido", + "skipped": "Omitido", + "failed": "Con error" + } + }, + "docs": { + "heading": "Documentos subidos · {{count}}", + "empty": "Aún no hay documentos · se compilan automáticamente en la base tras subirlos", + "pages_one": "{{count}} página", + "pages_other": "{{count}} páginas", + "delete": { + "action": "Eliminar documento", + "prompt": "¿Eliminar?", + "confirm": "Eliminar", + "cancel": "Cancelar", + "success": "{{name}} eliminado", + "error": "Error al eliminar: {{error}}", + "partial": "Se eliminaron los archivos locales, pero falló la limpieza del índice remoto: {{name}}", + "reasonSuffix": " ({{reason}})", + "multiple": "Error al eliminar: {{message}} (candidatos: {{names}})" + } + }, + "remote": { + "heading": "Fuentes de datos remotas", + "note": "Los conectores en la nube están en desarrollo y aún no disponibles · ¿quieres uno? Haz clic en una tarjeta para votar en GitHub" + }, + "overview": { + "index": { + "label": "Índice", + "caption": "raíz del wiki" + }, + "concepts": { + "label": "Conceptos", + "caption": "interconectados" + }, + "entities": { + "label": "Entidades", + "caption": "personas · orgs" + }, + "summaries": { + "label": "Resúmenes", + "caption": "por documento" + }, + "reports": { + "label": "Informes", + "caption": "lint · recompilar" + }, + "documents": { + "label": "Documentos", + "caption": "docs compilados" + } + }, + "pageList": { + "empty": "Aún no hay páginas de este tipo", + "prev": "Anterior", + "next": "Siguiente" + } +} diff --git a/frontend/src/locales/es/kbList.json b/frontend/src/locales/es/kbList.json new file mode 100644 index 00000000..c564b5d1 --- /dev/null +++ b/frontend/src/locales/es/kbList.json @@ -0,0 +1,22 @@ +{ + "notCompiled": "Aún sin compilar", + "updatedAt": "Actualizada {{date}}", + "title": "Bases de conocimiento", + "subtitle": "Cada base de conocimiento es un wiki compilado de forma continua que puede vincular varias fuentes de datos", + "docsLabel": "Docs", + "rawReady": "raw/ listo", + "rawMissing": "Sin raw/", + "create": { + "description": "Ponle un nombre a tu nueva base de conocimiento. El modelo y las credenciales heredan los valores globales por defecto y podrás ajustarlos después en sus ajustes.", + "nameLabel": "Nombre", + "namePlaceholder": "p. ej. my-kb", + "cancel": "Cancelar", + "submit": "Crear", + "submitting": "Creando…", + "previewLabel": "Se creará en {{path}}", + "advancedToggle": "Ruta personalizada", + "customPathLabel": "Ruta personalizada", + "customPathPlaceholder": "/ruta/absoluta/a/la/base", + "customPathHint": "Déjalo vacío para usar la raíz por defecto" + } +} diff --git a/frontend/src/locales/es/kbSettings.json b/frontend/src/locales/es/kbSettings.json new file mode 100644 index 00000000..6be2c6be --- /dev/null +++ b/frontend/src/locales/es/kbSettings.json @@ -0,0 +1,42 @@ +{ + "title": "Ajustes de la base de conocimiento", + "configHeading": "Configuración", + "credHeading": "Credenciales (el .env de esta base)", + "maintHeading": "Mantenimiento", + "credSaved": "Credenciales guardadas", + "keyCleared": "Clave de API borrada", + "clearError": "Error al borrar: {{error}}", + "keyPlaceholderSet": "Clave definida · déjalo en blanco para no cambiarla", + "keyPlaceholderUnset": "Sin definir · introdúcela para habilitarla", + "keyHintSet": "Clave definida (nunca se muestra; introduce un nuevo valor para rotarla)", + "keyHintUnset": "No hay clave definida", + "clear": "Borrar", + "baseLabel": "URL base de la API (opcional)", + "basePlaceholder": "En blanco usa el valor por defecto del proveedor; rellénalo para endpoints locales/compatibles", + "saveCred": "Guardar credenciales", + "inheritGlobal": "Heredado · global ({{value}})", + "inheritDefault": "Heredado · por defecto ({{value}})", + "override": "Anular para esta base", + "overrideAria": "Anular {{label}} para esta base", + "unnamed": "(sin nombre)", + "recompileFailed": "Error al recompilar", + "watchStarted": "Vigilancia de archivos iniciada", + "watchStopped": "Vigilancia de archivos detenida", + "recompileErrorToast": "Error al recompilar: {{error}}", + "lintSkipped": "Comprobación omitida", + "lintDone": "Comprobación completada", + "lintSuccessToast": "Comprobación de estructura completada", + "lintErrorToast": "Error en la comprobación: {{error}}", + "watchLabel": "Vigilancia de archivos", + "watchOn": "Vigilando", + "watchOnDir": "Vigilando · {{dir}}", + "watchOff": "Detenida · los archivos nuevos se compilan automáticamente al iniciarla", + "stop": "Detener", + "startWatch": "Iniciar vigilancia", + "noCompiledDocs": "Aún no hay documentos compilados", + "recompileAll": "Recompilar todo", + "lint": "Comprobación de estructura", + "recompileHeading": "Recompilar", + "recompileSummary": "· {{total}} en total · {{recompiled}} compilados · {{skipped}} omitidos", + "preparing": "Preparando…" +} diff --git a/frontend/src/locales/es/settings.json b/frontend/src/locales/es/settings.json new file mode 100644 index 00000000..e5d2f217 --- /dev/null +++ b/frontend/src/locales/es/settings.json @@ -0,0 +1,43 @@ +{ + "tabs": { + "model": "Modelo", + "general": "General", + "conn": "Fuentes de datos", + "about": "Acerca de" + }, + "savedToast": "Valores globales por defecto guardados", + "saveChanges": "Guardar cambios", + "unsaved": "Cambios sin guardar", + "modelSection": { + "title": "Modelo y umbral", + "desc": "Modelo y umbral globales por defecto (se escriben en ~/.config/openkb/global.yaml; cada base puede heredar o anular en sus propios ajustes)", + "thresholdInvalid": "El umbral debe ser un número entero de 1 o más." + }, + "credSection": { + "title": "Credenciales por defecto", + "desc": "Credenciales de API globales por defecto (se escriben en ~/.config/openkb/.env; el .env propio de una base y las variables de entorno del proceso tienen prioridad)", + "clearPending": "Marcada para eliminar; se aplica al guardar", + "undoClear": "Deshacer" + }, + "general": { + "langDesc": "El idioma de salida escrito en el prompt de compilación, p. ej. en / 中文 / 日本語", + "kbRootLabel": "Raíz de las bases de conocimiento", + "kbRootDesc": "Ubicación por defecto de las nuevas bases (/); déjalo vacío para restaurar el valor por defecto integrado. Cada base puede definir una ruta personalizada al crearse.", + "kbRootPlaceholder": "p. ej. ~/openkb", + "kbRootEnvPinned": "Fijado por la variable de entorno OPENKB_KB_ROOT; los cambios aquí no surtirán efecto hasta que se elimine." + }, + "conn": { + "note": "Los conectores de fuentes de datos en la nube (OAuth / S3) están en desarrollo y aún no disponibles; por ahora, sube archivos locales desde la página de detalle de la base. ¿Quieres un conector? Haz clic en una tarjeta de abajo para votar en GitHub y ayudarnos a priorizar." + }, + "about": { + "links": { + "repo": "Repositorio de GitHub", + "pageindex": "PageIndex (motor de recuperación)", + "docs": "Docs docs.pageindex.ai", + "company": "Vectify AI (empresa)" + }, + "blurb": "Compila documentos en bruto en una base de conocimiento estructurada e interconectada de tipo wiki, con la tecnología de recuperación de documentos largos de PageIndex, sin vectores y basada en el razonamiento.", + "byline": "Creado por Vectify AI · parte de la línea de productos PageIndex", + "latestRelease": "Ver la última versión →" + } +} diff --git a/frontend/src/locales/fr/artifacts.json b/frontend/src/locales/fr/artifacts.json new file mode 100644 index 00000000..8078fba2 --- /dev/null +++ b/frontend/src/locales/fr/artifacts.json @@ -0,0 +1,35 @@ +{ + "card": { + "done": "Généré", + "open": "Ouvrir" + }, + "deck": { + "subtitle": "Deck HTML · {{name}}" + }, + "file": { + "subtitle": "Fichier HTML · {{name}}" + }, + "graph": { + "label": "Graphe de connaissances", + "empty": "Aucun graphe de concepts à visualiser", + "subtitle_one": "{{count}} concept · {{edges}} liens", + "subtitle_other": "{{count}} concepts · {{edges}} liens", + "subtitleWithTypes_one": "{{count}} concept · {{edges}} liens · {{types}} types", + "subtitleWithTypes_other": "{{count}} concepts · {{edges}} liens · {{types}} types" + }, + "skill": { + "downloadError": "Échec du téléchargement du package de compétence : {{error}}", + "body": "La compétence a été générée sous forme de dossier installable. Téléchargez le <0>.zip, décompressez-le dans le dossier de compétences de votre agent (Claude Code / Codex / Gemini CLI), et elle est prête à l'emploi.", + "download": "Télécharger le package de compétence (.zip)" + }, + "unknown": "Artefact inconnu", + "previewUnsupported": "Ce type d'artefact ne peut pas être prévisualisé", + "loadError": "Échec du chargement de l'artefact : {{error}}", + "openError": "Échec de l'ouverture : {{error}}", + "downloadError": "Échec du téléchargement : {{error}}", + "panel": { + "resize": "Glisser pour redimensionner la largeur", + "openTab": "Ouvrir dans un nouvel onglet", + "download": "Télécharger" + } +} diff --git a/frontend/src/locales/fr/chat.json b/frontend/src/locales/fr/chat.json new file mode 100644 index 00000000..d12e6781 --- /dev/null +++ b/frontend/src/locales/fr/chat.json @@ -0,0 +1,63 @@ +{ + "phase": { + "generating": "Génération (appel LLM, peut prendre quelques minutes)…", + "done": "Terminé", + "preparing": "Préparation…", + "buildingGraph": "Construction du graphe de concepts…" + }, + "artifact": { + "failed": "Échec de la génération" + }, + "sources": { + "heading": "Sources", + "pageTip": "Cliquer pour afficher cette page du wiki", + "internalTip": "Contenu interne d'un long document (PageIndex) ; pas de page autonome à ouvrir" + }, + "reading": { + "page": "Lecture de <0>{{label}}", + "doc": "Lecture du long document <0>{{label}}", + "thinking": "Réflexion…" + }, + "step": { + "read": "Lu <0>{{path}}" + }, + "requestError": "Échec de la requête : {{error}}", + "savedTo": "Enregistré dans {{path}}", + "usage": { + "deck": "Utilisation : /deck , ex. « retrieval-intro présenter la recherche sans vecteurs aux ingénieurs »", + "skill": "Utilisation : /skill , ex. « pageindex-expert expert Q&R sur la recherche de longs documents »" + }, + "genErrorToast": "Échec de la génération : {{error}}", + "requestErrorToast": "Échec de la requête : {{error}}", + "errors": { + "noKb": "Impossible de déterminer à quelle base appartient cette session ; veuillez entrer depuis la page d'accueil", + "loadSession": "Échec du chargement de la session : {{error}}", + "openSource": "Impossible d'ouvrir la source {{path}} : {{error}}" + }, + "newSession": "Nouvelle session", + "inputPlaceholder": "Posez une question de suivi, ou tapez / pour les commandes…", + "commands": { + "paletteHeading": "Commandes · générateurs", + "deck": { + "label": "Générer des diapositives", + "desc": "Compiler les connaissances en un deck HTML d'un seul fichier" + }, + "skill": { + "label": "Distiller une compétence", + "desc": "Générer une Agent Skill installable" + }, + "visualize": { + "label": "Graphe de connaissances", + "desc": "Générer un graphe de concepts interactif" + } + }, + "input": { + "cmdPlaceholder": "{{label}} : décrivez votre intention…", + "defaultPlaceholder": "Interrogez votre base de connaissances, ou tapez / pour les commandes…", + "selectKb": "Sélectionner une base de connaissances", + "noKbs": "Aucune base de connaissances", + "current": "Actuelle", + "stop": "Arrêter", + "hint": "Tapez <0>/ pour les commandes" + } +} diff --git a/frontend/src/locales/fr/common.json b/frontend/src/locales/fr/common.json new file mode 100644 index 00000000..edc781c3 --- /dev/null +++ b/frontend/src/locales/fr/common.json @@ -0,0 +1,79 @@ +{ + "loading": "Chargement…", + "pageLoadError": "Échec du chargement de la page : {{error}}", + "noChanges": "Aucune modification à enregistrer", + "saveError": "Échec de l'enregistrement : {{error}}", + "configLoadError": "Échec du chargement de la configuration : {{error}}", + "actions": { + "newKb": "Nouvelle base de connaissances", + "close": "Fermer", + "refresh": "Actualiser" + }, + "fields": { + "model": "Modèle", + "wikiLanguage": "Langue de sortie du wiki", + "threshold": "Seuil PageIndex (pages)" + }, + "errors": { + "requestFailed": "Échec de la requête", + "uploadFailed": "Échec du téléversement : {{detail}}" + }, + "nav": { + "home": "Accueil", + "kbs": "Bases de connaissances", + "settings": "Paramètres" + }, + "titlebar": { + "chat": "Discussion", + "local": "Local" + }, + "theme": { + "light": "Clair", + "dark": "Sombre", + "system": "Système", + "toggleTitle": "Thème : {{label}} (cliquer pour changer)", + "toggleAria": "Thème : {{label}}" + }, + "language": { + "zh": "中文", + "en": "English", + "fr": "Français", + "es": "Español", + "ru": "Русский", + "toggleTitle": "Langue : {{label}}", + "toggleAria": "Langue : {{label}}" + }, + "auth": { + "title": "Jeton d'accès requis", + "description": "Ce serveur a un jeton d'accès configuré (OPENKB_API_TOKEN). Saisissez le jeton pour continuer ; il est stocké uniquement dans ce navigateur.", + "tokenLabel": "Jeton d'accès", + "baseLabel": "Adresse de l'API (facultatif ; laisser vide pour utiliser l'origine actuelle)", + "connect": "Se connecter" + }, + "connector": { + "tooltip": "La synchronisation cloud est en développement · votez pour elle sur GitHub", + "vote": "Vous la voulez ? Votez" + }, + "onboarding": { + "welcomeTitle": "Bienvenue sur OpenKB", + "welcomeBody": "Transformez vos documents en une base de connaissances interconnectée et toujours à jour. Deux étapes rapides et vous êtes prêt.", + "getStarted": "Commencer", + "skip": "Ignorer pour l'instant", + "configTitle": "Connectez votre modèle", + "configBody": "OpenKB utilise un LLM pour compiler et répondre. Collez une clé API — elle est stockée localement et ne quitte jamais votre machine.", + "modelLabel": "Modèle LLM", + "langLabel": "Langue du wiki", + "apiKeyLabel": "Clé API du LLM", + "apiKeyPlaceholder": "Collez votre clé API", + "baseUrlLabel": "URL de base personnalisée (facultatif)", + "baseUrlPlaceholder": "ex. http://localhost:11434 (Ollama, LM Studio)", + "continue": "Continuer", + "back": "Retour", + "kbTitle": "Créez votre première base de connaissances", + "kbBody": "Une base de connaissances contient vos documents et le wiki compilé. Vous pourrez en ajouter d'autres plus tard.", + "kbNameLabel": "Nom de la base de connaissances", + "createFinish": "Créer et terminer", + "saving": "Enregistrement…", + "createdToast": "{{name}} créée" + } +} diff --git a/frontend/src/locales/fr/home.json b/frontend/src/locales/fr/home.json new file mode 100644 index 00000000..f320d691 --- /dev/null +++ b/frontend/src/locales/fr/home.json @@ -0,0 +1,7 @@ +{ + "greeting": "Que souhaitez-vous demander ?", + "ready": "Connaissances compilées · <0>{{docs}} docs · <1>{{kbs}} bases", + "recentSessions": "Sessions récentes", + "untitledSession": "Session sans titre", + "tagline": "Propulsé par OpenKB · vos connaissances sont toujours en Markdown pur, et toujours à vous" +} diff --git a/frontend/src/locales/fr/kb.json b/frontend/src/locales/fr/kb.json new file mode 100644 index 00000000..a0a05502 --- /dev/null +++ b/frontend/src/locales/fr/kb.json @@ -0,0 +1,84 @@ +{ + "settingsButton": "Paramètres de la base de connaissances", + "loadError": "Échec du chargement : {{error}}", + "wikiNote": "wiki/ est un dossier Markdown pur sur cette machine — vos données restent les vôtres", + "reader": { + "empty": "Cette base de connaissances n'a pas encore de pages compilées", + "selectPage": "Sélectionnez une page à gauche pour afficher son contenu" + }, + "upload": { + "added": "{{count}} ajouté(s)", + "skipped": "{{count}} ignoré(s)", + "failed": "{{count}} échoué(s)", + "errorToast": "Échec du téléversement : {{summary}}", + "reasonSuffix": " ({{reason}})", + "partialToast": "Succès partiel : {{summary}}", + "successToast": "Téléversement terminé : {{summary}}", + "existsToast": "Les documents existent déjà, rien d'ajouté : {{summary}}", + "incompleteToast": "Téléversement interrompu : aucun signal de fin reçu ; actualisez pour vérifier les résultats", + "note": "Les documents téléversés vont dans le dossier local raw/ et sont compilés automatiquement dans la base ; les fichiers restent sur cette machine", + "inProgress": "Téléversement et compilation…", + "dropzone": "Déposez des fichiers ici, ou cliquez pour choisir", + "dropzoneHint": "PDF / Word / Markdown / texte et plus ; sélection multiple prise en charge", + "progressHeading": "Progression du téléversement · {{count}}", + "fileStatus": { + "pending": "En attente", + "processing": "Compilation…", + "added": "Ajouté", + "skipped": "Ignoré", + "failed": "Échoué" + } + }, + "docs": { + "heading": "Documents téléversés · {{count}}", + "empty": "Aucun document · ils sont compilés automatiquement dans la base après le téléversement", + "pages_one": "{{count}} page", + "pages_other": "{{count}} pages", + "delete": { + "action": "Supprimer le document", + "prompt": "Supprimer ?", + "confirm": "Supprimer", + "cancel": "Annuler", + "success": "{{name}} supprimé", + "error": "Échec de la suppression : {{error}}", + "partial": "Fichiers locaux supprimés, mais le nettoyage de l'index distant a échoué : {{name}}", + "reasonSuffix": " ({{reason}})", + "multiple": "Échec de la suppression : {{message}} (candidats : {{names}})" + } + }, + "remote": { + "heading": "Sources de données distantes", + "note": "Les connecteurs cloud sont en développement et pas encore disponibles · vous en voulez un ? Cliquez sur une carte pour voter sur GitHub" + }, + "overview": { + "index": { + "label": "Index", + "caption": "racine du wiki" + }, + "concepts": { + "label": "Concepts", + "caption": "reliés entre eux" + }, + "entities": { + "label": "Entités", + "caption": "personnes · orgs" + }, + "summaries": { + "label": "Résumés", + "caption": "par document" + }, + "reports": { + "label": "Rapports", + "caption": "lint · recompilation" + }, + "documents": { + "label": "Documents", + "caption": "docs compilés" + } + }, + "pageList": { + "empty": "Aucune page de ce type", + "prev": "Précédent", + "next": "Suivant" + } +} diff --git a/frontend/src/locales/fr/kbList.json b/frontend/src/locales/fr/kbList.json new file mode 100644 index 00000000..aef78c25 --- /dev/null +++ b/frontend/src/locales/fr/kbList.json @@ -0,0 +1,22 @@ +{ + "notCompiled": "Pas encore compilée", + "updatedAt": "Mise à jour {{date}}", + "title": "Bases de connaissances", + "subtitle": "Chaque base de connaissances est un wiki compilé en continu qui peut relier plusieurs sources de données", + "docsLabel": "Docs", + "rawReady": "raw/ prêt", + "rawMissing": "Pas de raw/", + "create": { + "description": "Donnez un nom à votre nouvelle base de connaissances. Le modèle et les identifiants héritent des valeurs globales par défaut et pourront être ajustés plus tard dans ses paramètres.", + "nameLabel": "Nom", + "namePlaceholder": "ex. my-kb", + "cancel": "Annuler", + "submit": "Créer", + "submitting": "Création…", + "previewLabel": "Sera créée dans {{path}}", + "advancedToggle": "Chemin personnalisé", + "customPathLabel": "Chemin personnalisé", + "customPathPlaceholder": "/chemin/absolu/vers/la/base", + "customPathHint": "Laisser vide pour utiliser la racine par défaut" + } +} diff --git a/frontend/src/locales/fr/kbSettings.json b/frontend/src/locales/fr/kbSettings.json new file mode 100644 index 00000000..634d3221 --- /dev/null +++ b/frontend/src/locales/fr/kbSettings.json @@ -0,0 +1,42 @@ +{ + "title": "Paramètres de la base de connaissances", + "configHeading": "Configuration", + "credHeading": "Identifiants (le .env de cette base)", + "maintHeading": "Maintenance", + "credSaved": "Identifiants enregistrés", + "keyCleared": "Clé API effacée", + "clearError": "Échec de l'effacement : {{error}}", + "keyPlaceholderSet": "Clé définie · laisser vide pour ne pas modifier", + "keyPlaceholderUnset": "Non définie · saisir pour activer", + "keyHintSet": "Clé définie (jamais affichée ; saisissez une nouvelle valeur pour la remplacer)", + "keyHintUnset": "Aucune clé définie", + "clear": "Effacer", + "baseLabel": "URL de base de l'API (facultatif)", + "basePlaceholder": "Vide = valeur par défaut du fournisseur ; renseignez pour des points de terminaison locaux/compatibles", + "saveCred": "Enregistrer les identifiants", + "inheritGlobal": "Hérité · global ({{value}})", + "inheritDefault": "Hérité · défaut ({{value}})", + "override": "Remplacer pour cette base", + "overrideAria": "Remplacer {{label}} pour cette base", + "unnamed": "(sans nom)", + "recompileFailed": "Échec de la recompilation", + "watchStarted": "Surveillance des fichiers démarrée", + "watchStopped": "Surveillance des fichiers arrêtée", + "recompileErrorToast": "Échec de la recompilation : {{error}}", + "lintSkipped": "Vérification ignorée", + "lintDone": "Vérification terminée", + "lintSuccessToast": "Vérification de structure terminée", + "lintErrorToast": "Échec de la vérification : {{error}}", + "watchLabel": "Surveillance des fichiers", + "watchOn": "Surveillance active", + "watchOnDir": "Surveillance · {{dir}}", + "watchOff": "Inactive · les nouveaux fichiers se compilent automatiquement une fois démarrée", + "stop": "Arrêter", + "startWatch": "Démarrer la surveillance", + "noCompiledDocs": "Aucun document compilé", + "recompileAll": "Tout recompiler", + "lint": "Vérification de structure", + "recompileHeading": "Recompilation", + "recompileSummary": "· {{total}} au total · {{recompiled}} compilés · {{skipped}} ignorés", + "preparing": "Préparation…" +} diff --git a/frontend/src/locales/fr/settings.json b/frontend/src/locales/fr/settings.json new file mode 100644 index 00000000..1ba8cedd --- /dev/null +++ b/frontend/src/locales/fr/settings.json @@ -0,0 +1,43 @@ +{ + "tabs": { + "model": "Modèle", + "general": "Général", + "conn": "Sources de données", + "about": "À propos" + }, + "savedToast": "Valeurs globales par défaut enregistrées", + "saveChanges": "Enregistrer les modifications", + "unsaved": "Modifications non enregistrées", + "modelSection": { + "title": "Modèle et seuil", + "desc": "Modèle et seuil globaux par défaut (écrits dans ~/.config/openkb/global.yaml ; chaque base peut hériter ou remplacer dans ses propres paramètres)", + "thresholdInvalid": "Le seuil doit être un entier supérieur ou égal à 1." + }, + "credSection": { + "title": "Identifiants par défaut", + "desc": "Identifiants API globaux par défaut (écrits dans ~/.config/openkb/.env ; le .env d'une base et les variables d'environnement du processus ont la priorité)", + "clearPending": "Marqué pour suppression ; prend effet à l'enregistrement", + "undoClear": "Annuler" + }, + "general": { + "langDesc": "La langue de sortie écrite dans le prompt de compilation, ex. en / 中文 / 日本語", + "kbRootLabel": "Racine des bases de connaissances", + "kbRootDesc": "Emplacement par défaut des nouvelles bases (/) ; laisser vide pour restaurer la valeur par défaut intégrée. Chaque base peut définir un chemin personnalisé à la création.", + "kbRootPlaceholder": "ex. ~/openkb", + "kbRootEnvPinned": "Fixé par la variable d'environnement OPENKB_KB_ROOT ; les modifications ici ne prendront pas effet tant qu'elle n'est pas retirée." + }, + "conn": { + "note": "Les connecteurs de sources de données cloud (OAuth / S3) sont en développement et pas encore disponibles ; pour l'instant, téléversez des fichiers locaux depuis la page de détail de la base. Vous voulez un connecteur ? Cliquez sur une carte ci-dessous pour voter sur GitHub et nous aider à prioriser." + }, + "about": { + "links": { + "repo": "Dépôt GitHub", + "pageindex": "PageIndex (moteur de recherche)", + "docs": "Docs docs.pageindex.ai", + "company": "Vectify AI (entreprise)" + }, + "blurb": "Compilez des documents bruts en une base de connaissances structurée et interconnectée de type wiki, propulsée par la recherche de documents longs de PageIndex, sans vecteurs et fondée sur le raisonnement.", + "byline": "Conçu par Vectify AI · fait partie de la gamme PageIndex", + "latestRelease": "Voir la dernière version →" + } +} diff --git a/frontend/src/locales/ja/artifacts.json b/frontend/src/locales/ja/artifacts.json new file mode 100644 index 00000000..52324033 --- /dev/null +++ b/frontend/src/locales/ja/artifacts.json @@ -0,0 +1,35 @@ +{ + "card": { + "done": "生成済み", + "open": "開く" + }, + "deck": { + "subtitle": "HTML スライド · {{name}}" + }, + "file": { + "subtitle": "HTML ファイル · {{name}}" + }, + "graph": { + "label": "ナレッジグラフ", + "empty": "可視化できる概念グラフはまだありません", + "subtitle_one": "{{count}} 概念 · {{edges}} リンク", + "subtitle_other": "{{count}} 概念 · {{edges}} リンク", + "subtitleWithTypes_one": "{{count}} 概念 · {{edges}} リンク · {{types}} 種類", + "subtitleWithTypes_other": "{{count}} 概念 · {{edges}} リンク · {{types}} 種類" + }, + "skill": { + "downloadError": "スキルパッケージのダウンロードに失敗しました: {{error}}", + "body": "スキルはインストール可能なディレクトリとして生成されました。<0>.zip をダウンロードし、エージェント(Claude Code / Codex / Gemini CLI)のスキルフォルダーに展開すればすぐに使えます。", + "download": "スキルパッケージをダウンロード(.zip)" + }, + "unknown": "不明なアーティファクト", + "previewUnsupported": "この種類のアーティファクトはプレビューできません", + "loadError": "アーティファクトの読み込みに失敗しました: {{error}}", + "openError": "オープンに失敗しました: {{error}}", + "downloadError": "ダウンロードに失敗しました: {{error}}", + "panel": { + "resize": "ドラッグして幅を変更", + "openTab": "新しいタブで開く", + "download": "ダウンロード" + } +} diff --git a/frontend/src/locales/ja/chat.json b/frontend/src/locales/ja/chat.json new file mode 100644 index 00000000..e9b159c2 --- /dev/null +++ b/frontend/src/locales/ja/chat.json @@ -0,0 +1,63 @@ +{ + "phase": { + "generating": "生成中(LLM 呼び出し。数分かかる場合があります)…", + "done": "完了", + "preparing": "準備中…", + "buildingGraph": "概念グラフを構築中…" + }, + "artifact": { + "failed": "生成に失敗しました" + }, + "sources": { + "heading": "ソース", + "pageTip": "クリックしてこの wiki ページを表示", + "internalTip": "長文ドキュメントの内部コンテンツ(PageIndex)。開ける独立したページはありません" + }, + "reading": { + "page": "<0>{{label}} を読み込み中", + "doc": "長文ドキュメント <0>{{label}} を読み込み中", + "thinking": "思考中…" + }, + "step": { + "read": "<0>{{path}} を読み込みました" + }, + "requestError": "リクエストに失敗しました: {{error}}", + "savedTo": "{{path}} に保存しました", + "usage": { + "deck": "使い方: /deck <名前> <意図>、例:「retrieval-intro エンジニア向けにベクトルなし検索を紹介」", + "skill": "使い方: /skill <名前> <意図>、例:「pageindex-expert 長文検索 Q&A のエキスパート」" + }, + "genErrorToast": "生成に失敗しました: {{error}}", + "requestErrorToast": "リクエストに失敗しました: {{error}}", + "errors": { + "noKb": "このセッションがどのナレッジベースに属するか判別できませんでした。ホームページから入り直してください", + "loadSession": "セッションの読み込みに失敗しました: {{error}}", + "openSource": "ソース {{path}} を開けませんでした: {{error}}" + }, + "newSession": "新しいセッション", + "inputPlaceholder": "追加の質問を入力、または / でコマンド…", + "commands": { + "paletteHeading": "コマンド · ジェネレーター", + "deck": { + "label": "スライドを生成", + "desc": "知識を単一ファイルの HTML スライドにコンパイル" + }, + "skill": { + "label": "スキルを抽出", + "desc": "インストール可能な Agent Skill を生成" + }, + "visualize": { + "label": "ナレッジグラフ", + "desc": "インタラクティブな概念グラフを生成" + } + }, + "input": { + "cmdPlaceholder": "{{label}}: 意図を記述してください…", + "defaultPlaceholder": "ナレッジベースに質問、または / でコマンド…", + "selectKb": "ナレッジベースを選択", + "noKbs": "ナレッジベースがまだありません", + "current": "現在", + "stop": "停止", + "hint": "<0>/ でコマンド" + } +} diff --git a/frontend/src/locales/ja/common.json b/frontend/src/locales/ja/common.json new file mode 100644 index 00000000..14b5b1d6 --- /dev/null +++ b/frontend/src/locales/ja/common.json @@ -0,0 +1,80 @@ +{ + "loading": "読み込み中…", + "pageLoadError": "ページの読み込みに失敗しました: {{error}}", + "noChanges": "保存する変更はありません", + "saveError": "保存に失敗しました: {{error}}", + "configLoadError": "設定の読み込みに失敗しました: {{error}}", + "actions": { + "newKb": "新しいナレッジベース", + "close": "閉じる", + "refresh": "更新" + }, + "fields": { + "model": "モデル", + "wikiLanguage": "wiki の出力言語", + "threshold": "PageIndex のしきい値(ページ)" + }, + "errors": { + "requestFailed": "リクエストに失敗しました", + "uploadFailed": "アップロードに失敗しました: {{detail}}" + }, + "nav": { + "home": "ホーム", + "kbs": "ナレッジベース", + "settings": "設定" + }, + "titlebar": { + "chat": "チャット", + "local": "ローカル" + }, + "theme": { + "light": "ライト", + "dark": "ダーク", + "system": "システム", + "toggleTitle": "テーマ: {{label}}(クリックで切り替え)", + "toggleAria": "テーマ: {{label}}" + }, + "language": { + "zh": "中文", + "en": "English", + "fr": "Français", + "es": "Español", + "ru": "Русский", + "ja": "日本語", + "toggleTitle": "言語: {{label}}", + "toggleAria": "言語: {{label}}" + }, + "auth": { + "title": "アクセストークンが必要です", + "description": "このサーバーにはアクセストークン(OPENKB_API_TOKEN)が設定されています。続行するにはトークンを入力してください。トークンはこのブラウザーにのみ保存されます。", + "tokenLabel": "アクセストークン", + "baseLabel": "API アドレス(任意。空欄の場合は現在のオリジンを使用)", + "connect": "接続" + }, + "connector": { + "tooltip": "クラウド同期は開発中です · GitHub で投票してください", + "vote": "欲しいですか? 投票する" + }, + "onboarding": { + "welcomeTitle": "OpenKB へようこそ", + "welcomeBody": "あなたのドキュメントを、相互にリンクされ常に最新のナレッジベースに変えましょう。2 つの簡単なステップで準備完了です。", + "getStarted": "はじめる", + "skip": "今はスキップ", + "configTitle": "モデルを接続", + "configBody": "OpenKB はコンパイルと回答に LLM を使用します。API キーを貼り付けてください — キーはローカルに保存され、この端末から外部に出ることはありません。", + "modelLabel": "LLM モデル", + "langLabel": "wiki の言語", + "apiKeyLabel": "LLM の API キー", + "apiKeyPlaceholder": "API キーを貼り付け", + "baseUrlLabel": "カスタム Base URL(任意)", + "baseUrlPlaceholder": "例: http://localhost:11434(Ollama、LM Studio)", + "continue": "続行", + "back": "戻る", + "kbTitle": "最初のナレッジベースを作成", + "kbBody": "ナレッジベースにはドキュメントとコンパイル済みの wiki が含まれます。後で追加できます。", + "kbNameLabel": "ナレッジベース名", + "createFinish": "作成して完了", + "saving": "保存中…", + "createdToast": "「{{name}}」を作成しました" + } +} diff --git a/frontend/src/locales/ja/home.json b/frontend/src/locales/ja/home.json new file mode 100644 index 00000000..e2729cb9 --- /dev/null +++ b/frontend/src/locales/ja/home.json @@ -0,0 +1,7 @@ +{ + "greeting": "何を質問しますか?", + "ready": "コンパイル済みの知識 · <0>{{docs}} 件のドキュメント · <1>{{kbs}} 件のベース", + "recentSessions": "最近のセッション", + "untitledSession": "無題のセッション", + "tagline": "Powered by OpenKB · あなたの知識は常にプレーンな Markdown で、常にあなたのものです" +} diff --git a/frontend/src/locales/ja/kb.json b/frontend/src/locales/ja/kb.json new file mode 100644 index 00000000..46a5c0b1 --- /dev/null +++ b/frontend/src/locales/ja/kb.json @@ -0,0 +1,84 @@ +{ + "settingsButton": "ナレッジベースの設定", + "loadError": "読み込みに失敗しました: {{error}}", + "wikiNote": "wiki/ はこの端末上のプレーンな Markdown フォルダーです — あなたのデータは常にあなたのものです", + "reader": { + "empty": "このナレッジベースにはまだコンパイル済みのページがありません", + "selectPage": "左のページを選択すると内容が表示されます" + }, + "upload": { + "added": "{{count}} 件追加", + "skipped": "{{count}} 件スキップ", + "failed": "{{count}} 件失敗", + "errorToast": "アップロードに失敗しました: {{summary}}", + "reasonSuffix": "({{reason}})", + "partialToast": "一部成功: {{summary}}", + "successToast": "アップロード完了: {{summary}}", + "existsToast": "ドキュメントは既に存在します。追加はありません: {{summary}}", + "incompleteToast": "アップロードが中断されました。完了信号を受信していません。結果を確認するには更新してください", + "note": "アップロードしたドキュメントはローカルの raw/ フォルダーに入り、自動的にナレッジベースへコンパイルされます。ファイルはこの端末に残ります", + "inProgress": "アップロードとコンパイル中…", + "dropzone": "ここにファイルをドロップ、またはクリックして選択", + "dropzoneHint": "PDF / Word / Markdown / テキストなど。複数選択に対応", + "progressHeading": "アップロードの進捗 · {{count}}", + "fileStatus": { + "pending": "待機中", + "processing": "コンパイル中…", + "added": "追加済み", + "skipped": "スキップ", + "failed": "失敗" + } + }, + "docs": { + "heading": "アップロード済みドキュメント · {{count}}", + "empty": "ドキュメントはまだありません · アップロード後、自動的にナレッジベースへコンパイルされます", + "pages_one": "{{count}} ページ", + "pages_other": "{{count}} ページ", + "delete": { + "action": "ドキュメントを削除", + "prompt": "削除しますか?", + "confirm": "削除", + "cancel": "キャンセル", + "success": "「{{name}}」を削除しました", + "error": "削除に失敗しました: {{error}}", + "partial": "ローカルファイルは削除しましたが、リモートインデックスのクリーンアップに失敗しました: {{name}}", + "reasonSuffix": "({{reason}})", + "multiple": "削除に失敗しました: {{message}}(候補: {{names}})" + } + }, + "remote": { + "heading": "リモートデータソース", + "note": "クラウドコネクタは開発中でまだ利用できません · 欲しいですか? カードをクリックして GitHub で投票してください" + }, + "overview": { + "index": { + "label": "インデックス", + "caption": "wiki ルート" + }, + "concepts": { + "label": "概念", + "caption": "相互リンク" + }, + "entities": { + "label": "エンティティ", + "caption": "人物 · 組織" + }, + "summaries": { + "label": "要約", + "caption": "ドキュメント別" + }, + "reports": { + "label": "レポート", + "caption": "lint · 再コンパイル" + }, + "documents": { + "label": "ドキュメント", + "caption": "コンパイル済み" + } + }, + "pageList": { + "empty": "この種類のページはまだありません", + "prev": "前へ", + "next": "次へ" + } +} diff --git a/frontend/src/locales/ja/kbList.json b/frontend/src/locales/ja/kbList.json new file mode 100644 index 00000000..e5c86396 --- /dev/null +++ b/frontend/src/locales/ja/kbList.json @@ -0,0 +1,22 @@ +{ + "notCompiled": "未コンパイル", + "updatedAt": "更新日 {{date}}", + "title": "ナレッジベース", + "subtitle": "各ナレッジベースは、複数のデータソースを束ねられる、継続的にコンパイルされる wiki です", + "docsLabel": "ドキュメント", + "rawReady": "raw/ 準備完了", + "rawMissing": "raw/ なし", + "create": { + "description": "新しいナレッジベースに名前を付けてください。モデルと認証情報はグローバルの既定値を引き継ぎ、後で設定から調整できます。", + "nameLabel": "名前", + "namePlaceholder": "例: my-kb", + "cancel": "キャンセル", + "submit": "作成", + "submitting": "作成中…", + "previewLabel": "{{path}} に作成されます", + "advancedToggle": "カスタムパス", + "customPathLabel": "カスタムパス", + "customPathPlaceholder": "/絶対パス/to/kb", + "customPathHint": "空欄の場合は既定のルートを使用します" + } +} diff --git a/frontend/src/locales/ja/kbSettings.json b/frontend/src/locales/ja/kbSettings.json new file mode 100644 index 00000000..60bc9d57 --- /dev/null +++ b/frontend/src/locales/ja/kbSettings.json @@ -0,0 +1,42 @@ +{ + "title": "ナレッジベースの設定", + "configHeading": "設定", + "credHeading": "認証情報(このベースの .env)", + "maintHeading": "メンテナンス", + "credSaved": "認証情報を保存しました", + "keyCleared": "API キーをクリアしました", + "clearError": "クリアに失敗しました: {{error}}", + "keyPlaceholderSet": "キー設定済み · 空欄のままにすると変更しません", + "keyPlaceholderUnset": "未設定 · 入力して有効化", + "keyHintSet": "キー設定済み(表示されません。新しい値を入力すると更新されます)", + "keyHintUnset": "キーは未設定です", + "clear": "クリア", + "baseLabel": "API Base URL(任意)", + "basePlaceholder": "空欄はプロバイダーの既定値。ローカル/互換エンドポイントの場合は入力してください", + "saveCred": "認証情報を保存", + "inheritGlobal": "継承 · グローバル({{value}})", + "inheritDefault": "継承 · 既定({{value}})", + "override": "このベースで上書き", + "overrideAria": "このベースで {{label}} を上書き", + "unnamed": "(名称未設定)", + "recompileFailed": "再コンパイルに失敗しました", + "watchStarted": "ファイル監視を開始しました", + "watchStopped": "ファイル監視を停止しました", + "recompileErrorToast": "再コンパイルに失敗しました: {{error}}", + "lintSkipped": "チェックをスキップしました", + "lintDone": "チェック完了", + "lintSuccessToast": "構造チェックが完了しました", + "lintErrorToast": "チェックに失敗しました: {{error}}", + "watchLabel": "ファイル監視", + "watchOn": "監視中", + "watchOnDir": "監視中 · {{dir}}", + "watchOff": "停止中 · 開始すると新しいファイルが自動的にコンパイルされます", + "stop": "停止", + "startWatch": "監視を開始", + "noCompiledDocs": "コンパイル済みのドキュメントはまだありません", + "recompileAll": "すべて再コンパイル", + "lint": "構造チェック", + "recompileHeading": "再コンパイル", + "recompileSummary": "· 合計 {{total}} · コンパイル {{recompiled}} · スキップ {{skipped}}", + "preparing": "準備中…" +} diff --git a/frontend/src/locales/ja/settings.json b/frontend/src/locales/ja/settings.json new file mode 100644 index 00000000..cd3e9ee4 --- /dev/null +++ b/frontend/src/locales/ja/settings.json @@ -0,0 +1,43 @@ +{ + "tabs": { + "model": "モデル", + "general": "一般", + "conn": "データソース", + "about": "情報" + }, + "savedToast": "グローバルの既定値を保存しました", + "saveChanges": "変更を保存", + "unsaved": "未保存の変更", + "modelSection": { + "title": "モデルとしきい値", + "desc": "グローバルの既定モデルとしきい値(~/.config/openkb/global.yaml に書き込まれます。各ベースは自身の設定で継承または上書きできます)", + "thresholdInvalid": "しきい値は 1 以上の整数である必要があります。" + }, + "credSection": { + "title": "既定の認証情報", + "desc": "グローバルの既定 API 認証情報(~/.config/openkb/.env に書き込まれます。ベース自身の .env とプロセスの環境変数が優先されます)", + "clearPending": "削除対象としてマーク。保存時に反映されます", + "undoClear": "元に戻す" + }, + "general": { + "langDesc": "コンパイルのプロンプトに書き込まれる出力言語。例: en / 中文 / 日本語", + "kbRootLabel": "ナレッジベースのルート", + "kbRootDesc": "新しいベースの既定の場所(/)。空欄にすると組み込みの既定値に戻ります。各ベースは作成時にカスタムパスを設定できます。", + "kbRootPlaceholder": "例: ~/openkb", + "kbRootEnvPinned": "環境変数 OPENKB_KB_ROOT で固定されています。解除するまでここでの編集は反映されません。" + }, + "conn": { + "note": "クラウドのデータソースコネクタ(OAuth / S3)は開発中でまだ利用できません。今のところ、ベース詳細ページからローカルファイルをアップロードしてください。コネクタが欲しいですか? 下のカードをクリックして GitHub で投票し、優先順位付けにご協力ください。" + }, + "about": { + "links": { + "repo": "GitHub リポジトリ", + "pageindex": "PageIndex(検索エンジン)", + "docs": "ドキュメント docs.pageindex.ai", + "company": "Vectify AI(企業)" + }, + "blurb": "PageIndex のベクトルを使わない推論ベースの長文検索を活用し、生のドキュメントを構造化された相互リンク型の wiki 風ナレッジベースにコンパイルします。", + "byline": "Vectify AI 製 · PageIndex 製品ラインの一部", + "latestRelease": "最新リリースを見る →" + } +} diff --git a/frontend/src/locales/ru/artifacts.json b/frontend/src/locales/ru/artifacts.json new file mode 100644 index 00000000..852b9687 --- /dev/null +++ b/frontend/src/locales/ru/artifacts.json @@ -0,0 +1,39 @@ +{ + "card": { + "done": "Сгенерировано", + "open": "Открыть" + }, + "deck": { + "subtitle": "HTML-презентация · {{name}}" + }, + "file": { + "subtitle": "HTML-файл · {{name}}" + }, + "graph": { + "label": "Граф знаний", + "empty": "Графа концептов для визуализации пока нет", + "subtitle_one": "{{count}} концепт · {{edges}} связей", + "subtitle_few": "{{count}} концепта · {{edges}} связей", + "subtitle_many": "{{count}} концептов · {{edges}} связей", + "subtitle_other": "{{count}} концепта · {{edges}} связей", + "subtitleWithTypes_one": "{{count}} концепт · {{edges}} связей · {{types}} типов", + "subtitleWithTypes_few": "{{count}} концепта · {{edges}} связей · {{types}} типов", + "subtitleWithTypes_many": "{{count}} концептов · {{edges}} связей · {{types}} типов", + "subtitleWithTypes_other": "{{count}} концепта · {{edges}} связей · {{types}} типов" + }, + "skill": { + "downloadError": "Не удалось скачать пакет навыка: {{error}}", + "body": "Навык сгенерирован в виде устанавливаемого каталога. Скачайте <0>.zip, распакуйте его в папку навыков вашего агента (Claude Code / Codex / Gemini CLI), и он готов к использованию.", + "download": "Скачать пакет навыка (.zip)" + }, + "unknown": "Неизвестный артефакт", + "previewUnsupported": "Этот тип артефакта нельзя предпросмотреть", + "loadError": "Не удалось загрузить артефакт: {{error}}", + "openError": "Ошибка открытия: {{error}}", + "downloadError": "Ошибка скачивания: {{error}}", + "panel": { + "resize": "Потяните, чтобы изменить ширину", + "openTab": "Открыть в новой вкладке", + "download": "Скачать" + } +} diff --git a/frontend/src/locales/ru/chat.json b/frontend/src/locales/ru/chat.json new file mode 100644 index 00000000..38ce876e --- /dev/null +++ b/frontend/src/locales/ru/chat.json @@ -0,0 +1,63 @@ +{ + "phase": { + "generating": "Генерация (вызов LLM, может занять несколько минут)…", + "done": "Готово", + "preparing": "Подготовка…", + "buildingGraph": "Построение графа концептов…" + }, + "artifact": { + "failed": "Ошибка генерации" + }, + "sources": { + "heading": "Источники", + "pageTip": "Нажмите, чтобы просмотреть эту страницу вики", + "internalTip": "Внутреннее содержимое длинного документа (PageIndex); отдельной страницы для открытия нет" + }, + "reading": { + "page": "Чтение <0>{{label}}", + "doc": "Чтение длинного документа <0>{{label}}", + "thinking": "Размышление…" + }, + "step": { + "read": "Прочитано <0>{{path}}" + }, + "requestError": "Ошибка запроса: {{error}}", + "savedTo": "Сохранено в {{path}}", + "usage": { + "deck": "Использование: /deck <имя> <замысел>, напр. «retrieval-intro рассказать инженерам о безвекторном поиске»", + "skill": "Использование: /skill <имя> <замысел>, напр. «pageindex-expert эксперт по вопросам и ответам о поиске в длинных документах»" + }, + "genErrorToast": "Ошибка генерации: {{error}}", + "requestErrorToast": "Ошибка запроса: {{error}}", + "errors": { + "noKb": "Не удалось определить, к какой базе знаний относится эта сессия; пожалуйста, войдите с главной страницы", + "loadSession": "Не удалось загрузить сессию: {{error}}", + "openSource": "Не удалось открыть источник {{path}}: {{error}}" + }, + "newSession": "Новая сессия", + "inputPlaceholder": "Задайте уточняющий вопрос или введите / для команд…", + "commands": { + "paletteHeading": "Команды · генераторы", + "deck": { + "label": "Сгенерировать слайды", + "desc": "Скомпилировать знания в HTML-презентацию одним файлом" + }, + "skill": { + "label": "Извлечь навык", + "desc": "Сгенерировать устанавливаемый Agent Skill" + }, + "visualize": { + "label": "Граф знаний", + "desc": "Сгенерировать интерактивный граф концептов" + } + }, + "input": { + "cmdPlaceholder": "{{label}}: опишите ваш замысел…", + "defaultPlaceholder": "Спросите свою базу знаний или введите / для команд…", + "selectKb": "Выберите базу знаний", + "noKbs": "Баз знаний пока нет", + "current": "Текущая", + "stop": "Остановить", + "hint": "Введите <0>/ для команд" + } +} diff --git a/frontend/src/locales/ru/common.json b/frontend/src/locales/ru/common.json new file mode 100644 index 00000000..b6898eb4 --- /dev/null +++ b/frontend/src/locales/ru/common.json @@ -0,0 +1,79 @@ +{ + "loading": "Загрузка…", + "pageLoadError": "Не удалось загрузить страницу: {{error}}", + "noChanges": "Нет изменений для сохранения", + "saveError": "Ошибка сохранения: {{error}}", + "configLoadError": "Не удалось загрузить конфигурацию: {{error}}", + "actions": { + "newKb": "Новая база знаний", + "close": "Закрыть", + "refresh": "Обновить" + }, + "fields": { + "model": "Модель", + "wikiLanguage": "Язык вывода вики", + "threshold": "Порог PageIndex (страниц)" + }, + "errors": { + "requestFailed": "Ошибка запроса", + "uploadFailed": "Ошибка загрузки: {{detail}}" + }, + "nav": { + "home": "Главная", + "kbs": "Базы знаний", + "settings": "Настройки" + }, + "titlebar": { + "chat": "Чат", + "local": "Локально" + }, + "theme": { + "light": "Светлая", + "dark": "Тёмная", + "system": "Системная", + "toggleTitle": "Тема: {{label}} (нажмите, чтобы сменить)", + "toggleAria": "Тема: {{label}}" + }, + "language": { + "zh": "中文", + "en": "English", + "fr": "Français", + "es": "Español", + "ru": "Русский", + "toggleTitle": "Язык: {{label}}", + "toggleAria": "Язык: {{label}}" + }, + "auth": { + "title": "Требуется токен доступа", + "description": "На этом сервере настроен токен доступа (OPENKB_API_TOKEN). Введите токен, чтобы продолжить; он хранится только в этом браузере.", + "tokenLabel": "Токен доступа", + "baseLabel": "Адрес API (необязательно; оставьте пустым, чтобы использовать текущий источник)", + "connect": "Подключиться" + }, + "connector": { + "tooltip": "Облачная синхронизация в разработке · проголосуйте за неё на GitHub", + "vote": "Нужна? Голосуйте" + }, + "onboarding": { + "welcomeTitle": "Добро пожаловать в OpenKB", + "welcomeBody": "Превратите свои документы во взаимосвязанную и всегда актуальную базу знаний. Два быстрых шага — и всё готово.", + "getStarted": "Начать", + "skip": "Пропустить пока", + "configTitle": "Подключите свою модель", + "configBody": "OpenKB использует LLM для компиляции и ответов. Вставьте ключ API — он хранится локально и никогда не покидает ваше устройство.", + "modelLabel": "Модель LLM", + "langLabel": "Язык вики", + "apiKeyLabel": "Ключ API для LLM", + "apiKeyPlaceholder": "Вставьте ваш ключ API", + "baseUrlLabel": "Пользовательский базовый URL (необязательно)", + "baseUrlPlaceholder": "напр. http://localhost:11434 (Ollama, LM Studio)", + "continue": "Продолжить", + "back": "Назад", + "kbTitle": "Создайте свою первую базу знаний", + "kbBody": "База знаний содержит ваши документы и скомпилированную вики. Позже можно добавить ещё.", + "kbNameLabel": "Название базы знаний", + "createFinish": "Создать и завершить", + "saving": "Сохранение…", + "createdToast": "База «{{name}}» создана" + } +} diff --git a/frontend/src/locales/ru/home.json b/frontend/src/locales/ru/home.json new file mode 100644 index 00000000..1e129c9f --- /dev/null +++ b/frontend/src/locales/ru/home.json @@ -0,0 +1,7 @@ +{ + "greeting": "Что бы вы хотели спросить?", + "ready": "Знания скомпилированы · <0>{{docs}} док. · <1>{{kbs}} баз", + "recentSessions": "Недавние сессии", + "untitledSession": "Сессия без названия", + "tagline": "На основе OpenKB · ваши знания всегда в чистом Markdown и всегда принадлежат вам" +} diff --git a/frontend/src/locales/ru/kb.json b/frontend/src/locales/ru/kb.json new file mode 100644 index 00000000..9171bb78 --- /dev/null +++ b/frontend/src/locales/ru/kb.json @@ -0,0 +1,86 @@ +{ + "settingsButton": "Настройки базы знаний", + "loadError": "Ошибка загрузки: {{error}}", + "wikiNote": "wiki/ — это папка с чистым Markdown на этом устройстве; ваши данные всегда принадлежат вам", + "reader": { + "empty": "В этой базе знаний ещё нет скомпилированных страниц", + "selectPage": "Выберите страницу слева, чтобы просмотреть её содержимое" + }, + "upload": { + "added": "{{count}} добавлено", + "skipped": "{{count}} пропущено", + "failed": "{{count}} с ошибкой", + "errorToast": "Ошибка загрузки: {{summary}}", + "reasonSuffix": " ({{reason}})", + "partialToast": "Частичный успех: {{summary}}", + "successToast": "Загрузка завершена: {{summary}}", + "existsToast": "Документы уже существуют, ничего не добавлено: {{summary}}", + "incompleteToast": "Загрузка прервана: сигнал о завершении не получен; обновите, чтобы проверить результаты", + "note": "Загруженные документы попадают в локальную папку raw/ и автоматически компилируются в базу; файлы остаются на этом устройстве", + "inProgress": "Загрузка и компиляция…", + "dropzone": "Перетащите файлы сюда или нажмите, чтобы выбрать", + "dropzoneHint": "PDF / Word / Markdown / текст и другое; поддерживается множественный выбор", + "progressHeading": "Ход загрузки · {{count}}", + "fileStatus": { + "pending": "Ожидание", + "processing": "Компиляция…", + "added": "Добавлено", + "skipped": "Пропущено", + "failed": "Ошибка" + } + }, + "docs": { + "heading": "Загруженные документы · {{count}}", + "empty": "Документов пока нет · после загрузки они автоматически компилируются в базу", + "pages_one": "{{count}} страница", + "pages_few": "{{count}} страницы", + "pages_many": "{{count}} страниц", + "pages_other": "{{count}} страницы", + "delete": { + "action": "Удалить документ", + "prompt": "Удалить?", + "confirm": "Удалить", + "cancel": "Отмена", + "success": "«{{name}}» удалён", + "error": "Ошибка удаления: {{error}}", + "partial": "Локальные файлы удалены, но не удалось очистить удалённый индекс: {{name}}", + "reasonSuffix": " ({{reason}})", + "multiple": "Ошибка удаления: {{message}} (кандидаты: {{names}})" + } + }, + "remote": { + "heading": "Удалённые источники данных", + "note": "Облачные коннекторы в разработке и пока недоступны · хотите такой? Нажмите на карточку, чтобы проголосовать на GitHub" + }, + "overview": { + "index": { + "label": "Индекс", + "caption": "корень вики" + }, + "concepts": { + "label": "Концепты", + "caption": "взаимосвязаны" + }, + "entities": { + "label": "Сущности", + "caption": "люди · орг." + }, + "summaries": { + "label": "Резюме", + "caption": "по документам" + }, + "reports": { + "label": "Отчёты", + "caption": "lint · перекомпиляция" + }, + "documents": { + "label": "Документы", + "caption": "скомпилир. док." + } + }, + "pageList": { + "empty": "Страниц этого типа пока нет", + "prev": "Назад", + "next": "Вперёд" + } +} diff --git a/frontend/src/locales/ru/kbList.json b/frontend/src/locales/ru/kbList.json new file mode 100644 index 00000000..2685c562 --- /dev/null +++ b/frontend/src/locales/ru/kbList.json @@ -0,0 +1,22 @@ +{ + "notCompiled": "Ещё не скомпилирована", + "updatedAt": "Обновлено {{date}}", + "title": "Базы знаний", + "subtitle": "Каждая база знаний — это непрерывно компилируемая вики, которая может связывать несколько источников данных", + "docsLabel": "Док.", + "rawReady": "raw/ готов", + "rawMissing": "Нет raw/", + "create": { + "description": "Дайте название новой базе знаний. Модель и учётные данные наследуются из глобальных значений по умолчанию и позже могут быть изменены в её настройках.", + "nameLabel": "Название", + "namePlaceholder": "напр. my-kb", + "cancel": "Отмена", + "submit": "Создать", + "submitting": "Создание…", + "previewLabel": "Будет создана в {{path}}", + "advancedToggle": "Пользовательский путь", + "customPathLabel": "Пользовательский путь", + "customPathPlaceholder": "/абсолютный/путь/к/базе", + "customPathHint": "Оставьте пустым, чтобы использовать корень по умолчанию" + } +} diff --git a/frontend/src/locales/ru/kbSettings.json b/frontend/src/locales/ru/kbSettings.json new file mode 100644 index 00000000..4ecef85c --- /dev/null +++ b/frontend/src/locales/ru/kbSettings.json @@ -0,0 +1,42 @@ +{ + "title": "Настройки базы знаний", + "configHeading": "Конфигурация", + "credHeading": "Учётные данные (.env этой базы)", + "maintHeading": "Обслуживание", + "credSaved": "Учётные данные сохранены", + "keyCleared": "Ключ API удалён", + "clearError": "Ошибка удаления: {{error}}", + "keyPlaceholderSet": "Ключ задан · оставьте пустым, чтобы не менять", + "keyPlaceholderUnset": "Не задан · введите, чтобы включить", + "keyHintSet": "Ключ задан (никогда не отображается; введите новое значение для замены)", + "keyHintUnset": "Ключ не задан", + "clear": "Очистить", + "baseLabel": "Базовый URL API (необязательно)", + "basePlaceholder": "Пусто — значение провайдера по умолчанию; заполните для локальных/совместимых эндпоинтов", + "saveCred": "Сохранить учётные данные", + "inheritGlobal": "Наследуется · глобально ({{value}})", + "inheritDefault": "Наследуется · по умолчанию ({{value}})", + "override": "Переопределить для этой базы", + "overrideAria": "Переопределить {{label}} для этой базы", + "unnamed": "(без названия)", + "recompileFailed": "Ошибка перекомпиляции", + "watchStarted": "Отслеживание файлов запущено", + "watchStopped": "Отслеживание файлов остановлено", + "recompileErrorToast": "Ошибка перекомпиляции: {{error}}", + "lintSkipped": "Проверка пропущена", + "lintDone": "Проверка завершена", + "lintSuccessToast": "Проверка структуры завершена", + "lintErrorToast": "Ошибка проверки: {{error}}", + "watchLabel": "Отслеживание файлов", + "watchOn": "Отслеживается", + "watchOnDir": "Отслеживается · {{dir}}", + "watchOff": "Не запущено · новые файлы компилируются автоматически после запуска", + "stop": "Остановить", + "startWatch": "Запустить отслеживание", + "noCompiledDocs": "Скомпилированных документов пока нет", + "recompileAll": "Перекомпилировать всё", + "lint": "Проверка структуры", + "recompileHeading": "Перекомпиляция", + "recompileSummary": "· всего {{total}} · скомпилировано {{recompiled}} · пропущено {{skipped}}", + "preparing": "Подготовка…" +} diff --git a/frontend/src/locales/ru/settings.json b/frontend/src/locales/ru/settings.json new file mode 100644 index 00000000..c30f8b4a --- /dev/null +++ b/frontend/src/locales/ru/settings.json @@ -0,0 +1,43 @@ +{ + "tabs": { + "model": "Модель", + "general": "Общие", + "conn": "Источники данных", + "about": "О программе" + }, + "savedToast": "Глобальные значения по умолчанию сохранены", + "saveChanges": "Сохранить изменения", + "unsaved": "Несохранённые изменения", + "modelSection": { + "title": "Модель и порог", + "desc": "Глобальные модель и порог по умолчанию (записываются в ~/.config/openkb/global.yaml; каждая база может наследовать или переопределить их в своих настройках)", + "thresholdInvalid": "Порог должен быть целым числом не меньше 1." + }, + "credSection": { + "title": "Учётные данные по умолчанию", + "desc": "Глобальные учётные данные API по умолчанию (записываются в ~/.config/openkb/.env; собственный .env базы и переменные окружения процесса имеют приоритет)", + "clearPending": "Помечено на удаление; вступит в силу при сохранении", + "undoClear": "Отменить" + }, + "general": { + "langDesc": "Язык вывода, записываемый в промпт компиляции, напр. en / 中文 / 日本語", + "kbRootLabel": "Корень баз знаний", + "kbRootDesc": "Расположение по умолчанию для новых баз (/); оставьте пустым, чтобы восстановить встроенное значение по умолчанию. Каждая база может задать пользовательский путь при создании.", + "kbRootPlaceholder": "напр. ~/openkb", + "kbRootEnvPinned": "Закреплено переменной окружения OPENKB_KB_ROOT; изменения здесь не вступят в силу, пока она не будет снята." + }, + "conn": { + "note": "Облачные коннекторы источников данных (OAuth / S3) в разработке и пока недоступны; пока что загружайте локальные файлы со страницы базы. Хотите коннектор? Нажмите на карточку ниже, чтобы проголосовать на GitHub и помочь нам расставить приоритеты." + }, + "about": { + "links": { + "repo": "Репозиторий GitHub", + "pageindex": "PageIndex (движок поиска)", + "docs": "Docs docs.pageindex.ai", + "company": "Vectify AI (компания)" + }, + "blurb": "Компилируйте исходные документы в структурированную взаимосвязанную базу знаний в стиле вики на основе безвекторного поиска по длинным документам PageIndex, основанного на рассуждении.", + "byline": "Создано Vectify AI · часть линейки продуктов PageIndex", + "latestRelease": "Смотреть последний выпуск →" + } +} diff --git a/frontend/src/locales/zh/common.json b/frontend/src/locales/zh/common.json index 524e0e0b..c1325e38 100644 --- a/frontend/src/locales/zh/common.json +++ b/frontend/src/locales/zh/common.json @@ -37,7 +37,11 @@ "language": { "zh": "中文", "en": "English", - "toggleTitle": "语言:{{label}}(点击切换)", + "fr": "Français", + "es": "Español", + "ru": "Русский", + "ja": "日本語", + "toggleTitle": "语言:{{label}}", "toggleAria": "语言:{{label}}" }, "auth": { @@ -50,5 +54,27 @@ "connector": { "tooltip": "云端同步开发中 · 去 GitHub 投票表达需求", "vote": "想要它?去投票" + }, + "onboarding": { + "welcomeTitle": "欢迎使用 OpenKB", + "welcomeBody": "把你的文档编译成互联、自动保持更新的知识库。两步即可开始。", + "getStarted": "开始设置", + "skip": "暂时跳过", + "configTitle": "连接你的模型", + "configBody": "OpenKB 用大模型来编译和回答。粘贴一个 API 密钥即可——它只存在本机,不会外传。", + "modelLabel": "模型", + "langLabel": "知识库语言", + "apiKeyLabel": "LLM API 密钥", + "apiKeyPlaceholder": "粘贴 API 密钥", + "baseUrlLabel": "自定义 Base URL(可选)", + "baseUrlPlaceholder": "如 http://localhost:11434(Ollama、LM Studio)", + "continue": "继续", + "back": "上一步", + "kbTitle": "创建你的第一个知识库", + "kbBody": "知识库存放你的文档和编译出的 wiki。之后可以再建更多。", + "kbNameLabel": "知识库名称", + "createFinish": "创建并完成", + "saving": "保存中…", + "createdToast": "已创建 {{name}}" } }