irongit

Open source voice dictation for your whole desktop. Local whisper.cpp transcription, global hotkeys, optional LLM enhancement via Claude Code, Gemini CLI, Codex, or any API. Wayland-first.

initial commit

huncholanehuncholaneauthored
commit 42b857ebd420ef90c334595d35a44389207d05b3Browse files

51 files changed, +11724 -0

+27-0.gitignore
@@ -0,0 +1,27 @@
1+# Logs
2+logs
3+*.log
4+npm-debug.log*
5+yarn-debug.log*
6+yarn-error.log*
7+pnpm-debug.log*
8+lerna-debug.log*
9+
10+node_modules
11+dist
12+dist-ssr
13+*.local
14+
15+# Editor directories and files
16+.vscode/*
17+!.vscode/extensions.json
18+.idea
19+.DS_Store
20+*.suo
21+*.ntvs*
22+*.njsproj
23+*.sln
24+*.sw?
25+
26+# local secrets
27+secrets.md
+3-0.vscode/extensions.json
@@ -0,0 +1,3 @@
1+{
2+ "recommendations": ["tauri-apps.tauri-vscode", "rust-lang.rust-analyzer"]
3+}
+98-0README.md
@@ -0,0 +1,98 @@
1+# mutterbox
2+
3+Open source voice dictation for your whole desktop. Press a hotkey anywhere,
4+speak, press it again, and the transcript lands in whatever input field has
5+focus. Transcription runs fully local through whisper.cpp; an optional
6+enhancement pass can route the raw transcript through Claude, Gemini, any
7+OpenAI-compatible endpoint, or a local Ollama model to clean it up or transform
8+it with your own instructions.
9+
10+Think Wispr Flow, but open source, cross platform, and local-first.
11+
12+## How it works
13+
14+```
15+hotkey ──▶ record mic (cpal) ──▶ whisper.cpp (local) ──▶ optional LLM cleanup ──▶ inject into focused field
16+```
17+
18+- One codebase for Linux, macOS, and Windows: Rust + Tauri 2, webview UI.
19+- Dictation models are whisper.cpp GGML files, installed with one click from the
20+ Models page and stored in the app data dir. Everything works offline once a
21+ model is downloaded.
22+- Enhancement is off by default and never required. API keys are read from
23+ environment variables only and are never stored.
24+- Text insertion uses clipboard paste (with clipboard restore) or synthetic
25+ keystrokes, selectable in settings.
26+
27+## Development
28+
29+Prerequisites: Rust, Node 18+, and on Linux the Tauri system deps
30+(`webkit2gtk-4.1`, `gtk3`), plus `cmake` and a C++ toolchain for whisper.cpp.
31+On Arch:
32+
33+```sh
34+sudo pacman -S --needed webkit2gtk-4.1 gtk3 cmake base-devel alsa-lib xdotool
35+```
36+
37+Run it:
38+
39+```sh
40+npm install
41+npm run tauri dev
42+```
43+
44+Build a release bundle:
45+
46+```sh
47+npm run tauri build
48+```
49+
50+## The hotkey on Wayland
51+
52+Global hotkeys are an X11 concept; Wayland compositors do not let apps grab
53+keys. mutterbox handles this with single-instance triggers: `mutterbox
54+--toggle`, `--start`, and `--stop` control dictation in the running instance.
55+When mutterbox detects Hyprland it shows a popup with the exact lines to copy
56+into your config, generated from your chosen hotkey. For example:
57+
58+- Toggle mode: `bind = CTRL ALT, SPACE, exec, mutterbox --toggle`
59+- Hold (push to talk): `bind = CTRL ALT, SPACE, exec, mutterbox --start` plus
60+ `bindr = CTRL ALT, SPACE, exec, mutterbox --stop`
61+- Sway: `bindsym $mod+d exec mutterbox --toggle`
62+- KDE / GNOME: add a custom shortcut running `mutterbox --toggle`
63+
64+On X11, macOS, and Windows the in-app hotkey (default `Ctrl+Alt+Space`, set by
65+clicking the hotkey field and pressing keys) works directly, in both toggle and
66+hold mode.
67+
68+For text injection on Wayland, install `ydotool` and enable the `ydotoold`
69+service; mutterbox falls back to it automatically when synthetic input via
70+enigo is unavailable:
71+
72+```sh
73+sudo pacman -S ydotool
74+systemctl --user enable --now ydotool
75+```
76+
77+## Enhancement providers
78+
79+| Provider | Key variable | Notes |
80+| --- | --- | --- |
81+| Claude | `ANTHROPIC_API_KEY` | default model `claude-opus-4-8` |
82+| Gemini | `GEMINI_API_KEY` | |
83+| OpenAI-compatible | `OPENAI_API_KEY` | custom base URL supported (OpenRouter, vLLM, LM Studio, llama.cpp server) |
84+| Ollama | none | local, defaults to `http://localhost:11434/v1` |
85+
86+The instructions field is a system prompt, so enhancement can do more than
87+cleanup: summarize rambles, force bullet points, translate, match email tone.
88+
89+## Status
90+
91+Early scaffold. Working: recording, local transcription, model manager with
92+one-click downloads, LLM enhancement, paste/type injection, tray, overlay
93+indicator, settings persistence. Not yet: push-to-talk mode, history, GPU
94+inference feature flags (Vulkan/Metal/CUDA), packaged releases.
95+
96+## License
97+
98+MIT
+13-0index.html
@@ -0,0 +1,13 @@
1+<!doctype html>
2+<html lang="en">
3+ <head>
4+ <meta charset="UTF-8" />
5+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+ <title>mutterbox</title>
7+ </head>
8+
9+ <body>
10+ <div id="root"></div>
11+ <script type="module" src="/src/main.tsx"></script>
12+ </body>
13+</html>
+2156-0package-lock.json
@@ -0,0 +1,2156 @@
1+{
2+ "name": "tauri-app",
3+ "version": "0.1.0",
4+ "lockfileVersion": 3,
5+ "requires": true,
6+ "packages": {
7+ "": {
8+ "name": "tauri-app",
9+ "version": "0.1.0",
10+ "dependencies": {
11+ "@tauri-apps/api": "^2",
12+ "@tauri-apps/plugin-autostart": "^2.5.1",
13+ "@tauri-apps/plugin-clipboard-manager": "^2.3.2",
14+ "@tauri-apps/plugin-global-shortcut": "^2.3.2",
15+ "@tauri-apps/plugin-notification": "^2.3.3",
16+ "@tauri-apps/plugin-opener": "^2",
17+ "react": "^19.1.0",
18+ "react-dom": "^19.1.0"
19+ },
20+ "devDependencies": {
21+ "@tauri-apps/cli": "^2",
22+ "@types/react": "^19.1.8",
23+ "@types/react-dom": "^19.1.6",
24+ "@vitejs/plugin-react": "^4.6.0",
25+ "typescript": "~5.8.3",
26+ "vite": "^7.0.4"
27+ }
28+ },
29+ "node_modules/@babel/code-frame": {
30+ "version": "7.29.7",
31+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz",
32+ "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==",
33+ "dev": true,
34+ "license": "MIT",
35+ "dependencies": {
36+ "@babel/helper-validator-identifier": "^7.29.7",
37+ "js-tokens": "^4.0.0",
38+ "picocolors": "^1.1.1"
39+ },
40+ "engines": {
41+ "node": ">=6.9.0"
42+ }
43+ },
44+ "node_modules/@babel/compat-data": {
45+ "version": "7.29.7",
46+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz",
47+ "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==",
48+ "dev": true,
49+ "license": "MIT",
50+ "engines": {
51+ "node": ">=6.9.0"
52+ }
53+ },
54+ "node_modules/@babel/core": {
55+ "version": "7.29.7",
56+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz",
57+ "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==",
58+ "dev": true,
59+ "license": "MIT",
60+ "dependencies": {
61+ "@babel/code-frame": "^7.29.7",
62+ "@babel/generator": "^7.29.7",
63+ "@babel/helper-compilation-targets": "^7.29.7",
64+ "@babel/helper-module-transforms": "^7.29.7",
65+ "@babel/helpers": "^7.29.7",
66+ "@babel/parser": "^7.29.7",
67+ "@babel/template": "^7.29.7",
68+ "@babel/traverse": "^7.29.7",
69+ "@babel/types": "^7.29.7",
70+ "@jridgewell/remapping": "^2.3.5",
71+ "convert-source-map": "^2.0.0",
72+ "debug": "^4.1.0",
73+ "gensync": "^1.0.0-beta.2",
74+ "json5": "^2.2.3",
75+ "semver": "^6.3.1"
76+ },
77+ "engines": {
78+ "node": ">=6.9.0"
79+ },
80+ "funding": {
81+ "type": "opencollective",
82+ "url": "https://opencollective.com/babel"
83+ }
84+ },
85+ "node_modules/@babel/generator": {
86+ "version": "7.29.7",
87+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz",
88+ "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==",
89+ "dev": true,
90+ "license": "MIT",
91+ "dependencies": {
92+ "@babel/parser": "^7.29.7",
93+ "@babel/types": "^7.29.7",
94+ "@jridgewell/gen-mapping": "^0.3.12",
95+ "@jridgewell/trace-mapping": "^0.3.28",
96+ "jsesc": "^3.0.2"
97+ },
98+ "engines": {
99+ "node": ">=6.9.0"
100+ }
101+ },
102+ "node_modules/@babel/helper-compilation-targets": {
103+ "version": "7.29.7",
104+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz",
105+ "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==",
106+ "dev": true,
107+ "license": "MIT",
108+ "dependencies": {
109+ "@babel/compat-data": "^7.29.7",
110+ "@babel/helper-validator-option": "^7.29.7",
111+ "browserslist": "^4.24.0",
112+ "lru-cache": "^5.1.1",
113+ "semver": "^6.3.1"
114+ },
115+ "engines": {
116+ "node": ">=6.9.0"
117+ }
118+ },
119+ "node_modules/@babel/helper-globals": {
120+ "version": "7.29.7",
121+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz",
122+ "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==",
123+ "dev": true,
124+ "license": "MIT",
125+ "engines": {
126+ "node": ">=6.9.0"
127+ }
128+ },
129+ "node_modules/@babel/helper-module-imports": {
130+ "version": "7.29.7",
131+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz",
132+ "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==",
133+ "dev": true,
134+ "license": "MIT",
135+ "dependencies": {
136+ "@babel/traverse": "^7.29.7",
137+ "@babel/types": "^7.29.7"
138+ },
139+ "engines": {
140+ "node": ">=6.9.0"
141+ }
142+ },
143+ "node_modules/@babel/helper-module-transforms": {
144+ "version": "7.29.7",
145+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz",
146+ "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==",
147+ "dev": true,
148+ "license": "MIT",
149+ "dependencies": {
150+ "@babel/helper-module-imports": "^7.29.7",
151+ "@babel/helper-validator-identifier": "^7.29.7",
152+ "@babel/traverse": "^7.29.7"
153+ },
154+ "engines": {
155+ "node": ">=6.9.0"
156+ },
157+ "peerDependencies": {
158+ "@babel/core": "^7.0.0"
159+ }
160+ },
161+ "node_modules/@babel/helper-plugin-utils": {
162+ "version": "7.29.7",
163+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz",
164+ "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==",
165+ "dev": true,
166+ "license": "MIT",
167+ "engines": {
168+ "node": ">=6.9.0"
169+ }
170+ },
171+ "node_modules/@babel/helper-string-parser": {
172+ "version": "7.29.7",
173+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz",
174+ "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==",
175+ "dev": true,
176+ "license": "MIT",
177+ "engines": {
178+ "node": ">=6.9.0"
179+ }
180+ },
181+ "node_modules/@babel/helper-validator-identifier": {
182+ "version": "7.29.7",
183+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",
184+ "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==",
185+ "dev": true,
186+ "license": "MIT",
187+ "engines": {
188+ "node": ">=6.9.0"
189+ }
190+ },
191+ "node_modules/@babel/helper-validator-option": {
192+ "version": "7.29.7",
193+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz",
194+ "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==",
195+ "dev": true,
196+ "license": "MIT",
197+ "engines": {
198+ "node": ">=6.9.0"
199+ }
200+ },
201+ "node_modules/@babel/helpers": {
202+ "version": "7.29.7",
203+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz",
204+ "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==",
205+ "dev": true,
206+ "license": "MIT",
207+ "dependencies": {
208+ "@babel/template": "^7.29.7",
209+ "@babel/types": "^7.29.7"
210+ },
211+ "engines": {
212+ "node": ">=6.9.0"
213+ }
214+ },
215+ "node_modules/@babel/parser": {
216+ "version": "7.29.7",
217+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz",
218+ "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==",
219+ "dev": true,
220+ "license": "MIT",
221+ "dependencies": {
222+ "@babel/types": "^7.29.7"
223+ },
224+ "bin": {
225+ "parser": "bin/babel-parser.js"
226+ },
227+ "engines": {
228+ "node": ">=6.0.0"
229+ }
230+ },
231+ "node_modules/@babel/plugin-transform-react-jsx-self": {
232+ "version": "7.29.7",
233+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.29.7.tgz",
234+ "integrity": "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==",
235+ "dev": true,
236+ "license": "MIT",
237+ "dependencies": {
238+ "@babel/helper-plugin-utils": "^7.29.7"
239+ },
240+ "engines": {
241+ "node": ">=6.9.0"
242+ },
243+ "peerDependencies": {
244+ "@babel/core": "^7.0.0-0"
245+ }
246+ },
247+ "node_modules/@babel/plugin-transform-react-jsx-source": {
248+ "version": "7.29.7",
249+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.29.7.tgz",
250+ "integrity": "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==",
251+ "dev": true,
252+ "license": "MIT",
253+ "dependencies": {
254+ "@babel/helper-plugin-utils": "^7.29.7"
255+ },
256+ "engines": {
257+ "node": ">=6.9.0"
258+ },
259+ "peerDependencies": {
260+ "@babel/core": "^7.0.0-0"
261+ }
262+ },
263+ "node_modules/@babel/template": {
264+ "version": "7.29.7",
265+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz",
266+ "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==",
267+ "dev": true,
268+ "license": "MIT",
269+ "dependencies": {
270+ "@babel/code-frame": "^7.29.7",
271+ "@babel/parser": "^7.29.7",
272+ "@babel/types": "^7.29.7"
273+ },
274+ "engines": {
275+ "node": ">=6.9.0"
276+ }
277+ },
278+ "node_modules/@babel/traverse": {
279+ "version": "7.29.7",
280+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz",
281+ "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==",
282+ "dev": true,
283+ "license": "MIT",
284+ "dependencies": {
285+ "@babel/code-frame": "^7.29.7",
286+ "@babel/generator": "^7.29.7",
287+ "@babel/helper-globals": "^7.29.7",
288+ "@babel/parser": "^7.29.7",
289+ "@babel/template": "^7.29.7",
290+ "@babel/types": "^7.29.7",
291+ "debug": "^4.3.1"
292+ },
293+ "engines": {
294+ "node": ">=6.9.0"
295+ }
296+ },
297+ "node_modules/@babel/types": {
298+ "version": "7.29.7",
299+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz",
300+ "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==",
301+ "dev": true,
302+ "license": "MIT",
303+ "dependencies": {
304+ "@babel/helper-string-parser": "^7.29.7",
305+ "@babel/helper-validator-identifier": "^7.29.7"
306+ },
307+ "engines": {
308+ "node": ">=6.9.0"
309+ }
310+ },
311+ "node_modules/@esbuild/aix-ppc64": {
312+ "version": "0.28.1",
313+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz",
314+ "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==",
315+ "cpu": [
316+ "ppc64"
317+ ],
318+ "dev": true,
319+ "license": "MIT",
320+ "optional": true,
321+ "os": [
322+ "aix"
323+ ],
324+ "engines": {
325+ "node": ">=18"
326+ }
327+ },
328+ "node_modules/@esbuild/android-arm": {
329+ "version": "0.28.1",
330+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz",
331+ "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==",
332+ "cpu": [
333+ "arm"
334+ ],
335+ "dev": true,
336+ "license": "MIT",
337+ "optional": true,
338+ "os": [
339+ "android"
340+ ],
341+ "engines": {
342+ "node": ">=18"
343+ }
344+ },
345+ "node_modules/@esbuild/android-arm64": {
346+ "version": "0.28.1",
347+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz",
348+ "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==",
349+ "cpu": [
350+ "arm64"
351+ ],
352+ "dev": true,
353+ "license": "MIT",
354+ "optional": true,
355+ "os": [
356+ "android"
357+ ],
358+ "engines": {
359+ "node": ">=18"
360+ }
361+ },
362+ "node_modules/@esbuild/android-x64": {
363+ "version": "0.28.1",
364+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz",
365+ "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==",
366+ "cpu": [
367+ "x64"
368+ ],
369+ "dev": true,
370+ "license": "MIT",
371+ "optional": true,
372+ "os": [
373+ "android"
374+ ],
375+ "engines": {
376+ "node": ">=18"
377+ }
378+ },
379+ "node_modules/@esbuild/darwin-arm64": {
380+ "version": "0.28.1",
381+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz",
382+ "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==",
383+ "cpu": [
384+ "arm64"
385+ ],
386+ "dev": true,
387+ "license": "MIT",
388+ "optional": true,
389+ "os": [
390+ "darwin"
391+ ],
392+ "engines": {
393+ "node": ">=18"
394+ }
395+ },
396+ "node_modules/@esbuild/darwin-x64": {
397+ "version": "0.28.1",
398+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz",
399+ "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==",
400+ "cpu": [
401+ "x64"
402+ ],
403+ "dev": true,
404+ "license": "MIT",
405+ "optional": true,
406+ "os": [
407+ "darwin"
408+ ],
409+ "engines": {
410+ "node": ">=18"
411+ }
412+ },
413+ "node_modules/@esbuild/freebsd-arm64": {
414+ "version": "0.28.1",
415+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz",
416+ "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==",
417+ "cpu": [
418+ "arm64"
419+ ],
420+ "dev": true,
421+ "license": "MIT",
422+ "optional": true,
423+ "os": [
424+ "freebsd"
425+ ],
426+ "engines": {
427+ "node": ">=18"
428+ }
429+ },
430+ "node_modules/@esbuild/freebsd-x64": {
431+ "version": "0.28.1",
432+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz",
433+ "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==",
434+ "cpu": [
435+ "x64"
436+ ],
437+ "dev": true,
438+ "license": "MIT",
439+ "optional": true,
440+ "os": [
441+ "freebsd"
442+ ],
443+ "engines": {
444+ "node": ">=18"
445+ }
446+ },
447+ "node_modules/@esbuild/linux-arm": {
448+ "version": "0.28.1",
449+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz",
450+ "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==",
451+ "cpu": [
452+ "arm"
453+ ],
454+ "dev": true,
455+ "license": "MIT",
456+ "optional": true,
457+ "os": [
458+ "linux"
459+ ],
460+ "engines": {
461+ "node": ">=18"
462+ }
463+ },
464+ "node_modules/@esbuild/linux-arm64": {
465+ "version": "0.28.1",
466+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz",
467+ "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==",
468+ "cpu": [
469+ "arm64"
470+ ],
471+ "dev": true,
472+ "license": "MIT",
473+ "optional": true,
474+ "os": [
475+ "linux"
476+ ],
477+ "engines": {
478+ "node": ">=18"
479+ }
480+ },
481+ "node_modules/@esbuild/linux-ia32": {
482+ "version": "0.28.1",
483+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz",
484+ "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==",
485+ "cpu": [
486+ "ia32"
487+ ],
488+ "dev": true,
489+ "license": "MIT",
490+ "optional": true,
491+ "os": [
492+ "linux"
493+ ],
494+ "engines": {
495+ "node": ">=18"
496+ }
497+ },
498+ "node_modules/@esbuild/linux-loong64": {
499+ "version": "0.28.1",
500+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz",
501+ "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==",
502+ "cpu": [
503+ "loong64"
504+ ],
505+ "dev": true,
506+ "license": "MIT",
507+ "optional": true,
508+ "os": [
509+ "linux"
510+ ],
511+ "engines": {
512+ "node": ">=18"
513+ }
514+ },
515+ "node_modules/@esbuild/linux-mips64el": {
516+ "version": "0.28.1",
517+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz",
518+ "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==",
519+ "cpu": [
520+ "mips64el"
521+ ],
522+ "dev": true,
523+ "license": "MIT",
524+ "optional": true,
525+ "os": [
526+ "linux"
527+ ],
528+ "engines": {
529+ "node": ">=18"
530+ }
531+ },
532+ "node_modules/@esbuild/linux-ppc64": {
533+ "version": "0.28.1",
534+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz",
535+ "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==",
536+ "cpu": [
537+ "ppc64"
538+ ],
539+ "dev": true,
540+ "license": "MIT",
541+ "optional": true,
542+ "os": [
543+ "linux"
544+ ],
545+ "engines": {
546+ "node": ">=18"
547+ }
548+ },
549+ "node_modules/@esbuild/linux-riscv64": {
550+ "version": "0.28.1",
551+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz",
552+ "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==",
553+ "cpu": [
554+ "riscv64"
555+ ],
556+ "dev": true,
557+ "license": "MIT",
558+ "optional": true,
559+ "os": [
560+ "linux"
561+ ],
562+ "engines": {
563+ "node": ">=18"
564+ }
565+ },
566+ "node_modules/@esbuild/linux-s390x": {
567+ "version": "0.28.1",
568+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz",
569+ "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==",
570+ "cpu": [
571+ "s390x"
572+ ],
573+ "dev": true,
574+ "license": "MIT",
575+ "optional": true,
576+ "os": [
577+ "linux"
578+ ],
579+ "engines": {
580+ "node": ">=18"
581+ }
582+ },
583+ "node_modules/@esbuild/linux-x64": {
584+ "version": "0.28.1",
585+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz",
586+ "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==",
587+ "cpu": [
588+ "x64"
589+ ],
590+ "dev": true,
591+ "license": "MIT",
592+ "optional": true,
593+ "os": [
594+ "linux"
595+ ],
596+ "engines": {
597+ "node": ">=18"
598+ }
599+ },
600+ "node_modules/@esbuild/netbsd-arm64": {
601+ "version": "0.28.1",
602+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz",
603+ "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==",
604+ "cpu": [
605+ "arm64"
606+ ],
607+ "dev": true,
608+ "license": "MIT",
609+ "optional": true,
610+ "os": [
611+ "netbsd"
612+ ],
613+ "engines": {
614+ "node": ">=18"
615+ }
616+ },
617+ "node_modules/@esbuild/netbsd-x64": {
618+ "version": "0.28.1",
619+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz",
620+ "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==",
621+ "cpu": [
622+ "x64"
623+ ],
624+ "dev": true,
625+ "license": "MIT",
626+ "optional": true,
627+ "os": [
628+ "netbsd"
629+ ],
630+ "engines": {
631+ "node": ">=18"
632+ }
633+ },
634+ "node_modules/@esbuild/openbsd-arm64": {
635+ "version": "0.28.1",
636+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz",
637+ "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==",
638+ "cpu": [
639+ "arm64"
640+ ],
641+ "dev": true,
642+ "license": "MIT",
643+ "optional": true,
644+ "os": [
645+ "openbsd"
646+ ],
647+ "engines": {
648+ "node": ">=18"
649+ }
650+ },
651+ "node_modules/@esbuild/openbsd-x64": {
652+ "version": "0.28.1",
653+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz",
654+ "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==",
655+ "cpu": [
656+ "x64"
657+ ],
658+ "dev": true,
659+ "license": "MIT",
660+ "optional": true,
661+ "os": [
662+ "openbsd"
663+ ],
664+ "engines": {
665+ "node": ">=18"
666+ }
667+ },
668+ "node_modules/@esbuild/openharmony-arm64": {
669+ "version": "0.28.1",
670+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz",
671+ "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==",
672+ "cpu": [
673+ "arm64"
674+ ],
675+ "dev": true,
676+ "license": "MIT",
677+ "optional": true,
678+ "os": [
679+ "openharmony"
680+ ],
681+ "engines": {
682+ "node": ">=18"
683+ }
684+ },
685+ "node_modules/@esbuild/sunos-x64": {
686+ "version": "0.28.1",
687+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz",
688+ "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==",
689+ "cpu": [
690+ "x64"
691+ ],
692+ "dev": true,
693+ "license": "MIT",
694+ "optional": true,
695+ "os": [
696+ "sunos"
697+ ],
698+ "engines": {
699+ "node": ">=18"
700+ }
701+ },
702+ "node_modules/@esbuild/win32-arm64": {
703+ "version": "0.28.1",
704+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz",
705+ "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==",
706+ "cpu": [
707+ "arm64"
708+ ],
709+ "dev": true,
710+ "license": "MIT",
711+ "optional": true,
712+ "os": [
713+ "win32"
714+ ],
715+ "engines": {
716+ "node": ">=18"
717+ }
718+ },
719+ "node_modules/@esbuild/win32-ia32": {
720+ "version": "0.28.1",
721+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz",
722+ "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==",
723+ "cpu": [
724+ "ia32"
725+ ],
726+ "dev": true,
727+ "license": "MIT",
728+ "optional": true,
729+ "os": [
730+ "win32"
731+ ],
732+ "engines": {
733+ "node": ">=18"
734+ }
735+ },
736+ "node_modules/@esbuild/win32-x64": {
737+ "version": "0.28.1",
738+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz",
739+ "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==",
740+ "cpu": [
741+ "x64"
742+ ],
743+ "dev": true,
744+ "license": "MIT",
745+ "optional": true,
746+ "os": [
747+ "win32"
748+ ],
749+ "engines": {
750+ "node": ">=18"
751+ }
752+ },
753+ "node_modules/@jridgewell/gen-mapping": {
754+ "version": "0.3.13",
755+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
756+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
757+ "dev": true,
758+ "license": "MIT",
759+ "dependencies": {
760+ "@jridgewell/sourcemap-codec": "^1.5.0",
761+ "@jridgewell/trace-mapping": "^0.3.24"
762+ }
763+ },
764+ "node_modules/@jridgewell/remapping": {
765+ "version": "2.3.5",
766+ "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
767+ "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
768+ "dev": true,
769+ "license": "MIT",
770+ "dependencies": {
771+ "@jridgewell/gen-mapping": "^0.3.5",
772+ "@jridgewell/trace-mapping": "^0.3.24"
773+ }
774+ },
775+ "node_modules/@jridgewell/resolve-uri": {
776+ "version": "3.1.2",
777+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
778+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
779+ "dev": true,
780+ "license": "MIT",
781+ "engines": {
782+ "node": ">=6.0.0"
783+ }
784+ },
785+ "node_modules/@jridgewell/sourcemap-codec": {
786+ "version": "1.5.5",
787+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
788+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
789+ "dev": true,
790+ "license": "MIT"
791+ },
792+ "node_modules/@jridgewell/trace-mapping": {
793+ "version": "0.3.31",
794+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
795+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
796+ "dev": true,
797+ "license": "MIT",
798+ "dependencies": {
799+ "@jridgewell/resolve-uri": "^3.1.0",
800+ "@jridgewell/sourcemap-codec": "^1.4.14"
801+ }
802+ },
803+ "node_modules/@rolldown/pluginutils": {
804+ "version": "1.0.0-beta.27",
805+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz",
806+ "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==",
807+ "dev": true,
808+ "license": "MIT"
809+ },
810+ "node_modules/@rollup/rollup-android-arm-eabi": {
811+ "version": "4.62.2",
812+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.2.tgz",
813+ "integrity": "sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==",
814+ "cpu": [
815+ "arm"
816+ ],
817+ "dev": true,
818+ "license": "MIT",
819+ "optional": true,
820+ "os": [
821+ "android"
822+ ]
823+ },
824+ "node_modules/@rollup/rollup-android-arm64": {
825+ "version": "4.62.2",
826+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.2.tgz",
827+ "integrity": "sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==",
828+ "cpu": [
829+ "arm64"
830+ ],
831+ "dev": true,
832+ "license": "MIT",
833+ "optional": true,
834+ "os": [
835+ "android"
836+ ]
837+ },
838+ "node_modules/@rollup/rollup-darwin-arm64": {
839+ "version": "4.62.2",
840+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.2.tgz",
841+ "integrity": "sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==",
842+ "cpu": [
843+ "arm64"
844+ ],
845+ "dev": true,
846+ "license": "MIT",
847+ "optional": true,
848+ "os": [
849+ "darwin"
850+ ]
851+ },
852+ "node_modules/@rollup/rollup-darwin-x64": {
853+ "version": "4.62.2",
854+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.2.tgz",
855+ "integrity": "sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==",
856+ "cpu": [
857+ "x64"
858+ ],
859+ "dev": true,
860+ "license": "MIT",
861+ "optional": true,
862+ "os": [
863+ "darwin"
864+ ]
865+ },
866+ "node_modules/@rollup/rollup-freebsd-arm64": {
867+ "version": "4.62.2",
868+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.2.tgz",
869+ "integrity": "sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==",
870+ "cpu": [
871+ "arm64"
872+ ],
873+ "dev": true,
874+ "license": "MIT",
875+ "optional": true,
876+ "os": [
877+ "freebsd"
878+ ]
879+ },
880+ "node_modules/@rollup/rollup-freebsd-x64": {
881+ "version": "4.62.2",
882+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.2.tgz",
883+ "integrity": "sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==",
884+ "cpu": [
885+ "x64"
886+ ],
887+ "dev": true,
888+ "license": "MIT",
889+ "optional": true,
890+ "os": [
891+ "freebsd"
892+ ]
893+ },
894+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
895+ "version": "4.62.2",
896+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.2.tgz",
897+ "integrity": "sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==",
898+ "cpu": [
899+ "arm"
900+ ],
901+ "dev": true,
902+ "libc": [
903+ "glibc"
904+ ],
905+ "license": "MIT",
906+ "optional": true,
907+ "os": [
908+ "linux"
909+ ]
910+ },
911+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
912+ "version": "4.62.2",
913+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.2.tgz",
914+ "integrity": "sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==",
915+ "cpu": [
916+ "arm"
917+ ],
918+ "dev": true,
919+ "libc": [
920+ "musl"
921+ ],
922+ "license": "MIT",
923+ "optional": true,
924+ "os": [
925+ "linux"
926+ ]
927+ },
928+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
929+ "version": "4.62.2",
930+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.2.tgz",
931+ "integrity": "sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==",
932+ "cpu": [
933+ "arm64"
934+ ],
935+ "dev": true,
936+ "libc": [
937+ "glibc"
938+ ],
939+ "license": "MIT",
940+ "optional": true,
941+ "os": [
942+ "linux"
943+ ]
944+ },
945+ "node_modules/@rollup/rollup-linux-arm64-musl": {
946+ "version": "4.62.2",
947+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.2.tgz",
948+ "integrity": "sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==",
949+ "cpu": [
950+ "arm64"
951+ ],
952+ "dev": true,
953+ "libc": [
954+ "musl"
955+ ],
956+ "license": "MIT",
957+ "optional": true,
958+ "os": [
959+ "linux"
960+ ]
961+ },
962+ "node_modules/@rollup/rollup-linux-loong64-gnu": {
963+ "version": "4.62.2",
964+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.2.tgz",
965+ "integrity": "sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==",
966+ "cpu": [
967+ "loong64"
968+ ],
969+ "dev": true,
970+ "libc": [
971+ "glibc"
972+ ],
973+ "license": "MIT",
974+ "optional": true,
975+ "os": [
976+ "linux"
977+ ]
978+ },
979+ "node_modules/@rollup/rollup-linux-loong64-musl": {
980+ "version": "4.62.2",
981+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.2.tgz",
982+ "integrity": "sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==",
983+ "cpu": [
984+ "loong64"
985+ ],
986+ "dev": true,
987+ "libc": [
988+ "musl"
989+ ],
990+ "license": "MIT",
991+ "optional": true,
992+ "os": [
993+ "linux"
994+ ]
995+ },
996+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {
997+ "version": "4.62.2",
998+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.2.tgz",
999+ "integrity": "sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==",
1000+ "cpu": [
1001+ "ppc64"
1002+ ],
1003+ "dev": true,
1004+ "libc": [
1005+ "glibc"
1006+ ],
1007+ "license": "MIT",
1008+ "optional": true,
1009+ "os": [
1010+ "linux"
1011+ ]
1012+ },
1013+ "node_modules/@rollup/rollup-linux-ppc64-musl": {
1014+ "version": "4.62.2",
1015+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.2.tgz",
1016+ "integrity": "sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==",
1017+ "cpu": [
1018+ "ppc64"
1019+ ],
1020+ "dev": true,
1021+ "libc": [
1022+ "musl"
1023+ ],
1024+ "license": "MIT",
1025+ "optional": true,
1026+ "os": [
1027+ "linux"
1028+ ]
1029+ },
1030+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
1031+ "version": "4.62.2",
1032+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.2.tgz",
1033+ "integrity": "sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==",
1034+ "cpu": [
1035+ "riscv64"
1036+ ],
1037+ "dev": true,
1038+ "libc": [
1039+ "glibc"
1040+ ],
1041+ "license": "MIT",
1042+ "optional": true,
1043+ "os": [
1044+ "linux"
1045+ ]
1046+ },
1047+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
1048+ "version": "4.62.2",
1049+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.2.tgz",
1050+ "integrity": "sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==",
1051+ "cpu": [
1052+ "riscv64"
1053+ ],
1054+ "dev": true,
1055+ "libc": [
1056+ "musl"
1057+ ],
1058+ "license": "MIT",
1059+ "optional": true,
1060+ "os": [
1061+ "linux"
1062+ ]
1063+ },
1064+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
1065+ "version": "4.62.2",
1066+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.2.tgz",
1067+ "integrity": "sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==",
1068+ "cpu": [
1069+ "s390x"
1070+ ],
1071+ "dev": true,
1072+ "libc": [
1073+ "glibc"
1074+ ],
1075+ "license": "MIT",
1076+ "optional": true,
1077+ "os": [
1078+ "linux"
1079+ ]
1080+ },
1081+ "node_modules/@rollup/rollup-linux-x64-gnu": {
1082+ "version": "4.62.2",
1083+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.2.tgz",
1084+ "integrity": "sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==",
1085+ "cpu": [
1086+ "x64"
1087+ ],
1088+ "dev": true,
1089+ "libc": [
1090+ "glibc"
1091+ ],
1092+ "license": "MIT",
1093+ "optional": true,
1094+ "os": [
1095+ "linux"
1096+ ]
1097+ },
1098+ "node_modules/@rollup/rollup-linux-x64-musl": {
1099+ "version": "4.62.2",
1100+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.2.tgz",
1101+ "integrity": "sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==",
1102+ "cpu": [
1103+ "x64"
1104+ ],
1105+ "dev": true,
1106+ "libc": [
1107+ "musl"
1108+ ],
1109+ "license": "MIT",
1110+ "optional": true,
1111+ "os": [
1112+ "linux"
1113+ ]
1114+ },
1115+ "node_modules/@rollup/rollup-openbsd-x64": {
1116+ "version": "4.62.2",
1117+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.2.tgz",
1118+ "integrity": "sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==",
1119+ "cpu": [
1120+ "x64"
1121+ ],
1122+ "dev": true,
1123+ "license": "MIT",
1124+ "optional": true,
1125+ "os": [
1126+ "openbsd"
1127+ ]
1128+ },
1129+ "node_modules/@rollup/rollup-openharmony-arm64": {
1130+ "version": "4.62.2",
1131+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.2.tgz",
1132+ "integrity": "sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==",
1133+ "cpu": [
1134+ "arm64"
1135+ ],
1136+ "dev": true,
1137+ "license": "MIT",
1138+ "optional": true,
1139+ "os": [
1140+ "openharmony"
1141+ ]
1142+ },
1143+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
1144+ "version": "4.62.2",
1145+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.2.tgz",
1146+ "integrity": "sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==",
1147+ "cpu": [
1148+ "arm64"
1149+ ],
1150+ "dev": true,
1151+ "license": "MIT",
1152+ "optional": true,
1153+ "os": [
1154+ "win32"
1155+ ]
1156+ },
1157+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
1158+ "version": "4.62.2",
1159+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.2.tgz",
1160+ "integrity": "sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==",
1161+ "cpu": [
1162+ "ia32"
1163+ ],
1164+ "dev": true,
1165+ "license": "MIT",
1166+ "optional": true,
1167+ "os": [
1168+ "win32"
1169+ ]
1170+ },
1171+ "node_modules/@rollup/rollup-win32-x64-gnu": {
1172+ "version": "4.62.2",
1173+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.2.tgz",
1174+ "integrity": "sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==",
1175+ "cpu": [
1176+ "x64"
1177+ ],
1178+ "dev": true,
1179+ "license": "MIT",
1180+ "optional": true,
1181+ "os": [
1182+ "win32"
1183+ ]
1184+ },
1185+ "node_modules/@rollup/rollup-win32-x64-msvc": {
1186+ "version": "4.62.2",
1187+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.2.tgz",
1188+ "integrity": "sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==",
1189+ "cpu": [
1190+ "x64"
1191+ ],
1192+ "dev": true,
1193+ "license": "MIT",
1194+ "optional": true,
1195+ "os": [
1196+ "win32"
1197+ ]
1198+ },
1199+ "node_modules/@tauri-apps/api": {
1200+ "version": "2.11.1",
1201+ "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.11.1.tgz",
1202+ "integrity": "sha512-M2FPuYND2m+wh5hfW9ZpSdxMPdEJovPBWwoHJmwUpysTYNHaOkVFN419m/K0LIgjb/7KU2vBgsUepJWugQCvAA==",
1203+ "license": "Apache-2.0 OR MIT",
1204+ "funding": {
1205+ "type": "opencollective",
1206+ "url": "https://opencollective.com/tauri"
1207+ }
1208+ },
1209+ "node_modules/@tauri-apps/cli": {
1210+ "version": "2.11.4",
1211+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.11.4.tgz",
1212+ "integrity": "sha512-R8xGtMpwyetawSqm9kYOuMmEqkhUbvcUy8n0aNXIxollKBLESUu5f4Fx+64hgASYm1H+jSWq6jCW6zqTnH6hqQ==",
1213+ "dev": true,
1214+ "license": "Apache-2.0 OR MIT",
1215+ "bin": {
1216+ "tauri": "tauri.js"
1217+ },
1218+ "engines": {
1219+ "node": ">= 10"
1220+ },
1221+ "funding": {
1222+ "type": "opencollective",
1223+ "url": "https://opencollective.com/tauri"
1224+ },
1225+ "optionalDependencies": {
1226+ "@tauri-apps/cli-darwin-arm64": "2.11.4",
1227+ "@tauri-apps/cli-darwin-x64": "2.11.4",
1228+ "@tauri-apps/cli-linux-arm-gnueabihf": "2.11.4",
1229+ "@tauri-apps/cli-linux-arm64-gnu": "2.11.4",
1230+ "@tauri-apps/cli-linux-arm64-musl": "2.11.4",
1231+ "@tauri-apps/cli-linux-riscv64-gnu": "2.11.4",
1232+ "@tauri-apps/cli-linux-x64-gnu": "2.11.4",
1233+ "@tauri-apps/cli-linux-x64-musl": "2.11.4",
1234+ "@tauri-apps/cli-win32-arm64-msvc": "2.11.4",
1235+ "@tauri-apps/cli-win32-ia32-msvc": "2.11.4",
1236+ "@tauri-apps/cli-win32-x64-msvc": "2.11.4"
1237+ }
1238+ },
1239+ "node_modules/@tauri-apps/cli-darwin-arm64": {
1240+ "version": "2.11.4",
1241+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.11.4.tgz",
1242+ "integrity": "sha512-1ryOF3ZhpZ/nemHV5zVwBQBz9jDGKmKPvWPADOhc83ig0P4bMc2iER4NbC6r9sjeIZ6RVQ4g3RZIYvezhcl4TQ==",
1243+ "cpu": [
1244+ "arm64"
1245+ ],
1246+ "dev": true,
1247+ "license": "Apache-2.0 OR MIT",
1248+ "optional": true,
1249+ "os": [
1250+ "darwin"
1251+ ],
1252+ "engines": {
1253+ "node": ">= 10"
1254+ }
1255+ },
1256+ "node_modules/@tauri-apps/cli-darwin-x64": {
1257+ "version": "2.11.4",
1258+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.11.4.tgz",
1259+ "integrity": "sha512-uFsGQAAfuyz1k/yGLmkWfkBlgKAqZfxqlHmLWx81QU27RJWfmbNHCIq8T8w1e+VClleIuZUjpHWfoE4E3DLo3A==",
1260+ "cpu": [
1261+ "x64"
1262+ ],
1263+ "dev": true,
1264+ "license": "Apache-2.0 OR MIT",
1265+ "optional": true,
1266+ "os": [
1267+ "darwin"
1268+ ],
1269+ "engines": {
1270+ "node": ">= 10"
1271+ }
1272+ },
1273+ "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": {
1274+ "version": "2.11.4",
1275+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.11.4.tgz",
1276+ "integrity": "sha512-IaHZn5CdBL21oUmjiVOS1ctw6Ip1O0pjp70FwOWmYz1myWe0SY96ZIj2FYf7pT0m8bI2h/hrs5ZbEXXh44/MkQ==",
1277+ "cpu": [
1278+ "arm"
1279+ ],
1280+ "dev": true,
1281+ "license": "Apache-2.0 OR MIT",
1282+ "optional": true,
1283+ "os": [
1284+ "linux"
1285+ ],
1286+ "engines": {
1287+ "node": ">= 10"
1288+ }
1289+ },
1290+ "node_modules/@tauri-apps/cli-linux-arm64-gnu": {
1291+ "version": "2.11.4",
1292+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.11.4.tgz",
1293+ "integrity": "sha512-N41/ukTRVe6XSuUTESuFdGeOW2i7k62tK+6gHK5Kd5/q5RPvvi19GaWAVPPb9u95HSGmTChSolBfzynUsssFaA==",
1294+ "cpu": [
1295+ "arm64"
1296+ ],
1297+ "dev": true,
1298+ "libc": [
1299+ "glibc"
1300+ ],
1301+ "license": "Apache-2.0 OR MIT",
1302+ "optional": true,
1303+ "os": [
1304+ "linux"
1305+ ],
1306+ "engines": {
1307+ "node": ">= 10"
1308+ }
1309+ },
1310+ "node_modules/@tauri-apps/cli-linux-arm64-musl": {
1311+ "version": "2.11.4",
1312+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.11.4.tgz",
1313+ "integrity": "sha512-v277UnT/fB64xAfSroL5N3Km3tLmvATWqJJw/wRI+g6o+HkeD0slyE7gOhNs1MbjE41R7bQOTxMVoL3aomUJmw==",
1314+ "cpu": [
1315+ "arm64"
1316+ ],
1317+ "dev": true,
1318+ "libc": [
1319+ "musl"
1320+ ],
1321+ "license": "Apache-2.0 OR MIT",
1322+ "optional": true,
1323+ "os": [
1324+ "linux"
1325+ ],
1326+ "engines": {
1327+ "node": ">= 10"
1328+ }
1329+ },
1330+ "node_modules/@tauri-apps/cli-linux-riscv64-gnu": {
1331+ "version": "2.11.4",
1332+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-riscv64-gnu/-/cli-linux-riscv64-gnu-2.11.4.tgz",
1333+ "integrity": "sha512-qqgNkQ2u1yZHxjhxsZaxUtRDW8dIqIYm33rx/mzwQv0SfY9x1B+iraj8vWeFiXjjSVVhEMepXSOts1TqPzvXNQ==",
1334+ "cpu": [
1335+ "riscv64"
1336+ ],
1337+ "dev": true,
1338+ "libc": [
1339+ "glibc"
1340+ ],
1341+ "license": "Apache-2.0 OR MIT",
1342+ "optional": true,
1343+ "os": [
1344+ "linux"
1345+ ],
1346+ "engines": {
1347+ "node": ">= 10"
1348+ }
1349+ },
1350+ "node_modules/@tauri-apps/cli-linux-x64-gnu": {
1351+ "version": "2.11.4",
1352+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.11.4.tgz",
1353+ "integrity": "sha512-2VRNWl84FOH0m2giiDkO2h0QXlcMJeX+zJDpI5kDIQAx6s+geF3v48F4DXfJez4GS/FdoDGnPnw1C2iYGbQ7bQ==",
1354+ "cpu": [
1355+ "x64"
1356+ ],
1357+ "dev": true,
1358+ "libc": [
1359+ "glibc"
1360+ ],
1361+ "license": "Apache-2.0 OR MIT",
1362+ "optional": true,
1363+ "os": [
1364+ "linux"
1365+ ],
1366+ "engines": {
1367+ "node": ">= 10"
1368+ }
1369+ },
1370+ "node_modules/@tauri-apps/cli-linux-x64-musl": {
1371+ "version": "2.11.4",
1372+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.11.4.tgz",
1373+ "integrity": "sha512-o9GyhYor/nc7xarmwDE3ka2szuW3uuZzXjHWh64Q8YX5AtSgxdQkFWzrY4O8KiGtVNvFBI14H3Q49Qj5TOIP/A==",
1374+ "cpu": [
1375+ "x64"
1376+ ],
1377+ "dev": true,
1378+ "libc": [
1379+ "musl"
1380+ ],
1381+ "license": "Apache-2.0 OR MIT",
1382+ "optional": true,
1383+ "os": [
1384+ "linux"
1385+ ],
1386+ "engines": {
1387+ "node": ">= 10"
1388+ }
1389+ },
1390+ "node_modules/@tauri-apps/cli-win32-arm64-msvc": {
1391+ "version": "2.11.4",
1392+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.11.4.tgz",
1393+ "integrity": "sha512-ld5Ehb598m0VkYyylRPNeCFsBe/km0jxis6KgMpl3IGY6I/i1RwQXO05I1AsXUXO2WC6AvB/Lw4qTf/asiuEiQ==",
1394+ "cpu": [
1395+ "arm64"
1396+ ],
1397+ "dev": true,
1398+ "license": "Apache-2.0 OR MIT",
1399+ "optional": true,
1400+ "os": [
1401+ "win32"
1402+ ],
1403+ "engines": {
1404+ "node": ">= 10"
1405+ }
1406+ },
1407+ "node_modules/@tauri-apps/cli-win32-ia32-msvc": {
1408+ "version": "2.11.4",
1409+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.11.4.tgz",
1410+ "integrity": "sha512-12Hxi0XX/H5VFxO/bGgHkFWhml9VMgEOu9CidjeCeTNQ1l6fpUlbiGgSP7CLI3PFtW9/FfbeHieZ+kyWK5H7CA==",
1411+ "cpu": [
1412+ "ia32"
1413+ ],
1414+ "dev": true,
1415+ "license": "Apache-2.0 OR MIT",
1416+ "optional": true,
1417+ "os": [
1418+ "win32"
1419+ ],
1420+ "engines": {
1421+ "node": ">= 10"
1422+ }
1423+ },
1424+ "node_modules/@tauri-apps/cli-win32-x64-msvc": {
1425+ "version": "2.11.4",
1426+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.11.4.tgz",
1427+ "integrity": "sha512-+vDiqBIU5dMISg/wNvX3sF+ZHfgJGJ5T0AcO+EHNXV9GGAG+P5fzodlDXD3QdKCRgZxMoCm5PPvj3BqLNjBthw==",
1428+ "cpu": [
1429+ "x64"
1430+ ],
1431+ "dev": true,
1432+ "license": "Apache-2.0 OR MIT",
1433+ "optional": true,
1434+ "os": [
1435+ "win32"
1436+ ],
1437+ "engines": {
1438+ "node": ">= 10"
1439+ }
1440+ },
1441+ "node_modules/@tauri-apps/plugin-autostart": {
1442+ "version": "2.5.1",
1443+ "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-autostart/-/plugin-autostart-2.5.1.tgz",
1444+ "integrity": "sha512-zS/xx7yzveCcotkA+8TqkI2lysmG2wvQXv2HGAVExITmnFfHAdj1arGsbbfs3o6EktRHf6l34pJxc3YGG2mg7w==",
1445+ "license": "MIT OR Apache-2.0",
1446+ "dependencies": {
1447+ "@tauri-apps/api": "^2.8.0"
1448+ }
1449+ },
1450+ "node_modules/@tauri-apps/plugin-clipboard-manager": {
1451+ "version": "2.3.2",
1452+ "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-clipboard-manager/-/plugin-clipboard-manager-2.3.2.tgz",
1453+ "integrity": "sha512-CUlb5Hqi2oZbcZf4VUyUH53XWPPdtpw43EUpCza5HWZJwxEoDowFzNUDt1tRUXA8Uq+XPn17Ysfptip33sG4eQ==",
1454+ "license": "MIT OR Apache-2.0",
1455+ "dependencies": {
1456+ "@tauri-apps/api": "^2.8.0"
1457+ }
1458+ },
1459+ "node_modules/@tauri-apps/plugin-global-shortcut": {
1460+ "version": "2.3.2",
1461+ "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-global-shortcut/-/plugin-global-shortcut-2.3.2.tgz",
1462+ "integrity": "sha512-UReHNXrLvpEjylE4jb4oCYiy96uRykPUthoCQCmRXYrd5hs5X9DrW+qOn7GLW57EJN4tdK8bgK5twBTz2NOxzA==",
1463+ "license": "MIT OR Apache-2.0",
1464+ "dependencies": {
1465+ "@tauri-apps/api": "^2.11.0"
1466+ }
1467+ },
1468+ "node_modules/@tauri-apps/plugin-notification": {
1469+ "version": "2.3.3",
1470+ "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-notification/-/plugin-notification-2.3.3.tgz",
1471+ "integrity": "sha512-Zw+ZH18RJb41G4NrfHgIuofJiymusqN+q8fGUIIV7vyCH+5sSn5coqRv/MWB9qETsUs97vmU045q7OyseCV3Qg==",
1472+ "license": "MIT OR Apache-2.0",
1473+ "dependencies": {
1474+ "@tauri-apps/api": "^2.8.0"
1475+ }
1476+ },
1477+ "node_modules/@tauri-apps/plugin-opener": {
1478+ "version": "2.5.4",
1479+ "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-opener/-/plugin-opener-2.5.4.tgz",
1480+ "integrity": "sha512-1HnPkb+AmgO29HBazm4uPLKB+r7zzcTBW1d0fyYp1uP+jwtpoiNDGKMMzz58SFp49nOIrxdE3aUJtT57lfO9CQ==",
1481+ "license": "MIT OR Apache-2.0",
1482+ "dependencies": {
1483+ "@tauri-apps/api": "^2.11.0"
1484+ }
1485+ },
1486+ "node_modules/@types/babel__core": {
1487+ "version": "7.20.5",
1488+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
1489+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
1490+ "dev": true,
1491+ "license": "MIT",
1492+ "dependencies": {
1493+ "@babel/parser": "^7.20.7",
1494+ "@babel/types": "^7.20.7",
1495+ "@types/babel__generator": "*",
1496+ "@types/babel__template": "*",
1497+ "@types/babel__traverse": "*"
1498+ }
1499+ },
1500+ "node_modules/@types/babel__generator": {
1501+ "version": "7.27.0",
1502+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
1503+ "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
1504+ "dev": true,
1505+ "license": "MIT",
1506+ "dependencies": {
1507+ "@babel/types": "^7.0.0"
1508+ }
1509+ },
1510+ "node_modules/@types/babel__template": {
1511+ "version": "7.4.4",
1512+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
1513+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
1514+ "dev": true,
1515+ "license": "MIT",
1516+ "dependencies": {
1517+ "@babel/parser": "^7.1.0",
1518+ "@babel/types": "^7.0.0"
1519+ }
1520+ },
1521+ "node_modules/@types/babel__traverse": {
1522+ "version": "7.28.0",
1523+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
1524+ "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
1525+ "dev": true,
1526+ "license": "MIT",
1527+ "dependencies": {
1528+ "@babel/types": "^7.28.2"
1529+ }
1530+ },
1531+ "node_modules/@types/estree": {
1532+ "version": "1.0.9",
1533+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
1534+ "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",
1535+ "dev": true,
1536+ "license": "MIT"
1537+ },
1538+ "node_modules/@types/react": {
1539+ "version": "19.2.17",
1540+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz",
1541+ "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==",
1542+ "dev": true,
1543+ "license": "MIT",
1544+ "dependencies": {
1545+ "csstype": "^3.2.2"
1546+ }
1547+ },
1548+ "node_modules/@types/react-dom": {
1549+ "version": "19.2.3",
1550+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
1551+ "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
1552+ "dev": true,
1553+ "license": "MIT",
1554+ "peerDependencies": {
1555+ "@types/react": "^19.2.0"
1556+ }
1557+ },
1558+ "node_modules/@vitejs/plugin-react": {
1559+ "version": "4.7.0",
1560+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz",
1561+ "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==",
1562+ "dev": true,
1563+ "license": "MIT",
1564+ "dependencies": {
1565+ "@babel/core": "^7.28.0",
1566+ "@babel/plugin-transform-react-jsx-self": "^7.27.1",
1567+ "@babel/plugin-transform-react-jsx-source": "^7.27.1",
1568+ "@rolldown/pluginutils": "1.0.0-beta.27",
1569+ "@types/babel__core": "^7.20.5",
1570+ "react-refresh": "^0.17.0"
1571+ },
1572+ "engines": {
1573+ "node": "^14.18.0 || >=16.0.0"
1574+ },
1575+ "peerDependencies": {
1576+ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
1577+ }
1578+ },
1579+ "node_modules/baseline-browser-mapping": {
1580+ "version": "2.11.1",
1581+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.1.tgz",
1582+ "integrity": "sha512-HYXq73DDpCtNzOmrFsm9eSwCvWCql0RzqjpDzXN9EadiLJ4DNat0nsZ/Bzmy+Ud12mb4/zKDY0cQ805ZzN+i0A==",
1583+ "dev": true,
1584+ "license": "Apache-2.0",
1585+ "bin": {
1586+ "baseline-browser-mapping": "dist/cli.cjs"
1587+ },
1588+ "engines": {
1589+ "node": ">=6.0.0"
1590+ }
1591+ },
1592+ "node_modules/browserslist": {
1593+ "version": "4.28.7",
1594+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.7.tgz",
1595+ "integrity": "sha512-JxV13hNrFxqjOc8alRbq9dK1MM79NEXYpma2B2J4wAtpWS5zIEIKqWPGCl7N4o7Uc7B7itylh7SuDujATRyyTw==",
1596+ "dev": true,
1597+ "funding": [
1598+ {
1599+ "type": "opencollective",
1600+ "url": "https://opencollective.com/browserslist"
1601+ },
1602+ {
1603+ "type": "tidelift",
1604+ "url": "https://tidelift.com/funding/github/npm/browserslist"
1605+ },
1606+ {
1607+ "type": "github",
1608+ "url": "https://github.com/sponsors/ai"
1609+ }
1610+ ],
1611+ "license": "MIT",
1612+ "dependencies": {
1613+ "baseline-browser-mapping": "^2.10.44",
1614+ "caniuse-lite": "^1.0.30001806",
1615+ "electron-to-chromium": "^1.5.393",
1616+ "node-releases": "^2.0.51",
1617+ "update-browserslist-db": "^1.2.3"
1618+ },
1619+ "bin": {
1620+ "browserslist": "cli.js"
1621+ },
1622+ "engines": {
1623+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
1624+ }
1625+ },
1626+ "node_modules/caniuse-lite": {
1627+ "version": "1.0.30001806",
1628+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001806.tgz",
1629+ "integrity": "sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==",
1630+ "dev": true,
1631+ "funding": [
1632+ {
1633+ "type": "opencollective",
1634+ "url": "https://opencollective.com/browserslist"
1635+ },
1636+ {
1637+ "type": "tidelift",
1638+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
1639+ },
1640+ {
1641+ "type": "github",
1642+ "url": "https://github.com/sponsors/ai"
1643+ }
1644+ ],
1645+ "license": "CC-BY-4.0"
1646+ },
1647+ "node_modules/convert-source-map": {
1648+ "version": "2.0.0",
1649+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
1650+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
1651+ "dev": true,
1652+ "license": "MIT"
1653+ },
1654+ "node_modules/csstype": {
1655+ "version": "3.2.3",
1656+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
1657+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
1658+ "dev": true,
1659+ "license": "MIT"
1660+ },
1661+ "node_modules/debug": {
1662+ "version": "4.4.3",
1663+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
1664+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
1665+ "dev": true,
1666+ "license": "MIT",
1667+ "dependencies": {
1668+ "ms": "^2.1.3"
1669+ },
1670+ "engines": {
1671+ "node": ">=6.0"
1672+ },
1673+ "peerDependenciesMeta": {
1674+ "supports-color": {
1675+ "optional": true
1676+ }
1677+ }
1678+ },
1679+ "node_modules/electron-to-chromium": {
1680+ "version": "1.5.395",
1681+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.395.tgz",
1682+ "integrity": "sha512-7zt9Aw+SrmxLWLN0zhaTWZQiCdryLVrYTq5R7iZakLvi2UQPYMMsROYV/2qVCzMeCiSXHwKOU+sZ4zOVVlrtKA==",
1683+ "dev": true,
1684+ "license": "ISC"
1685+ },
1686+ "node_modules/esbuild": {
1687+ "version": "0.28.1",
1688+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz",
1689+ "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==",
1690+ "dev": true,
1691+ "hasInstallScript": true,
1692+ "license": "MIT",
1693+ "bin": {
1694+ "esbuild": "bin/esbuild"
1695+ },
1696+ "engines": {
1697+ "node": ">=18"
1698+ },
1699+ "optionalDependencies": {
1700+ "@esbuild/aix-ppc64": "0.28.1",
1701+ "@esbuild/android-arm": "0.28.1",
1702+ "@esbuild/android-arm64": "0.28.1",
1703+ "@esbuild/android-x64": "0.28.1",
1704+ "@esbuild/darwin-arm64": "0.28.1",
1705+ "@esbuild/darwin-x64": "0.28.1",
1706+ "@esbuild/freebsd-arm64": "0.28.1",
1707+ "@esbuild/freebsd-x64": "0.28.1",
1708+ "@esbuild/linux-arm": "0.28.1",
1709+ "@esbuild/linux-arm64": "0.28.1",
1710+ "@esbuild/linux-ia32": "0.28.1",
1711+ "@esbuild/linux-loong64": "0.28.1",
1712+ "@esbuild/linux-mips64el": "0.28.1",
1713+ "@esbuild/linux-ppc64": "0.28.1",
1714+ "@esbuild/linux-riscv64": "0.28.1",
1715+ "@esbuild/linux-s390x": "0.28.1",
1716+ "@esbuild/linux-x64": "0.28.1",
1717+ "@esbuild/netbsd-arm64": "0.28.1",
1718+ "@esbuild/netbsd-x64": "0.28.1",
1719+ "@esbuild/openbsd-arm64": "0.28.1",
1720+ "@esbuild/openbsd-x64": "0.28.1",
1721+ "@esbuild/openharmony-arm64": "0.28.1",
1722+ "@esbuild/sunos-x64": "0.28.1",
1723+ "@esbuild/win32-arm64": "0.28.1",
1724+ "@esbuild/win32-ia32": "0.28.1",
1725+ "@esbuild/win32-x64": "0.28.1"
1726+ }
1727+ },
1728+ "node_modules/escalade": {
1729+ "version": "3.2.0",
1730+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
1731+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
1732+ "dev": true,
1733+ "license": "MIT",
1734+ "engines": {
1735+ "node": ">=6"
1736+ }
1737+ },
1738+ "node_modules/fdir": {
1739+ "version": "6.5.0",
1740+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
1741+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
1742+ "dev": true,
1743+ "license": "MIT",
1744+ "engines": {
1745+ "node": ">=12.0.0"
1746+ },
1747+ "peerDependencies": {
1748+ "picomatch": "^3 || ^4"
1749+ },
1750+ "peerDependenciesMeta": {
1751+ "picomatch": {
1752+ "optional": true
1753+ }
1754+ }
1755+ },
1756+ "node_modules/fsevents": {
1757+ "version": "2.3.3",
1758+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
1759+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
1760+ "dev": true,
1761+ "hasInstallScript": true,
1762+ "license": "MIT",
1763+ "optional": true,
1764+ "os": [
1765+ "darwin"
1766+ ],
1767+ "engines": {
1768+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
1769+ }
1770+ },
1771+ "node_modules/gensync": {
1772+ "version": "1.0.0-beta.2",
1773+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
1774+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
1775+ "dev": true,
1776+ "license": "MIT",
1777+ "engines": {
1778+ "node": ">=6.9.0"
1779+ }
1780+ },
1781+ "node_modules/js-tokens": {
1782+ "version": "4.0.0",
1783+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
1784+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
1785+ "dev": true,
1786+ "license": "MIT"
1787+ },
1788+ "node_modules/jsesc": {
1789+ "version": "3.1.0",
1790+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
1791+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
1792+ "dev": true,
1793+ "license": "MIT",
1794+ "bin": {
1795+ "jsesc": "bin/jsesc"
1796+ },
1797+ "engines": {
1798+ "node": ">=6"
1799+ }
1800+ },
1801+ "node_modules/json5": {
1802+ "version": "2.2.3",
1803+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
1804+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
1805+ "dev": true,
1806+ "license": "MIT",
1807+ "bin": {
1808+ "json5": "lib/cli.js"
1809+ },
1810+ "engines": {
1811+ "node": ">=6"
1812+ }
1813+ },
1814+ "node_modules/lru-cache": {
1815+ "version": "5.1.1",
1816+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
1817+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
1818+ "dev": true,
1819+ "license": "ISC",
1820+ "dependencies": {
1821+ "yallist": "^3.0.2"
1822+ }
1823+ },
1824+ "node_modules/ms": {
1825+ "version": "2.1.3",
1826+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
1827+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
1828+ "dev": true,
1829+ "license": "MIT"
1830+ },
1831+ "node_modules/nanoid": {
1832+ "version": "3.3.16",
1833+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz",
1834+ "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==",
1835+ "dev": true,
1836+ "funding": [
1837+ {
1838+ "type": "github",
1839+ "url": "https://github.com/sponsors/ai"
1840+ }
1841+ ],
1842+ "license": "MIT",
1843+ "bin": {
1844+ "nanoid": "bin/nanoid.cjs"
1845+ },
1846+ "engines": {
1847+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
1848+ }
1849+ },
1850+ "node_modules/node-releases": {
1851+ "version": "2.0.51",
1852+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.51.tgz",
1853+ "integrity": "sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==",
1854+ "dev": true,
1855+ "license": "MIT",
1856+ "engines": {
1857+ "node": ">=18"
1858+ }
1859+ },
1860+ "node_modules/picocolors": {
1861+ "version": "1.1.1",
1862+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
1863+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
1864+ "dev": true,
1865+ "license": "ISC"
1866+ },
1867+ "node_modules/picomatch": {
1868+ "version": "4.0.5",
1869+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz",
1870+ "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==",
1871+ "dev": true,
1872+ "license": "MIT",
1873+ "engines": {
1874+ "node": ">=12"
1875+ },
1876+ "funding": {
1877+ "url": "https://github.com/sponsors/jonschlinkert"
1878+ }
1879+ },
1880+ "node_modules/postcss": {
1881+ "version": "8.5.22",
1882+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.22.tgz",
1883+ "integrity": "sha512-KBDEIpLrvpv16pp3K0Fw+UCoZfopFjjgeB+0tA/aaThfEE74kKDLrgg603YvOWJyg3+WYtyq3xYsQWsIyZlPqQ==",
1884+ "dev": true,
1885+ "funding": [
1886+ {
1887+ "type": "opencollective",
1888+ "url": "https://opencollective.com/postcss/"
1889+ },
1890+ {
1891+ "type": "tidelift",
1892+ "url": "https://tidelift.com/funding/github/npm/postcss"
1893+ },
1894+ {
1895+ "type": "github",
1896+ "url": "https://github.com/sponsors/ai"
1897+ }
1898+ ],
1899+ "license": "MIT",
1900+ "dependencies": {
1901+ "nanoid": "^3.3.16",
1902+ "picocolors": "^1.1.1",
1903+ "source-map-js": "^1.2.1"
1904+ },
1905+ "engines": {
1906+ "node": "^10 || ^12 || >=14"
1907+ }
1908+ },
1909+ "node_modules/react": {
1910+ "version": "19.2.8",
1911+ "resolved": "https://registry.npmjs.org/react/-/react-19.2.8.tgz",
1912+ "integrity": "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==",
1913+ "license": "MIT",
1914+ "engines": {
1915+ "node": ">=0.10.0"
1916+ }
1917+ },
1918+ "node_modules/react-dom": {
1919+ "version": "19.2.8",
1920+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.8.tgz",
1921+ "integrity": "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==",
1922+ "license": "MIT",
1923+ "dependencies": {
1924+ "scheduler": "^0.27.0"
1925+ },
1926+ "peerDependencies": {
1927+ "react": "^19.2.8"
1928+ }
1929+ },
1930+ "node_modules/react-refresh": {
1931+ "version": "0.17.0",
1932+ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz",
1933+ "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==",
1934+ "dev": true,
1935+ "license": "MIT",
1936+ "engines": {
1937+ "node": ">=0.10.0"
1938+ }
1939+ },
1940+ "node_modules/rollup": {
1941+ "version": "4.62.2",
1942+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.2.tgz",
1943+ "integrity": "sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==",
1944+ "dev": true,
1945+ "license": "MIT",
1946+ "dependencies": {
1947+ "@types/estree": "1.0.9"
1948+ },
1949+ "bin": {
1950+ "rollup": "dist/bin/rollup"
1951+ },
1952+ "engines": {
1953+ "node": ">=18.0.0",
1954+ "npm": ">=8.0.0"
1955+ },
1956+ "optionalDependencies": {
1957+ "@rollup/rollup-android-arm-eabi": "4.62.2",
1958+ "@rollup/rollup-android-arm64": "4.62.2",
1959+ "@rollup/rollup-darwin-arm64": "4.62.2",
1960+ "@rollup/rollup-darwin-x64": "4.62.2",
1961+ "@rollup/rollup-freebsd-arm64": "4.62.2",
1962+ "@rollup/rollup-freebsd-x64": "4.62.2",
1963+ "@rollup/rollup-linux-arm-gnueabihf": "4.62.2",
1964+ "@rollup/rollup-linux-arm-musleabihf": "4.62.2",
1965+ "@rollup/rollup-linux-arm64-gnu": "4.62.2",
1966+ "@rollup/rollup-linux-arm64-musl": "4.62.2",
1967+ "@rollup/rollup-linux-loong64-gnu": "4.62.2",
1968+ "@rollup/rollup-linux-loong64-musl": "4.62.2",
1969+ "@rollup/rollup-linux-ppc64-gnu": "4.62.2",
1970+ "@rollup/rollup-linux-ppc64-musl": "4.62.2",
1971+ "@rollup/rollup-linux-riscv64-gnu": "4.62.2",
1972+ "@rollup/rollup-linux-riscv64-musl": "4.62.2",
1973+ "@rollup/rollup-linux-s390x-gnu": "4.62.2",
1974+ "@rollup/rollup-linux-x64-gnu": "4.62.2",
1975+ "@rollup/rollup-linux-x64-musl": "4.62.2",
1976+ "@rollup/rollup-openbsd-x64": "4.62.2",
1977+ "@rollup/rollup-openharmony-arm64": "4.62.2",
1978+ "@rollup/rollup-win32-arm64-msvc": "4.62.2",
1979+ "@rollup/rollup-win32-ia32-msvc": "4.62.2",
1980+ "@rollup/rollup-win32-x64-gnu": "4.62.2",
1981+ "@rollup/rollup-win32-x64-msvc": "4.62.2",
1982+ "fsevents": "~2.3.2"
1983+ }
1984+ },
1985+ "node_modules/scheduler": {
1986+ "version": "0.27.0",
1987+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
1988+ "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
1989+ "license": "MIT"
1990+ },
1991+ "node_modules/semver": {
1992+ "version": "6.3.1",
1993+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
1994+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
1995+ "dev": true,
1996+ "license": "ISC",
1997+ "bin": {
1998+ "semver": "bin/semver.js"
1999+ }
2000+ },
2001+ "node_modules/source-map-js": {
2002+ "version": "1.2.1",
2003+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
2004+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
2005+ "dev": true,
2006+ "license": "BSD-3-Clause",
2007+ "engines": {
2008+ "node": ">=0.10.0"
2009+ }
2010+ },
2011+ "node_modules/tinyglobby": {
2012+ "version": "0.2.17",
2013+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
2014+ "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
2015+ "dev": true,
2016+ "license": "MIT",
2017+ "dependencies": {
2018+ "fdir": "^6.5.0",
2019+ "picomatch": "^4.0.4"
2020+ },
2021+ "engines": {
2022+ "node": ">=12.0.0"
2023+ },
2024+ "funding": {
2025+ "url": "https://github.com/sponsors/SuperchupuDev"
2026+ }
2027+ },
2028+ "node_modules/typescript": {
2029+ "version": "5.8.3",
2030+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
2031+ "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
2032+ "dev": true,
2033+ "license": "Apache-2.0",
2034+ "bin": {
2035+ "tsc": "bin/tsc",
2036+ "tsserver": "bin/tsserver"
2037+ },
2038+ "engines": {
2039+ "node": ">=14.17"
2040+ }
2041+ },
2042+ "node_modules/update-browserslist-db": {
2043+ "version": "1.2.3",
2044+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
2045+ "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
2046+ "dev": true,
2047+ "funding": [
2048+ {
2049+ "type": "opencollective",
2050+ "url": "https://opencollective.com/browserslist"
2051+ },
2052+ {
2053+ "type": "tidelift",
2054+ "url": "https://tidelift.com/funding/github/npm/browserslist"
2055+ },
2056+ {
2057+ "type": "github",
2058+ "url": "https://github.com/sponsors/ai"
2059+ }
2060+ ],
2061+ "license": "MIT",
2062+ "dependencies": {
2063+ "escalade": "^3.2.0",
2064+ "picocolors": "^1.1.1"
2065+ },
2066+ "bin": {
2067+ "update-browserslist-db": "cli.js"
2068+ },
2069+ "peerDependencies": {
2070+ "browserslist": ">= 4.21.0"
2071+ }
2072+ },
2073+ "node_modules/vite": {
2074+ "version": "7.3.6",
2075+ "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.6.tgz",
2076+ "integrity": "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg==",
2077+ "dev": true,
2078+ "license": "MIT",
2079+ "dependencies": {
2080+ "esbuild": "^0.27.0 || ^0.28.0",
2081+ "fdir": "^6.5.0",
2082+ "picomatch": "^4.0.3",
2083+ "postcss": "^8.5.6",
2084+ "rollup": "^4.43.0",
2085+ "tinyglobby": "^0.2.15"
2086+ },
2087+ "bin": {
2088+ "vite": "bin/vite.js"
2089+ },
2090+ "engines": {
2091+ "node": "^20.19.0 || >=22.12.0"
2092+ },
2093+ "funding": {
2094+ "url": "https://github.com/vitejs/vite?sponsor=1"
2095+ },
2096+ "optionalDependencies": {
2097+ "fsevents": "~2.3.3"
2098+ },
2099+ "peerDependencies": {
2100+ "@types/node": "^20.19.0 || >=22.12.0",
2101+ "jiti": ">=1.21.0",
2102+ "less": "^4.0.0",
2103+ "lightningcss": "^1.21.0",
2104+ "sass": "^1.70.0",
2105+ "sass-embedded": "^1.70.0",
2106+ "stylus": ">=0.54.8",
2107+ "sugarss": "^5.0.0",
2108+ "terser": "^5.16.0",
2109+ "tsx": "^4.8.1",
2110+ "yaml": "^2.4.2"
2111+ },
2112+ "peerDependenciesMeta": {
2113+ "@types/node": {
2114+ "optional": true
2115+ },
2116+ "jiti": {
2117+ "optional": true
2118+ },
2119+ "less": {
2120+ "optional": true
2121+ },
2122+ "lightningcss": {
2123+ "optional": true
2124+ },
2125+ "sass": {
2126+ "optional": true
2127+ },
2128+ "sass-embedded": {
2129+ "optional": true
2130+ },
2131+ "stylus": {
2132+ "optional": true
2133+ },
2134+ "sugarss": {
2135+ "optional": true
2136+ },
2137+ "terser": {
2138+ "optional": true
2139+ },
2140+ "tsx": {
2141+ "optional": true
2142+ },
2143+ "yaml": {
2144+ "optional": true
2145+ }
2146+ }
2147+ },
2148+ "node_modules/yallist": {
2149+ "version": "3.1.1",
2150+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
2151+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
2152+ "dev": true,
2153+ "license": "ISC"
2154+ }
2155+ }
2156+}
+33-0package.json
@@ -0,0 +1,33 @@
1+{
2+ "name": "mutterbox",
3+ "private": true,
4+ "version": "0.1.0",
5+ "type": "module",
6+ "scripts": {
7+ "dev": "vite",
8+ "build": "tsc && vite build",
9+ "preview": "vite preview",
10+ "tauri": "tauri"
11+ },
12+ "dependencies": {
13+ "@tauri-apps/api": "^2",
14+ "@tauri-apps/plugin-autostart": "^2.5.1",
15+ "@tauri-apps/plugin-clipboard-manager": "^2.3.2",
16+ "@tauri-apps/plugin-global-shortcut": "^2.3.2",
17+ "@tauri-apps/plugin-notification": "^2.3.3",
18+ "@tauri-apps/plugin-opener": "^2",
19+ "react": "^19.1.0",
20+ "react-dom": "^19.1.0"
21+ },
22+ "devDependencies": {
23+ "@tauri-apps/cli": "^2",
24+ "@types/react": "^19.1.8",
25+ "@types/react-dom": "^19.1.6",
26+ "@vitejs/plugin-react": "^4.6.0",
27+ "typescript": "~5.8.3",
28+ "vite": "^7.0.4"
29+ },
30+ "allowScripts": {
31+ "esbuild@0.28.1": true
32+ }
33+}
+7-0src-tauri/.gitignore
@@ -0,0 +1,7 @@
1+# Generated by Cargo
2+# will have compiled files and executables
3+/target/
4+
5+# Generated by Tauri
6+# will have schema files for capabilities auto-completion
7+/gen/schemas
+6205-0src-tauri/Cargo.lock
@@ -0,0 +1,6205 @@
1+# This file is automatically @generated by Cargo.
2+# It is not intended for manual editing.
3+version = 4
4+
5+[[package]]
6+name = "adler2"
7+version = "2.0.1"
8+source = "registry+https://github.com/rust-lang/crates.io-index"
9+checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
10+
11+[[package]]
12+name = "aho-corasick"
13+version = "1.1.4"
14+source = "registry+https://github.com/rust-lang/crates.io-index"
15+checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
16+dependencies = [
17+ "memchr",
18+]
19+
20+[[package]]
21+name = "alloc-no-stdlib"
22+version = "2.0.4"
23+source = "registry+https://github.com/rust-lang/crates.io-index"
24+checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3"
25+
26+[[package]]
27+name = "alloc-stdlib"
28+version = "0.2.4"
29+source = "registry+https://github.com/rust-lang/crates.io-index"
30+checksum = "0e76a019e91224d279006ff972f1e984179a6e9feb050adba6ce8274aef23195"
31+dependencies = [
32+ "alloc-no-stdlib",
33+]
34+
35+[[package]]
36+name = "alsa"
37+version = "0.9.1"
38+source = "registry+https://github.com/rust-lang/crates.io-index"
39+checksum = "ed7572b7ba83a31e20d1b48970ee402d2e3e0537dcfe0a3ff4d6eb7508617d43"
40+dependencies = [
41+ "alsa-sys",
42+ "bitflags 2.13.1",
43+ "cfg-if",
44+ "libc",
45+]
46+
47+[[package]]
48+name = "alsa-sys"
49+version = "0.3.1"
50+source = "registry+https://github.com/rust-lang/crates.io-index"
51+checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527"
52+dependencies = [
53+ "libc",
54+ "pkg-config",
55+]
56+
57+[[package]]
58+name = "android_system_properties"
59+version = "0.1.5"
60+source = "registry+https://github.com/rust-lang/crates.io-index"
61+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
62+dependencies = [
63+ "libc",
64+]
65+
66+[[package]]
67+name = "anyhow"
68+version = "1.0.104"
69+source = "registry+https://github.com/rust-lang/crates.io-index"
70+checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470"
71+
72+[[package]]
73+name = "arboard"
74+version = "3.6.1"
75+source = "registry+https://github.com/rust-lang/crates.io-index"
76+checksum = "0348a1c054491f4bfe6ab86a7b6ab1e44e45d899005de92f58b3df180b36ddaf"
77+dependencies = [
78+ "clipboard-win",
79+ "image",
80+ "log",
81+ "objc2",
82+ "objc2-app-kit",
83+ "objc2-core-foundation",
84+ "objc2-core-graphics",
85+ "objc2-foundation",
86+ "parking_lot",
87+ "percent-encoding",
88+ "windows-sys 0.60.2",
89+ "wl-clipboard-rs",
90+ "x11rb",
91+]
92+
93+[[package]]
94+name = "async-broadcast"
95+version = "0.7.2"
96+source = "registry+https://github.com/rust-lang/crates.io-index"
97+checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532"
98+dependencies = [
99+ "event-listener",
100+ "event-listener-strategy",
101+ "futures-core",
102+ "pin-project-lite",
103+]
104+
105+[[package]]
106+name = "async-channel"
107+version = "2.5.0"
108+source = "registry+https://github.com/rust-lang/crates.io-index"
109+checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2"
110+dependencies = [
111+ "concurrent-queue",
112+ "event-listener-strategy",
113+ "futures-core",
114+ "pin-project-lite",
115+]
116+
117+[[package]]
118+name = "async-executor"
119+version = "1.14.0"
120+source = "registry+https://github.com/rust-lang/crates.io-index"
121+checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a"
122+dependencies = [
123+ "async-task",
124+ "concurrent-queue",
125+ "fastrand",
126+ "futures-lite",
127+ "pin-project-lite",
128+ "slab",
129+]
130+
131+[[package]]
132+name = "async-io"
133+version = "2.6.0"
134+source = "registry+https://github.com/rust-lang/crates.io-index"
135+checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc"
136+dependencies = [
137+ "autocfg",
138+ "cfg-if",
139+ "concurrent-queue",
140+ "futures-io",
141+ "futures-lite",
142+ "parking",
143+ "polling",
144+ "rustix",
145+ "slab",
146+ "windows-sys 0.61.2",
147+]
148+
149+[[package]]
150+name = "async-lock"
151+version = "3.4.2"
152+source = "registry+https://github.com/rust-lang/crates.io-index"
153+checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311"
154+dependencies = [
155+ "event-listener",
156+ "event-listener-strategy",
157+ "pin-project-lite",
158+]
159+
160+[[package]]
161+name = "async-process"
162+version = "2.5.0"
163+source = "registry+https://github.com/rust-lang/crates.io-index"
164+checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75"
165+dependencies = [
166+ "async-channel",
167+ "async-io",
168+ "async-lock",
169+ "async-signal",
170+ "async-task",
171+ "blocking",
172+ "cfg-if",
173+ "event-listener",
174+ "futures-lite",
175+ "rustix",
176+]
177+
178+[[package]]
179+name = "async-recursion"
180+version = "1.1.1"
181+source = "registry+https://github.com/rust-lang/crates.io-index"
182+checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
183+dependencies = [
184+ "proc-macro2",
185+ "quote",
186+ "syn 2.0.119",
187+]
188+
189+[[package]]
190+name = "async-signal"
191+version = "0.2.14"
192+source = "registry+https://github.com/rust-lang/crates.io-index"
193+checksum = "52b5aaafa020cf5053a01f2a60e8ff5dccf550f0f77ec54a4e47285ac2bab485"
194+dependencies = [
195+ "async-io",
196+ "async-lock",
197+ "atomic-waker",
198+ "cfg-if",
199+ "futures-core",
200+ "futures-io",
201+ "rustix",
202+ "signal-hook-registry",
203+ "slab",
204+ "windows-sys 0.61.2",
205+]
206+
207+[[package]]
208+name = "async-task"
209+version = "4.7.1"
210+source = "registry+https://github.com/rust-lang/crates.io-index"
211+checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de"
212+
213+[[package]]
214+name = "async-trait"
215+version = "0.1.91"
216+source = "registry+https://github.com/rust-lang/crates.io-index"
217+checksum = "ae36dc4177970ef04fde5178d3e2429882def40e57a451f919c098f72baa6cec"
218+dependencies = [
219+ "proc-macro2",
220+ "quote",
221+ "syn 3.0.3",
222+]
223+
224+[[package]]
225+name = "atk"
226+version = "0.18.2"
227+source = "registry+https://github.com/rust-lang/crates.io-index"
228+checksum = "241b621213072e993be4f6f3a9e4b45f65b7e6faad43001be957184b7bb1824b"
229+dependencies = [
230+ "atk-sys",
231+ "glib",
232+ "libc",
233+]
234+
235+[[package]]
236+name = "atk-sys"
237+version = "0.18.2"
238+source = "registry+https://github.com/rust-lang/crates.io-index"
239+checksum = "c5e48b684b0ca77d2bbadeef17424c2ea3c897d44d566a1617e7e8f30614d086"
240+dependencies = [
241+ "glib-sys",
242+ "gobject-sys",
243+ "libc",
244+ "system-deps",
245+]
246+
247+[[package]]
248+name = "atomic-waker"
249+version = "1.1.2"
250+source = "registry+https://github.com/rust-lang/crates.io-index"
251+checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
252+
253+[[package]]
254+name = "auto-launch"
255+version = "0.5.0"
256+source = "registry+https://github.com/rust-lang/crates.io-index"
257+checksum = "1f012b8cc0c850f34117ec8252a44418f2e34a2cf501de89e29b241ae5f79471"
258+dependencies = [
259+ "dirs 4.0.0",
260+ "thiserror 1.0.69",
261+ "winreg 0.10.1",
262+]
263+
264+[[package]]
265+name = "autocfg"
266+version = "1.5.1"
267+source = "registry+https://github.com/rust-lang/crates.io-index"
268+checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
269+
270+[[package]]
271+name = "base64"
272+version = "0.21.7"
273+source = "registry+https://github.com/rust-lang/crates.io-index"
274+checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
275+
276+[[package]]
277+name = "base64"
278+version = "0.22.1"
279+source = "registry+https://github.com/rust-lang/crates.io-index"
280+checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
281+
282+[[package]]
283+name = "bindgen"
284+version = "0.72.1"
285+source = "registry+https://github.com/rust-lang/crates.io-index"
286+checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895"
287+dependencies = [
288+ "bitflags 2.13.1",
289+ "cexpr",
290+ "clang-sys",
291+ "itertools",
292+ "log",
293+ "prettyplease",
294+ "proc-macro2",
295+ "quote",
296+ "regex",
297+ "rustc-hash",
298+ "shlex 1.3.0",
299+ "syn 2.0.119",
300+]
301+
302+[[package]]
303+name = "bit-set"
304+version = "0.8.0"
305+source = "registry+https://github.com/rust-lang/crates.io-index"
306+checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3"
307+dependencies = [
308+ "bit-vec",
309+]
310+
311+[[package]]
312+name = "bit-vec"
313+version = "0.8.0"
314+source = "registry+https://github.com/rust-lang/crates.io-index"
315+checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
316+
317+[[package]]
318+name = "bitflags"
319+version = "1.3.2"
320+source = "registry+https://github.com/rust-lang/crates.io-index"
321+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
322+
323+[[package]]
324+name = "bitflags"
325+version = "2.13.1"
326+source = "registry+https://github.com/rust-lang/crates.io-index"
327+checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da"
328+dependencies = [
329+ "serde_core",
330+]
331+
332+[[package]]
333+name = "block-buffer"
334+version = "0.10.4"
335+source = "registry+https://github.com/rust-lang/crates.io-index"
336+checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
337+dependencies = [
338+ "generic-array",
339+]
340+
341+[[package]]
342+name = "block2"
343+version = "0.6.2"
344+source = "registry+https://github.com/rust-lang/crates.io-index"
345+checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5"
346+dependencies = [
347+ "objc2",
348+]
349+
350+[[package]]
351+name = "blocking"
352+version = "1.6.2"
353+source = "registry+https://github.com/rust-lang/crates.io-index"
354+checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21"
355+dependencies = [
356+ "async-channel",
357+ "async-task",
358+ "futures-io",
359+ "futures-lite",
360+ "piper",
361+]
362+
363+[[package]]
364+name = "brotli"
365+version = "8.0.4"
366+source = "registry+https://github.com/rust-lang/crates.io-index"
367+checksum = "5cc91aac060a7a1e25823bdccbfb6af1875b88f17c6daac97894eed8207166b3"
368+dependencies = [
369+ "alloc-no-stdlib",
370+ "alloc-stdlib",
371+ "brotli-decompressor",
372+]
373+
374+[[package]]
375+name = "brotli-decompressor"
376+version = "5.0.3"
377+source = "registry+https://github.com/rust-lang/crates.io-index"
378+checksum = "3a32acac15fe1967bc3986b2a6347dffc965602354ea6f450ad07e8bfd253583"
379+dependencies = [
380+ "alloc-no-stdlib",
381+ "alloc-stdlib",
382+]
383+
384+[[package]]
385+name = "bs58"
386+version = "0.5.1"
387+source = "registry+https://github.com/rust-lang/crates.io-index"
388+checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4"
389+dependencies = [
390+ "tinyvec",
391+]
392+
393+[[package]]
394+name = "bumpalo"
395+version = "3.20.3"
396+source = "registry+https://github.com/rust-lang/crates.io-index"
397+checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
398+
399+[[package]]
400+name = "bytemuck"
401+version = "1.25.2"
402+source = "registry+https://github.com/rust-lang/crates.io-index"
403+checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797"
404+
405+[[package]]
406+name = "byteorder"
407+version = "1.5.0"
408+source = "registry+https://github.com/rust-lang/crates.io-index"
409+checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
410+
411+[[package]]
412+name = "byteorder-lite"
413+version = "0.1.0"
414+source = "registry+https://github.com/rust-lang/crates.io-index"
415+checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"
416+
417+[[package]]
418+name = "bytes"
419+version = "1.12.1"
420+source = "registry+https://github.com/rust-lang/crates.io-index"
421+checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04"
422+dependencies = [
423+ "serde",
424+]
425+
426+[[package]]
427+name = "cairo-rs"
428+version = "0.18.5"
429+source = "registry+https://github.com/rust-lang/crates.io-index"
430+checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2"
431+dependencies = [
432+ "bitflags 2.13.1",
433+ "cairo-sys-rs",
434+ "glib",
435+ "libc",
436+ "once_cell",
437+ "thiserror 1.0.69",
438+]
439+
440+[[package]]
441+name = "cairo-sys-rs"
442+version = "0.18.2"
443+source = "registry+https://github.com/rust-lang/crates.io-index"
444+checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51"
445+dependencies = [
446+ "glib-sys",
447+ "libc",
448+ "system-deps",
449+]
450+
451+[[package]]
452+name = "camino"
453+version = "1.2.4"
454+source = "registry+https://github.com/rust-lang/crates.io-index"
455+checksum = "5f2d30e4173c4026932d51d31d6b0613b1fd3014bf3f9f8943d4ba139c437ba0"
456+dependencies = [
457+ "serde_core",
458+]
459+
460+[[package]]
461+name = "cargo-platform"
462+version = "0.1.9"
463+source = "registry+https://github.com/rust-lang/crates.io-index"
464+checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea"
465+dependencies = [
466+ "serde",
467+]
468+
469+[[package]]
470+name = "cargo_metadata"
471+version = "0.19.2"
472+source = "registry+https://github.com/rust-lang/crates.io-index"
473+checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba"
474+dependencies = [
475+ "camino",
476+ "cargo-platform",
477+ "semver",
478+ "serde",
479+ "serde_json",
480+ "thiserror 2.0.19",
481+]
482+
483+[[package]]
484+name = "cargo_toml"
485+version = "0.22.3"
486+source = "registry+https://github.com/rust-lang/crates.io-index"
487+checksum = "374b7c592d9c00c1f4972ea58390ac6b18cbb6ab79011f3bdc90a0b82ca06b77"
488+dependencies = [
489+ "serde",
490+ "toml 0.9.12+spec-1.1.0",
491+]
492+
493+[[package]]
494+name = "cc"
495+version = "1.3.0"
496+source = "registry+https://github.com/rust-lang/crates.io-index"
497+checksum = "c89588d05638b5b4594a3348a2d6c20277e43a7f5c5202b05cc56888475a47b8"
498+dependencies = [
499+ "find-msvc-tools",
500+ "shlex 2.0.1",
501+]
502+
503+[[package]]
504+name = "cesu8"
505+version = "1.1.0"
506+source = "registry+https://github.com/rust-lang/crates.io-index"
507+checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
508+
509+[[package]]
510+name = "cexpr"
511+version = "0.6.0"
512+source = "registry+https://github.com/rust-lang/crates.io-index"
513+checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
514+dependencies = [
515+ "nom 7.1.3",
516+]
517+
518+[[package]]
519+name = "cfb"
520+version = "0.7.3"
521+source = "registry+https://github.com/rust-lang/crates.io-index"
522+checksum = "d38f2da7a0a2c4ccf0065be06397cc26a81f4e528be095826eee9d4adbb8c60f"
523+dependencies = [
524+ "byteorder",
525+ "fnv",
526+ "uuid",
527+]
528+
529+[[package]]
530+name = "cfg-expr"
531+version = "0.15.8"
532+source = "registry+https://github.com/rust-lang/crates.io-index"
533+checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02"
534+dependencies = [
535+ "smallvec",
536+ "target-lexicon",
537+]
538+
539+[[package]]
540+name = "cfg-if"
541+version = "1.0.4"
542+source = "registry+https://github.com/rust-lang/crates.io-index"
543+checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
544+
545+[[package]]
546+name = "cfg_aliases"
547+version = "0.2.2"
548+source = "registry+https://github.com/rust-lang/crates.io-index"
549+checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527"
550+
551+[[package]]
552+name = "chacha20"
553+version = "0.10.1"
554+source = "registry+https://github.com/rust-lang/crates.io-index"
555+checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81"
556+dependencies = [
557+ "cfg-if",
558+ "cpufeatures 0.3.0",
559+ "rand_core 0.10.1",
560+]
561+
562+[[package]]
563+name = "chrono"
564+version = "0.4.45"
565+source = "registry+https://github.com/rust-lang/crates.io-index"
566+checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327"
567+dependencies = [
568+ "iana-time-zone",
569+ "num-traits",
570+ "serde",
571+ "windows-link 0.2.1",
572+]
573+
574+[[package]]
575+name = "clang-sys"
576+version = "1.8.1"
577+source = "registry+https://github.com/rust-lang/crates.io-index"
578+checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
579+dependencies = [
580+ "glob",
581+ "libc",
582+ "libloading 0.8.9",
583+]
584+
585+[[package]]
586+name = "clipboard-win"
587+version = "5.4.1"
588+source = "registry+https://github.com/rust-lang/crates.io-index"
589+checksum = "bde03770d3df201d4fb868f2c9c59e66a3e4e2bd06692a0fe701e7103c7e84d4"
590+dependencies = [
591+ "error-code",
592+]
593+
594+[[package]]
595+name = "cmake"
596+version = "0.1.58"
597+source = "registry+https://github.com/rust-lang/crates.io-index"
598+checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678"
599+dependencies = [
600+ "cc",
601+]
602+
603+[[package]]
604+name = "combine"
605+version = "4.6.7"
606+source = "registry+https://github.com/rust-lang/crates.io-index"
607+checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd"
608+dependencies = [
609+ "bytes",
610+ "memchr",
611+]
612+
613+[[package]]
614+name = "concurrent-queue"
615+version = "2.5.0"
616+source = "registry+https://github.com/rust-lang/crates.io-index"
617+checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
618+dependencies = [
619+ "crossbeam-utils",
620+]
621+
622+[[package]]
623+name = "cookie"
624+version = "0.18.1"
625+source = "registry+https://github.com/rust-lang/crates.io-index"
626+checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747"
627+dependencies = [
628+ "time",
629+ "version_check",
630+]
631+
632+[[package]]
633+name = "core-foundation"
634+version = "0.10.1"
635+source = "registry+https://github.com/rust-lang/crates.io-index"
636+checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6"
637+dependencies = [
638+ "core-foundation-sys",
639+ "libc",
640+]
641+
642+[[package]]
643+name = "core-foundation-sys"
644+version = "0.8.7"
645+source = "registry+https://github.com/rust-lang/crates.io-index"
646+checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
647+
648+[[package]]
649+name = "core-graphics"
650+version = "0.25.0"
651+source = "registry+https://github.com/rust-lang/crates.io-index"
652+checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97"
653+dependencies = [
654+ "bitflags 2.13.1",
655+ "core-foundation",
656+ "core-graphics-types",
657+ "foreign-types",
658+ "libc",
659+]
660+
661+[[package]]
662+name = "core-graphics-types"
663+version = "0.2.0"
664+source = "registry+https://github.com/rust-lang/crates.io-index"
665+checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb"
666+dependencies = [
667+ "bitflags 2.13.1",
668+ "core-foundation",
669+ "libc",
670+]
671+
672+[[package]]
673+name = "coreaudio-rs"
674+version = "0.13.0"
675+source = "registry+https://github.com/rust-lang/crates.io-index"
676+checksum = "1aae284fbaf7d27aa0e292f7677dfbe26503b0d555026f702940805a630eac17"
677+dependencies = [
678+ "bitflags 1.3.2",
679+ "libc",
680+ "objc2-audio-toolbox",
681+ "objc2-core-audio",
682+ "objc2-core-audio-types",
683+ "objc2-core-foundation",
684+]
685+
686+[[package]]
687+name = "cpal"
688+version = "0.16.0"
689+source = "registry+https://github.com/rust-lang/crates.io-index"
690+checksum = "cbd307f43cc2a697e2d1f8bc7a1d824b5269e052209e28883e5bc04d095aaa3f"
691+dependencies = [
692+ "alsa",
693+ "coreaudio-rs",
694+ "dasp_sample",
695+ "jni",
696+ "js-sys",
697+ "libc",
698+ "mach2",
699+ "ndk",
700+ "ndk-context",
701+ "num-derive",
702+ "num-traits",
703+ "objc2-audio-toolbox",
704+ "objc2-core-audio",
705+ "objc2-core-audio-types",
706+ "wasm-bindgen",
707+ "wasm-bindgen-futures",
708+ "web-sys",
709+ "windows 0.54.0",
710+]
711+
712+[[package]]
713+name = "cpufeatures"
714+version = "0.2.17"
715+source = "registry+https://github.com/rust-lang/crates.io-index"
716+checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
717+dependencies = [
718+ "libc",
719+]
720+
721+[[package]]
722+name = "cpufeatures"
723+version = "0.3.0"
724+source = "registry+https://github.com/rust-lang/crates.io-index"
725+checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201"
726+dependencies = [
727+ "libc",
728+]
729+
730+[[package]]
731+name = "crc32fast"
732+version = "1.5.0"
733+source = "registry+https://github.com/rust-lang/crates.io-index"
734+checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
735+dependencies = [
736+ "cfg-if",
737+]
738+
739+[[package]]
740+name = "crossbeam-channel"
741+version = "0.5.16"
742+source = "registry+https://github.com/rust-lang/crates.io-index"
743+checksum = "d85363c37faeca707aef026efa9f3b34d077bce547e48f770770625c6013679e"
744+dependencies = [
745+ "crossbeam-utils",
746+]
747+
748+[[package]]
749+name = "crossbeam-utils"
750+version = "0.8.22"
751+source = "registry+https://github.com/rust-lang/crates.io-index"
752+checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17"
753+
754+[[package]]
755+name = "crunchy"
756+version = "0.2.4"
757+source = "registry+https://github.com/rust-lang/crates.io-index"
758+checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
759+
760+[[package]]
761+name = "crypto-common"
762+version = "0.1.7"
763+source = "registry+https://github.com/rust-lang/crates.io-index"
764+checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
765+dependencies = [
766+ "generic-array",
767+ "typenum",
768+]
769+
770+[[package]]
771+name = "cssparser"
772+version = "0.36.0"
773+source = "registry+https://github.com/rust-lang/crates.io-index"
774+checksum = "dae61cf9c0abb83bd659dab65b7e4e38d8236824c85f0f804f173567bda257d2"
775+dependencies = [
776+ "cssparser-macros",
777+ "dtoa-short",
778+ "itoa",
779+ "phf",
780+ "smallvec",
781+]
782+
783+[[package]]
784+name = "cssparser-macros"
785+version = "0.6.1"
786+source = "registry+https://github.com/rust-lang/crates.io-index"
787+checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"
788+dependencies = [
789+ "quote",
790+ "syn 2.0.119",
791+]
792+
793+[[package]]
794+name = "ctor"
795+version = "0.8.0"
796+source = "registry+https://github.com/rust-lang/crates.io-index"
797+checksum = "352d39c2f7bef1d6ad73db6f5160efcaed66d94ef8c6c573a8410c00bf909a98"
798+dependencies = [
799+ "ctor-proc-macro",
800+ "dtor",
801+]
802+
803+[[package]]
804+name = "ctor-proc-macro"
805+version = "0.0.7"
806+source = "registry+https://github.com/rust-lang/crates.io-index"
807+checksum = "52560adf09603e58c9a7ee1fe1dcb95a16927b17c127f0ac02d6e768a0e25bc1"
808+
809+[[package]]
810+name = "darling"
811+version = "0.23.0"
812+source = "registry+https://github.com/rust-lang/crates.io-index"
813+checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d"
814+dependencies = [
815+ "darling_core",
816+ "darling_macro",
817+]
818+
819+[[package]]
820+name = "darling_core"
821+version = "0.23.0"
822+source = "registry+https://github.com/rust-lang/crates.io-index"
823+checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0"
824+dependencies = [
825+ "ident_case",
826+ "proc-macro2",
827+ "quote",
828+ "strsim",
829+ "syn 2.0.119",
830+]
831+
832+[[package]]
833+name = "darling_macro"
834+version = "0.23.0"
835+source = "registry+https://github.com/rust-lang/crates.io-index"
836+checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d"
837+dependencies = [
838+ "darling_core",
839+ "quote",
840+ "syn 2.0.119",
841+]
842+
843+[[package]]
844+name = "dasp_sample"
845+version = "0.11.0"
846+source = "registry+https://github.com/rust-lang/crates.io-index"
847+checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f"
848+
849+[[package]]
850+name = "dbus"
851+version = "0.9.12"
852+source = "registry+https://github.com/rust-lang/crates.io-index"
853+checksum = "3ab69f03cc8c4340c9c8e315114e1658e6775a9b16a04357973aa21cec22b32e"
854+dependencies = [
855+ "libc",
856+ "libdbus-sys",
857+ "windows-sys 0.61.2",
858+]
859+
860+[[package]]
861+name = "deranged"
862+version = "0.5.8"
863+source = "registry+https://github.com/rust-lang/crates.io-index"
864+checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c"
865+dependencies = [
866+ "serde_core",
867+]
868+
869+[[package]]
870+name = "derive_more"
871+version = "2.1.1"
872+source = "registry+https://github.com/rust-lang/crates.io-index"
873+checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134"
874+dependencies = [
875+ "derive_more-impl",
876+]
877+
878+[[package]]
879+name = "derive_more-impl"
880+version = "2.1.1"
881+source = "registry+https://github.com/rust-lang/crates.io-index"
882+checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb"
883+dependencies = [
884+ "proc-macro2",
885+ "quote",
886+ "rustc_version",
887+ "syn 2.0.119",
888+]
889+
890+[[package]]
891+name = "digest"
892+version = "0.10.7"
893+source = "registry+https://github.com/rust-lang/crates.io-index"
894+checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
895+dependencies = [
896+ "block-buffer",
897+ "crypto-common",
898+]
899+
900+[[package]]
901+name = "dirs"
902+version = "4.0.0"
903+source = "registry+https://github.com/rust-lang/crates.io-index"
904+checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
905+dependencies = [
906+ "dirs-sys 0.3.7",
907+]
908+
909+[[package]]
910+name = "dirs"
911+version = "6.0.0"
912+source = "registry+https://github.com/rust-lang/crates.io-index"
913+checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e"
914+dependencies = [
915+ "dirs-sys 0.5.0",
916+]
917+
918+[[package]]
919+name = "dirs-sys"
920+version = "0.3.7"
921+source = "registry+https://github.com/rust-lang/crates.io-index"
922+checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
923+dependencies = [
924+ "libc",
925+ "redox_users 0.4.6",
926+ "winapi",
927+]
928+
929+[[package]]
930+name = "dirs-sys"
931+version = "0.5.0"
932+source = "registry+https://github.com/rust-lang/crates.io-index"
933+checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab"
934+dependencies = [
935+ "libc",
936+ "option-ext",
937+ "redox_users 0.5.2",
938+ "windows-sys 0.61.2",
939+]
940+
941+[[package]]
942+name = "dispatch2"
943+version = "0.3.1"
944+source = "registry+https://github.com/rust-lang/crates.io-index"
945+checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38"
946+dependencies = [
947+ "bitflags 2.13.1",
948+ "block2",
949+ "libc",
950+ "objc2",
951+]
952+
953+[[package]]
954+name = "displaydoc"
955+version = "0.2.6"
956+source = "registry+https://github.com/rust-lang/crates.io-index"
957+checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f"
958+dependencies = [
959+ "proc-macro2",
960+ "quote",
961+ "syn 2.0.119",
962+]
963+
964+[[package]]
965+name = "dlopen2"
966+version = "0.8.2"
967+source = "registry+https://github.com/rust-lang/crates.io-index"
968+checksum = "5e2c5bd4158e66d1e215c49b837e11d62f3267b30c92f1d171c4d3105e3dc4d4"
969+dependencies = [
970+ "dlopen2_derive",
971+ "libc",
972+ "once_cell",
973+ "winapi",
974+]
975+
976+[[package]]
977+name = "dlopen2_derive"
978+version = "0.4.3"
979+source = "registry+https://github.com/rust-lang/crates.io-index"
980+checksum = "0fbbb781877580993a8707ec48672673ec7b81eeba04cfd2310bd28c08e47c8f"
981+dependencies = [
982+ "proc-macro2",
983+ "quote",
984+ "syn 2.0.119",
985+]
986+
987+[[package]]
988+name = "dom_query"
989+version = "0.27.0"
990+source = "registry+https://github.com/rust-lang/crates.io-index"
991+checksum = "521e380c0c8afb8d9a1e83a1822ee03556fc3e3e7dbc1fd30be14e37f9cb3f89"
992+dependencies = [
993+ "bit-set",
994+ "cssparser",
995+ "foldhash 0.2.0",
996+ "html5ever",
997+ "precomputed-hash",
998+ "selectors",
999+ "tendril",
1000+]
1001+
1002+[[package]]
1003+name = "downcast-rs"
1004+version = "1.2.1"
1005+source = "registry+https://github.com/rust-lang/crates.io-index"
1006+checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2"
1007+
1008+[[package]]
1009+name = "dpi"
1010+version = "0.1.2"
1011+source = "registry+https://github.com/rust-lang/crates.io-index"
1012+checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76"
1013+dependencies = [
1014+ "serde",
1015+]
1016+
1017+[[package]]
1018+name = "dtoa"
1019+version = "1.0.11"
1020+source = "registry+https://github.com/rust-lang/crates.io-index"
1021+checksum = "4c3cf4824e2d5f025c7b531afcb2325364084a16806f6d47fbc1f5fbd9960590"
1022+
1023+[[package]]
1024+name = "dtoa-short"
1025+version = "0.3.5"
1026+source = "registry+https://github.com/rust-lang/crates.io-index"
1027+checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87"
1028+dependencies = [
1029+ "dtoa",
1030+]
1031+
1032+[[package]]
1033+name = "dtor"
1034+version = "0.3.0"
1035+source = "registry+https://github.com/rust-lang/crates.io-index"
1036+checksum = "f1057d6c64987086ff8ed0fd3fbf377a6b7d205cc7715868cd401705f715cbe4"
1037+dependencies = [
1038+ "dtor-proc-macro",
1039+]
1040+
1041+[[package]]
1042+name = "dtor-proc-macro"
1043+version = "0.0.6"
1044+source = "registry+https://github.com/rust-lang/crates.io-index"
1045+checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5"
1046+
1047+[[package]]
1048+name = "dunce"
1049+version = "1.0.5"
1050+source = "registry+https://github.com/rust-lang/crates.io-index"
1051+checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
1052+
1053+[[package]]
1054+name = "dyn-clone"
1055+version = "1.0.20"
1056+source = "registry+https://github.com/rust-lang/crates.io-index"
1057+checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555"
1058+
1059+[[package]]
1060+name = "either"
1061+version = "1.16.0"
1062+source = "registry+https://github.com/rust-lang/crates.io-index"
1063+checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e"
1064+
1065+[[package]]
1066+name = "embed-resource"
1067+version = "3.0.11"
1068+source = "registry+https://github.com/rust-lang/crates.io-index"
1069+checksum = "fbfdaacccebec3b28e4866b8973543c7647797db5ada1bdab552e48fe665fbbd"
1070+dependencies = [
1071+ "cc",
1072+ "memchr",
1073+ "rustc_version",
1074+ "toml 1.1.3+spec-1.1.0",
1075+ "vswhom",
1076+ "winreg 0.55.0",
1077+]
1078+
1079+[[package]]
1080+name = "embed_plist"
1081+version = "1.2.2"
1082+source = "registry+https://github.com/rust-lang/crates.io-index"
1083+checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7"
1084+
1085+[[package]]
1086+name = "endi"
1087+version = "1.1.1"
1088+source = "registry+https://github.com/rust-lang/crates.io-index"
1089+checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099"
1090+
1091+[[package]]
1092+name = "enigo"
1093+version = "0.6.1"
1094+source = "registry+https://github.com/rust-lang/crates.io-index"
1095+checksum = "71c6c56e50f7acae2906a0dcbb34529ca647e40421119ad5d12e7f8ba6e50010"
1096+dependencies = [
1097+ "core-foundation",
1098+ "core-graphics",
1099+ "foreign-types-shared",
1100+ "libc",
1101+ "log",
1102+ "nom 8.0.0",
1103+ "objc2",
1104+ "objc2-app-kit",
1105+ "objc2-foundation",
1106+ "windows 0.61.3",
1107+ "x11rb",
1108+ "xkbcommon",
1109+ "xkeysym",
1110+]
1111+
1112+[[package]]
1113+name = "enumflags2"
1114+version = "0.7.12"
1115+source = "registry+https://github.com/rust-lang/crates.io-index"
1116+checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef"
1117+dependencies = [
1118+ "enumflags2_derive",
1119+ "serde",
1120+]
1121+
1122+[[package]]
1123+name = "enumflags2_derive"
1124+version = "0.7.12"
1125+source = "registry+https://github.com/rust-lang/crates.io-index"
1126+checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827"
1127+dependencies = [
1128+ "proc-macro2",
1129+ "quote",
1130+ "syn 2.0.119",
1131+]
1132+
1133+[[package]]
1134+name = "equivalent"
1135+version = "1.0.2"
1136+source = "registry+https://github.com/rust-lang/crates.io-index"
1137+checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
1138+
1139+[[package]]
1140+name = "erased-serde"
1141+version = "0.4.10"
1142+source = "registry+https://github.com/rust-lang/crates.io-index"
1143+checksum = "d2add8a07dd6a8d93ff627029c51de145e12686fbc36ecb298ac22e74cf02dec"
1144+dependencies = [
1145+ "serde",
1146+ "serde_core",
1147+ "typeid",
1148+]
1149+
1150+[[package]]
1151+name = "errno"
1152+version = "0.3.14"
1153+source = "registry+https://github.com/rust-lang/crates.io-index"
1154+checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
1155+dependencies = [
1156+ "libc",
1157+ "windows-sys 0.61.2",
1158+]
1159+
1160+[[package]]
1161+name = "error-code"
1162+version = "3.3.2"
1163+source = "registry+https://github.com/rust-lang/crates.io-index"
1164+checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59"
1165+
1166+[[package]]
1167+name = "event-listener"
1168+version = "5.4.1"
1169+source = "registry+https://github.com/rust-lang/crates.io-index"
1170+checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab"
1171+dependencies = [
1172+ "concurrent-queue",
1173+ "parking",
1174+ "pin-project-lite",
1175+]
1176+
1177+[[package]]
1178+name = "event-listener-strategy"
1179+version = "0.5.4"
1180+source = "registry+https://github.com/rust-lang/crates.io-index"
1181+checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93"
1182+dependencies = [
1183+ "event-listener",
1184+ "pin-project-lite",
1185+]
1186+
1187+[[package]]
1188+name = "fastrand"
1189+version = "2.5.0"
1190+source = "registry+https://github.com/rust-lang/crates.io-index"
1191+checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223"
1192+
1193+[[package]]
1194+name = "fax"
1195+version = "0.2.7"
1196+source = "registry+https://github.com/rust-lang/crates.io-index"
1197+checksum = "caf1079563223d5d59d83c85886a56e586cfd5c1a26292e971a0fa266531ac5a"
1198+
1199+[[package]]
1200+name = "fdeflate"
1201+version = "0.3.7"
1202+source = "registry+https://github.com/rust-lang/crates.io-index"
1203+checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c"
1204+dependencies = [
1205+ "simd-adler32",
1206+]
1207+
1208+[[package]]
1209+name = "field-offset"
1210+version = "0.3.6"
1211+source = "registry+https://github.com/rust-lang/crates.io-index"
1212+checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f"
1213+dependencies = [
1214+ "memoffset",
1215+ "rustc_version",
1216+]
1217+
1218+[[package]]
1219+name = "find-msvc-tools"
1220+version = "0.1.9"
1221+source = "registry+https://github.com/rust-lang/crates.io-index"
1222+checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
1223+
1224+[[package]]
1225+name = "fixedbitset"
1226+version = "0.5.7"
1227+source = "registry+https://github.com/rust-lang/crates.io-index"
1228+checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
1229+
1230+[[package]]
1231+name = "flate2"
1232+version = "1.1.9"
1233+source = "registry+https://github.com/rust-lang/crates.io-index"
1234+checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c"
1235+dependencies = [
1236+ "crc32fast",
1237+ "miniz_oxide",
1238+]
1239+
1240+[[package]]
1241+name = "fnv"
1242+version = "1.0.7"
1243+source = "registry+https://github.com/rust-lang/crates.io-index"
1244+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
1245+
1246+[[package]]
1247+name = "foldhash"
1248+version = "0.1.5"
1249+source = "registry+https://github.com/rust-lang/crates.io-index"
1250+checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
1251+
1252+[[package]]
1253+name = "foldhash"
1254+version = "0.2.0"
1255+source = "registry+https://github.com/rust-lang/crates.io-index"
1256+checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
1257+
1258+[[package]]
1259+name = "foreign-types"
1260+version = "0.5.0"
1261+source = "registry+https://github.com/rust-lang/crates.io-index"
1262+checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965"
1263+dependencies = [
1264+ "foreign-types-macros",
1265+ "foreign-types-shared",
1266+]
1267+
1268+[[package]]
1269+name = "foreign-types-macros"
1270+version = "0.2.4"
1271+source = "registry+https://github.com/rust-lang/crates.io-index"
1272+checksum = "ea5190182e6915eb873ddbc16e23b711b6eb1f9c00a0d0a3a91b5f6228475225"
1273+dependencies = [
1274+ "proc-macro2",
1275+ "quote",
1276+ "syn 3.0.3",
1277+]
1278+
1279+[[package]]
1280+name = "foreign-types-shared"
1281+version = "0.3.1"
1282+source = "registry+https://github.com/rust-lang/crates.io-index"
1283+checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b"
1284+
1285+[[package]]
1286+name = "form_urlencoded"
1287+version = "1.2.2"
1288+source = "registry+https://github.com/rust-lang/crates.io-index"
1289+checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"
1290+dependencies = [
1291+ "percent-encoding",
1292+]
1293+
1294+[[package]]
1295+name = "fs_extra"
1296+version = "1.3.0"
1297+source = "registry+https://github.com/rust-lang/crates.io-index"
1298+checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
1299+
1300+[[package]]
1301+name = "futures-channel"
1302+version = "0.3.33"
1303+source = "registry+https://github.com/rust-lang/crates.io-index"
1304+checksum = "262590f4fe6afeb0bc83be1daa64e52657fe185690a958af7f3ad0e92085c5ae"
1305+dependencies = [
1306+ "futures-core",
1307+]
1308+
1309+[[package]]
1310+name = "futures-core"
1311+version = "0.3.33"
1312+source = "registry+https://github.com/rust-lang/crates.io-index"
1313+checksum = "2cd50c473c80f6d7c3670a752354b8e569b1a7cbfdc0419ec88e5edad85e0dc7"
1314+
1315+[[package]]
1316+name = "futures-executor"
1317+version = "0.3.33"
1318+source = "registry+https://github.com/rust-lang/crates.io-index"
1319+checksum = "6754879cc9f2c66f88c6e5c35344bb0bdb0708b0352b1201815667c7eabc7458"
1320+dependencies = [
1321+ "futures-core",
1322+ "futures-task",
1323+ "futures-util",
1324+]
1325+
1326+[[package]]
1327+name = "futures-io"
1328+version = "0.3.33"
1329+source = "registry+https://github.com/rust-lang/crates.io-index"
1330+checksum = "4577ecaa3c4f96589d473f679a71b596316f6641bc350038b962a5daf0085d7a"
1331+
1332+[[package]]
1333+name = "futures-lite"
1334+version = "2.6.1"
1335+source = "registry+https://github.com/rust-lang/crates.io-index"
1336+checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad"
1337+dependencies = [
1338+ "fastrand",
1339+ "futures-core",
1340+ "futures-io",
1341+ "parking",
1342+ "pin-project-lite",
1343+]
1344+
1345+[[package]]
1346+name = "futures-macro"
1347+version = "0.3.33"
1348+source = "registry+https://github.com/rust-lang/crates.io-index"
1349+checksum = "2d6d3cde68c518367be28956066ddfef33813991b77a55005a69dae04bf3b10b"
1350+dependencies = [
1351+ "proc-macro2",
1352+ "quote",
1353+ "syn 2.0.119",
1354+]
1355+
1356+[[package]]
1357+name = "futures-sink"
1358+version = "0.3.33"
1359+source = "registry+https://github.com/rust-lang/crates.io-index"
1360+checksum = "e34418ac499d6305c2fb5ad0ed2f6ac998c5f8ca209b4510f7f94242c647e307"
1361+
1362+[[package]]
1363+name = "futures-task"
1364+version = "0.3.33"
1365+source = "registry+https://github.com/rust-lang/crates.io-index"
1366+checksum = "b231ed28831efb4a61a08580c4bc233ec56bc009f4cd8f52da2c3cb97df0c109"
1367+
1368+[[package]]
1369+name = "futures-util"
1370+version = "0.3.33"
1371+source = "registry+https://github.com/rust-lang/crates.io-index"
1372+checksum = "a77a90a256fce34da66415271e30f94ee91c57b04b8a2c042d9cf3220179deaa"
1373+dependencies = [
1374+ "futures-core",
1375+ "futures-io",
1376+ "futures-macro",
1377+ "futures-sink",
1378+ "futures-task",
1379+ "memchr",
1380+ "pin-project-lite",
1381+ "slab",
1382+]
1383+
1384+[[package]]
1385+name = "gdk"
1386+version = "0.18.2"
1387+source = "registry+https://github.com/rust-lang/crates.io-index"
1388+checksum = "d9f245958c627ac99d8e529166f9823fb3b838d1d41fd2b297af3075093c2691"
1389+dependencies = [
1390+ "cairo-rs",
1391+ "gdk-pixbuf",
1392+ "gdk-sys",
1393+ "gio",
1394+ "glib",
1395+ "libc",
1396+ "pango",
1397+]
1398+
1399+[[package]]
1400+name = "gdk-pixbuf"
1401+version = "0.18.5"
1402+source = "registry+https://github.com/rust-lang/crates.io-index"
1403+checksum = "50e1f5f1b0bfb830d6ccc8066d18db35c487b1b2b1e8589b5dfe9f07e8defaec"
1404+dependencies = [
1405+ "gdk-pixbuf-sys",
1406+ "gio",
1407+ "glib",
1408+ "libc",
1409+ "once_cell",
1410+]
1411+
1412+[[package]]
1413+name = "gdk-pixbuf-sys"
1414+version = "0.18.0"
1415+source = "registry+https://github.com/rust-lang/crates.io-index"
1416+checksum = "3f9839ea644ed9c97a34d129ad56d38a25e6756f99f3a88e15cd39c20629caf7"
1417+dependencies = [
1418+ "gio-sys",
1419+ "glib-sys",
1420+ "gobject-sys",
1421+ "libc",
1422+ "system-deps",
1423+]
1424+
1425+[[package]]
1426+name = "gdk-sys"
1427+version = "0.18.2"
1428+source = "registry+https://github.com/rust-lang/crates.io-index"
1429+checksum = "5c2d13f38594ac1e66619e188c6d5a1adb98d11b2fcf7894fc416ad76aa2f3f7"
1430+dependencies = [
1431+ "cairo-sys-rs",
1432+ "gdk-pixbuf-sys",
1433+ "gio-sys",
1434+ "glib-sys",
1435+ "gobject-sys",
1436+ "libc",
1437+ "pango-sys",
1438+ "pkg-config",
1439+ "system-deps",
1440+]
1441+
1442+[[package]]
1443+name = "gdkwayland-sys"
1444+version = "0.18.2"
1445+source = "registry+https://github.com/rust-lang/crates.io-index"
1446+checksum = "140071d506d223f7572b9f09b5e155afbd77428cd5cc7af8f2694c41d98dfe69"
1447+dependencies = [
1448+ "gdk-sys",
1449+ "glib-sys",
1450+ "gobject-sys",
1451+ "libc",
1452+ "pkg-config",
1453+ "system-deps",
1454+]
1455+
1456+[[package]]
1457+name = "gdkx11"
1458+version = "0.18.2"
1459+source = "registry+https://github.com/rust-lang/crates.io-index"
1460+checksum = "3caa00e14351bebbc8183b3c36690327eb77c49abc2268dd4bd36b856db3fbfe"
1461+dependencies = [
1462+ "gdk",
1463+ "gdkx11-sys",
1464+ "gio",
1465+ "glib",
1466+ "libc",
1467+ "x11",
1468+]
1469+
1470+[[package]]
1471+name = "gdkx11-sys"
1472+version = "0.18.2"
1473+source = "registry+https://github.com/rust-lang/crates.io-index"
1474+checksum = "6e2e7445fe01ac26f11601db260dd8608fe172514eb63b3b5e261ea6b0f4428d"
1475+dependencies = [
1476+ "gdk-sys",
1477+ "glib-sys",
1478+ "libc",
1479+ "system-deps",
1480+ "x11",
1481+]
1482+
1483+[[package]]
1484+name = "generic-array"
1485+version = "0.14.7"
1486+source = "registry+https://github.com/rust-lang/crates.io-index"
1487+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
1488+dependencies = [
1489+ "typenum",
1490+ "version_check",
1491+]
1492+
1493+[[package]]
1494+name = "gethostname"
1495+version = "1.1.0"
1496+source = "registry+https://github.com/rust-lang/crates.io-index"
1497+checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8"
1498+dependencies = [
1499+ "rustix",
1500+ "windows-link 0.2.1",
1501+]
1502+
1503+[[package]]
1504+name = "getrandom"
1505+version = "0.2.17"
1506+source = "registry+https://github.com/rust-lang/crates.io-index"
1507+checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
1508+dependencies = [
1509+ "cfg-if",
1510+ "js-sys",
1511+ "libc",
1512+ "wasi",
1513+ "wasm-bindgen",
1514+]
1515+
1516+[[package]]
1517+name = "getrandom"
1518+version = "0.3.4"
1519+source = "registry+https://github.com/rust-lang/crates.io-index"
1520+checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
1521+dependencies = [
1522+ "cfg-if",
1523+ "libc",
1524+ "r-efi 5.3.0",
1525+ "wasip2",
1526+]
1527+
1528+[[package]]
1529+name = "getrandom"
1530+version = "0.4.3"
1531+source = "registry+https://github.com/rust-lang/crates.io-index"
1532+checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
1533+dependencies = [
1534+ "cfg-if",
1535+ "js-sys",
1536+ "libc",
1537+ "r-efi 6.0.0",
1538+ "rand_core 0.10.1",
1539+ "wasm-bindgen",
1540+]
1541+
1542+[[package]]
1543+name = "gio"
1544+version = "0.18.4"
1545+source = "registry+https://github.com/rust-lang/crates.io-index"
1546+checksum = "d4fc8f532f87b79cbc51a79748f16a6828fb784be93145a322fa14d06d354c73"
1547+dependencies = [
1548+ "futures-channel",
1549+ "futures-core",
1550+ "futures-io",
1551+ "futures-util",
1552+ "gio-sys",
1553+ "glib",
1554+ "libc",
1555+ "once_cell",
1556+ "pin-project-lite",
1557+ "smallvec",
1558+ "thiserror 1.0.69",
1559+]
1560+
1561+[[package]]
1562+name = "gio-sys"
1563+version = "0.18.1"
1564+source = "registry+https://github.com/rust-lang/crates.io-index"
1565+checksum = "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2"
1566+dependencies = [
1567+ "glib-sys",
1568+ "gobject-sys",
1569+ "libc",
1570+ "system-deps",
1571+ "winapi",
1572+]
1573+
1574+[[package]]
1575+name = "glib"
1576+version = "0.18.5"
1577+source = "registry+https://github.com/rust-lang/crates.io-index"
1578+checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5"
1579+dependencies = [
1580+ "bitflags 2.13.1",
1581+ "futures-channel",
1582+ "futures-core",
1583+ "futures-executor",
1584+ "futures-task",
1585+ "futures-util",
1586+ "gio-sys",
1587+ "glib-macros",
1588+ "glib-sys",
1589+ "gobject-sys",
1590+ "libc",
1591+ "memchr",
1592+ "once_cell",
1593+ "smallvec",
1594+ "thiserror 1.0.69",
1595+]
1596+
1597+[[package]]
1598+name = "glib-macros"
1599+version = "0.18.5"
1600+source = "registry+https://github.com/rust-lang/crates.io-index"
1601+checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc"
1602+dependencies = [
1603+ "heck 0.4.1",
1604+ "proc-macro-crate 2.0.2",
1605+ "proc-macro-error",
1606+ "proc-macro2",
1607+ "quote",
1608+ "syn 2.0.119",
1609+]
1610+
1611+[[package]]
1612+name = "glib-sys"
1613+version = "0.18.1"
1614+source = "registry+https://github.com/rust-lang/crates.io-index"
1615+checksum = "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898"
1616+dependencies = [
1617+ "libc",
1618+ "system-deps",
1619+]
1620+
1621+[[package]]
1622+name = "glob"
1623+version = "0.3.4"
1624+source = "registry+https://github.com/rust-lang/crates.io-index"
1625+checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b"
1626+
1627+[[package]]
1628+name = "global-hotkey"
1629+version = "0.8.0"
1630+source = "registry+https://github.com/rust-lang/crates.io-index"
1631+checksum = "8c386b0a4a70cb2d39fffd74480f985b6f0bfbcb934b6a6b6b7e630e448f242e"
1632+dependencies = [
1633+ "crossbeam-channel",
1634+ "keyboard-types",
1635+ "objc2",
1636+ "objc2-app-kit",
1637+ "once_cell",
1638+ "serde",
1639+ "thiserror 2.0.19",
1640+ "windows-sys 0.59.0",
1641+ "x11rb",
1642+ "xkeysym",
1643+]
1644+
1645+[[package]]
1646+name = "gobject-sys"
1647+version = "0.18.0"
1648+source = "registry+https://github.com/rust-lang/crates.io-index"
1649+checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44"
1650+dependencies = [
1651+ "glib-sys",
1652+ "libc",
1653+ "system-deps",
1654+]
1655+
1656+[[package]]
1657+name = "gtk"
1658+version = "0.18.2"
1659+source = "registry+https://github.com/rust-lang/crates.io-index"
1660+checksum = "fd56fb197bfc42bd5d2751f4f017d44ff59fbb58140c6b49f9b3b2bdab08506a"
1661+dependencies = [
1662+ "atk",
1663+ "cairo-rs",
1664+ "field-offset",
1665+ "futures-channel",
1666+ "gdk",
1667+ "gdk-pixbuf",
1668+ "gio",
1669+ "glib",
1670+ "gtk-sys",
1671+ "gtk3-macros",
1672+ "libc",
1673+ "pango",
1674+ "pkg-config",
1675+]
1676+
1677+[[package]]
1678+name = "gtk-sys"
1679+version = "0.18.2"
1680+source = "registry+https://github.com/rust-lang/crates.io-index"
1681+checksum = "8f29a1c21c59553eb7dd40e918be54dccd60c52b049b75119d5d96ce6b624414"
1682+dependencies = [
1683+ "atk-sys",
1684+ "cairo-sys-rs",
1685+ "gdk-pixbuf-sys",
1686+ "gdk-sys",
1687+ "gio-sys",
1688+ "glib-sys",
1689+ "gobject-sys",
1690+ "libc",
1691+ "pango-sys",
1692+ "system-deps",
1693+]
1694+
1695+[[package]]
1696+name = "gtk3-macros"
1697+version = "0.18.2"
1698+source = "registry+https://github.com/rust-lang/crates.io-index"
1699+checksum = "52ff3c5b21f14f0736fed6dcfc0bfb4225ebf5725f3c0209edeec181e4d73e9d"
1700+dependencies = [
1701+ "proc-macro-crate 1.3.1",
1702+ "proc-macro-error",
1703+ "proc-macro2",
1704+ "quote",
1705+ "syn 2.0.119",
1706+]
1707+
1708+[[package]]
1709+name = "half"
1710+version = "2.7.1"
1711+source = "registry+https://github.com/rust-lang/crates.io-index"
1712+checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b"
1713+dependencies = [
1714+ "cfg-if",
1715+ "crunchy",
1716+ "zerocopy",
1717+]
1718+
1719+[[package]]
1720+name = "hashbrown"
1721+version = "0.12.3"
1722+source = "registry+https://github.com/rust-lang/crates.io-index"
1723+checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
1724+
1725+[[package]]
1726+name = "hashbrown"
1727+version = "0.15.5"
1728+source = "registry+https://github.com/rust-lang/crates.io-index"
1729+checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
1730+dependencies = [
1731+ "foldhash 0.1.5",
1732+]
1733+
1734+[[package]]
1735+name = "hashbrown"
1736+version = "0.17.1"
1737+source = "registry+https://github.com/rust-lang/crates.io-index"
1738+checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
1739+
1740+[[package]]
1741+name = "heck"
1742+version = "0.4.1"
1743+source = "registry+https://github.com/rust-lang/crates.io-index"
1744+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
1745+
1746+[[package]]
1747+name = "heck"
1748+version = "0.5.0"
1749+source = "registry+https://github.com/rust-lang/crates.io-index"
1750+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
1751+
1752+[[package]]
1753+name = "hermit-abi"
1754+version = "0.5.2"
1755+source = "registry+https://github.com/rust-lang/crates.io-index"
1756+checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
1757+
1758+[[package]]
1759+name = "hex"
1760+version = "0.4.3"
1761+source = "registry+https://github.com/rust-lang/crates.io-index"
1762+checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
1763+
1764+[[package]]
1765+name = "html5ever"
1766+version = "0.38.0"
1767+source = "registry+https://github.com/rust-lang/crates.io-index"
1768+checksum = "1054432bae2f14e0061e33d23402fbaa67a921d319d56adc6bcf887ddad1cbc2"
1769+dependencies = [
1770+ "log",
1771+ "markup5ever",
1772+]
1773+
1774+[[package]]
1775+name = "http"
1776+version = "1.4.2"
1777+source = "registry+https://github.com/rust-lang/crates.io-index"
1778+checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425"
1779+dependencies = [
1780+ "bytes",
1781+ "itoa",
1782+]
1783+
1784+[[package]]
1785+name = "http-body"
1786+version = "1.1.0"
1787+source = "registry+https://github.com/rust-lang/crates.io-index"
1788+checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c"
1789+dependencies = [
1790+ "bytes",
1791+ "http",
1792+]
1793+
1794+[[package]]
1795+name = "http-body-util"
1796+version = "0.1.4"
1797+source = "registry+https://github.com/rust-lang/crates.io-index"
1798+checksum = "e9f41fd6a08e4d4ec69df65976da761afd5ad5e58a9d4acb46bd1c953a9e3ff2"
1799+dependencies = [
1800+ "bytes",
1801+ "futures-core",
1802+ "http",
1803+ "http-body",
1804+ "pin-project-lite",
1805+]
1806+
1807+[[package]]
1808+name = "httparse"
1809+version = "1.10.1"
1810+source = "registry+https://github.com/rust-lang/crates.io-index"
1811+checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
1812+
1813+[[package]]
1814+name = "hyper"
1815+version = "1.11.0"
1816+source = "registry+https://github.com/rust-lang/crates.io-index"
1817+checksum = "d22053281f852e11534f5198498373cbb59295120a20771d90f7ed1897490a72"
1818+dependencies = [
1819+ "atomic-waker",
1820+ "bytes",
1821+ "futures-channel",
1822+ "futures-core",
1823+ "http",
1824+ "http-body",
1825+ "httparse",
1826+ "itoa",
1827+ "pin-project-lite",
1828+ "smallvec",
1829+ "tokio",
1830+ "want",
1831+]
1832+
1833+[[package]]
1834+name = "hyper-rustls"
1835+version = "0.27.9"
1836+source = "registry+https://github.com/rust-lang/crates.io-index"
1837+checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f"
1838+dependencies = [
1839+ "http",
1840+ "hyper",
1841+ "hyper-util",
1842+ "rustls",
1843+ "tokio",
1844+ "tokio-rustls",
1845+ "tower-service",
1846+ "webpki-roots",
1847+]
1848+
1849+[[package]]
1850+name = "hyper-util"
1851+version = "0.1.20"
1852+source = "registry+https://github.com/rust-lang/crates.io-index"
1853+checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0"
1854+dependencies = [
1855+ "base64 0.22.1",
1856+ "bytes",
1857+ "futures-channel",
1858+ "futures-util",
1859+ "http",
1860+ "http-body",
1861+ "hyper",
1862+ "ipnet",
1863+ "libc",
1864+ "percent-encoding",
1865+ "pin-project-lite",
1866+ "socket2",
1867+ "tokio",
1868+ "tower-service",
1869+ "tracing",
1870+]
1871+
1872+[[package]]
1873+name = "iana-time-zone"
1874+version = "0.1.65"
1875+source = "registry+https://github.com/rust-lang/crates.io-index"
1876+checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470"
1877+dependencies = [
1878+ "android_system_properties",
1879+ "core-foundation-sys",
1880+ "iana-time-zone-haiku",
1881+ "js-sys",
1882+ "log",
1883+ "wasm-bindgen",
1884+ "windows-core 0.62.2",
1885+]
1886+
1887+[[package]]
1888+name = "iana-time-zone-haiku"
1889+version = "0.1.2"
1890+source = "registry+https://github.com/rust-lang/crates.io-index"
1891+checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
1892+dependencies = [
1893+ "cc",
1894+]
1895+
1896+[[package]]
1897+name = "ico"
1898+version = "0.5.0"
1899+source = "registry+https://github.com/rust-lang/crates.io-index"
1900+checksum = "3e795dff5605e0f04bff85ca41b51a96b83e80b281e96231bcaaf1ac35103371"
1901+dependencies = [
1902+ "byteorder",
1903+ "png 0.17.16",
1904+]
1905+
1906+[[package]]
1907+name = "icu_collections"
1908+version = "2.2.0"
1909+source = "registry+https://github.com/rust-lang/crates.io-index"
1910+checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c"
1911+dependencies = [
1912+ "displaydoc",
1913+ "potential_utf",
1914+ "utf8_iter",
1915+ "yoke",
1916+ "zerofrom",
1917+ "zerovec",
1918+]
1919+
1920+[[package]]
1921+name = "icu_locale_core"
1922+version = "2.2.0"
1923+source = "registry+https://github.com/rust-lang/crates.io-index"
1924+checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29"
1925+dependencies = [
1926+ "displaydoc",
1927+ "litemap",
1928+ "tinystr",
1929+ "writeable",
1930+ "zerovec",
1931+]
1932+
1933+[[package]]
1934+name = "icu_normalizer"
1935+version = "2.2.0"
1936+source = "registry+https://github.com/rust-lang/crates.io-index"
1937+checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4"
1938+dependencies = [
1939+ "icu_collections",
1940+ "icu_normalizer_data",
1941+ "icu_properties",
1942+ "icu_provider",
1943+ "smallvec",
1944+ "zerovec",
1945+]
1946+
1947+[[package]]
1948+name = "icu_normalizer_data"
1949+version = "2.2.0"
1950+source = "registry+https://github.com/rust-lang/crates.io-index"
1951+checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38"
1952+
1953+[[package]]
1954+name = "icu_properties"
1955+version = "2.2.0"
1956+source = "registry+https://github.com/rust-lang/crates.io-index"
1957+checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de"
1958+dependencies = [
1959+ "icu_collections",
1960+ "icu_locale_core",
1961+ "icu_properties_data",
1962+ "icu_provider",
1963+ "zerotrie",
1964+ "zerovec",
1965+]
1966+
1967+[[package]]
1968+name = "icu_properties_data"
1969+version = "2.2.0"
1970+source = "registry+https://github.com/rust-lang/crates.io-index"
1971+checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14"
1972+
1973+[[package]]
1974+name = "icu_provider"
1975+version = "2.2.0"
1976+source = "registry+https://github.com/rust-lang/crates.io-index"
1977+checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421"
1978+dependencies = [
1979+ "displaydoc",
1980+ "icu_locale_core",
1981+ "writeable",
1982+ "yoke",
1983+ "zerofrom",
1984+ "zerotrie",
1985+ "zerovec",
1986+]
1987+
1988+[[package]]
1989+name = "ident_case"
1990+version = "1.0.1"
1991+source = "registry+https://github.com/rust-lang/crates.io-index"
1992+checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
1993+
1994+[[package]]
1995+name = "idna"
1996+version = "1.1.0"
1997+source = "registry+https://github.com/rust-lang/crates.io-index"
1998+checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de"
1999+dependencies = [
2000+ "idna_adapter",
2001+ "smallvec",
2002+ "utf8_iter",
2003+]
2004+
2005+[[package]]
2006+name = "idna_adapter"
2007+version = "1.2.2"
2008+source = "registry+https://github.com/rust-lang/crates.io-index"
2009+checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714"
2010+dependencies = [
2011+ "icu_normalizer",
2012+ "icu_properties",
2013+]
2014+
2015+[[package]]
2016+name = "image"
2017+version = "0.25.10"
2018+source = "registry+https://github.com/rust-lang/crates.io-index"
2019+checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104"
2020+dependencies = [
2021+ "bytemuck",
2022+ "byteorder-lite",
2023+ "moxcms",
2024+ "num-traits",
2025+ "png 0.18.1",
2026+ "tiff",
2027+]
2028+
2029+[[package]]
2030+name = "indexmap"
2031+version = "1.9.3"
2032+source = "registry+https://github.com/rust-lang/crates.io-index"
2033+checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
2034+dependencies = [
2035+ "autocfg",
2036+ "hashbrown 0.12.3",
2037+ "serde",
2038+]
2039+
2040+[[package]]
2041+name = "indexmap"
2042+version = "2.14.0"
2043+source = "registry+https://github.com/rust-lang/crates.io-index"
2044+checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
2045+dependencies = [
2046+ "equivalent",
2047+ "hashbrown 0.17.1",
2048+ "serde",
2049+ "serde_core",
2050+]
2051+
2052+[[package]]
2053+name = "infer"
2054+version = "0.19.0"
2055+source = "registry+https://github.com/rust-lang/crates.io-index"
2056+checksum = "a588916bfdfd92e71cacef98a63d9b1f0d74d6599980d11894290e7ddefffcf7"
2057+dependencies = [
2058+ "cfb",
2059+]
2060+
2061+[[package]]
2062+name = "ipnet"
2063+version = "2.12.0"
2064+source = "registry+https://github.com/rust-lang/crates.io-index"
2065+checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2"
2066+
2067+[[package]]
2068+name = "is-docker"
2069+version = "0.2.0"
2070+source = "registry+https://github.com/rust-lang/crates.io-index"
2071+checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3"
2072+dependencies = [
2073+ "once_cell",
2074+]
2075+
2076+[[package]]
2077+name = "is-wsl"
2078+version = "0.4.0"
2079+source = "registry+https://github.com/rust-lang/crates.io-index"
2080+checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5"
2081+dependencies = [
2082+ "is-docker",
2083+ "once_cell",
2084+]
2085+
2086+[[package]]
2087+name = "itertools"
2088+version = "0.13.0"
2089+source = "registry+https://github.com/rust-lang/crates.io-index"
2090+checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
2091+dependencies = [
2092+ "either",
2093+]
2094+
2095+[[package]]
2096+name = "itoa"
2097+version = "1.0.18"
2098+source = "registry+https://github.com/rust-lang/crates.io-index"
2099+checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
2100+
2101+[[package]]
2102+name = "javascriptcore-rs"
2103+version = "1.1.2"
2104+source = "registry+https://github.com/rust-lang/crates.io-index"
2105+checksum = "ca5671e9ffce8ffba57afc24070e906da7fc4b1ba66f2cabebf61bf2ea257fcc"
2106+dependencies = [
2107+ "bitflags 1.3.2",
2108+ "glib",
2109+ "javascriptcore-rs-sys",
2110+]
2111+
2112+[[package]]
2113+name = "javascriptcore-rs-sys"
2114+version = "1.1.1"
2115+source = "registry+https://github.com/rust-lang/crates.io-index"
2116+checksum = "af1be78d14ffa4b75b66df31840478fef72b51f8c2465d4ca7c194da9f7a5124"
2117+dependencies = [
2118+ "glib-sys",
2119+ "gobject-sys",
2120+ "libc",
2121+ "system-deps",
2122+]
2123+
2124+[[package]]
2125+name = "jni"
2126+version = "0.21.1"
2127+source = "registry+https://github.com/rust-lang/crates.io-index"
2128+checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97"
2129+dependencies = [
2130+ "cesu8",
2131+ "cfg-if",
2132+ "combine",
2133+ "jni-sys 0.3.1",
2134+ "log",
2135+ "thiserror 1.0.69",
2136+ "walkdir",
2137+ "windows-sys 0.45.0",
2138+]
2139+
2140+[[package]]
2141+name = "jni-sys"
2142+version = "0.3.1"
2143+source = "registry+https://github.com/rust-lang/crates.io-index"
2144+checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258"
2145+dependencies = [
2146+ "jni-sys 0.4.1",
2147+]
2148+
2149+[[package]]
2150+name = "jni-sys"
2151+version = "0.4.1"
2152+source = "registry+https://github.com/rust-lang/crates.io-index"
2153+checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2"
2154+dependencies = [
2155+ "jni-sys-macros",
2156+]
2157+
2158+[[package]]
2159+name = "jni-sys-macros"
2160+version = "0.4.1"
2161+source = "registry+https://github.com/rust-lang/crates.io-index"
2162+checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264"
2163+dependencies = [
2164+ "quote",
2165+ "syn 2.0.119",
2166+]
2167+
2168+[[package]]
2169+name = "js-sys"
2170+version = "0.3.103"
2171+source = "registry+https://github.com/rust-lang/crates.io-index"
2172+checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102"
2173+dependencies = [
2174+ "cfg-if",
2175+ "futures-util",
2176+ "wasm-bindgen",
2177+]
2178+
2179+[[package]]
2180+name = "json-patch"
2181+version = "3.0.1"
2182+source = "registry+https://github.com/rust-lang/crates.io-index"
2183+checksum = "863726d7afb6bc2590eeff7135d923545e5e964f004c2ccf8716c25e70a86f08"
2184+dependencies = [
2185+ "jsonptr",
2186+ "serde",
2187+ "serde_json",
2188+ "thiserror 1.0.69",
2189+]
2190+
2191+[[package]]
2192+name = "jsonptr"
2193+version = "0.6.3"
2194+source = "registry+https://github.com/rust-lang/crates.io-index"
2195+checksum = "5dea2b27dd239b2556ed7a25ba842fe47fd602e7fc7433c2a8d6106d4d9edd70"
2196+dependencies = [
2197+ "serde",
2198+ "serde_json",
2199+]
2200+
2201+[[package]]
2202+name = "keyboard-types"
2203+version = "0.7.0"
2204+source = "registry+https://github.com/rust-lang/crates.io-index"
2205+checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a"
2206+dependencies = [
2207+ "bitflags 2.13.1",
2208+ "serde",
2209+ "unicode-segmentation",
2210+]
2211+
2212+[[package]]
2213+name = "libappindicator"
2214+version = "0.9.0"
2215+source = "registry+https://github.com/rust-lang/crates.io-index"
2216+checksum = "03589b9607c868cc7ae54c0b2a22c8dc03dd41692d48f2d7df73615c6a95dc0a"
2217+dependencies = [
2218+ "glib",
2219+ "gtk",
2220+ "gtk-sys",
2221+ "libappindicator-sys",
2222+ "log",
2223+]
2224+
2225+[[package]]
2226+name = "libappindicator-sys"
2227+version = "0.9.0"
2228+source = "registry+https://github.com/rust-lang/crates.io-index"
2229+checksum = "6e9ec52138abedcc58dc17a7c6c0c00a2bdb4f3427c7f63fa97fd0d859155caf"
2230+dependencies = [
2231+ "gtk-sys",
2232+ "libloading 0.7.4",
2233+ "once_cell",
2234+]
2235+
2236+[[package]]
2237+name = "libc"
2238+version = "0.2.189"
2239+source = "registry+https://github.com/rust-lang/crates.io-index"
2240+checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
2241+
2242+[[package]]
2243+name = "libdbus-sys"
2244+version = "0.2.7"
2245+source = "registry+https://github.com/rust-lang/crates.io-index"
2246+checksum = "328c4789d42200f1eeec05bd86c9c13c7f091d2ba9a6ea35acdf51f31bc0f043"
2247+dependencies = [
2248+ "pkg-config",
2249+]
2250+
2251+[[package]]
2252+name = "libloading"
2253+version = "0.7.4"
2254+source = "registry+https://github.com/rust-lang/crates.io-index"
2255+checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
2256+dependencies = [
2257+ "cfg-if",
2258+ "winapi",
2259+]
2260+
2261+[[package]]
2262+name = "libloading"
2263+version = "0.8.9"
2264+source = "registry+https://github.com/rust-lang/crates.io-index"
2265+checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55"
2266+dependencies = [
2267+ "cfg-if",
2268+ "windows-link 0.2.1",
2269+]
2270+
2271+[[package]]
2272+name = "libredox"
2273+version = "0.1.18"
2274+source = "registry+https://github.com/rust-lang/crates.io-index"
2275+checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652"
2276+dependencies = [
2277+ "libc",
2278+]
2279+
2280+[[package]]
2281+name = "linux-raw-sys"
2282+version = "0.12.1"
2283+source = "registry+https://github.com/rust-lang/crates.io-index"
2284+checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
2285+
2286+[[package]]
2287+name = "litemap"
2288+version = "0.8.2"
2289+source = "registry+https://github.com/rust-lang/crates.io-index"
2290+checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0"
2291+
2292+[[package]]
2293+name = "lock_api"
2294+version = "0.4.14"
2295+source = "registry+https://github.com/rust-lang/crates.io-index"
2296+checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
2297+dependencies = [
2298+ "scopeguard",
2299+]
2300+
2301+[[package]]
2302+name = "log"
2303+version = "0.4.33"
2304+source = "registry+https://github.com/rust-lang/crates.io-index"
2305+checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad"
2306+
2307+[[package]]
2308+name = "lru-slab"
2309+version = "0.1.2"
2310+source = "registry+https://github.com/rust-lang/crates.io-index"
2311+checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
2312+
2313+[[package]]
2314+name = "mac-notification-sys"
2315+version = "0.6.15"
2316+source = "registry+https://github.com/rust-lang/crates.io-index"
2317+checksum = "fd604973958ddcc11b561193c0fb96ba146506ef2f231ef2e7c35fd2cbc9beca"
2318+dependencies = [
2319+ "cc",
2320+ "log",
2321+ "objc2",
2322+ "objc2-foundation",
2323+ "time",
2324+ "uuid",
2325+]
2326+
2327+[[package]]
2328+name = "mach2"
2329+version = "0.4.3"
2330+source = "registry+https://github.com/rust-lang/crates.io-index"
2331+checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44"
2332+dependencies = [
2333+ "libc",
2334+]
2335+
2336+[[package]]
2337+name = "markup5ever"
2338+version = "0.38.0"
2339+source = "registry+https://github.com/rust-lang/crates.io-index"
2340+checksum = "8983d30f2915feeaaab2d6babdd6bc7e9ed1a00b66b5e6d74df19aa9c0e91862"
2341+dependencies = [
2342+ "log",
2343+ "tendril",
2344+ "web_atoms",
2345+]
2346+
2347+[[package]]
2348+name = "memchr"
2349+version = "2.8.3"
2350+source = "registry+https://github.com/rust-lang/crates.io-index"
2351+checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
2352+
2353+[[package]]
2354+name = "memmap2"
2355+version = "0.9.11"
2356+source = "registry+https://github.com/rust-lang/crates.io-index"
2357+checksum = "d1219ed1b7f229ee7104d281dd01d6802fe28bb6e95d292942c4daacdeb798c0"
2358+dependencies = [
2359+ "libc",
2360+]
2361+
2362+[[package]]
2363+name = "memoffset"
2364+version = "0.9.1"
2365+source = "registry+https://github.com/rust-lang/crates.io-index"
2366+checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
2367+dependencies = [
2368+ "autocfg",
2369+]
2370+
2371+[[package]]
2372+name = "mime"
2373+version = "0.3.17"
2374+source = "registry+https://github.com/rust-lang/crates.io-index"
2375+checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
2376+
2377+[[package]]
2378+name = "minimal-lexical"
2379+version = "0.2.1"
2380+source = "registry+https://github.com/rust-lang/crates.io-index"
2381+checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
2382+
2383+[[package]]
2384+name = "miniz_oxide"
2385+version = "0.8.9"
2386+source = "registry+https://github.com/rust-lang/crates.io-index"
2387+checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
2388+dependencies = [
2389+ "adler2",
2390+ "simd-adler32",
2391+]
2392+
2393+[[package]]
2394+name = "mio"
2395+version = "1.2.2"
2396+source = "registry+https://github.com/rust-lang/crates.io-index"
2397+checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427"
2398+dependencies = [
2399+ "libc",
2400+ "wasi",
2401+ "windows-sys 0.61.2",
2402+]
2403+
2404+[[package]]
2405+name = "moxcms"
2406+version = "0.8.1"
2407+source = "registry+https://github.com/rust-lang/crates.io-index"
2408+checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b"
2409+dependencies = [
2410+ "num-traits",
2411+ "pxfm",
2412+]
2413+
2414+[[package]]
2415+name = "muda"
2416+version = "0.19.3"
2417+source = "registry+https://github.com/rust-lang/crates.io-index"
2418+checksum = "1dd04e60bc0b07438a6771710ee1698f98f6ebbc7f89b61264af1563b8aeb878"
2419+dependencies = [
2420+ "crossbeam-channel",
2421+ "dpi",
2422+ "gtk",
2423+ "keyboard-types",
2424+ "objc2",
2425+ "objc2-app-kit",
2426+ "objc2-core-foundation",
2427+ "objc2-foundation",
2428+ "once_cell",
2429+ "png 0.18.1",
2430+ "serde",
2431+ "thiserror 2.0.19",
2432+ "windows-sys 0.61.2",
2433+]
2434+
2435+[[package]]
2436+name = "mutterbox"
2437+version = "0.1.0"
2438+dependencies = [
2439+ "cpal",
2440+ "enigo",
2441+ "futures-util",
2442+ "reqwest 0.12.28",
2443+ "serde",
2444+ "serde_json",
2445+ "tauri",
2446+ "tauri-build",
2447+ "tauri-plugin-autostart",
2448+ "tauri-plugin-clipboard-manager",
2449+ "tauri-plugin-global-shortcut",
2450+ "tauri-plugin-notification",
2451+ "tauri-plugin-opener",
2452+ "tauri-plugin-single-instance",
2453+ "tokio",
2454+ "whisper-rs",
2455+]
2456+
2457+[[package]]
2458+name = "ndk"
2459+version = "0.9.0"
2460+source = "registry+https://github.com/rust-lang/crates.io-index"
2461+checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4"
2462+dependencies = [
2463+ "bitflags 2.13.1",
2464+ "jni-sys 0.3.1",
2465+ "log",
2466+ "ndk-sys",
2467+ "num_enum",
2468+ "raw-window-handle",
2469+ "thiserror 1.0.69",
2470+]
2471+
2472+[[package]]
2473+name = "ndk-context"
2474+version = "0.1.1"
2475+source = "registry+https://github.com/rust-lang/crates.io-index"
2476+checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b"
2477+
2478+[[package]]
2479+name = "ndk-sys"
2480+version = "0.6.0+11769913"
2481+source = "registry+https://github.com/rust-lang/crates.io-index"
2482+checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873"
2483+dependencies = [
2484+ "jni-sys 0.3.1",
2485+]
2486+
2487+[[package]]
2488+name = "new_debug_unreachable"
2489+version = "1.0.6"
2490+source = "registry+https://github.com/rust-lang/crates.io-index"
2491+checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
2492+
2493+[[package]]
2494+name = "nom"
2495+version = "7.1.3"
2496+source = "registry+https://github.com/rust-lang/crates.io-index"
2497+checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
2498+dependencies = [
2499+ "memchr",
2500+ "minimal-lexical",
2501+]
2502+
2503+[[package]]
2504+name = "nom"
2505+version = "8.0.0"
2506+source = "registry+https://github.com/rust-lang/crates.io-index"
2507+checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405"
2508+dependencies = [
2509+ "memchr",
2510+]
2511+
2512+[[package]]
2513+name = "notify-rust"
2514+version = "4.18.0"
2515+source = "registry+https://github.com/rust-lang/crates.io-index"
2516+checksum = "c5b4c1b4f2aa9f25f63a7a49d3dd0ed567b3670da15330a66b29434be899b891"
2517+dependencies = [
2518+ "futures-lite",
2519+ "log",
2520+ "mac-notification-sys",
2521+ "serde",
2522+ "tauri-winrt-notification",
2523+ "zbus",
2524+]
2525+
2526+[[package]]
2527+name = "num-conv"
2528+version = "0.2.2"
2529+source = "registry+https://github.com/rust-lang/crates.io-index"
2530+checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441"
2531+
2532+[[package]]
2533+name = "num-derive"
2534+version = "0.4.2"
2535+source = "registry+https://github.com/rust-lang/crates.io-index"
2536+checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
2537+dependencies = [
2538+ "proc-macro2",
2539+ "quote",
2540+ "syn 2.0.119",
2541+]
2542+
2543+[[package]]
2544+name = "num-traits"
2545+version = "0.2.19"
2546+source = "registry+https://github.com/rust-lang/crates.io-index"
2547+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
2548+dependencies = [
2549+ "autocfg",
2550+]
2551+
2552+[[package]]
2553+name = "num_enum"
2554+version = "0.7.6"
2555+source = "registry+https://github.com/rust-lang/crates.io-index"
2556+checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26"
2557+dependencies = [
2558+ "num_enum_derive",
2559+ "rustversion",
2560+]
2561+
2562+[[package]]
2563+name = "num_enum_derive"
2564+version = "0.7.6"
2565+source = "registry+https://github.com/rust-lang/crates.io-index"
2566+checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8"
2567+dependencies = [
2568+ "proc-macro-crate 3.5.0",
2569+ "proc-macro2",
2570+ "quote",
2571+ "syn 2.0.119",
2572+]
2573+
2574+[[package]]
2575+name = "objc2"
2576+version = "0.6.4"
2577+source = "registry+https://github.com/rust-lang/crates.io-index"
2578+checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f"
2579+dependencies = [
2580+ "objc2-encode",
2581+ "objc2-exception-helper",
2582+]
2583+
2584+[[package]]
2585+name = "objc2-app-kit"
2586+version = "0.3.2"
2587+source = "registry+https://github.com/rust-lang/crates.io-index"
2588+checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c"
2589+dependencies = [
2590+ "bitflags 2.13.1",
2591+ "block2",
2592+ "objc2",
2593+ "objc2-core-foundation",
2594+ "objc2-core-graphics",
2595+ "objc2-foundation",
2596+]
2597+
2598+[[package]]
2599+name = "objc2-audio-toolbox"
2600+version = "0.3.2"
2601+source = "registry+https://github.com/rust-lang/crates.io-index"
2602+checksum = "6948501a91121d6399b79abaa33a8aa4ea7857fe019f341b8c23ad6e81b79b08"
2603+dependencies = [
2604+ "bitflags 2.13.1",
2605+ "libc",
2606+ "objc2",
2607+ "objc2-core-audio",
2608+ "objc2-core-audio-types",
2609+ "objc2-core-foundation",
2610+ "objc2-foundation",
2611+]
2612+
2613+[[package]]
2614+name = "objc2-cloud-kit"
2615+version = "0.3.2"
2616+source = "registry+https://github.com/rust-lang/crates.io-index"
2617+checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c"
2618+dependencies = [
2619+ "bitflags 2.13.1",
2620+ "objc2",
2621+ "objc2-foundation",
2622+]
2623+
2624+[[package]]
2625+name = "objc2-core-audio"
2626+version = "0.3.2"
2627+source = "registry+https://github.com/rust-lang/crates.io-index"
2628+checksum = "e1eebcea8b0dbff5f7c8504f3107c68fc061a3eb44932051c8cf8a68d969c3b2"
2629+dependencies = [
2630+ "dispatch2",
2631+ "objc2",
2632+ "objc2-core-audio-types",
2633+ "objc2-core-foundation",
2634+]
2635+
2636+[[package]]
2637+name = "objc2-core-audio-types"
2638+version = "0.3.2"
2639+source = "registry+https://github.com/rust-lang/crates.io-index"
2640+checksum = "5a89f2ec274a0cf4a32642b2991e8b351a404d290da87bb6a9a9d8632490bd1c"
2641+dependencies = [
2642+ "bitflags 2.13.1",
2643+ "objc2",
2644+]
2645+
2646+[[package]]
2647+name = "objc2-core-data"
2648+version = "0.3.2"
2649+source = "registry+https://github.com/rust-lang/crates.io-index"
2650+checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa"
2651+dependencies = [
2652+ "objc2",
2653+ "objc2-foundation",
2654+]
2655+
2656+[[package]]
2657+name = "objc2-core-foundation"
2658+version = "0.3.2"
2659+source = "registry+https://github.com/rust-lang/crates.io-index"
2660+checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
2661+dependencies = [
2662+ "bitflags 2.13.1",
2663+ "dispatch2",
2664+ "objc2",
2665+]
2666+
2667+[[package]]
2668+name = "objc2-core-graphics"
2669+version = "0.3.2"
2670+source = "registry+https://github.com/rust-lang/crates.io-index"
2671+checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807"
2672+dependencies = [
2673+ "bitflags 2.13.1",
2674+ "dispatch2",
2675+ "objc2",
2676+ "objc2-core-foundation",
2677+ "objc2-io-surface",
2678+]
2679+
2680+[[package]]
2681+name = "objc2-core-image"
2682+version = "0.3.2"
2683+source = "registry+https://github.com/rust-lang/crates.io-index"
2684+checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006"
2685+dependencies = [
2686+ "objc2",
2687+ "objc2-foundation",
2688+]
2689+
2690+[[package]]
2691+name = "objc2-core-location"
2692+version = "0.3.2"
2693+source = "registry+https://github.com/rust-lang/crates.io-index"
2694+checksum = "ca347214e24bc973fc025fd0d36ebb179ff30536ed1f80252706db19ee452009"
2695+dependencies = [
2696+ "objc2",
2697+ "objc2-foundation",
2698+]
2699+
2700+[[package]]
2701+name = "objc2-core-text"
2702+version = "0.3.2"
2703+source = "registry+https://github.com/rust-lang/crates.io-index"
2704+checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d"
2705+dependencies = [
2706+ "bitflags 2.13.1",
2707+ "objc2",
2708+ "objc2-core-foundation",
2709+ "objc2-core-graphics",
2710+]
2711+
2712+[[package]]
2713+name = "objc2-encode"
2714+version = "4.1.0"
2715+source = "registry+https://github.com/rust-lang/crates.io-index"
2716+checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
2717+
2718+[[package]]
2719+name = "objc2-exception-helper"
2720+version = "0.1.1"
2721+source = "registry+https://github.com/rust-lang/crates.io-index"
2722+checksum = "c7a1c5fbb72d7735b076bb47b578523aedc40f3c439bea6dfd595c089d79d98a"
2723+dependencies = [
2724+ "cc",
2725+]
2726+
2727+[[package]]
2728+name = "objc2-foundation"
2729+version = "0.3.2"
2730+source = "registry+https://github.com/rust-lang/crates.io-index"
2731+checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
2732+dependencies = [
2733+ "bitflags 2.13.1",
2734+ "block2",
2735+ "libc",
2736+ "objc2",
2737+ "objc2-core-foundation",
2738+]
2739+
2740+[[package]]
2741+name = "objc2-io-surface"
2742+version = "0.3.2"
2743+source = "registry+https://github.com/rust-lang/crates.io-index"
2744+checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d"
2745+dependencies = [
2746+ "bitflags 2.13.1",
2747+ "objc2",
2748+ "objc2-core-foundation",
2749+]
2750+
2751+[[package]]
2752+name = "objc2-quartz-core"
2753+version = "0.3.2"
2754+source = "registry+https://github.com/rust-lang/crates.io-index"
2755+checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f"
2756+dependencies = [
2757+ "bitflags 2.13.1",
2758+ "objc2",
2759+ "objc2-core-foundation",
2760+ "objc2-foundation",
2761+]
2762+
2763+[[package]]
2764+name = "objc2-ui-kit"
2765+version = "0.3.2"
2766+source = "registry+https://github.com/rust-lang/crates.io-index"
2767+checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22"
2768+dependencies = [
2769+ "bitflags 2.13.1",
2770+ "block2",
2771+ "objc2",
2772+ "objc2-cloud-kit",
2773+ "objc2-core-data",
2774+ "objc2-core-foundation",
2775+ "objc2-core-graphics",
2776+ "objc2-core-image",
2777+ "objc2-core-location",
2778+ "objc2-core-text",
2779+ "objc2-foundation",
2780+ "objc2-quartz-core",
2781+ "objc2-user-notifications",
2782+]
2783+
2784+[[package]]
2785+name = "objc2-user-notifications"
2786+version = "0.3.2"
2787+source = "registry+https://github.com/rust-lang/crates.io-index"
2788+checksum = "9df9128cbbfef73cda168416ccf7f837b62737d748333bfe9ab71c245d76613e"
2789+dependencies = [
2790+ "objc2",
2791+ "objc2-foundation",
2792+]
2793+
2794+[[package]]
2795+name = "objc2-web-kit"
2796+version = "0.3.2"
2797+source = "registry+https://github.com/rust-lang/crates.io-index"
2798+checksum = "b2e5aaab980c433cf470df9d7af96a7b46a9d892d521a2cbbb2f8a4c16751e7f"
2799+dependencies = [
2800+ "bitflags 2.13.1",
2801+ "block2",
2802+ "objc2",
2803+ "objc2-app-kit",
2804+ "objc2-core-foundation",
2805+ "objc2-foundation",
2806+]
2807+
2808+[[package]]
2809+name = "once_cell"
2810+version = "1.21.4"
2811+source = "registry+https://github.com/rust-lang/crates.io-index"
2812+checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
2813+
2814+[[package]]
2815+name = "open"
2816+version = "5.4.0"
2817+source = "registry+https://github.com/rust-lang/crates.io-index"
2818+checksum = "a0b3d059e795d52b8a72fef45658620edd4d9c359b338564aa14391ffa511ed5"
2819+dependencies = [
2820+ "dunce",
2821+ "is-wsl",
2822+ "libc",
2823+]
2824+
2825+[[package]]
2826+name = "option-ext"
2827+version = "0.2.0"
2828+source = "registry+https://github.com/rust-lang/crates.io-index"
2829+checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
2830+
2831+[[package]]
2832+name = "ordered-stream"
2833+version = "0.2.0"
2834+source = "registry+https://github.com/rust-lang/crates.io-index"
2835+checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50"
2836+dependencies = [
2837+ "futures-core",
2838+ "pin-project-lite",
2839+]
2840+
2841+[[package]]
2842+name = "os_pipe"
2843+version = "1.2.3"
2844+source = "registry+https://github.com/rust-lang/crates.io-index"
2845+checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967"
2846+dependencies = [
2847+ "libc",
2848+ "windows-sys 0.61.2",
2849+]
2850+
2851+[[package]]
2852+name = "pango"
2853+version = "0.18.3"
2854+source = "registry+https://github.com/rust-lang/crates.io-index"
2855+checksum = "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4"
2856+dependencies = [
2857+ "gio",
2858+ "glib",
2859+ "libc",
2860+ "once_cell",
2861+ "pango-sys",
2862+]
2863+
2864+[[package]]
2865+name = "pango-sys"
2866+version = "0.18.0"
2867+source = "registry+https://github.com/rust-lang/crates.io-index"
2868+checksum = "436737e391a843e5933d6d9aa102cb126d501e815b83601365a948a518555dc5"
2869+dependencies = [
2870+ "glib-sys",
2871+ "gobject-sys",
2872+ "libc",
2873+ "system-deps",
2874+]
2875+
2876+[[package]]
2877+name = "parking"
2878+version = "2.2.1"
2879+source = "registry+https://github.com/rust-lang/crates.io-index"
2880+checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"
2881+
2882+[[package]]
2883+name = "parking_lot"
2884+version = "0.12.5"
2885+source = "registry+https://github.com/rust-lang/crates.io-index"
2886+checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
2887+dependencies = [
2888+ "lock_api",
2889+ "parking_lot_core",
2890+]
2891+
2892+[[package]]
2893+name = "parking_lot_core"
2894+version = "0.9.12"
2895+source = "registry+https://github.com/rust-lang/crates.io-index"
2896+checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
2897+dependencies = [
2898+ "cfg-if",
2899+ "libc",
2900+ "redox_syscall",
2901+ "smallvec",
2902+ "windows-link 0.2.1",
2903+]
2904+
2905+[[package]]
2906+name = "percent-encoding"
2907+version = "2.3.2"
2908+source = "registry+https://github.com/rust-lang/crates.io-index"
2909+checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
2910+
2911+[[package]]
2912+name = "petgraph"
2913+version = "0.8.3"
2914+source = "registry+https://github.com/rust-lang/crates.io-index"
2915+checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455"
2916+dependencies = [
2917+ "fixedbitset",
2918+ "hashbrown 0.15.5",
2919+ "indexmap 2.14.0",
2920+]
2921+
2922+[[package]]
2923+name = "phf"
2924+version = "0.13.1"
2925+source = "registry+https://github.com/rust-lang/crates.io-index"
2926+checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf"
2927+dependencies = [
2928+ "phf_macros",
2929+ "phf_shared",
2930+ "serde",
2931+]
2932+
2933+[[package]]
2934+name = "phf_codegen"
2935+version = "0.13.1"
2936+source = "registry+https://github.com/rust-lang/crates.io-index"
2937+checksum = "49aa7f9d80421bca176ca8dbfebe668cc7a2684708594ec9f3c0db0805d5d6e1"
2938+dependencies = [
2939+ "phf_generator",
2940+ "phf_shared",
2941+]
2942+
2943+[[package]]
2944+name = "phf_generator"
2945+version = "0.13.1"
2946+source = "registry+https://github.com/rust-lang/crates.io-index"
2947+checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737"
2948+dependencies = [
2949+ "fastrand",
2950+ "phf_shared",
2951+]
2952+
2953+[[package]]
2954+name = "phf_macros"
2955+version = "0.13.1"
2956+source = "registry+https://github.com/rust-lang/crates.io-index"
2957+checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef"
2958+dependencies = [
2959+ "phf_generator",
2960+ "phf_shared",
2961+ "proc-macro2",
2962+ "quote",
2963+ "syn 2.0.119",
2964+]
2965+
2966+[[package]]
2967+name = "phf_shared"
2968+version = "0.13.1"
2969+source = "registry+https://github.com/rust-lang/crates.io-index"
2970+checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266"
2971+dependencies = [
2972+ "siphasher",
2973+]
2974+
2975+[[package]]
2976+name = "pin-project-lite"
2977+version = "0.2.17"
2978+source = "registry+https://github.com/rust-lang/crates.io-index"
2979+checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
2980+
2981+[[package]]
2982+name = "piper"
2983+version = "0.2.5"
2984+source = "registry+https://github.com/rust-lang/crates.io-index"
2985+checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1"
2986+dependencies = [
2987+ "atomic-waker",
2988+ "fastrand",
2989+ "futures-io",
2990+]
2991+
2992+[[package]]
2993+name = "pkg-config"
2994+version = "0.3.33"
2995+source = "registry+https://github.com/rust-lang/crates.io-index"
2996+checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e"
2997+
2998+[[package]]
2999+name = "plist"
3000+version = "1.10.0"
3001+source = "registry+https://github.com/rust-lang/crates.io-index"
3002+checksum = "7da1d65da6dd5d1e44199ac0f58712d241c0f439f80adea8924d832384087f85"
3003+dependencies = [
3004+ "base64 0.22.1",
3005+ "indexmap 2.14.0",
3006+ "quick-xml",
3007+ "serde",
3008+ "time",
3009+]
3010+
3011+[[package]]
3012+name = "png"
3013+version = "0.17.16"
3014+source = "registry+https://github.com/rust-lang/crates.io-index"
3015+checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526"
3016+dependencies = [
3017+ "bitflags 1.3.2",
3018+ "crc32fast",
3019+ "fdeflate",
3020+ "flate2",
3021+ "miniz_oxide",
3022+]
3023+
3024+[[package]]
3025+name = "png"
3026+version = "0.18.1"
3027+source = "registry+https://github.com/rust-lang/crates.io-index"
3028+checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61"
3029+dependencies = [
3030+ "bitflags 2.13.1",
3031+ "crc32fast",
3032+ "fdeflate",
3033+ "flate2",
3034+ "miniz_oxide",
3035+]
3036+
3037+[[package]]
3038+name = "polling"
3039+version = "3.11.0"
3040+source = "registry+https://github.com/rust-lang/crates.io-index"
3041+checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218"
3042+dependencies = [
3043+ "cfg-if",
3044+ "concurrent-queue",
3045+ "hermit-abi",
3046+ "pin-project-lite",
3047+ "rustix",
3048+ "windows-sys 0.61.2",
3049+]
3050+
3051+[[package]]
3052+name = "potential_utf"
3053+version = "0.1.5"
3054+source = "registry+https://github.com/rust-lang/crates.io-index"
3055+checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564"
3056+dependencies = [
3057+ "zerovec",
3058+]
3059+
3060+[[package]]
3061+name = "powerfmt"
3062+version = "0.2.0"
3063+source = "registry+https://github.com/rust-lang/crates.io-index"
3064+checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
3065+
3066+[[package]]
3067+name = "ppv-lite86"
3068+version = "0.2.21"
3069+source = "registry+https://github.com/rust-lang/crates.io-index"
3070+checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
3071+dependencies = [
3072+ "zerocopy",
3073+]
3074+
3075+[[package]]
3076+name = "precomputed-hash"
3077+version = "0.1.1"
3078+source = "registry+https://github.com/rust-lang/crates.io-index"
3079+checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
3080+
3081+[[package]]
3082+name = "prettyplease"
3083+version = "0.2.37"
3084+source = "registry+https://github.com/rust-lang/crates.io-index"
3085+checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
3086+dependencies = [
3087+ "proc-macro2",
3088+ "syn 2.0.119",
3089+]
3090+
3091+[[package]]
3092+name = "proc-macro-crate"
3093+version = "1.3.1"
3094+source = "registry+https://github.com/rust-lang/crates.io-index"
3095+checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919"
3096+dependencies = [
3097+ "once_cell",
3098+ "toml_edit 0.19.15",
3099+]
3100+
3101+[[package]]
3102+name = "proc-macro-crate"
3103+version = "2.0.2"
3104+source = "registry+https://github.com/rust-lang/crates.io-index"
3105+checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24"
3106+dependencies = [
3107+ "toml_datetime 0.6.3",
3108+ "toml_edit 0.20.2",
3109+]
3110+
3111+[[package]]
3112+name = "proc-macro-crate"
3113+version = "3.5.0"
3114+source = "registry+https://github.com/rust-lang/crates.io-index"
3115+checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f"
3116+dependencies = [
3117+ "toml_edit 0.25.13+spec-1.1.0",
3118+]
3119+
3120+[[package]]
3121+name = "proc-macro-error"
3122+version = "1.0.4"
3123+source = "registry+https://github.com/rust-lang/crates.io-index"
3124+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
3125+dependencies = [
3126+ "proc-macro-error-attr",
3127+ "proc-macro2",
3128+ "quote",
3129+ "syn 1.0.109",
3130+ "version_check",
3131+]
3132+
3133+[[package]]
3134+name = "proc-macro-error-attr"
3135+version = "1.0.4"
3136+source = "registry+https://github.com/rust-lang/crates.io-index"
3137+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
3138+dependencies = [
3139+ "proc-macro2",
3140+ "quote",
3141+ "version_check",
3142+]
3143+
3144+[[package]]
3145+name = "proc-macro2"
3146+version = "1.0.107"
3147+source = "registry+https://github.com/rust-lang/crates.io-index"
3148+checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
3149+dependencies = [
3150+ "unicode-ident",
3151+]
3152+
3153+[[package]]
3154+name = "pxfm"
3155+version = "0.1.30"
3156+source = "registry+https://github.com/rust-lang/crates.io-index"
3157+checksum = "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea"
3158+
3159+[[package]]
3160+name = "quick-error"
3161+version = "2.0.1"
3162+source = "registry+https://github.com/rust-lang/crates.io-index"
3163+checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
3164+
3165+[[package]]
3166+name = "quick-xml"
3167+version = "0.41.0"
3168+source = "registry+https://github.com/rust-lang/crates.io-index"
3169+checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1"
3170+dependencies = [
3171+ "memchr",
3172+]
3173+
3174+[[package]]
3175+name = "quinn"
3176+version = "0.11.11"
3177+source = "registry+https://github.com/rust-lang/crates.io-index"
3178+checksum = "0c1a41e437b6bbd489372cd4971de128e85c855f56c57f283d20ff016cf7c0a8"
3179+dependencies = [
3180+ "bytes",
3181+ "cfg_aliases",
3182+ "pin-project-lite",
3183+ "quinn-proto",
3184+ "quinn-udp",
3185+ "rustc-hash",
3186+ "rustls",
3187+ "socket2",
3188+ "thiserror 2.0.19",
3189+ "tokio",
3190+ "tracing",
3191+ "web-time",
3192+]
3193+
3194+[[package]]
3195+name = "quinn-proto"
3196+version = "0.11.16"
3197+source = "registry+https://github.com/rust-lang/crates.io-index"
3198+checksum = "2f4bfc015262b9df63c8845072ce59068853ff5872180c2ce2f13038b970e560"
3199+dependencies = [
3200+ "bytes",
3201+ "getrandom 0.4.3",
3202+ "lru-slab",
3203+ "rand 0.10.2",
3204+ "rand_pcg",
3205+ "ring",
3206+ "rustc-hash",
3207+ "rustls",
3208+ "rustls-pki-types",
3209+ "slab",
3210+ "thiserror 2.0.19",
3211+ "tinyvec",
3212+ "tracing",
3213+ "web-time",
3214+]
3215+
3216+[[package]]
3217+name = "quinn-udp"
3218+version = "0.5.15"
3219+source = "registry+https://github.com/rust-lang/crates.io-index"
3220+checksum = "35a133f956daabe89a61a685c2649f13d82d5aa4bd5d12d1277e1072a21c0694"
3221+dependencies = [
3222+ "cfg_aliases",
3223+ "libc",
3224+ "once_cell",
3225+ "socket2",
3226+ "tracing",
3227+ "windows-sys 0.61.2",
3228+]
3229+
3230+[[package]]
3231+name = "quote"
3232+version = "1.0.47"
3233+source = "registry+https://github.com/rust-lang/crates.io-index"
3234+checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
3235+dependencies = [
3236+ "proc-macro2",
3237+]
3238+
3239+[[package]]
3240+name = "r-efi"
3241+version = "5.3.0"
3242+source = "registry+https://github.com/rust-lang/crates.io-index"
3243+checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
3244+
3245+[[package]]
3246+name = "r-efi"
3247+version = "6.0.0"
3248+source = "registry+https://github.com/rust-lang/crates.io-index"
3249+checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
3250+
3251+[[package]]
3252+name = "rand"
3253+version = "0.9.5"
3254+source = "registry+https://github.com/rust-lang/crates.io-index"
3255+checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41"
3256+dependencies = [
3257+ "rand_chacha",
3258+ "rand_core 0.9.5",
3259+]
3260+
3261+[[package]]
3262+name = "rand"
3263+version = "0.10.2"
3264+source = "registry+https://github.com/rust-lang/crates.io-index"
3265+checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80"
3266+dependencies = [
3267+ "chacha20",
3268+ "getrandom 0.4.3",
3269+ "rand_core 0.10.1",
3270+]
3271+
3272+[[package]]
3273+name = "rand_chacha"
3274+version = "0.9.0"
3275+source = "registry+https://github.com/rust-lang/crates.io-index"
3276+checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
3277+dependencies = [
3278+ "ppv-lite86",
3279+ "rand_core 0.9.5",
3280+]
3281+
3282+[[package]]
3283+name = "rand_core"
3284+version = "0.9.5"
3285+source = "registry+https://github.com/rust-lang/crates.io-index"
3286+checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
3287+dependencies = [
3288+ "getrandom 0.3.4",
3289+]
3290+
3291+[[package]]
3292+name = "rand_core"
3293+version = "0.10.1"
3294+source = "registry+https://github.com/rust-lang/crates.io-index"
3295+checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
3296+
3297+[[package]]
3298+name = "rand_pcg"
3299+version = "0.10.2"
3300+source = "registry+https://github.com/rust-lang/crates.io-index"
3301+checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a"
3302+dependencies = [
3303+ "rand_core 0.10.1",
3304+]
3305+
3306+[[package]]
3307+name = "raw-window-handle"
3308+version = "0.6.2"
3309+source = "registry+https://github.com/rust-lang/crates.io-index"
3310+checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
3311+
3312+[[package]]
3313+name = "redox_syscall"
3314+version = "0.5.18"
3315+source = "registry+https://github.com/rust-lang/crates.io-index"
3316+checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
3317+dependencies = [
3318+ "bitflags 2.13.1",
3319+]
3320+
3321+[[package]]
3322+name = "redox_users"
3323+version = "0.4.6"
3324+source = "registry+https://github.com/rust-lang/crates.io-index"
3325+checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
3326+dependencies = [
3327+ "getrandom 0.2.17",
3328+ "libredox",
3329+ "thiserror 1.0.69",
3330+]
3331+
3332+[[package]]
3333+name = "redox_users"
3334+version = "0.5.2"
3335+source = "registry+https://github.com/rust-lang/crates.io-index"
3336+checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac"
3337+dependencies = [
3338+ "getrandom 0.2.17",
3339+ "libredox",
3340+ "thiserror 2.0.19",
3341+]
3342+
3343+[[package]]
3344+name = "ref-cast"
3345+version = "1.0.26"
3346+source = "registry+https://github.com/rust-lang/crates.io-index"
3347+checksum = "216e8f773d7923bcba9ceb86a86c93cabb3903a11872fc3f138c49630e50b96d"
3348+dependencies = [
3349+ "ref-cast-impl",
3350+]
3351+
3352+[[package]]
3353+name = "ref-cast-impl"
3354+version = "1.0.26"
3355+source = "registry+https://github.com/rust-lang/crates.io-index"
3356+checksum = "2c9283685feec7d69af75fb0e858d5e7378f33fe4fc699383b2916ab9273e03c"
3357+dependencies = [
3358+ "proc-macro2",
3359+ "quote",
3360+ "syn 3.0.3",
3361+]
3362+
3363+[[package]]
3364+name = "regex"
3365+version = "1.13.1"
3366+source = "registry+https://github.com/rust-lang/crates.io-index"
3367+checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d"
3368+dependencies = [
3369+ "aho-corasick",
3370+ "memchr",
3371+ "regex-automata",
3372+ "regex-syntax",
3373+]
3374+
3375+[[package]]
3376+name = "regex-automata"
3377+version = "0.4.16"
3378+source = "registry+https://github.com/rust-lang/crates.io-index"
3379+checksum = "8fcfdb36bda0c880c5931cdc7a2bcdc8ba4556847b9d912bca70bc94708711ad"
3380+dependencies = [
3381+ "aho-corasick",
3382+ "memchr",
3383+ "regex-syntax",
3384+]
3385+
3386+[[package]]
3387+name = "regex-syntax"
3388+version = "0.8.11"
3389+source = "registry+https://github.com/rust-lang/crates.io-index"
3390+checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
3391+
3392+[[package]]
3393+name = "reqwest"
3394+version = "0.12.28"
3395+source = "registry+https://github.com/rust-lang/crates.io-index"
3396+checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147"
3397+dependencies = [
3398+ "base64 0.22.1",
3399+ "bytes",
3400+ "futures-core",
3401+ "futures-util",
3402+ "http",
3403+ "http-body",
3404+ "http-body-util",
3405+ "hyper",
3406+ "hyper-rustls",
3407+ "hyper-util",
3408+ "js-sys",
3409+ "log",
3410+ "percent-encoding",
3411+ "pin-project-lite",
3412+ "quinn",
3413+ "rustls",
3414+ "rustls-pki-types",
3415+ "serde",
3416+ "serde_json",
3417+ "serde_urlencoded",
3418+ "sync_wrapper",
3419+ "tokio",
3420+ "tokio-rustls",
3421+ "tokio-util",
3422+ "tower",
3423+ "tower-http",
3424+ "tower-service",
3425+ "url",
3426+ "wasm-bindgen",
3427+ "wasm-bindgen-futures",
3428+ "wasm-streams 0.4.2",
3429+ "web-sys",
3430+ "webpki-roots",
3431+]
3432+
3433+[[package]]
3434+name = "reqwest"
3435+version = "0.13.4"
3436+source = "registry+https://github.com/rust-lang/crates.io-index"
3437+checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3"
3438+dependencies = [
3439+ "base64 0.22.1",
3440+ "bytes",
3441+ "futures-core",
3442+ "futures-util",
3443+ "http",
3444+ "http-body",
3445+ "http-body-util",
3446+ "hyper",
3447+ "hyper-util",
3448+ "js-sys",
3449+ "log",
3450+ "percent-encoding",
3451+ "pin-project-lite",
3452+ "serde",
3453+ "serde_json",
3454+ "sync_wrapper",
3455+ "tokio",
3456+ "tokio-util",
3457+ "tower",
3458+ "tower-http",
3459+ "tower-service",
3460+ "url",
3461+ "wasm-bindgen",
3462+ "wasm-bindgen-futures",
3463+ "wasm-streams 0.5.0",
3464+ "web-sys",
3465+]
3466+
3467+[[package]]
3468+name = "ring"
3469+version = "0.17.14"
3470+source = "registry+https://github.com/rust-lang/crates.io-index"
3471+checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
3472+dependencies = [
3473+ "cc",
3474+ "cfg-if",
3475+ "getrandom 0.2.17",
3476+ "libc",
3477+ "untrusted",
3478+ "windows-sys 0.52.0",
3479+]
3480+
3481+[[package]]
3482+name = "rustc-hash"
3483+version = "2.1.3"
3484+source = "registry+https://github.com/rust-lang/crates.io-index"
3485+checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d"
3486+
3487+[[package]]
3488+name = "rustc_version"
3489+version = "0.4.1"
3490+source = "registry+https://github.com/rust-lang/crates.io-index"
3491+checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
3492+dependencies = [
3493+ "semver",
3494+]
3495+
3496+[[package]]
3497+name = "rustix"
3498+version = "1.1.4"
3499+source = "registry+https://github.com/rust-lang/crates.io-index"
3500+checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
3501+dependencies = [
3502+ "bitflags 2.13.1",
3503+ "errno",
3504+ "libc",
3505+ "linux-raw-sys",
3506+ "windows-sys 0.61.2",
3507+]
3508+
3509+[[package]]
3510+name = "rustls"
3511+version = "0.23.42"
3512+source = "registry+https://github.com/rust-lang/crates.io-index"
3513+checksum = "3c54fcab019b409d04215d3a17cb438fd7fbf192ee61461f20f4fe18704bc138"
3514+dependencies = [
3515+ "once_cell",
3516+ "ring",
3517+ "rustls-pki-types",
3518+ "rustls-webpki",
3519+ "subtle",
3520+ "zeroize",
3521+]
3522+
3523+[[package]]
3524+name = "rustls-pki-types"
3525+version = "1.15.0"
3526+source = "registry+https://github.com/rust-lang/crates.io-index"
3527+checksum = "764899a24af3980067ee14bc143654f297b22eaebfe3c7b6b211920a5a59b046"
3528+dependencies = [
3529+ "web-time",
3530+ "zeroize",
3531+]
3532+
3533+[[package]]
3534+name = "rustls-webpki"
3535+version = "0.103.13"
3536+source = "registry+https://github.com/rust-lang/crates.io-index"
3537+checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e"
3538+dependencies = [
3539+ "ring",
3540+ "rustls-pki-types",
3541+ "untrusted",
3542+]
3543+
3544+[[package]]
3545+name = "rustversion"
3546+version = "1.0.23"
3547+source = "registry+https://github.com/rust-lang/crates.io-index"
3548+checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"
3549+
3550+[[package]]
3551+name = "ryu"
3552+version = "1.0.23"
3553+source = "registry+https://github.com/rust-lang/crates.io-index"
3554+checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f"
3555+
3556+[[package]]
3557+name = "same-file"
3558+version = "1.0.6"
3559+source = "registry+https://github.com/rust-lang/crates.io-index"
3560+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
3561+dependencies = [
3562+ "winapi-util",
3563+]
3564+
3565+[[package]]
3566+name = "schemars"
3567+version = "0.8.22"
3568+source = "registry+https://github.com/rust-lang/crates.io-index"
3569+checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615"
3570+dependencies = [
3571+ "dyn-clone",
3572+ "indexmap 1.9.3",
3573+ "schemars_derive",
3574+ "serde",
3575+ "serde_json",
3576+ "url",
3577+ "uuid",
3578+]
3579+
3580+[[package]]
3581+name = "schemars"
3582+version = "0.9.0"
3583+source = "registry+https://github.com/rust-lang/crates.io-index"
3584+checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f"
3585+dependencies = [
3586+ "dyn-clone",
3587+ "ref-cast",
3588+ "serde",
3589+ "serde_json",
3590+]
3591+
3592+[[package]]
3593+name = "schemars"
3594+version = "1.2.1"
3595+source = "registry+https://github.com/rust-lang/crates.io-index"
3596+checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc"
3597+dependencies = [
3598+ "dyn-clone",
3599+ "ref-cast",
3600+ "serde",
3601+ "serde_json",
3602+]
3603+
3604+[[package]]
3605+name = "schemars_derive"
3606+version = "0.8.22"
3607+source = "registry+https://github.com/rust-lang/crates.io-index"
3608+checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d"
3609+dependencies = [
3610+ "proc-macro2",
3611+ "quote",
3612+ "serde_derive_internals",
3613+ "syn 2.0.119",
3614+]
3615+
3616+[[package]]
3617+name = "scopeguard"
3618+version = "1.2.0"
3619+source = "registry+https://github.com/rust-lang/crates.io-index"
3620+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
3621+
3622+[[package]]
3623+name = "selectors"
3624+version = "0.36.1"
3625+source = "registry+https://github.com/rust-lang/crates.io-index"
3626+checksum = "c5d9c0c92a92d33f08817311cf3f2c29a3538a8240e94a6a3c622ce652d7e00c"
3627+dependencies = [
3628+ "bitflags 2.13.1",
3629+ "cssparser",
3630+ "derive_more",
3631+ "log",
3632+ "new_debug_unreachable",
3633+ "phf",
3634+ "phf_codegen",
3635+ "precomputed-hash",
3636+ "rustc-hash",
3637+ "servo_arc",
3638+ "smallvec",
3639+]
3640+
3641+[[package]]
3642+name = "semver"
3643+version = "1.0.28"
3644+source = "registry+https://github.com/rust-lang/crates.io-index"
3645+checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
3646+dependencies = [
3647+ "serde",
3648+ "serde_core",
3649+]
3650+
3651+[[package]]
3652+name = "serde"
3653+version = "1.0.229"
3654+source = "registry+https://github.com/rust-lang/crates.io-index"
3655+checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
3656+dependencies = [
3657+ "serde_core",
3658+ "serde_derive",
3659+]
3660+
3661+[[package]]
3662+name = "serde-untagged"
3663+version = "0.1.9"
3664+source = "registry+https://github.com/rust-lang/crates.io-index"
3665+checksum = "f9faf48a4a2d2693be24c6289dbe26552776eb7737074e6722891fadbe6c5058"
3666+dependencies = [
3667+ "erased-serde",
3668+ "serde",
3669+ "serde_core",
3670+ "typeid",
3671+]
3672+
3673+[[package]]
3674+name = "serde_core"
3675+version = "1.0.229"
3676+source = "registry+https://github.com/rust-lang/crates.io-index"
3677+checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
3678+dependencies = [
3679+ "serde_derive",
3680+]
3681+
3682+[[package]]
3683+name = "serde_derive"
3684+version = "1.0.229"
3685+source = "registry+https://github.com/rust-lang/crates.io-index"
3686+checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
3687+dependencies = [
3688+ "proc-macro2",
3689+ "quote",
3690+ "syn 3.0.3",
3691+]
3692+
3693+[[package]]
3694+name = "serde_derive_internals"
3695+version = "0.29.1"
3696+source = "registry+https://github.com/rust-lang/crates.io-index"
3697+checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
3698+dependencies = [
3699+ "proc-macro2",
3700+ "quote",
3701+ "syn 2.0.119",
3702+]
3703+
3704+[[package]]
3705+name = "serde_json"
3706+version = "1.0.151"
3707+source = "registry+https://github.com/rust-lang/crates.io-index"
3708+checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
3709+dependencies = [
3710+ "itoa",
3711+ "memchr",
3712+ "serde",
3713+ "serde_core",
3714+ "zmij",
3715+]
3716+
3717+[[package]]
3718+name = "serde_repr"
3719+version = "0.1.21"
3720+source = "registry+https://github.com/rust-lang/crates.io-index"
3721+checksum = "8d3b1629de253c70a0508c3899572da79ca359fdab27c7920ff00406df418906"
3722+dependencies = [
3723+ "proc-macro2",
3724+ "quote",
3725+ "syn 3.0.3",
3726+]
3727+
3728+[[package]]
3729+name = "serde_spanned"
3730+version = "0.6.9"
3731+source = "registry+https://github.com/rust-lang/crates.io-index"
3732+checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
3733+dependencies = [
3734+ "serde",
3735+]
3736+
3737+[[package]]
3738+name = "serde_spanned"
3739+version = "1.1.1"
3740+source = "registry+https://github.com/rust-lang/crates.io-index"
3741+checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26"
3742+dependencies = [
3743+ "serde_core",
3744+]
3745+
3746+[[package]]
3747+name = "serde_urlencoded"
3748+version = "0.7.1"
3749+source = "registry+https://github.com/rust-lang/crates.io-index"
3750+checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
3751+dependencies = [
3752+ "form_urlencoded",
3753+ "itoa",
3754+ "ryu",
3755+ "serde",
3756+]
3757+
3758+[[package]]
3759+name = "serde_with"
3760+version = "3.21.0"
3761+source = "registry+https://github.com/rust-lang/crates.io-index"
3762+checksum = "76a5c54c7310e7b8b9577c286d7e399ddd876c3e12b3ed917a8aabc4b96e9e8c"
3763+dependencies = [
3764+ "base64 0.22.1",
3765+ "bs58",
3766+ "chrono",
3767+ "hex",
3768+ "indexmap 1.9.3",
3769+ "indexmap 2.14.0",
3770+ "schemars 0.9.0",
3771+ "schemars 1.2.1",
3772+ "serde_core",
3773+ "serde_json",
3774+ "serde_with_macros",
3775+ "time",
3776+]
3777+
3778+[[package]]
3779+name = "serde_with_macros"
3780+version = "3.21.0"
3781+source = "registry+https://github.com/rust-lang/crates.io-index"
3782+checksum = "84d57bc0c8b9a17920c178daa6bb924850d54a9c97ab45194bb8c17ad66bb660"
3783+dependencies = [
3784+ "darling",
3785+ "proc-macro2",
3786+ "quote",
3787+ "syn 2.0.119",
3788+]
3789+
3790+[[package]]
3791+name = "serialize-to-javascript"
3792+version = "0.1.2"
3793+source = "registry+https://github.com/rust-lang/crates.io-index"
3794+checksum = "04f3666a07a197cdb77cdf306c32be9b7f598d7060d50cfd4d5aa04bfd92f6c5"
3795+dependencies = [
3796+ "serde",
3797+ "serde_json",
3798+ "serialize-to-javascript-impl",
3799+]
3800+
3801+[[package]]
3802+name = "serialize-to-javascript-impl"
3803+version = "0.1.2"
3804+source = "registry+https://github.com/rust-lang/crates.io-index"
3805+checksum = "772ee033c0916d670af7860b6e1ef7d658a4629a6d0b4c8c3e67f09b3765b75d"
3806+dependencies = [
3807+ "proc-macro2",
3808+ "quote",
3809+ "syn 2.0.119",
3810+]
3811+
3812+[[package]]
3813+name = "servo_arc"
3814+version = "0.4.3"
3815+source = "registry+https://github.com/rust-lang/crates.io-index"
3816+checksum = "170fb83ab34de17dc69aa7c67482b22218ddb85da56546f9bd6b929e32a05930"
3817+dependencies = [
3818+ "stable_deref_trait",
3819+]
3820+
3821+[[package]]
3822+name = "sha2"
3823+version = "0.10.9"
3824+source = "registry+https://github.com/rust-lang/crates.io-index"
3825+checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
3826+dependencies = [
3827+ "cfg-if",
3828+ "cpufeatures 0.2.17",
3829+ "digest",
3830+]
3831+
3832+[[package]]
3833+name = "shlex"
3834+version = "1.3.0"
3835+source = "registry+https://github.com/rust-lang/crates.io-index"
3836+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
3837+
3838+[[package]]
3839+name = "shlex"
3840+version = "2.0.1"
3841+source = "registry+https://github.com/rust-lang/crates.io-index"
3842+checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
3843+
3844+[[package]]
3845+name = "signal-hook-registry"
3846+version = "1.4.8"
3847+source = "registry+https://github.com/rust-lang/crates.io-index"
3848+checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b"
3849+dependencies = [
3850+ "errno",
3851+ "libc",
3852+]
3853+
3854+[[package]]
3855+name = "simd-adler32"
3856+version = "0.3.10"
3857+source = "registry+https://github.com/rust-lang/crates.io-index"
3858+checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea"
3859+
3860+[[package]]
3861+name = "siphasher"
3862+version = "1.0.3"
3863+source = "registry+https://github.com/rust-lang/crates.io-index"
3864+checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649"
3865+
3866+[[package]]
3867+name = "slab"
3868+version = "0.4.12"
3869+source = "registry+https://github.com/rust-lang/crates.io-index"
3870+checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
3871+
3872+[[package]]
3873+name = "smallvec"
3874+version = "1.15.2"
3875+source = "registry+https://github.com/rust-lang/crates.io-index"
3876+checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90"
3877+
3878+[[package]]
3879+name = "socket2"
3880+version = "0.6.5"
3881+source = "registry+https://github.com/rust-lang/crates.io-index"
3882+checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4"
3883+dependencies = [
3884+ "libc",
3885+ "windows-sys 0.61.2",
3886+]
3887+
3888+[[package]]
3889+name = "softbuffer"
3890+version = "0.4.8"
3891+source = "registry+https://github.com/rust-lang/crates.io-index"
3892+checksum = "aac18da81ebbf05109ab275b157c22a653bb3c12cf884450179942f81bcbf6c3"
3893+dependencies = [
3894+ "bytemuck",
3895+ "js-sys",
3896+ "ndk",
3897+ "objc2",
3898+ "objc2-core-foundation",
3899+ "objc2-core-graphics",
3900+ "objc2-foundation",
3901+ "objc2-quartz-core",
3902+ "raw-window-handle",
3903+ "redox_syscall",
3904+ "tracing",
3905+ "wasm-bindgen",
3906+ "web-sys",
3907+ "windows-sys 0.61.2",
3908+]
3909+
3910+[[package]]
3911+name = "soup3"
3912+version = "0.5.0"
3913+source = "registry+https://github.com/rust-lang/crates.io-index"
3914+checksum = "471f924a40f31251afc77450e781cb26d55c0b650842efafc9c6cbd2f7cc4f9f"
3915+dependencies = [
3916+ "futures-channel",
3917+ "gio",
3918+ "glib",
3919+ "libc",
3920+ "soup3-sys",
3921+]
3922+
3923+[[package]]
3924+name = "soup3-sys"
3925+version = "0.5.0"
3926+source = "registry+https://github.com/rust-lang/crates.io-index"
3927+checksum = "7ebe8950a680a12f24f15ebe1bf70db7af98ad242d9db43596ad3108aab86c27"
3928+dependencies = [
3929+ "gio-sys",
3930+ "glib-sys",
3931+ "gobject-sys",
3932+ "libc",
3933+ "system-deps",
3934+]
3935+
3936+[[package]]
3937+name = "stable_deref_trait"
3938+version = "1.2.1"
3939+source = "registry+https://github.com/rust-lang/crates.io-index"
3940+checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
3941+
3942+[[package]]
3943+name = "string_cache"
3944+version = "0.9.0"
3945+source = "registry+https://github.com/rust-lang/crates.io-index"
3946+checksum = "a18596f8c785a729f2819c0f6a7eae6ebeebdfffbfe4214ae6b087f690e31901"
3947+dependencies = [
3948+ "new_debug_unreachable",
3949+ "parking_lot",
3950+ "phf_shared",
3951+ "precomputed-hash",
3952+]
3953+
3954+[[package]]
3955+name = "string_cache_codegen"
3956+version = "0.6.1"
3957+source = "registry+https://github.com/rust-lang/crates.io-index"
3958+checksum = "585635e46db231059f76c5849798146164652513eb9e8ab2685939dd90f29b69"
3959+dependencies = [
3960+ "phf_generator",
3961+ "phf_shared",
3962+ "proc-macro2",
3963+ "quote",
3964+]
3965+
3966+[[package]]
3967+name = "strsim"
3968+version = "0.11.1"
3969+source = "registry+https://github.com/rust-lang/crates.io-index"
3970+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
3971+
3972+[[package]]
3973+name = "subtle"
3974+version = "2.6.1"
3975+source = "registry+https://github.com/rust-lang/crates.io-index"
3976+checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
3977+
3978+[[package]]
3979+name = "swift-rs"
3980+version = "1.0.7"
3981+source = "registry+https://github.com/rust-lang/crates.io-index"
3982+checksum = "4057c98e2e852d51fdcfca832aac7b571f6b351ad159f9eda5db1655f8d0c4d7"
3983+dependencies = [
3984+ "base64 0.21.7",
3985+ "serde",
3986+ "serde_json",
3987+]
3988+
3989+[[package]]
3990+name = "syn"
3991+version = "1.0.109"
3992+source = "registry+https://github.com/rust-lang/crates.io-index"
3993+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
3994+dependencies = [
3995+ "proc-macro2",
3996+ "unicode-ident",
3997+]
3998+
3999+[[package]]
4000+name = "syn"
4001+version = "2.0.119"
4002+source = "registry+https://github.com/rust-lang/crates.io-index"
4003+checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
4004+dependencies = [
4005+ "proc-macro2",
4006+ "quote",
4007+ "unicode-ident",
4008+]
4009+
4010+[[package]]
4011+name = "syn"
4012+version = "3.0.3"
4013+source = "registry+https://github.com/rust-lang/crates.io-index"
4014+checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3"
4015+dependencies = [
4016+ "proc-macro2",
4017+ "quote",
4018+ "unicode-ident",
4019+]
4020+
4021+[[package]]
4022+name = "sync_wrapper"
4023+version = "1.0.2"
4024+source = "registry+https://github.com/rust-lang/crates.io-index"
4025+checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
4026+dependencies = [
4027+ "futures-core",
4028+]
4029+
4030+[[package]]
4031+name = "synstructure"
4032+version = "0.13.2"
4033+source = "registry+https://github.com/rust-lang/crates.io-index"
4034+checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
4035+dependencies = [
4036+ "proc-macro2",
4037+ "quote",
4038+ "syn 2.0.119",
4039+]
4040+
4041+[[package]]
4042+name = "system-deps"
4043+version = "6.2.2"
4044+source = "registry+https://github.com/rust-lang/crates.io-index"
4045+checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349"
4046+dependencies = [
4047+ "cfg-expr",
4048+ "heck 0.5.0",
4049+ "pkg-config",
4050+ "toml 0.8.2",
4051+ "version-compare",
4052+]
4053+
4054+[[package]]
4055+name = "tao"
4056+version = "0.35.3"
4057+source = "registry+https://github.com/rust-lang/crates.io-index"
4058+checksum = "d1c93047acf68669466a34690ac58cca7010bd1b201e1ec86f1fd0a75d3dd4a9"
4059+dependencies = [
4060+ "bitflags 2.13.1",
4061+ "block2",
4062+ "core-foundation",
4063+ "core-graphics",
4064+ "crossbeam-channel",
4065+ "dbus",
4066+ "dispatch2",
4067+ "dlopen2",
4068+ "dpi",
4069+ "gdkwayland-sys",
4070+ "gdkx11-sys",
4071+ "gtk",
4072+ "jni",
4073+ "libc",
4074+ "log",
4075+ "ndk",
4076+ "ndk-sys",
4077+ "objc2",
4078+ "objc2-app-kit",
4079+ "objc2-foundation",
4080+ "objc2-ui-kit",
4081+ "once_cell",
4082+ "parking_lot",
4083+ "percent-encoding",
4084+ "raw-window-handle",
4085+ "tao-macros",
4086+ "unicode-segmentation",
4087+ "url",
4088+ "windows 0.61.3",
4089+ "windows-core 0.61.2",
4090+ "windows-version",
4091+ "x11-dl",
4092+]
4093+
4094+[[package]]
4095+name = "tao-macros"
4096+version = "0.1.3"
4097+source = "registry+https://github.com/rust-lang/crates.io-index"
4098+checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd"
4099+dependencies = [
4100+ "proc-macro2",
4101+ "quote",
4102+ "syn 2.0.119",
4103+]
4104+
4105+[[package]]
4106+name = "target-lexicon"
4107+version = "0.12.16"
4108+source = "registry+https://github.com/rust-lang/crates.io-index"
4109+checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
4110+
4111+[[package]]
4112+name = "tauri"
4113+version = "2.11.5"
4114+source = "registry+https://github.com/rust-lang/crates.io-index"
4115+checksum = "667b20e2726d572dea2de7370da16e188eb06008faf9a92fab7cdc46791190b5"
4116+dependencies = [
4117+ "anyhow",
4118+ "bytes",
4119+ "cookie",
4120+ "dirs 6.0.0",
4121+ "dunce",
4122+ "embed_plist",
4123+ "getrandom 0.3.4",
4124+ "glob",
4125+ "gtk",
4126+ "heck 0.5.0",
4127+ "http",
4128+ "image",
4129+ "jni",
4130+ "libc",
4131+ "log",
4132+ "mime",
4133+ "muda",
4134+ "objc2",
4135+ "objc2-app-kit",
4136+ "objc2-foundation",
4137+ "objc2-ui-kit",
4138+ "objc2-web-kit",
4139+ "percent-encoding",
4140+ "plist",
4141+ "raw-window-handle",
4142+ "reqwest 0.13.4",
4143+ "serde",
4144+ "serde_json",
4145+ "serde_repr",
4146+ "serialize-to-javascript",
4147+ "swift-rs",
4148+ "tauri-build",
4149+ "tauri-macros",
4150+ "tauri-runtime",
4151+ "tauri-runtime-wry",
4152+ "tauri-utils",
4153+ "thiserror 2.0.19",
4154+ "tokio",
4155+ "tray-icon",
4156+ "url",
4157+ "webkit2gtk",
4158+ "webview2-com",
4159+ "window-vibrancy",
4160+ "windows 0.61.3",
4161+]
4162+
4163+[[package]]
4164+name = "tauri-build"
4165+version = "2.6.3"
4166+source = "registry+https://github.com/rust-lang/crates.io-index"
4167+checksum = "bc9ce40b16101cb6ea63d3e221567affd1c3a9205f95d7bc574941a10636b632"
4168+dependencies = [
4169+ "anyhow",
4170+ "cargo_toml",
4171+ "dirs 6.0.0",
4172+ "glob",
4173+ "heck 0.5.0",
4174+ "json-patch",
4175+ "schemars 0.8.22",
4176+ "semver",
4177+ "serde",
4178+ "serde_json",
4179+ "tauri-utils",
4180+ "tauri-winres",
4181+ "walkdir",
4182+]
4183+
4184+[[package]]
4185+name = "tauri-codegen"
4186+version = "2.6.3"
4187+source = "registry+https://github.com/rust-lang/crates.io-index"
4188+checksum = "08279169ff42f8fc45a1dbc9dcae888893ba95288142e5880c59b93a26d2cfc5"
4189+dependencies = [
4190+ "base64 0.22.1",
4191+ "brotli",
4192+ "ico",
4193+ "json-patch",
4194+ "plist",
4195+ "png 0.17.16",
4196+ "proc-macro2",
4197+ "quote",
4198+ "semver",
4199+ "serde",
4200+ "serde_json",
4201+ "sha2",
4202+ "syn 2.0.119",
4203+ "tauri-utils",
4204+ "thiserror 2.0.19",
4205+ "time",
4206+ "url",
4207+ "uuid",
4208+ "walkdir",
4209+]
4210+
4211+[[package]]
4212+name = "tauri-macros"
4213+version = "2.6.3"
4214+source = "registry+https://github.com/rust-lang/crates.io-index"
4215+checksum = "e8b394794f399a421811d06966343e7933fcae92d59f5180b9388d1174497a45"
4216+dependencies = [
4217+ "heck 0.5.0",
4218+ "proc-macro2",
4219+ "quote",
4220+ "syn 2.0.119",
4221+ "tauri-codegen",
4222+ "tauri-utils",
4223+]
4224+
4225+[[package]]
4226+name = "tauri-plugin"
4227+version = "2.6.3"
4228+source = "registry+https://github.com/rust-lang/crates.io-index"
4229+checksum = "74be5dd4bed9afbd145e5716b5fa2ec28cbc29c34ffa61c258c9273d896c8020"
4230+dependencies = [
4231+ "anyhow",
4232+ "glob",
4233+ "plist",
4234+ "schemars 0.8.22",
4235+ "serde",
4236+ "serde_json",
4237+ "tauri-utils",
4238+ "walkdir",
4239+]
4240+
4241+[[package]]
4242+name = "tauri-plugin-autostart"
4243+version = "2.5.1"
4244+source = "registry+https://github.com/rust-lang/crates.io-index"
4245+checksum = "459383cebc193cdd03d1ba4acc40f2c408a7abce419d64bdcd2d745bc2886f70"
4246+dependencies = [
4247+ "auto-launch",
4248+ "serde",
4249+ "serde_json",
4250+ "tauri",
4251+ "tauri-plugin",
4252+ "thiserror 2.0.19",
4253+]
4254+
4255+[[package]]
4256+name = "tauri-plugin-clipboard-manager"
4257+version = "2.3.2"
4258+source = "registry+https://github.com/rust-lang/crates.io-index"
4259+checksum = "206dc20af4ed210748ba945c2774e60fd0acd52b9a73a028402caf809e9b6ecf"
4260+dependencies = [
4261+ "arboard",
4262+ "log",
4263+ "serde",
4264+ "serde_json",
4265+ "tauri",
4266+ "tauri-plugin",
4267+ "thiserror 2.0.19",
4268+]
4269+
4270+[[package]]
4271+name = "tauri-plugin-global-shortcut"
4272+version = "2.3.2"
4273+source = "registry+https://github.com/rust-lang/crates.io-index"
4274+checksum = "b4dd9f4c5136c09cd962da0c86dc4accd4666db2ea591cf16e6597435843bd2b"
4275+dependencies = [
4276+ "global-hotkey",
4277+ "log",
4278+ "serde",
4279+ "serde_json",
4280+ "tauri",
4281+ "tauri-plugin",
4282+ "thiserror 2.0.19",
4283+]
4284+
4285+[[package]]
4286+name = "tauri-plugin-notification"
4287+version = "2.3.3"
4288+source = "registry+https://github.com/rust-lang/crates.io-index"
4289+checksum = "01fc2c5ff41105bd1f7242d8201fdf3efd70749b82fa013a17f2126357d194cc"
4290+dependencies = [
4291+ "log",
4292+ "notify-rust",
4293+ "rand 0.9.5",
4294+ "serde",
4295+ "serde_json",
4296+ "serde_repr",
4297+ "tauri",
4298+ "tauri-plugin",
4299+ "thiserror 2.0.19",
4300+ "time",
4301+ "url",
4302+]
4303+
4304+[[package]]
4305+name = "tauri-plugin-opener"
4306+version = "2.5.4"
4307+source = "registry+https://github.com/rust-lang/crates.io-index"
4308+checksum = "17e1bea14edce6b793a04e2417e3fd924b9bc4faae83cdee7d714156cceeed29"
4309+dependencies = [
4310+ "dunce",
4311+ "glob",
4312+ "objc2-app-kit",
4313+ "objc2-foundation",
4314+ "open",
4315+ "schemars 0.8.22",
4316+ "serde",
4317+ "serde_json",
4318+ "tauri",
4319+ "tauri-plugin",
4320+ "thiserror 2.0.19",
4321+ "url",
4322+ "windows 0.61.3",
4323+ "zbus",
4324+]
4325+
4326+[[package]]
4327+name = "tauri-plugin-single-instance"
4328+version = "2.4.3"
4329+source = "registry+https://github.com/rust-lang/crates.io-index"
4330+checksum = "b3214becf9ef5783c0ae99a3bb25adf5353a7a16ebf53e74b909e29205735c6c"
4331+dependencies = [
4332+ "serde",
4333+ "serde_json",
4334+ "tauri",
4335+ "thiserror 2.0.19",
4336+ "tokio",
4337+ "tracing",
4338+ "windows-sys 0.60.2",
4339+ "zbus",
4340+]
4341+
4342+[[package]]
4343+name = "tauri-runtime"
4344+version = "2.11.3"
4345+source = "registry+https://github.com/rust-lang/crates.io-index"
4346+checksum = "b0b4bc95aed361b0019067d189a1174a603d460d0f6c72606512d59fc9c12ec8"
4347+dependencies = [
4348+ "cookie",
4349+ "dpi",
4350+ "gtk",
4351+ "http",
4352+ "jni",
4353+ "objc2",
4354+ "objc2-ui-kit",
4355+ "objc2-web-kit",
4356+ "raw-window-handle",
4357+ "serde",
4358+ "serde_json",
4359+ "tauri-utils",
4360+ "thiserror 2.0.19",
4361+ "url",
4362+ "webkit2gtk",
4363+ "webview2-com",
4364+ "windows 0.61.3",
4365+]
4366+
4367+[[package]]
4368+name = "tauri-runtime-wry"
4369+version = "2.11.4"
4370+source = "registry+https://github.com/rust-lang/crates.io-index"
4371+checksum = "4e6fac707727b7a2f48e4ded90976324267371073edbb415ffb73bb0458d203f"
4372+dependencies = [
4373+ "gtk",
4374+ "http",
4375+ "jni",
4376+ "log",
4377+ "objc2",
4378+ "objc2-app-kit",
4379+ "once_cell",
4380+ "percent-encoding",
4381+ "raw-window-handle",
4382+ "softbuffer",
4383+ "tao",
4384+ "tauri-runtime",
4385+ "tauri-utils",
4386+ "url",
4387+ "webkit2gtk",
4388+ "webview2-com",
4389+ "windows 0.61.3",
4390+ "wry",
4391+]
4392+
4393+[[package]]
4394+name = "tauri-utils"
4395+version = "2.9.3"
4396+source = "registry+https://github.com/rust-lang/crates.io-index"
4397+checksum = "3e176a18e67764923c4f1ce66f25ae4abe5f688384d5eb1a0fa6c77f3d90f887"
4398+dependencies = [
4399+ "anyhow",
4400+ "brotli",
4401+ "cargo_metadata",
4402+ "ctor",
4403+ "dom_query",
4404+ "dunce",
4405+ "glob",
4406+ "http",
4407+ "infer",
4408+ "json-patch",
4409+ "log",
4410+ "memchr",
4411+ "phf",
4412+ "plist",
4413+ "proc-macro2",
4414+ "quote",
4415+ "regex",
4416+ "schemars 0.8.22",
4417+ "semver",
4418+ "serde",
4419+ "serde-untagged",
4420+ "serde_json",
4421+ "serde_with",
4422+ "swift-rs",
4423+ "thiserror 2.0.19",
4424+ "toml 1.1.3+spec-1.1.0",
4425+ "url",
4426+ "urlpattern",
4427+ "uuid",
4428+ "walkdir",
4429+]
4430+
4431+[[package]]
4432+name = "tauri-winres"
4433+version = "0.3.6"
4434+source = "registry+https://github.com/rust-lang/crates.io-index"
4435+checksum = "cc65d45c68858bfe420dd29e834b5d15dbecf8a07a8a16cf4d532c7b1f69d4b6"
4436+dependencies = [
4437+ "dunce",
4438+ "embed-resource",
4439+ "toml 1.1.3+spec-1.1.0",
4440+]
4441+
4442+[[package]]
4443+name = "tauri-winrt-notification"
4444+version = "0.7.3"
4445+source = "registry+https://github.com/rust-lang/crates.io-index"
4446+checksum = "9ed071c670382e85fc2f48ae706492d8c338f4f89bf72520d32f8abfe880aade"
4447+dependencies = [
4448+ "thiserror 2.0.19",
4449+ "windows 0.61.3",
4450+ "windows-version",
4451+]
4452+
4453+[[package]]
4454+name = "tempfile"
4455+version = "3.27.0"
4456+source = "registry+https://github.com/rust-lang/crates.io-index"
4457+checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
4458+dependencies = [
4459+ "fastrand",
4460+ "getrandom 0.4.3",
4461+ "once_cell",
4462+ "rustix",
4463+ "windows-sys 0.61.2",
4464+]
4465+
4466+[[package]]
4467+name = "tendril"
4468+version = "0.5.1"
4469+source = "registry+https://github.com/rust-lang/crates.io-index"
4470+checksum = "5fed54709c5b3a53d09bb1c113ea4f5ceafd1e772ddcb0030a82e1d56c087b08"
4471+dependencies = [
4472+ "new_debug_unreachable",
4473+]
4474+
4475+[[package]]
4476+name = "thiserror"
4477+version = "1.0.69"
4478+source = "registry+https://github.com/rust-lang/crates.io-index"
4479+checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
4480+dependencies = [
4481+ "thiserror-impl 1.0.69",
4482+]
4483+
4484+[[package]]
4485+name = "thiserror"
4486+version = "2.0.19"
4487+source = "registry+https://github.com/rust-lang/crates.io-index"
4488+checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9"
4489+dependencies = [
4490+ "thiserror-impl 2.0.19",
4491+]
4492+
4493+[[package]]
4494+name = "thiserror-impl"
4495+version = "1.0.69"
4496+source = "registry+https://github.com/rust-lang/crates.io-index"
4497+checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
4498+dependencies = [
4499+ "proc-macro2",
4500+ "quote",
4501+ "syn 2.0.119",
4502+]
4503+
4504+[[package]]
4505+name = "thiserror-impl"
4506+version = "2.0.19"
4507+source = "registry+https://github.com/rust-lang/crates.io-index"
4508+checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd"
4509+dependencies = [
4510+ "proc-macro2",
4511+ "quote",
4512+ "syn 3.0.3",
4513+]
4514+
4515+[[package]]
4516+name = "tiff"
4517+version = "0.11.3"
4518+source = "registry+https://github.com/rust-lang/crates.io-index"
4519+checksum = "b63feaf3343d35b6ca4d50483f94843803b0f51634937cc2ec519fc32232bc52"
4520+dependencies = [
4521+ "fax",
4522+ "flate2",
4523+ "half",
4524+ "quick-error",
4525+ "weezl",
4526+ "zune-jpeg",
4527+]
4528+
4529+[[package]]
4530+name = "time"
4531+version = "0.3.54"
4532+source = "registry+https://github.com/rust-lang/crates.io-index"
4533+checksum = "3e1d5e639ff6bab73cb6885cc7e7b1de96c3f32c68ec55f3952614bec1092244"
4534+dependencies = [
4535+ "deranged",
4536+ "num-conv",
4537+ "powerfmt",
4538+ "serde_core",
4539+ "time-core",
4540+ "time-macros",
4541+]
4542+
4543+[[package]]
4544+name = "time-core"
4545+version = "0.1.9"
4546+source = "registry+https://github.com/rust-lang/crates.io-index"
4547+checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109"
4548+
4549+[[package]]
4550+name = "time-macros"
4551+version = "0.2.32"
4552+source = "registry+https://github.com/rust-lang/crates.io-index"
4553+checksum = "7e689342a48d2ea927c87ea50cabf8594854bf940e9310208848d680d668ed85"
4554+dependencies = [
4555+ "num-conv",
4556+ "time-core",
4557+]
4558+
4559+[[package]]
4560+name = "tinystr"
4561+version = "0.8.3"
4562+source = "registry+https://github.com/rust-lang/crates.io-index"
4563+checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d"
4564+dependencies = [
4565+ "displaydoc",
4566+ "zerovec",
4567+]
4568+
4569+[[package]]
4570+name = "tinyvec"
4571+version = "1.12.0"
4572+source = "registry+https://github.com/rust-lang/crates.io-index"
4573+checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f"
4574+dependencies = [
4575+ "tinyvec_macros",
4576+]
4577+
4578+[[package]]
4579+name = "tinyvec_macros"
4580+version = "0.1.1"
4581+source = "registry+https://github.com/rust-lang/crates.io-index"
4582+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
4583+
4584+[[package]]
4585+name = "tokio"
4586+version = "1.53.1"
4587+source = "registry+https://github.com/rust-lang/crates.io-index"
4588+checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed"
4589+dependencies = [
4590+ "bytes",
4591+ "libc",
4592+ "mio",
4593+ "pin-project-lite",
4594+ "socket2",
4595+ "windows-sys 0.61.2",
4596+]
4597+
4598+[[package]]
4599+name = "tokio-rustls"
4600+version = "0.26.4"
4601+source = "registry+https://github.com/rust-lang/crates.io-index"
4602+checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61"
4603+dependencies = [
4604+ "rustls",
4605+ "tokio",
4606+]
4607+
4608+[[package]]
4609+name = "tokio-util"
4610+version = "0.7.19"
4611+source = "registry+https://github.com/rust-lang/crates.io-index"
4612+checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52"
4613+dependencies = [
4614+ "bytes",
4615+ "futures-core",
4616+ "futures-sink",
4617+ "pin-project-lite",
4618+ "tokio",
4619+]
4620+
4621+[[package]]
4622+name = "toml"
4623+version = "0.8.2"
4624+source = "registry+https://github.com/rust-lang/crates.io-index"
4625+checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d"
4626+dependencies = [
4627+ "serde",
4628+ "serde_spanned 0.6.9",
4629+ "toml_datetime 0.6.3",
4630+ "toml_edit 0.20.2",
4631+]
4632+
4633+[[package]]
4634+name = "toml"
4635+version = "0.9.12+spec-1.1.0"
4636+source = "registry+https://github.com/rust-lang/crates.io-index"
4637+checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863"
4638+dependencies = [
4639+ "indexmap 2.14.0",
4640+ "serde_core",
4641+ "serde_spanned 1.1.1",
4642+ "toml_datetime 0.7.5+spec-1.1.0",
4643+ "toml_parser",
4644+ "toml_writer",
4645+ "winnow 0.7.15",
4646+]
4647+
4648+[[package]]
4649+name = "toml"
4650+version = "1.1.3+spec-1.1.0"
4651+source = "registry+https://github.com/rust-lang/crates.io-index"
4652+checksum = "53c96ecdfa941c8fc4fcaed14f99ada8ebed502eef533015095a07e3301d4c3c"
4653+dependencies = [
4654+ "indexmap 2.14.0",
4655+ "serde_core",
4656+ "serde_spanned 1.1.1",
4657+ "toml_datetime 1.1.1+spec-1.1.0",
4658+ "toml_parser",
4659+ "toml_writer",
4660+ "winnow 1.0.4",
4661+]
4662+
4663+[[package]]
4664+name = "toml_datetime"
4665+version = "0.6.3"
4666+source = "registry+https://github.com/rust-lang/crates.io-index"
4667+checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"
4668+dependencies = [
4669+ "serde",
4670+]
4671+
4672+[[package]]
4673+name = "toml_datetime"
4674+version = "0.7.5+spec-1.1.0"
4675+source = "registry+https://github.com/rust-lang/crates.io-index"
4676+checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347"
4677+dependencies = [
4678+ "serde_core",
4679+]
4680+
4681+[[package]]
4682+name = "toml_datetime"
4683+version = "1.1.1+spec-1.1.0"
4684+source = "registry+https://github.com/rust-lang/crates.io-index"
4685+checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7"
4686+dependencies = [
4687+ "serde_core",
4688+]
4689+
4690+[[package]]
4691+name = "toml_edit"
4692+version = "0.19.15"
4693+source = "registry+https://github.com/rust-lang/crates.io-index"
4694+checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
4695+dependencies = [
4696+ "indexmap 2.14.0",
4697+ "toml_datetime 0.6.3",
4698+ "winnow 0.5.40",
4699+]
4700+
4701+[[package]]
4702+name = "toml_edit"
4703+version = "0.20.2"
4704+source = "registry+https://github.com/rust-lang/crates.io-index"
4705+checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338"
4706+dependencies = [
4707+ "indexmap 2.14.0",
4708+ "serde",
4709+ "serde_spanned 0.6.9",
4710+ "toml_datetime 0.6.3",
4711+ "winnow 0.5.40",
4712+]
4713+
4714+[[package]]
4715+name = "toml_edit"
4716+version = "0.25.13+spec-1.1.0"
4717+source = "registry+https://github.com/rust-lang/crates.io-index"
4718+checksum = "6975367e4d2ef766d86af01ffad14b622fecc8d4357a998fbc4deb6e9bacaf9b"
4719+dependencies = [
4720+ "indexmap 2.14.0",
4721+ "toml_datetime 1.1.1+spec-1.1.0",
4722+ "toml_parser",
4723+ "winnow 1.0.4",
4724+]
4725+
4726+[[package]]
4727+name = "toml_parser"
4728+version = "1.1.2+spec-1.1.0"
4729+source = "registry+https://github.com/rust-lang/crates.io-index"
4730+checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526"
4731+dependencies = [
4732+ "winnow 1.0.4",
4733+]
4734+
4735+[[package]]
4736+name = "toml_writer"
4737+version = "1.1.2+spec-1.1.0"
4738+source = "registry+https://github.com/rust-lang/crates.io-index"
4739+checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2"
4740+
4741+[[package]]
4742+name = "tower"
4743+version = "0.5.3"
4744+source = "registry+https://github.com/rust-lang/crates.io-index"
4745+checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4"
4746+dependencies = [
4747+ "futures-core",
4748+ "futures-util",
4749+ "pin-project-lite",
4750+ "sync_wrapper",
4751+ "tokio",
4752+ "tower-layer",
4753+ "tower-service",
4754+]
4755+
4756+[[package]]
4757+name = "tower-http"
4758+version = "0.6.11"
4759+source = "registry+https://github.com/rust-lang/crates.io-index"
4760+checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840"
4761+dependencies = [
4762+ "bitflags 2.13.1",
4763+ "bytes",
4764+ "futures-util",
4765+ "http",
4766+ "http-body",
4767+ "pin-project-lite",
4768+ "tower",
4769+ "tower-layer",
4770+ "tower-service",
4771+ "url",
4772+]
4773+
4774+[[package]]
4775+name = "tower-layer"
4776+version = "0.3.3"
4777+source = "registry+https://github.com/rust-lang/crates.io-index"
4778+checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e"
4779+
4780+[[package]]
4781+name = "tower-service"
4782+version = "0.3.3"
4783+source = "registry+https://github.com/rust-lang/crates.io-index"
4784+checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
4785+
4786+[[package]]
4787+name = "tracing"
4788+version = "0.1.44"
4789+source = "registry+https://github.com/rust-lang/crates.io-index"
4790+checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"
4791+dependencies = [
4792+ "pin-project-lite",
4793+ "tracing-attributes",
4794+ "tracing-core",
4795+]
4796+
4797+[[package]]
4798+name = "tracing-attributes"
4799+version = "0.1.31"
4800+source = "registry+https://github.com/rust-lang/crates.io-index"
4801+checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
4802+dependencies = [
4803+ "proc-macro2",
4804+ "quote",
4805+ "syn 2.0.119",
4806+]
4807+
4808+[[package]]
4809+name = "tracing-core"
4810+version = "0.1.36"
4811+source = "registry+https://github.com/rust-lang/crates.io-index"
4812+checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a"
4813+dependencies = [
4814+ "once_cell",
4815+]
4816+
4817+[[package]]
4818+name = "tray-icon"
4819+version = "0.24.1"
4820+source = "registry+https://github.com/rust-lang/crates.io-index"
4821+checksum = "65ba1e5f6b9ef9fd87e21b9c6f351554dbd717960089168fcfdef854686961dc"
4822+dependencies = [
4823+ "crossbeam-channel",
4824+ "dirs 6.0.0",
4825+ "libappindicator",
4826+ "muda",
4827+ "objc2",
4828+ "objc2-app-kit",
4829+ "objc2-core-foundation",
4830+ "objc2-core-graphics",
4831+ "objc2-foundation",
4832+ "once_cell",
4833+ "png 0.18.1",
4834+ "serde",
4835+ "thiserror 2.0.19",
4836+ "windows-sys 0.61.2",
4837+]
4838+
4839+[[package]]
4840+name = "tree_magic_mini"
4841+version = "3.2.2"
4842+source = "registry+https://github.com/rust-lang/crates.io-index"
4843+checksum = "b8765b90061cba6c22b5831f675da109ae5561588290f9fa2317adab2714d5a6"
4844+dependencies = [
4845+ "memchr",
4846+ "nom 8.0.0",
4847+ "petgraph",
4848+]
4849+
4850+[[package]]
4851+name = "try-lock"
4852+version = "0.2.5"
4853+source = "registry+https://github.com/rust-lang/crates.io-index"
4854+checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
4855+
4856+[[package]]
4857+name = "typeid"
4858+version = "1.0.3"
4859+source = "registry+https://github.com/rust-lang/crates.io-index"
4860+checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c"
4861+
4862+[[package]]
4863+name = "typenum"
4864+version = "1.20.1"
4865+source = "registry+https://github.com/rust-lang/crates.io-index"
4866+checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20"
4867+
4868+[[package]]
4869+name = "uds_windows"
4870+version = "1.2.1"
4871+source = "registry+https://github.com/rust-lang/crates.io-index"
4872+checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e"
4873+dependencies = [
4874+ "memoffset",
4875+ "tempfile",
4876+ "windows-sys 0.61.2",
4877+]
4878+
4879+[[package]]
4880+name = "unic-char-property"
4881+version = "0.9.0"
4882+source = "registry+https://github.com/rust-lang/crates.io-index"
4883+checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221"
4884+dependencies = [
4885+ "unic-char-range",
4886+]
4887+
4888+[[package]]
4889+name = "unic-char-range"
4890+version = "0.9.0"
4891+source = "registry+https://github.com/rust-lang/crates.io-index"
4892+checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc"
4893+
4894+[[package]]
4895+name = "unic-common"
4896+version = "0.9.0"
4897+source = "registry+https://github.com/rust-lang/crates.io-index"
4898+checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc"
4899+
4900+[[package]]
4901+name = "unic-ucd-ident"
4902+version = "0.9.0"
4903+source = "registry+https://github.com/rust-lang/crates.io-index"
4904+checksum = "e230a37c0381caa9219d67cf063aa3a375ffed5bf541a452db16e744bdab6987"
4905+dependencies = [
4906+ "unic-char-property",
4907+ "unic-char-range",
4908+ "unic-ucd-version",
4909+]
4910+
4911+[[package]]
4912+name = "unic-ucd-version"
4913+version = "0.9.0"
4914+source = "registry+https://github.com/rust-lang/crates.io-index"
4915+checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4"
4916+dependencies = [
4917+ "unic-common",
4918+]
4919+
4920+[[package]]
4921+name = "unicode-ident"
4922+version = "1.0.24"
4923+source = "registry+https://github.com/rust-lang/crates.io-index"
4924+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
4925+
4926+[[package]]
4927+name = "unicode-segmentation"
4928+version = "1.13.3"
4929+source = "registry+https://github.com/rust-lang/crates.io-index"
4930+checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8"
4931+
4932+[[package]]
4933+name = "untrusted"
4934+version = "0.9.0"
4935+source = "registry+https://github.com/rust-lang/crates.io-index"
4936+checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
4937+
4938+[[package]]
4939+name = "url"
4940+version = "2.5.8"
4941+source = "registry+https://github.com/rust-lang/crates.io-index"
4942+checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed"
4943+dependencies = [
4944+ "form_urlencoded",
4945+ "idna",
4946+ "percent-encoding",
4947+ "serde",
4948+ "serde_derive",
4949+]
4950+
4951+[[package]]
4952+name = "urlpattern"
4953+version = "0.3.0"
4954+source = "registry+https://github.com/rust-lang/crates.io-index"
4955+checksum = "70acd30e3aa1450bc2eece896ce2ad0d178e9c079493819301573dae3c37ba6d"
4956+dependencies = [
4957+ "regex",
4958+ "serde",
4959+ "unic-ucd-ident",
4960+ "url",
4961+]
4962+
4963+[[package]]
4964+name = "utf8_iter"
4965+version = "1.0.4"
4966+source = "registry+https://github.com/rust-lang/crates.io-index"
4967+checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
4968+
4969+[[package]]
4970+name = "uuid"
4971+version = "1.24.0"
4972+source = "registry+https://github.com/rust-lang/crates.io-index"
4973+checksum = "bf3923a6f5c4c6382e0b653c4117f48d631ea17f38ed86e2a828e6f7412f5239"
4974+dependencies = [
4975+ "getrandom 0.4.3",
4976+ "js-sys",
4977+ "serde_core",
4978+ "wasm-bindgen",
4979+]
4980+
4981+[[package]]
4982+name = "version-compare"
4983+version = "0.2.1"
4984+source = "registry+https://github.com/rust-lang/crates.io-index"
4985+checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e"
4986+
4987+[[package]]
4988+name = "version_check"
4989+version = "0.9.5"
4990+source = "registry+https://github.com/rust-lang/crates.io-index"
4991+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
4992+
4993+[[package]]
4994+name = "vswhom"
4995+version = "0.1.0"
4996+source = "registry+https://github.com/rust-lang/crates.io-index"
4997+checksum = "be979b7f07507105799e854203b470ff7c78a1639e330a58f183b5fea574608b"
4998+dependencies = [
4999+ "libc",
5000+ "vswhom-sys",
5001+]
5002+
5003+[[package]]
5004+name = "vswhom-sys"
5005+version = "0.1.3"
5006+source = "registry+https://github.com/rust-lang/crates.io-index"
5007+checksum = "fb067e4cbd1ff067d1df46c9194b5de0e98efd2810bbc95c5d5e5f25a3231150"
5008+dependencies = [
5009+ "cc",
5010+ "libc",
5011+]
5012+
5013+[[package]]
5014+name = "walkdir"
5015+version = "2.5.0"
5016+source = "registry+https://github.com/rust-lang/crates.io-index"
5017+checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
5018+dependencies = [
5019+ "same-file",
5020+ "winapi-util",
5021+]
5022+
5023+[[package]]
5024+name = "want"
5025+version = "0.3.1"
5026+source = "registry+https://github.com/rust-lang/crates.io-index"
5027+checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
5028+dependencies = [
5029+ "try-lock",
5030+]
5031+
5032+[[package]]
5033+name = "wasi"
5034+version = "0.11.1+wasi-snapshot-preview1"
5035+source = "registry+https://github.com/rust-lang/crates.io-index"
5036+checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
5037+
5038+[[package]]
5039+name = "wasip2"
5040+version = "1.0.4+wasi-0.2.12"
5041+source = "registry+https://github.com/rust-lang/crates.io-index"
5042+checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487"
5043+dependencies = [
5044+ "wit-bindgen",
5045+]
5046+
5047+[[package]]
5048+name = "wasm-bindgen"
5049+version = "0.2.126"
5050+source = "registry+https://github.com/rust-lang/crates.io-index"
5051+checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4"
5052+dependencies = [
5053+ "cfg-if",
5054+ "once_cell",
5055+ "rustversion",
5056+ "wasm-bindgen-macro",
5057+ "wasm-bindgen-shared",
5058+]
5059+
5060+[[package]]
5061+name = "wasm-bindgen-futures"
5062+version = "0.4.76"
5063+source = "registry+https://github.com/rust-lang/crates.io-index"
5064+checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d"
5065+dependencies = [
5066+ "js-sys",
5067+ "wasm-bindgen",
5068+]
5069+
5070+[[package]]
5071+name = "wasm-bindgen-macro"
5072+version = "0.2.126"
5073+source = "registry+https://github.com/rust-lang/crates.io-index"
5074+checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1"
5075+dependencies = [
5076+ "quote",
5077+ "wasm-bindgen-macro-support",
5078+]
5079+
5080+[[package]]
5081+name = "wasm-bindgen-macro-support"
5082+version = "0.2.126"
5083+source = "registry+https://github.com/rust-lang/crates.io-index"
5084+checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e"
5085+dependencies = [
5086+ "bumpalo",
5087+ "proc-macro2",
5088+ "quote",
5089+ "syn 2.0.119",
5090+ "wasm-bindgen-shared",
5091+]
5092+
5093+[[package]]
5094+name = "wasm-bindgen-shared"
5095+version = "0.2.126"
5096+source = "registry+https://github.com/rust-lang/crates.io-index"
5097+checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24"
5098+dependencies = [
5099+ "unicode-ident",
5100+]
5101+
5102+[[package]]
5103+name = "wasm-streams"
5104+version = "0.4.2"
5105+source = "registry+https://github.com/rust-lang/crates.io-index"
5106+checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65"
5107+dependencies = [
5108+ "futures-util",
5109+ "js-sys",
5110+ "wasm-bindgen",
5111+ "wasm-bindgen-futures",
5112+ "web-sys",
5113+]
5114+
5115+[[package]]
5116+name = "wasm-streams"
5117+version = "0.5.0"
5118+source = "registry+https://github.com/rust-lang/crates.io-index"
5119+checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb"
5120+dependencies = [
5121+ "futures-util",
5122+ "js-sys",
5123+ "wasm-bindgen",
5124+ "wasm-bindgen-futures",
5125+ "web-sys",
5126+]
5127+
5128+[[package]]
5129+name = "wayland-backend"
5130+version = "0.3.16"
5131+source = "registry+https://github.com/rust-lang/crates.io-index"
5132+checksum = "016ccf01d1c58b6f8999612813e17c9b2390f7d70671428869913310f83f54b8"
5133+dependencies = [
5134+ "cc",
5135+ "downcast-rs",
5136+ "rustix",
5137+ "smallvec",
5138+ "wayland-sys",
5139+]
5140+
5141+[[package]]
5142+name = "wayland-client"
5143+version = "0.31.15"
5144+source = "registry+https://github.com/rust-lang/crates.io-index"
5145+checksum = "e3c36a0f861ad76d0901f2800b46321410d9f73f2ea88aac0650d86c32688073"
5146+dependencies = [
5147+ "bitflags 2.13.1",
5148+ "rustix",
5149+ "wayland-backend",
5150+ "wayland-scanner",
5151+]
5152+
5153+[[package]]
5154+name = "wayland-protocols"
5155+version = "0.32.13"
5156+source = "registry+https://github.com/rust-lang/crates.io-index"
5157+checksum = "23d0c813de3daa2ed6520af85a3bd49b0e722a3078506899aa9686fea58dc4b6"
5158+dependencies = [
5159+ "bitflags 2.13.1",
5160+ "wayland-backend",
5161+ "wayland-client",
5162+ "wayland-scanner",
5163+]
5164+
5165+[[package]]
5166+name = "wayland-protocols-wlr"
5167+version = "0.3.12"
5168+source = "registry+https://github.com/rust-lang/crates.io-index"
5169+checksum = "eb04e52f7836d7c7976c78ca0250d61e33873c34156a2a1fc9474828ec268234"
5170+dependencies = [
5171+ "bitflags 2.13.1",
5172+ "wayland-backend",
5173+ "wayland-client",
5174+ "wayland-protocols",
5175+ "wayland-scanner",
5176+]
5177+
5178+[[package]]
5179+name = "wayland-scanner"
5180+version = "0.31.11"
5181+source = "registry+https://github.com/rust-lang/crates.io-index"
5182+checksum = "338e30461b3a2b67d70eb30a6d89f8e0c93a833e07d2ae89085cd070c4a00ac0"
5183+dependencies = [
5184+ "proc-macro2",
5185+ "quick-xml",
5186+ "quote",
5187+]
5188+
5189+[[package]]
5190+name = "wayland-sys"
5191+version = "0.31.11"
5192+source = "registry+https://github.com/rust-lang/crates.io-index"
5193+checksum = "d8eab23fefc9e41f8e841df4a9c707e8a8c4ed26e944ef69297184de2785e3be"
5194+dependencies = [
5195+ "pkg-config",
5196+]
5197+
5198+[[package]]
5199+name = "web-sys"
5200+version = "0.3.103"
5201+source = "registry+https://github.com/rust-lang/crates.io-index"
5202+checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141"
5203+dependencies = [
5204+ "js-sys",
5205+ "wasm-bindgen",
5206+]
5207+
5208+[[package]]
5209+name = "web-time"
5210+version = "1.1.0"
5211+source = "registry+https://github.com/rust-lang/crates.io-index"
5212+checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
5213+dependencies = [
5214+ "js-sys",
5215+ "wasm-bindgen",
5216+]
5217+
5218+[[package]]
5219+name = "web_atoms"
5220+version = "0.2.5"
5221+source = "registry+https://github.com/rust-lang/crates.io-index"
5222+checksum = "075474b12bcb3d2e3d4546580e9de478eeeead668a1761e2a8860c836b7ef297"
5223+dependencies = [
5224+ "phf",
5225+ "phf_codegen",
5226+ "string_cache",
5227+ "string_cache_codegen",
5228+]
5229+
5230+[[package]]
5231+name = "webkit2gtk"
5232+version = "2.0.2"
5233+source = "registry+https://github.com/rust-lang/crates.io-index"
5234+checksum = "a1027150013530fb2eaf806408df88461ae4815a45c541c8975e61d6f2fc4793"
5235+dependencies = [
5236+ "bitflags 1.3.2",
5237+ "cairo-rs",
5238+ "gdk",
5239+ "gdk-sys",
5240+ "gio",
5241+ "gio-sys",
5242+ "glib",
5243+ "glib-sys",
5244+ "gobject-sys",
5245+ "gtk",
5246+ "gtk-sys",
5247+ "javascriptcore-rs",
5248+ "libc",
5249+ "once_cell",
5250+ "soup3",
5251+ "webkit2gtk-sys",
5252+]
5253+
5254+[[package]]
5255+name = "webkit2gtk-sys"
5256+version = "2.0.2"
5257+source = "registry+https://github.com/rust-lang/crates.io-index"
5258+checksum = "916a5f65c2ef0dfe12fff695960a2ec3d4565359fdbb2e9943c974e06c734ea5"
5259+dependencies = [
5260+ "bitflags 1.3.2",
5261+ "cairo-sys-rs",
5262+ "gdk-sys",
5263+ "gio-sys",
5264+ "glib-sys",
5265+ "gobject-sys",
5266+ "gtk-sys",
5267+ "javascriptcore-rs-sys",
5268+ "libc",
5269+ "pkg-config",
5270+ "soup3-sys",
5271+ "system-deps",
5272+]
5273+
5274+[[package]]
5275+name = "webpki-roots"
5276+version = "1.0.9"
5277+source = "registry+https://github.com/rust-lang/crates.io-index"
5278+checksum = "7dcd9d09a39985f5344844e66b0c530a33843579125f23e21e9f0f220850f22a"
5279+dependencies = [
5280+ "rustls-pki-types",
5281+]
5282+
5283+[[package]]
5284+name = "webview2-com"
5285+version = "0.38.2"
5286+source = "registry+https://github.com/rust-lang/crates.io-index"
5287+checksum = "7130243a7a5b33c54a444e54842e6a9e133de08b5ad7b5861cd8ed9a6a5bc96a"
5288+dependencies = [
5289+ "webview2-com-macros",
5290+ "webview2-com-sys",
5291+ "windows 0.61.3",
5292+ "windows-core 0.61.2",
5293+ "windows-implement",
5294+ "windows-interface",
5295+]
5296+
5297+[[package]]
5298+name = "webview2-com-macros"
5299+version = "0.8.1"
5300+source = "registry+https://github.com/rust-lang/crates.io-index"
5301+checksum = "67a921c1b6914c367b2b823cd4cde6f96beec77d30a939c8199bb377cf9b9b54"
5302+dependencies = [
5303+ "proc-macro2",
5304+ "quote",
5305+ "syn 2.0.119",
5306+]
5307+
5308+[[package]]
5309+name = "webview2-com-sys"
5310+version = "0.38.2"
5311+source = "registry+https://github.com/rust-lang/crates.io-index"
5312+checksum = "381336cfffd772377d291702245447a5251a2ffa5bad679c99e61bc48bacbf9c"
5313+dependencies = [
5314+ "thiserror 2.0.19",
5315+ "windows 0.61.3",
5316+ "windows-core 0.61.2",
5317+]
5318+
5319+[[package]]
5320+name = "weezl"
5321+version = "0.1.12"
5322+source = "registry+https://github.com/rust-lang/crates.io-index"
5323+checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88"
5324+
5325+[[package]]
5326+name = "whisper-rs"
5327+version = "0.16.0"
5328+source = "registry+https://github.com/rust-lang/crates.io-index"
5329+checksum = "2088172d00f936c348d6a72f488dc2660ab3f507263a195df308a3c2383229f6"
5330+dependencies = [
5331+ "whisper-rs-sys",
5332+]
5333+
5334+[[package]]
5335+name = "whisper-rs-sys"
5336+version = "0.15.0"
5337+source = "registry+https://github.com/rust-lang/crates.io-index"
5338+checksum = "6986c0fe081241d391f09b9a071fbcbb59720c3563628c3c829057cf69f2a56f"
5339+dependencies = [
5340+ "bindgen",
5341+ "cfg-if",
5342+ "cmake",
5343+ "fs_extra",
5344+ "semver",
5345+]
5346+
5347+[[package]]
5348+name = "winapi"
5349+version = "0.3.9"
5350+source = "registry+https://github.com/rust-lang/crates.io-index"
5351+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
5352+dependencies = [
5353+ "winapi-i686-pc-windows-gnu",
5354+ "winapi-x86_64-pc-windows-gnu",
5355+]
5356+
5357+[[package]]
5358+name = "winapi-i686-pc-windows-gnu"
5359+version = "0.4.0"
5360+source = "registry+https://github.com/rust-lang/crates.io-index"
5361+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
5362+
5363+[[package]]
5364+name = "winapi-util"
5365+version = "0.1.11"
5366+source = "registry+https://github.com/rust-lang/crates.io-index"
5367+checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
5368+dependencies = [
5369+ "windows-sys 0.61.2",
5370+]
5371+
5372+[[package]]
5373+name = "winapi-x86_64-pc-windows-gnu"
5374+version = "0.4.0"
5375+source = "registry+https://github.com/rust-lang/crates.io-index"
5376+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
5377+
5378+[[package]]
5379+name = "window-vibrancy"
5380+version = "0.6.0"
5381+source = "registry+https://github.com/rust-lang/crates.io-index"
5382+checksum = "d9bec5a31f3f9362f2258fd0e9c9dd61a9ca432e7306cc78c444258f0dce9a9c"
5383+dependencies = [
5384+ "objc2",
5385+ "objc2-app-kit",
5386+ "objc2-core-foundation",
5387+ "objc2-foundation",
5388+ "raw-window-handle",
5389+ "windows-sys 0.59.0",
5390+ "windows-version",
5391+]
5392+
5393+[[package]]
5394+name = "windows"
5395+version = "0.54.0"
5396+source = "registry+https://github.com/rust-lang/crates.io-index"
5397+checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49"
5398+dependencies = [
5399+ "windows-core 0.54.0",
5400+ "windows-targets 0.52.6",
5401+]
5402+
5403+[[package]]
5404+name = "windows"
5405+version = "0.61.3"
5406+source = "registry+https://github.com/rust-lang/crates.io-index"
5407+checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893"
5408+dependencies = [
5409+ "windows-collections",
5410+ "windows-core 0.61.2",
5411+ "windows-future",
5412+ "windows-link 0.1.3",
5413+ "windows-numerics",
5414+]
5415+
5416+[[package]]
5417+name = "windows-collections"
5418+version = "0.2.0"
5419+source = "registry+https://github.com/rust-lang/crates.io-index"
5420+checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8"
5421+dependencies = [
5422+ "windows-core 0.61.2",
5423+]
5424+
5425+[[package]]
5426+name = "windows-core"
5427+version = "0.54.0"
5428+source = "registry+https://github.com/rust-lang/crates.io-index"
5429+checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65"
5430+dependencies = [
5431+ "windows-result 0.1.2",
5432+ "windows-targets 0.52.6",
5433+]
5434+
5435+[[package]]
5436+name = "windows-core"
5437+version = "0.61.2"
5438+source = "registry+https://github.com/rust-lang/crates.io-index"
5439+checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
5440+dependencies = [
5441+ "windows-implement",
5442+ "windows-interface",
5443+ "windows-link 0.1.3",
5444+ "windows-result 0.3.4",
5445+ "windows-strings 0.4.2",
5446+]
5447+
5448+[[package]]
5449+name = "windows-core"
5450+version = "0.62.2"
5451+source = "registry+https://github.com/rust-lang/crates.io-index"
5452+checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
5453+dependencies = [
5454+ "windows-implement",
5455+ "windows-interface",
5456+ "windows-link 0.2.1",
5457+ "windows-result 0.4.1",
5458+ "windows-strings 0.5.1",
5459+]
5460+
5461+[[package]]
5462+name = "windows-future"
5463+version = "0.2.1"
5464+source = "registry+https://github.com/rust-lang/crates.io-index"
5465+checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e"
5466+dependencies = [
5467+ "windows-core 0.61.2",
5468+ "windows-link 0.1.3",
5469+ "windows-threading",
5470+]
5471+
5472+[[package]]
5473+name = "windows-implement"
5474+version = "0.60.2"
5475+source = "registry+https://github.com/rust-lang/crates.io-index"
5476+checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
5477+dependencies = [
5478+ "proc-macro2",
5479+ "quote",
5480+ "syn 2.0.119",
5481+]
5482+
5483+[[package]]
5484+name = "windows-interface"
5485+version = "0.59.3"
5486+source = "registry+https://github.com/rust-lang/crates.io-index"
5487+checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
5488+dependencies = [
5489+ "proc-macro2",
5490+ "quote",
5491+ "syn 2.0.119",
5492+]
5493+
5494+[[package]]
5495+name = "windows-link"
5496+version = "0.1.3"
5497+source = "registry+https://github.com/rust-lang/crates.io-index"
5498+checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
5499+
5500+[[package]]
5501+name = "windows-link"
5502+version = "0.2.1"
5503+source = "registry+https://github.com/rust-lang/crates.io-index"
5504+checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
5505+
5506+[[package]]
5507+name = "windows-numerics"
5508+version = "0.2.0"
5509+source = "registry+https://github.com/rust-lang/crates.io-index"
5510+checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1"
5511+dependencies = [
5512+ "windows-core 0.61.2",
5513+ "windows-link 0.1.3",
5514+]
5515+
5516+[[package]]
5517+name = "windows-result"
5518+version = "0.1.2"
5519+source = "registry+https://github.com/rust-lang/crates.io-index"
5520+checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8"
5521+dependencies = [
5522+ "windows-targets 0.52.6",
5523+]
5524+
5525+[[package]]
5526+name = "windows-result"
5527+version = "0.3.4"
5528+source = "registry+https://github.com/rust-lang/crates.io-index"
5529+checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
5530+dependencies = [
5531+ "windows-link 0.1.3",
5532+]
5533+
5534+[[package]]
5535+name = "windows-result"
5536+version = "0.4.1"
5537+source = "registry+https://github.com/rust-lang/crates.io-index"
5538+checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
5539+dependencies = [
5540+ "windows-link 0.2.1",
5541+]
5542+
5543+[[package]]
5544+name = "windows-strings"
5545+version = "0.4.2"
5546+source = "registry+https://github.com/rust-lang/crates.io-index"
5547+checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
5548+dependencies = [
5549+ "windows-link 0.1.3",
5550+]
5551+
5552+[[package]]
5553+name = "windows-strings"
5554+version = "0.5.1"
5555+source = "registry+https://github.com/rust-lang/crates.io-index"
5556+checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
5557+dependencies = [
5558+ "windows-link 0.2.1",
5559+]
5560+
5561+[[package]]
5562+name = "windows-sys"
5563+version = "0.45.0"
5564+source = "registry+https://github.com/rust-lang/crates.io-index"
5565+checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
5566+dependencies = [
5567+ "windows-targets 0.42.2",
5568+]
5569+
5570+[[package]]
5571+name = "windows-sys"
5572+version = "0.52.0"
5573+source = "registry+https://github.com/rust-lang/crates.io-index"
5574+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
5575+dependencies = [
5576+ "windows-targets 0.52.6",
5577+]
5578+
5579+[[package]]
5580+name = "windows-sys"
5581+version = "0.59.0"
5582+source = "registry+https://github.com/rust-lang/crates.io-index"
5583+checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
5584+dependencies = [
5585+ "windows-targets 0.52.6",
5586+]
5587+
5588+[[package]]
5589+name = "windows-sys"
5590+version = "0.60.2"
5591+source = "registry+https://github.com/rust-lang/crates.io-index"
5592+checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
5593+dependencies = [
5594+ "windows-targets 0.53.5",
5595+]
5596+
5597+[[package]]
5598+name = "windows-sys"
5599+version = "0.61.2"
5600+source = "registry+https://github.com/rust-lang/crates.io-index"
5601+checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
5602+dependencies = [
5603+ "windows-link 0.2.1",
5604+]
5605+
5606+[[package]]
5607+name = "windows-targets"
5608+version = "0.42.2"
5609+source = "registry+https://github.com/rust-lang/crates.io-index"
5610+checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
5611+dependencies = [
5612+ "windows_aarch64_gnullvm 0.42.2",
5613+ "windows_aarch64_msvc 0.42.2",
5614+ "windows_i686_gnu 0.42.2",
5615+ "windows_i686_msvc 0.42.2",
5616+ "windows_x86_64_gnu 0.42.2",
5617+ "windows_x86_64_gnullvm 0.42.2",
5618+ "windows_x86_64_msvc 0.42.2",
5619+]
5620+
5621+[[package]]
5622+name = "windows-targets"
5623+version = "0.52.6"
5624+source = "registry+https://github.com/rust-lang/crates.io-index"
5625+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
5626+dependencies = [
5627+ "windows_aarch64_gnullvm 0.52.6",
5628+ "windows_aarch64_msvc 0.52.6",
5629+ "windows_i686_gnu 0.52.6",
5630+ "windows_i686_gnullvm 0.52.6",
5631+ "windows_i686_msvc 0.52.6",
5632+ "windows_x86_64_gnu 0.52.6",
5633+ "windows_x86_64_gnullvm 0.52.6",
5634+ "windows_x86_64_msvc 0.52.6",
5635+]
5636+
5637+[[package]]
5638+name = "windows-targets"
5639+version = "0.53.5"
5640+source = "registry+https://github.com/rust-lang/crates.io-index"
5641+checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
5642+dependencies = [
5643+ "windows-link 0.2.1",
5644+ "windows_aarch64_gnullvm 0.53.1",
5645+ "windows_aarch64_msvc 0.53.1",
5646+ "windows_i686_gnu 0.53.1",
5647+ "windows_i686_gnullvm 0.53.1",
5648+ "windows_i686_msvc 0.53.1",
5649+ "windows_x86_64_gnu 0.53.1",
5650+ "windows_x86_64_gnullvm 0.53.1",
5651+ "windows_x86_64_msvc 0.53.1",
5652+]
5653+
5654+[[package]]
5655+name = "windows-threading"
5656+version = "0.1.0"
5657+source = "registry+https://github.com/rust-lang/crates.io-index"
5658+checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6"
5659+dependencies = [
5660+ "windows-link 0.1.3",
5661+]
5662+
5663+[[package]]
5664+name = "windows-version"
5665+version = "0.1.7"
5666+source = "registry+https://github.com/rust-lang/crates.io-index"
5667+checksum = "e4060a1da109b9d0326b7262c8e12c84df67cc0dbc9e33cf49e01ccc2eb63631"
5668+dependencies = [
5669+ "windows-link 0.2.1",
5670+]
5671+
5672+[[package]]
5673+name = "windows_aarch64_gnullvm"
5674+version = "0.42.2"
5675+source = "registry+https://github.com/rust-lang/crates.io-index"
5676+checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
5677+
5678+[[package]]
5679+name = "windows_aarch64_gnullvm"
5680+version = "0.52.6"
5681+source = "registry+https://github.com/rust-lang/crates.io-index"
5682+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
5683+
5684+[[package]]
5685+name = "windows_aarch64_gnullvm"
5686+version = "0.53.1"
5687+source = "registry+https://github.com/rust-lang/crates.io-index"
5688+checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
5689+
5690+[[package]]
5691+name = "windows_aarch64_msvc"
5692+version = "0.42.2"
5693+source = "registry+https://github.com/rust-lang/crates.io-index"
5694+checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
5695+
5696+[[package]]
5697+name = "windows_aarch64_msvc"
5698+version = "0.52.6"
5699+source = "registry+https://github.com/rust-lang/crates.io-index"
5700+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
5701+
5702+[[package]]
5703+name = "windows_aarch64_msvc"
5704+version = "0.53.1"
5705+source = "registry+https://github.com/rust-lang/crates.io-index"
5706+checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
5707+
5708+[[package]]
5709+name = "windows_i686_gnu"
5710+version = "0.42.2"
5711+source = "registry+https://github.com/rust-lang/crates.io-index"
5712+checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
5713+
5714+[[package]]
5715+name = "windows_i686_gnu"
5716+version = "0.52.6"
5717+source = "registry+https://github.com/rust-lang/crates.io-index"
5718+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
5719+
5720+[[package]]
5721+name = "windows_i686_gnu"
5722+version = "0.53.1"
5723+source = "registry+https://github.com/rust-lang/crates.io-index"
5724+checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"
5725+
5726+[[package]]
5727+name = "windows_i686_gnullvm"
5728+version = "0.52.6"
5729+source = "registry+https://github.com/rust-lang/crates.io-index"
5730+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
5731+
5732+[[package]]
5733+name = "windows_i686_gnullvm"
5734+version = "0.53.1"
5735+source = "registry+https://github.com/rust-lang/crates.io-index"
5736+checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
5737+
5738+[[package]]
5739+name = "windows_i686_msvc"
5740+version = "0.42.2"
5741+source = "registry+https://github.com/rust-lang/crates.io-index"
5742+checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
5743+
5744+[[package]]
5745+name = "windows_i686_msvc"
5746+version = "0.52.6"
5747+source = "registry+https://github.com/rust-lang/crates.io-index"
5748+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
5749+
5750+[[package]]
5751+name = "windows_i686_msvc"
5752+version = "0.53.1"
5753+source = "registry+https://github.com/rust-lang/crates.io-index"
5754+checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
5755+
5756+[[package]]
5757+name = "windows_x86_64_gnu"
5758+version = "0.42.2"
5759+source = "registry+https://github.com/rust-lang/crates.io-index"
5760+checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
5761+
5762+[[package]]
5763+name = "windows_x86_64_gnu"
5764+version = "0.52.6"
5765+source = "registry+https://github.com/rust-lang/crates.io-index"
5766+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
5767+
5768+[[package]]
5769+name = "windows_x86_64_gnu"
5770+version = "0.53.1"
5771+source = "registry+https://github.com/rust-lang/crates.io-index"
5772+checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
5773+
5774+[[package]]
5775+name = "windows_x86_64_gnullvm"
5776+version = "0.42.2"
5777+source = "registry+https://github.com/rust-lang/crates.io-index"
5778+checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
5779+
5780+[[package]]
5781+name = "windows_x86_64_gnullvm"
5782+version = "0.52.6"
5783+source = "registry+https://github.com/rust-lang/crates.io-index"
5784+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
5785+
5786+[[package]]
5787+name = "windows_x86_64_gnullvm"
5788+version = "0.53.1"
5789+source = "registry+https://github.com/rust-lang/crates.io-index"
5790+checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
5791+
5792+[[package]]
5793+name = "windows_x86_64_msvc"
5794+version = "0.42.2"
5795+source = "registry+https://github.com/rust-lang/crates.io-index"
5796+checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
5797+
5798+[[package]]
5799+name = "windows_x86_64_msvc"
5800+version = "0.52.6"
5801+source = "registry+https://github.com/rust-lang/crates.io-index"
5802+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
5803+
5804+[[package]]
5805+name = "windows_x86_64_msvc"
5806+version = "0.53.1"
5807+source = "registry+https://github.com/rust-lang/crates.io-index"
5808+checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
5809+
5810+[[package]]
5811+name = "winnow"
5812+version = "0.5.40"
5813+source = "registry+https://github.com/rust-lang/crates.io-index"
5814+checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876"
5815+dependencies = [
5816+ "memchr",
5817+]
5818+
5819+[[package]]
5820+name = "winnow"
5821+version = "0.7.15"
5822+source = "registry+https://github.com/rust-lang/crates.io-index"
5823+checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
5824+
5825+[[package]]
5826+name = "winnow"
5827+version = "1.0.4"
5828+source = "registry+https://github.com/rust-lang/crates.io-index"
5829+checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81"
5830+dependencies = [
5831+ "memchr",
5832+]
5833+
5834+[[package]]
5835+name = "winreg"
5836+version = "0.10.1"
5837+source = "registry+https://github.com/rust-lang/crates.io-index"
5838+checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
5839+dependencies = [
5840+ "winapi",
5841+]
5842+
5843+[[package]]
5844+name = "winreg"
5845+version = "0.55.0"
5846+source = "registry+https://github.com/rust-lang/crates.io-index"
5847+checksum = "cb5a765337c50e9ec252c2069be9bf91c7df47afb103b642ba3a53bf8101be97"
5848+dependencies = [
5849+ "cfg-if",
5850+ "windows-sys 0.59.0",
5851+]
5852+
5853+[[package]]
5854+name = "wit-bindgen"
5855+version = "0.57.1"
5856+source = "registry+https://github.com/rust-lang/crates.io-index"
5857+checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
5858+
5859+[[package]]
5860+name = "wl-clipboard-rs"
5861+version = "0.9.3"
5862+source = "registry+https://github.com/rust-lang/crates.io-index"
5863+checksum = "e9651471a32e87d96ef3a127715382b2d11cc7c8bb9822ded8a7cc94072eb0a3"
5864+dependencies = [
5865+ "libc",
5866+ "log",
5867+ "os_pipe",
5868+ "rustix",
5869+ "thiserror 2.0.19",
5870+ "tree_magic_mini",
5871+ "wayland-backend",
5872+ "wayland-client",
5873+ "wayland-protocols",
5874+ "wayland-protocols-wlr",
5875+]
5876+
5877+[[package]]
5878+name = "writeable"
5879+version = "0.6.3"
5880+source = "registry+https://github.com/rust-lang/crates.io-index"
5881+checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4"
5882+
5883+[[package]]
5884+name = "wry"
5885+version = "0.55.1"
5886+source = "registry+https://github.com/rust-lang/crates.io-index"
5887+checksum = "186f9871daa55fd9c016578b810d149de58367113db7fb72b462d2323ce19514"
5888+dependencies = [
5889+ "base64 0.22.1",
5890+ "block2",
5891+ "cookie",
5892+ "crossbeam-channel",
5893+ "dirs 6.0.0",
5894+ "dom_query",
5895+ "dpi",
5896+ "dunce",
5897+ "gdkx11",
5898+ "gtk",
5899+ "http",
5900+ "javascriptcore-rs",
5901+ "jni",
5902+ "libc",
5903+ "ndk",
5904+ "objc2",
5905+ "objc2-app-kit",
5906+ "objc2-core-foundation",
5907+ "objc2-foundation",
5908+ "objc2-ui-kit",
5909+ "objc2-web-kit",
5910+ "once_cell",
5911+ "percent-encoding",
5912+ "raw-window-handle",
5913+ "sha2",
5914+ "soup3",
5915+ "tao-macros",
5916+ "thiserror 2.0.19",
5917+ "url",
5918+ "webkit2gtk",
5919+ "webkit2gtk-sys",
5920+ "webview2-com",
5921+ "windows 0.61.3",
5922+ "windows-core 0.61.2",
5923+ "windows-version",
5924+ "x11-dl",
5925+]
5926+
5927+[[package]]
5928+name = "x11"
5929+version = "2.21.0"
5930+source = "registry+https://github.com/rust-lang/crates.io-index"
5931+checksum = "502da5464ccd04011667b11c435cb992822c2c0dbde1770c988480d312a0db2e"
5932+dependencies = [
5933+ "libc",
5934+ "pkg-config",
5935+]
5936+
5937+[[package]]
5938+name = "x11-dl"
5939+version = "2.21.0"
5940+source = "registry+https://github.com/rust-lang/crates.io-index"
5941+checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f"
5942+dependencies = [
5943+ "libc",
5944+ "once_cell",
5945+ "pkg-config",
5946+]
5947+
5948+[[package]]
5949+name = "x11rb"
5950+version = "0.13.2"
5951+source = "registry+https://github.com/rust-lang/crates.io-index"
5952+checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414"
5953+dependencies = [
5954+ "gethostname",
5955+ "rustix",
5956+ "x11rb-protocol",
5957+]
5958+
5959+[[package]]
5960+name = "x11rb-protocol"
5961+version = "0.13.2"
5962+source = "registry+https://github.com/rust-lang/crates.io-index"
5963+checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd"
5964+
5965+[[package]]
5966+name = "xkbcommon"
5967+version = "0.9.0"
5968+source = "registry+https://github.com/rust-lang/crates.io-index"
5969+checksum = "a7a974f48060a14e95705c01f24ad9c3345022f4d97441b8a36beb7ed5c4a02d"
5970+dependencies = [
5971+ "libc",
5972+ "memmap2",
5973+ "xkeysym",
5974+]
5975+
5976+[[package]]
5977+name = "xkeysym"
5978+version = "0.2.1"
5979+source = "registry+https://github.com/rust-lang/crates.io-index"
5980+checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56"
5981+
5982+[[package]]
5983+name = "yoke"
5984+version = "0.8.3"
5985+source = "registry+https://github.com/rust-lang/crates.io-index"
5986+checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5"
5987+dependencies = [
5988+ "stable_deref_trait",
5989+ "yoke-derive",
5990+ "zerofrom",
5991+]
5992+
5993+[[package]]
5994+name = "yoke-derive"
5995+version = "0.8.2"
5996+source = "registry+https://github.com/rust-lang/crates.io-index"
5997+checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e"
5998+dependencies = [
5999+ "proc-macro2",
6000+ "quote",
6001+ "syn 2.0.119",
6002+ "synstructure",
6003+]
6004+
6005+[[package]]
6006+name = "zbus"
6007+version = "5.18.0"
6008+source = "registry+https://github.com/rust-lang/crates.io-index"
6009+checksum = "fe18fb60dc696039e738717b76eaea21e7a4489bbb1885020b43c94236d7e98a"
6010+dependencies = [
6011+ "async-broadcast",
6012+ "async-executor",
6013+ "async-io",
6014+ "async-lock",
6015+ "async-process",
6016+ "async-recursion",
6017+ "async-task",
6018+ "async-trait",
6019+ "blocking",
6020+ "enumflags2",
6021+ "event-listener",
6022+ "futures-core",
6023+ "futures-lite",
6024+ "hex",
6025+ "libc",
6026+ "ordered-stream",
6027+ "rustix",
6028+ "serde",
6029+ "serde_repr",
6030+ "tracing",
6031+ "uds_windows",
6032+ "uuid",
6033+ "windows-sys 0.61.2",
6034+ "winnow 1.0.4",
6035+ "zbus_macros",
6036+ "zbus_names",
6037+ "zvariant",
6038+]
6039+
6040+[[package]]
6041+name = "zbus_macros"
6042+version = "5.18.0"
6043+source = "registry+https://github.com/rust-lang/crates.io-index"
6044+checksum = "fe96480bed92df2b442a1a30df364e12d08eed03aeb061f2b8dc6afb2be91119"
6045+dependencies = [
6046+ "proc-macro-crate 3.5.0",
6047+ "proc-macro2",
6048+ "quote",
6049+ "syn 2.0.119",
6050+ "zbus_names",
6051+ "zvariant",
6052+ "zvariant_utils",
6053+]
6054+
6055+[[package]]
6056+name = "zbus_names"
6057+version = "4.3.4"
6058+source = "registry+https://github.com/rust-lang/crates.io-index"
6059+checksum = "d8bf88b4a3ff53e883001e0e0115b297a9d53c31b9c1edd2bfdd853e3428624e"
6060+dependencies = [
6061+ "serde",
6062+ "winnow 1.0.4",
6063+ "zvariant",
6064+]
6065+
6066+[[package]]
6067+name = "zerocopy"
6068+version = "0.8.55"
6069+source = "registry+https://github.com/rust-lang/crates.io-index"
6070+checksum = "b5a105cd7b140f6eeec8acff2ea38135d3cab283ada58540f629fe51e46696eb"
6071+dependencies = [
6072+ "zerocopy-derive",
6073+]
6074+
6075+[[package]]
6076+name = "zerocopy-derive"
6077+version = "0.8.55"
6078+source = "registry+https://github.com/rust-lang/crates.io-index"
6079+checksum = "0fe976fb70c78cd64cccfe3a6fc142244e8a77b70959b30faf9d0ac37ee228eb"
6080+dependencies = [
6081+ "proc-macro2",
6082+ "quote",
6083+ "syn 2.0.119",
6084+]
6085+
6086+[[package]]
6087+name = "zerofrom"
6088+version = "0.1.8"
6089+source = "registry+https://github.com/rust-lang/crates.io-index"
6090+checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272"
6091+dependencies = [
6092+ "zerofrom-derive",
6093+]
6094+
6095+[[package]]
6096+name = "zerofrom-derive"
6097+version = "0.1.7"
6098+source = "registry+https://github.com/rust-lang/crates.io-index"
6099+checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1"
6100+dependencies = [
6101+ "proc-macro2",
6102+ "quote",
6103+ "syn 2.0.119",
6104+ "synstructure",
6105+]
6106+
6107+[[package]]
6108+name = "zeroize"
6109+version = "1.9.0"
6110+source = "registry+https://github.com/rust-lang/crates.io-index"
6111+checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e"
6112+
6113+[[package]]
6114+name = "zerotrie"
6115+version = "0.2.4"
6116+source = "registry+https://github.com/rust-lang/crates.io-index"
6117+checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf"
6118+dependencies = [
6119+ "displaydoc",
6120+ "yoke",
6121+ "zerofrom",
6122+]
6123+
6124+[[package]]
6125+name = "zerovec"
6126+version = "0.11.6"
6127+source = "registry+https://github.com/rust-lang/crates.io-index"
6128+checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239"
6129+dependencies = [
6130+ "yoke",
6131+ "zerofrom",
6132+ "zerovec-derive",
6133+]
6134+
6135+[[package]]
6136+name = "zerovec-derive"
6137+version = "0.11.3"
6138+source = "registry+https://github.com/rust-lang/crates.io-index"
6139+checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555"
6140+dependencies = [
6141+ "proc-macro2",
6142+ "quote",
6143+ "syn 2.0.119",
6144+]
6145+
6146+[[package]]
6147+name = "zmij"
6148+version = "1.0.23"
6149+source = "registry+https://github.com/rust-lang/crates.io-index"
6150+checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
6151+
6152+[[package]]
6153+name = "zune-core"
6154+version = "0.5.1"
6155+source = "registry+https://github.com/rust-lang/crates.io-index"
6156+checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9"
6157+
6158+[[package]]
6159+name = "zune-jpeg"
6160+version = "0.5.15"
6161+source = "registry+https://github.com/rust-lang/crates.io-index"
6162+checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296"
6163+dependencies = [
6164+ "zune-core",
6165+]
6166+
6167+[[package]]
6168+name = "zvariant"
6169+version = "5.13.1"
6170+source = "registry+https://github.com/rust-lang/crates.io-index"
6171+checksum = "bee2a0bcd2a907786a456fff45aaaaf54c9ba5f50b71ae9ec1a4edd200c94911"
6172+dependencies = [
6173+ "endi",
6174+ "enumflags2",
6175+ "serde",
6176+ "winnow 1.0.4",
6177+ "zvariant_derive",
6178+ "zvariant_utils",
6179+]
6180+
6181+[[package]]
6182+name = "zvariant_derive"
6183+version = "5.13.1"
6184+source = "registry+https://github.com/rust-lang/crates.io-index"
6185+checksum = "38a708216a18780796770bfe3f4739c7c83a3e8f789b755534bbbc06e4e23e12"
6186+dependencies = [
6187+ "proc-macro-crate 3.5.0",
6188+ "proc-macro2",
6189+ "quote",
6190+ "syn 2.0.119",
6191+ "zvariant_utils",
6192+]
6193+
6194+[[package]]
6195+name = "zvariant_utils"
6196+version = "3.5.0"
6197+source = "registry+https://github.com/rust-lang/crates.io-index"
6198+checksum = "90cb9383f9b45290407a1258b202d3f8f01db719eb60b4e4055c6375af4fc7c7"
6199+dependencies = [
6200+ "proc-macro2",
6201+ "quote",
6202+ "serde",
6203+ "syn 2.0.119",
6204+ "winnow 1.0.4",
6205+]
+37-0src-tauri/Cargo.toml
@@ -0,0 +1,37 @@
1+[package]
2+name = "mutterbox"
3+version = "0.1.0"
4+description = "Open source dictation with local whisper models and optional LLM cleanup"
5+authors = ["mutterbox contributors"]
6+license = "MIT"
7+edition = "2021"
8+
9+[lib]
10+name = "mutterbox_lib"
11+crate-type = ["staticlib", "cdylib", "rlib"]
12+
13+[build-dependencies]
14+tauri-build = { version = "2", features = [] }
15+
16+[dependencies]
17+tauri = { version = "2", features = ["tray-icon", "image-png"] }
18+tauri-plugin-opener = "2"
19+serde = { version = "1", features = ["derive"] }
20+serde_json = "1"
21+tauri-plugin-clipboard-manager = "2"
22+tauri-plugin-notification = "2"
23+cpal = "0.16"
24+whisper-rs = "0.16"
25+enigo = "0.6"
26+reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls", "stream"] }
27+futures-util = "0.3"
28+tokio = { version = "1", features = ["fs", "io-util"] }
29+
30+[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
31+tauri-plugin-autostart = "2"
32+tauri-plugin-global-shortcut = "2"
33+tauri-plugin-single-instance = "2"
34+
35+[profile.release]
36+lto = true
37+codegen-units = 1
+3-0src-tauri/build.rs
@@ -0,0 +1,3 @@
1+fn main() {
2+ tauri_build::build()
3+}
+11-0src-tauri/capabilities/default.json
@@ -0,0 +1,11 @@
1+{
2+ "$schema": "../gen/schemas/desktop-schema.json",
3+ "identifier": "default",
4+ "description": "Capability for the main and overlay windows",
5+ "windows": ["main", "overlay"],
6+ "permissions": [
7+ "core:default",
8+ "opener:default",
9+ "clipboard-manager:allow-write-text"
10+ ]
11+}
+15-0src-tauri/capabilities/desktop.json
@@ -0,0 +1,15 @@
1+{
2+ "identifier": "desktop-capability",
3+ "platforms": [
4+ "macOS",
5+ "windows",
6+ "linux"
7+ ],
8+ "windows": [
9+ "main"
10+ ],
11+ "permissions": [
12+ "global-shortcut:default",
13+ "autostart:default"
14+ ]
15+}
+0-0src-tauri/icons/128x128.png

Binary file changed.

+0-0src-tauri/icons/128x128@2x.png

Binary file changed.

+0-0src-tauri/icons/32x32.png

Binary file changed.

+0-0src-tauri/icons/Square107x107Logo.png

Binary file changed.

+0-0src-tauri/icons/Square142x142Logo.png

Binary file changed.

+0-0src-tauri/icons/Square150x150Logo.png

Binary file changed.

+0-0src-tauri/icons/Square284x284Logo.png

Binary file changed.

+0-0src-tauri/icons/Square30x30Logo.png

Binary file changed.

+0-0src-tauri/icons/Square310x310Logo.png

Binary file changed.

+0-0src-tauri/icons/Square44x44Logo.png

Binary file changed.

+0-0src-tauri/icons/Square71x71Logo.png

Binary file changed.

+0-0src-tauri/icons/Square89x89Logo.png

Binary file changed.

+0-0src-tauri/icons/StoreLogo.png

Binary file changed.

+0-0src-tauri/icons/icon.icns

Binary file changed.

+0-0src-tauri/icons/icon.ico

Binary file changed.

+0-0src-tauri/icons/icon.png

Binary file changed.

+166-0src-tauri/src/audio.rs
@@ -0,0 +1,166 @@
1+use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
2+use std::sync::mpsc;
3+use std::sync::{Arc, Mutex};
4+use std::thread::JoinHandle;
5+
6+pub const WHISPER_SAMPLE_RATE: u32 = 16_000;
7+
8+struct ActiveRecording {
9+ stop_tx: mpsc::Sender<()>,
10+ handle: JoinHandle<Result<(), String>>,
11+ samples: Arc<Mutex<Vec<f32>>>,
12+ sample_rate: u32,
13+ channels: u16,
14+}
15+
16+#[derive(Default)]
17+pub struct Recorder {
18+ active: Option<ActiveRecording>,
19+}
20+
21+impl Recorder {
22+ pub fn is_recording(&self) -> bool {
23+ self.active.is_some()
24+ }
25+
26+ pub fn start(&mut self) -> Result<(), String> {
27+ if self.active.is_some() {
28+ return Err("already recording".into());
29+ }
30+
31+ let host = cpal::default_host();
32+ let device = host
33+ .default_input_device()
34+ .ok_or("no microphone found".to_string())?;
35+ let config = device
36+ .default_input_config()
37+ .map_err(|e| format!("no input config: {e}"))?;
38+
39+ let sample_rate = config.sample_rate().0;
40+ let channels = config.channels();
41+ let sample_format = config.sample_format();
42+ let stream_config: cpal::StreamConfig = config.into();
43+
44+ let samples: Arc<Mutex<Vec<f32>>> = Arc::new(Mutex::new(Vec::new()));
45+ let (stop_tx, stop_rx) = mpsc::channel::<()>();
46+ let (ready_tx, ready_rx) = mpsc::channel::<Result<(), String>>();
47+ let sink = samples.clone();
48+
49+ // cpal streams are not Send, so the stream lives on its own thread
50+ let handle = std::thread::spawn(move || -> Result<(), String> {
51+ let err_fn = |e| eprintln!("audio stream error: {e}");
52+ let build = match sample_format {
53+ cpal::SampleFormat::F32 => {
54+ let sink = sink.clone();
55+ device.build_input_stream(
56+ &stream_config,
57+ move |data: &[f32], _| {
58+ sink.lock().unwrap().extend_from_slice(data);
59+ },
60+ err_fn,
61+ None,
62+ )
63+ }
64+ cpal::SampleFormat::I16 => {
65+ let sink = sink.clone();
66+ device.build_input_stream(
67+ &stream_config,
68+ move |data: &[i16], _| {
69+ let mut buf = sink.lock().unwrap();
70+ buf.extend(data.iter().map(|s| *s as f32 / 32_768.0));
71+ },
72+ err_fn,
73+ None,
74+ )
75+ }
76+ cpal::SampleFormat::U16 => {
77+ let sink = sink.clone();
78+ device.build_input_stream(
79+ &stream_config,
80+ move |data: &[u16], _| {
81+ let mut buf = sink.lock().unwrap();
82+ buf.extend(data.iter().map(|s| (*s as f32 - 32_768.0) / 32_768.0));
83+ },
84+ err_fn,
85+ None,
86+ )
87+ }
88+ other => {
89+ let _ = ready_tx.send(Err(format!("unsupported sample format: {other:?}")));
90+ return Err("unsupported sample format".into());
91+ }
92+ };
93+
94+ let stream = match build {
95+ Ok(s) => s,
96+ Err(e) => {
97+ let _ = ready_tx.send(Err(format!("open microphone: {e}")));
98+ return Err(e.to_string());
99+ }
100+ };
101+ if let Err(e) = stream.play() {
102+ let _ = ready_tx.send(Err(format!("start microphone: {e}")));
103+ return Err(e.to_string());
104+ }
105+ let _ = ready_tx.send(Ok(()));
106+ let _ = stop_rx.recv();
107+ drop(stream);
108+ Ok(())
109+ });
110+
111+ match ready_rx.recv() {
112+ Ok(Ok(())) => {
113+ self.active = Some(ActiveRecording {
114+ stop_tx,
115+ handle,
116+ samples,
117+ sample_rate,
118+ channels,
119+ });
120+ Ok(())
121+ }
122+ Ok(Err(e)) => {
123+ let _ = handle.join();
124+ Err(e)
125+ }
126+ Err(_) => Err("audio thread died before starting".into()),
127+ }
128+ }
129+
130+ /// Stops recording and returns mono samples resampled to 16 kHz.
131+ pub fn stop(&mut self) -> Result<Vec<f32>, String> {
132+ let active = self.active.take().ok_or("not recording".to_string())?;
133+ let _ = active.stop_tx.send(());
134+ let _ = active.handle.join();
135+ let raw = std::mem::take(&mut *active.samples.lock().unwrap());
136+ Ok(to_mono_16k(&raw, active.sample_rate, active.channels))
137+ }
138+}
139+
140+fn to_mono_16k(samples: &[f32], sample_rate: u32, channels: u16) -> Vec<f32> {
141+ let ch = channels.max(1) as usize;
142+ let mono: Vec<f32> = samples
143+ .chunks_exact(ch)
144+ .map(|frame| frame.iter().sum::<f32>() / ch as f32)
145+ .collect();
146+
147+ if sample_rate == WHISPER_SAMPLE_RATE {
148+ return mono;
149+ }
150+ if mono.is_empty() {
151+ return mono;
152+ }
153+
154+ let ratio = sample_rate as f64 / WHISPER_SAMPLE_RATE as f64;
155+ let out_len = (mono.len() as f64 / ratio) as usize;
156+ let mut out = Vec::with_capacity(out_len);
157+ for i in 0..out_len {
158+ let pos = i as f64 * ratio;
159+ let idx = pos as usize;
160+ let frac = (pos - idx as f64) as f32;
161+ let a = mono[idx.min(mono.len() - 1)];
162+ let b = mono[(idx + 1).min(mono.len() - 1)];
163+ out.push(a + (b - a) * frac);
164+ }
165+ out
166+}
+262-0src-tauri/src/inject.rs
@@ -0,0 +1,262 @@
1+use enigo::{Direction, Enigo, Key, Keyboard, Settings as EnigoSettings};
2+use std::io::Write as _;
3+use std::process::{Command, Stdio};
4+use std::thread::sleep;
5+use std::time::Duration;
6+use tauri::AppHandle;
7+use tauri_plugin_clipboard_manager::ClipboardExt;
8+
9+/// Injects text into whatever field currently has focus.
10+/// mode: "paste" (clipboard + ctrl+v) or "type" (synthetic keystrokes).
11+pub fn inject(
12+ app: &AppHandle,
13+ text: &str,
14+ mode: &str,
15+ restore_clipboard: bool,
16+) -> Result<(), String> {
17+ match mode {
18+ "type" => type_text(text),
19+ _ => paste_text(app, text, restore_clipboard),
20+ }
21+}
22+
23+fn is_wayland() -> bool {
24+ std::env::var_os("WAYLAND_DISPLAY").is_some()
25+ || std::env::var("XDG_SESSION_TYPE")
26+ .map(|v| v == "wayland")
27+ .unwrap_or(false)
28+}
29+
30+fn run_with_stdin(cmd: &str, args: &[&str], input: &str) -> Result<(), String> {
31+ let mut child = Command::new(cmd)
32+ .args(args)
33+ .stdin(Stdio::piped())
34+ .stdout(Stdio::null())
35+ .stderr(Stdio::piped())
36+ .spawn()
37+ .map_err(|e| format!("{cmd}: {e}"))?;
38+ {
39+ let mut stdin = child.stdin.take().ok_or(format!("{cmd}: no stdin"))?;
40+ stdin
41+ .write_all(input.as_bytes())
42+ .map_err(|e| format!("{cmd} stdin: {e}"))?;
43+ }
44+ let out = child
45+ .wait_with_output()
46+ .map_err(|e| format!("{cmd}: {e}"))?;
47+ if out.status.success() {
48+ Ok(())
49+ } else {
50+ Err(format!(
51+ "{cmd} failed: {}",
52+ String::from_utf8_lossy(&out.stderr).trim()
53+ ))
54+ }
55+}
56+
57+fn run_simple(cmd: &str, args: &[&str]) -> Result<(), String> {
58+ match Command::new(cmd).args(args).output() {
59+ Ok(o) if o.status.success() => Ok(()),
60+ Ok(o) => Err(format!(
61+ "{cmd} failed: {}",
62+ String::from_utf8_lossy(&o.stderr).trim()
63+ )),
64+ Err(e) => Err(format!("{cmd}: {e}")),
65+ }
66+}
67+
68+fn write_clipboard(app: &AppHandle, text: &str) -> Result<(), String> {
69+ // wl-copy talks to the Wayland clipboard directly; the plugin (arboard)
70+ // may only reach the XWayland side under some setups.
71+ if is_wayland() && run_with_stdin("wl-copy", &[], text).is_ok() {
72+ return Ok(());
73+ }
74+ app.clipboard()
75+ .write_text(text.to_string())
76+ .map_err(|e| format!("clipboard write: {e}"))
77+}
78+
79+fn read_clipboard(app: &AppHandle) -> Option<String> {
80+ if is_wayland() {
81+ if let Ok(out) = Command::new("wl-paste").arg("--no-newline").output() {
82+ if out.status.success() {
83+ return Some(String::from_utf8_lossy(&out.stdout).to_string());
84+ }
85+ }
86+ return None; // empty Wayland clipboard
87+ }
88+ app.clipboard().read_text().ok()
89+}
90+
91+/// Focused window (class, title) when running under Hyprland, else None.
92+fn hyprland_active_window() -> Option<(String, String)> {
93+ std::env::var_os("HYPRLAND_INSTANCE_SIGNATURE")?;
94+ let out = Command::new("hyprctl")
95+ .args(["activewindow", "-j"])
96+ .output()
97+ .ok()?;
98+ if !out.status.success() {
99+ return None;
100+ }
101+ let v: serde_json::Value = serde_json::from_slice(&out.stdout).ok()?;
102+ Some((
103+ v["class"].as_str()?.to_string(),
104+ v["title"].as_str().unwrap_or("").to_string(),
105+ ))
106+}
107+
108+/// Terminals paste with Ctrl+Shift+V; Ctrl+V is a literal control char there.
109+fn is_terminal_class(class: &str) -> bool {
110+ let c = class.to_lowercase();
111+ [
112+ "kitty",
113+ "alacritty",
114+ "foot",
115+ "wezterm",
116+ "ghostty",
117+ "konsole",
118+ "tilix",
119+ "terminator",
120+ "urxvt",
121+ "xterm",
122+ "termite",
123+ "terminal",
124+ ]
125+ .iter()
126+ .any(|t| c == *t || c.contains(t))
127+}
128+
129+fn enigo_paste_chord(with_shift: bool) -> Result<(), String> {
130+ let mut enigo = Enigo::new(&EnigoSettings::default()).map_err(|e| format!("enigo init: {e}"))?;
131+ enigo
132+ .key(Key::Control, Direction::Press)
133+ .map_err(|e| format!("enigo: {e}"))?;
134+ if with_shift {
135+ enigo
136+ .key(Key::Shift, Direction::Press)
137+ .map_err(|e| format!("enigo: {e}"))?;
138+ }
139+ let result = enigo.key(Key::Unicode('v'), Direction::Click);
140+ if with_shift {
141+ let _ = enigo.key(Key::Shift, Direction::Release);
142+ }
143+ let _ = enigo.key(Key::Control, Direction::Release);
144+ result.map_err(|e| format!("enigo: {e}"))
145+}
146+
147+fn send_paste_chord(with_shift: bool) -> Result<(), String> {
148+ let mut errors: Vec<String> = Vec::new();
149+
150+ if is_wayland() {
151+ // wtype uses the virtual-keyboard protocol (Hyprland, Sway, wlroots);
152+ // no daemon needed.
153+ let wtype_args: &[&str] = if with_shift {
154+ &["-M", "ctrl", "-M", "shift", "-k", "v", "-m", "shift", "-m", "ctrl"]
155+ } else {
156+ &["-M", "ctrl", "-k", "v", "-m", "ctrl"]
157+ };
158+ match run_simple("wtype", wtype_args) {
159+ Ok(()) => return Ok(()),
160+ Err(e) => errors.push(e),
161+ }
162+ // ydotool works everywhere via uinput but needs ydotoold running.
163+ // 29 = LEFTCTRL, 42 = LEFTSHIFT, 47 = V
164+ let ydotool_args: &[&str] = if with_shift {
165+ &["key", "29:1", "42:1", "47:1", "47:0", "42:0", "29:0"]
166+ } else {
167+ &["key", "29:1", "47:1", "47:0", "29:0"]
168+ };
169+ match run_simple("ydotool", ydotool_args) {
170+ Ok(()) => return Ok(()),
171+ Err(e) => errors.push(e),
172+ }
173+ }
174+
175+ // enigo covers X11, macOS, and Windows. Under Wayland it only reaches
176+ // XWayland windows, which is why it is the last resort there.
177+ match enigo_paste_chord(with_shift) {
178+ Ok(()) => return Ok(()),
179+ Err(e) => errors.push(e),
180+ }
181+
182+ Err(errors.join("; "))
183+}
184+
185+fn paste_text(app: &AppHandle, text: &str, restore_clipboard: bool) -> Result<(), String> {
186+ let target = hyprland_active_window();
187+
188+ // Pasting into mutterbox itself means focus was stolen (overlay windowrules
189+ // missing) or dictation was triggered from the settings window.
190+ if let Some((class, title)) = &target {
191+ if class == "mutterbox" || title == "mutterbox overlay" {
192+ write_clipboard(app, text)?;
193+ return Err(
194+ "the focused window is mutterbox itself, so there is nowhere to paste. \
195+ Trigger dictation with your compositor keybind while the target field is \
196+ focused, and add the overlay windowrules from the hyprland setup popup. \
197+ The transcript is in your clipboard."
198+ .into(),
199+ );
200+ }
201+ }
202+
203+ let with_shift = target
204+ .as_ref()
205+ .map(|(class, _)| is_terminal_class(class))
206+ .unwrap_or(false);
207+ eprintln!(
208+ "mutterbox: pasting into {:?} via ctrl+{}v",
209+ target.as_ref().map(|(c, _)| c.as_str()).unwrap_or("unknown"),
210+ if with_shift { "shift+" } else { "" }
211+ );
212+
213+ let previous = read_clipboard(app);
214+ write_clipboard(app, text)?;
215+
216+ // Give the clipboard owner change time to propagate before pasting
217+ sleep(Duration::from_millis(120));
218+ if let Err(e) = send_paste_chord(with_shift) {
219+ // Leave the transcript on the clipboard so nothing is lost.
220+ return Err(format!(
221+ "could not send the paste keystroke ({e}). The transcript is in your clipboard, paste it manually. On Wayland install wtype, or enable ydotool: systemctl --user enable --now ydotool"
222+ ));
223+ }
224+ sleep(Duration::from_millis(300));
225+
226+ if restore_clipboard {
227+ if let Some(previous) = previous {
228+ let _ = write_clipboard(app, &previous);
229+ }
230+ }
231+ Ok(())
232+}
233+
234+fn type_text(text: &str) -> Result<(), String> {
235+ let mut errors: Vec<String> = Vec::new();
236+
237+ if is_wayland() {
238+ // "-" makes wtype read the text from stdin, which is safe for
239+ // arbitrary content
240+ match run_with_stdin("wtype", &["-"], text) {
241+ Ok(()) => return Ok(()),
242+ Err(e) => errors.push(e),
243+ }
244+ match run_simple("ydotool", &["type", "--", text]) {
245+ Ok(()) => return Ok(()),
246+ Err(e) => errors.push(e),
247+ }
248+ }
249+
250+ match Enigo::new(&EnigoSettings::default()) {
251+ Ok(mut enigo) => match enigo.text(text) {
252+ Ok(()) => return Ok(()),
253+ Err(e) => errors.push(format!("enigo: {e}")),
254+ },
255+ Err(e) => errors.push(format!("enigo init: {e}")),
256+ }
257+
258+ Err(format!(
259+ "could not type text ({}). On Wayland install wtype, or enable ydotool: systemctl --user enable --now ydotool",
260+ errors.join("; ")
261+ ))
262+}
+285-0src-tauri/src/lib.rs
@@ -0,0 +1,285 @@
1+mod audio;
2+mod inject;
3+mod llm;
4+mod models;
5+mod pipeline;
6+mod settings;
7+mod transcribe;
8+
9+use pipeline::AppState;
10+use std::sync::Mutex;
11+use tauri::menu::{Menu, MenuItem};
12+use tauri::tray::TrayIconBuilder;
13+use tauri::{AppHandle, Manager, WindowEvent};
14+
15+#[cfg(desktop)]
16+fn register_hotkey(app: &AppHandle, accel: &str) -> Result<(), String> {
17+ use tauri_plugin_global_shortcut::GlobalShortcutExt;
18+ let shortcuts = app.global_shortcut();
19+ let _ = shortcuts.unregister_all();
20+ if accel.trim().is_empty() {
21+ return Ok(());
22+ }
23+ let shortcut: tauri_plugin_global_shortcut::Shortcut = accel
24+ .parse()
25+ .map_err(|e| format!("invalid hotkey {accel:?}: {e:?}"))?;
26+ shortcuts
27+ .register(shortcut)
28+ .map_err(|e| format!("register hotkey: {e}"))?;
29+ Ok(())
30+}
31+
32+#[tauri::command]
33+fn get_settings(state: tauri::State<AppState>) -> settings::Settings {
34+ state.settings.lock().unwrap().clone()
35+}
36+
37+#[tauri::command]
38+fn set_settings(
39+ app: AppHandle,
40+ state: tauri::State<AppState>,
41+ new_settings: settings::Settings,
42+) -> Result<(), String> {
43+ let hotkey_changed = {
44+ let mut current = state.settings.lock().unwrap();
45+ let changed = current.hotkey != new_settings.hotkey;
46+ *current = new_settings.clone();
47+ changed
48+ };
49+ settings::save(&app, &new_settings)?;
50+ #[cfg(desktop)]
51+ if hotkey_changed {
52+ register_hotkey(&app, &new_settings.hotkey)?;
53+ }
54+ Ok(())
55+}
56+
57+#[tauri::command]
58+fn list_models(app: AppHandle) -> Result<Vec<models::ModelInfo>, String> {
59+ models::list(&app)
60+}
61+
62+#[tauri::command]
63+async fn download_model(app: AppHandle, id: String) -> Result<(), String> {
64+ models::download(app, id).await
65+}
66+
67+#[tauri::command]
68+fn delete_model(app: AppHandle, id: String) -> Result<(), String> {
69+ models::delete(&app, &id)
70+}
71+
72+#[tauri::command]
73+fn toggle_dictation(app: AppHandle) {
74+ pipeline::toggle(&app);
75+}
76+
77+#[tauri::command]
78+fn enhance_key_present(state: tauri::State<AppState>) -> bool {
79+ llm::key_present(&state.settings.lock().unwrap().enhance)
80+}
81+
82+#[derive(serde::Serialize, Clone)]
83+struct EnvironmentInfo {
84+ wayland: bool,
85+ compositor: String,
86+ exe: String,
87+}
88+
89+#[tauri::command]
90+fn get_environment() -> EnvironmentInfo {
91+ let exe = std::env::current_exe()
92+ .ok()
93+ .and_then(|p| p.to_str().map(String::from))
94+ .unwrap_or_else(|| "mutterbox".into());
95+
96+ #[cfg(target_os = "linux")]
97+ {
98+ let wayland = std::env::var("XDG_SESSION_TYPE")
99+ .map(|v| v == "wayland")
100+ .unwrap_or(false)
101+ || std::env::var_os("WAYLAND_DISPLAY").is_some();
102+ let desktop = std::env::var("XDG_CURRENT_DESKTOP")
103+ .unwrap_or_default()
104+ .to_lowercase();
105+ let compositor = if std::env::var_os("HYPRLAND_INSTANCE_SIGNATURE").is_some()
106+ || desktop.contains("hyprland")
107+ {
108+ "hyprland"
109+ } else if desktop.contains("sway") {
110+ "sway"
111+ } else if desktop.contains("kde") {
112+ "kde"
113+ } else if desktop.contains("gnome") {
114+ "gnome"
115+ } else {
116+ ""
117+ };
118+ return EnvironmentInfo {
119+ wayland,
120+ compositor: compositor.into(),
121+ exe,
122+ };
123+ }
124+
125+ #[cfg(not(target_os = "linux"))]
126+ EnvironmentInfo {
127+ wayland: false,
128+ compositor: "".into(),
129+ exe,
130+ }
131+}
132+
133+/// In hold mode, X11 autorepeat produces synthetic release/press pairs while
134+/// the key is held. A release only counts if no new press lands within 200 ms.
135+#[cfg(desktop)]
136+fn hold_release(app: &AppHandle) {
137+ use std::sync::atomic::Ordering;
138+ let state = app.state::<AppState>();
139+ let my_gen = state.hold_gen.fetch_add(1, Ordering::SeqCst) + 1;
140+ let app = app.clone();
141+ std::thread::spawn(move || {
142+ std::thread::sleep(std::time::Duration::from_millis(200));
143+ let state = app.state::<AppState>();
144+ if state.hold_gen.load(Ordering::SeqCst) == my_gen {
145+ pipeline::stop(&app);
146+ }
147+ });
148+}
149+
150+#[cfg_attr(mobile, tauri::mobile_entry_point)]
151+pub fn run() {
152+ let mut builder = tauri::Builder::default();
153+
154+ #[cfg(desktop)]
155+ {
156+ builder = builder
157+ .plugin(tauri_plugin_single_instance::init(|app, argv, _cwd| {
158+ if argv.iter().any(|a| a == "--toggle") {
159+ pipeline::toggle(app);
160+ } else if argv.iter().any(|a| a == "--start") {
161+ pipeline::start(app);
162+ } else if argv.iter().any(|a| a == "--stop") {
163+ pipeline::stop(app);
164+ } else {
165+ pipeline::show_main(app);
166+ }
167+ }))
168+ .plugin(tauri_plugin_autostart::Builder::new().args(["--hidden"]).build())
169+ .plugin(
170+ tauri_plugin_global_shortcut::Builder::new()
171+ .with_handler(|app, _shortcut, event| {
172+ use std::sync::atomic::Ordering;
173+ use tauri_plugin_global_shortcut::ShortcutState;
174+ let state = app.state::<AppState>();
175+ let hold = state.settings.lock().unwrap().activation == "hold";
176+ match event.state {
177+ ShortcutState::Pressed => {
178+ if hold {
179+ state.hold_gen.fetch_add(1, Ordering::SeqCst);
180+ pipeline::start(app);
181+ } else {
182+ pipeline::toggle(app);
183+ }
184+ }
185+ ShortcutState::Released => {
186+ if hold {
187+ hold_release(app);
188+ }
189+ }
190+ }
191+ })
192+ .build(),
193+ );
194+ }
195+
196+ builder
197+ .plugin(tauri_plugin_notification::init())
198+ .plugin(tauri_plugin_clipboard_manager::init())
199+ .plugin(tauri_plugin_opener::init())
200+ .on_window_event(|window, event| {
201+ if let WindowEvent::CloseRequested { api, .. } = event {
202+ if window.label() == "main" {
203+ let _ = window.hide();
204+ api.prevent_close();
205+ }
206+ }
207+ })
208+ .setup(|app| {
209+ let handle = app.handle().clone();
210+ let loaded = settings::load(&handle);
211+ app.manage(AppState {
212+ recorder: Mutex::new(audio::Recorder::default()),
213+ settings: Mutex::new(loaded.clone()),
214+ whisper: transcribe::WhisperCache::default(),
215+ hold_gen: std::sync::atomic::AtomicU64::new(0),
216+ });
217+
218+ // Recording indicator: frameless pill, hidden until dictation starts
219+ tauri::WebviewWindowBuilder::new(
220+ app,
221+ "overlay",
222+ tauri::WebviewUrl::App("index.html#overlay".into()),
223+ )
224+ .title("mutterbox overlay")
225+ .inner_size(280.0, 72.0)
226+ .decorations(false)
227+ .resizable(false)
228+ .transparent(true)
229+ .always_on_top(true)
230+ .skip_taskbar(true)
231+ .focused(false)
232+ .shadow(false)
233+ .visible(false)
234+ .build()?;
235+
236+ let toggle_item = MenuItem::with_id(app, "toggle", "Toggle dictation", true, None::<&str>)?;
237+ let open_item = MenuItem::with_id(app, "open", "Open mutterbox", true, None::<&str>)?;
238+ let quit_item = MenuItem::with_id(app, "quit", "Quit", true, None::<&str>)?;
239+ let menu = Menu::with_items(app, &[&toggle_item, &open_item, &quit_item])?;
240+ TrayIconBuilder::with_id("tray")
241+ .icon(app.default_window_icon().unwrap().clone())
242+ .menu(&menu)
243+ .on_menu_event(|app, event| match event.id.as_ref() {
244+ "toggle" => pipeline::toggle(app),
245+ "open" => pipeline::show_main(app),
246+ "quit" => app.exit(0),
247+ _ => {}
248+ })
249+ .build(app)?;
250+
251+ #[cfg(desktop)]
252+ if let Err(e) = register_hotkey(&handle, &loaded.hotkey) {
253+ eprintln!("hotkey registration failed (normal on Wayland, use a compositor keybind running `mutterbox --toggle`): {e}");
254+ }
255+
256+ let args: Vec<String> = std::env::args().collect();
257+ let triggered = args
258+ .iter()
259+ .any(|a| a == "--hidden" || a == "--toggle" || a == "--start" || a == "--stop");
260+ if triggered {
261+ if let Some(window) = app.get_webview_window("main") {
262+ let _ = window.hide();
263+ }
264+ }
265+ if args.iter().any(|a| a == "--toggle") {
266+ pipeline::toggle(&handle);
267+ } else if args.iter().any(|a| a == "--start") {
268+ pipeline::start(&handle);
269+ }
270+
271+ Ok(())
272+ })
273+ .invoke_handler(tauri::generate_handler![
274+ get_settings,
275+ set_settings,
276+ list_models,
277+ download_model,
278+ delete_model,
279+ toggle_dictation,
280+ enhance_key_present,
281+ get_environment
282+ ])
283+ .run(tauri::generate_context!())
284+ .expect("error while running tauri application");
285+}
+162-0src-tauri/src/llm.rs
@@ -0,0 +1,162 @@
1+use crate::settings::EnhanceSettings;
2+use serde_json::{json, Value};
3+
4+const MAX_TOKENS: u32 = 8192;
5+
6+fn api_key(cfg: &EnhanceSettings) -> Result<String, String> {
7+ let var = if cfg.api_key_env.is_empty() {
8+ match cfg.provider.as_str() {
9+ "anthropic" => "ANTHROPIC_API_KEY",
10+ "gemini" => "GEMINI_API_KEY",
11+ "openai" => "OPENAI_API_KEY",
12+ _ => return Ok(String::new()), // ollama needs no key
13+ }
14+ .to_string()
15+ } else {
16+ cfg.api_key_env.clone()
17+ };
18+ std::env::var(&var).map_err(|_| {
19+ format!("environment variable {var} is not set. Export it in your shell profile and restart mutterbox.")
20+ })
21+}
22+
23+pub fn key_present(cfg: &EnhanceSettings) -> bool {
24+ cfg.provider == "ollama" || api_key(cfg).map(|k| !k.is_empty()).unwrap_or(false)
25+}
26+
27+/// Sends the raw transcript through the configured LLM and returns cleaned text.
28+pub async fn enhance(cfg: &EnhanceSettings, transcript: &str) -> Result<String, String> {
29+ match cfg.provider.as_str() {
30+ "anthropic" => anthropic(cfg, transcript).await,
31+ "gemini" => gemini(cfg, transcript).await,
32+ "openai" | "ollama" => openai_compatible(cfg, transcript).await,
33+ other => Err(format!("unknown provider: {other}")),
34+ }
35+}
36+
37+async fn anthropic(cfg: &EnhanceSettings, transcript: &str) -> Result<String, String> {
38+ let key = api_key(cfg)?;
39+ let body = json!({
40+ "model": cfg.model,
41+ "max_tokens": MAX_TOKENS,
42+ "system": cfg.instructions,
43+ "messages": [{"role": "user", "content": transcript}],
44+ });
45+ let resp = reqwest::Client::new()
46+ .post("https://api.anthropic.com/v1/messages")
47+ .header("x-api-key", key)
48+ .header("anthropic-version", "2023-06-01")
49+ .json(&body)
50+ .send()
51+ .await
52+ .map_err(|e| format!("anthropic request: {e}"))?;
53+
54+ let status = resp.status();
55+ let payload: Value = resp
56+ .json()
57+ .await
58+ .map_err(|e| format!("anthropic response: {e}"))?;
59+ if !status.is_success() {
60+ let msg = payload["error"]["message"].as_str().unwrap_or("unknown error");
61+ return Err(format!("anthropic {status}: {msg}"));
62+ }
63+ if payload["stop_reason"].as_str() == Some("refusal") {
64+ return Err("the model declined this request".into());
65+ }
66+ let text: String = payload["content"]
67+ .as_array()
68+ .map(|blocks| {
69+ blocks
70+ .iter()
71+ .filter(|b| b["type"] == "text")
72+ .filter_map(|b| b["text"].as_str())
73+ .collect()
74+ })
75+ .unwrap_or_default();
76+ non_empty(text, "anthropic")
77+}
78+
79+async fn gemini(cfg: &EnhanceSettings, transcript: &str) -> Result<String, String> {
80+ let key = api_key(cfg)?;
81+ let url = format!(
82+ "https://generativelanguage.googleapis.com/v1beta/models/{}:generateContent",
83+ cfg.model
84+ );
85+ let body = json!({
86+ "system_instruction": {"parts": [{"text": cfg.instructions}]},
87+ "contents": [{"role": "user", "parts": [{"text": transcript}]}],
88+ });
89+ let resp = reqwest::Client::new()
90+ .post(url)
91+ .header("x-goog-api-key", key)
92+ .json(&body)
93+ .send()
94+ .await
95+ .map_err(|e| format!("gemini request: {e}"))?;
96+
97+ let status = resp.status();
98+ let payload: Value = resp
99+ .json()
100+ .await
101+ .map_err(|e| format!("gemini response: {e}"))?;
102+ if !status.is_success() {
103+ let msg = payload["error"]["message"].as_str().unwrap_or("unknown error");
104+ return Err(format!("gemini {status}: {msg}"));
105+ }
106+ let text: String = payload["candidates"][0]["content"]["parts"]
107+ .as_array()
108+ .map(|parts| parts.iter().filter_map(|p| p["text"].as_str()).collect())
109+ .unwrap_or_default();
110+ non_empty(text, "gemini")
111+}
112+
113+async fn openai_compatible(cfg: &EnhanceSettings, transcript: &str) -> Result<String, String> {
114+ let base = if !cfg.base_url.is_empty() {
115+ cfg.base_url.trim_end_matches('/').to_string()
116+ } else if cfg.provider == "ollama" {
117+ "http://localhost:11434/v1".to_string()
118+ } else {
119+ "https://api.openai.com/v1".to_string()
120+ };
121+ let body = json!({
122+ "model": cfg.model,
123+ "messages": [
124+ {"role": "system", "content": cfg.instructions},
125+ {"role": "user", "content": transcript},
126+ ],
127+ });
128+ let mut req = reqwest::Client::new()
129+ .post(format!("{base}/chat/completions"))
130+ .json(&body);
131+ if cfg.provider != "ollama" {
132+ req = req.bearer_auth(api_key(cfg)?);
133+ }
134+ let resp = req
135+ .send()
136+ .await
137+ .map_err(|e| format!("{} request: {e}", cfg.provider))?;
138+
139+ let status = resp.status();
140+ let payload: Value = resp
141+ .json()
142+ .await
143+ .map_err(|e| format!("{} response: {e}", cfg.provider))?;
144+ if !status.is_success() {
145+ let msg = payload["error"]["message"].as_str().unwrap_or("unknown error");
146+ return Err(format!("{} {status}: {msg}", cfg.provider));
147+ }
148+ let text = payload["choices"][0]["message"]["content"]
149+ .as_str()
150+ .unwrap_or_default()
151+ .to_string();
152+ non_empty(text, &cfg.provider)
153+}
154+
155+fn non_empty(text: String, provider: &str) -> Result<String, String> {
156+ let trimmed = text.trim().to_string();
157+ if trimmed.is_empty() {
158+ Err(format!("{provider} returned an empty response"))
159+ } else {
160+ Ok(trimmed)
161+ }
162+}
+15-0src-tauri/src/main.rs
@@ -0,0 +1,15 @@
1+// Prevents additional console window on Windows in release, DO NOT REMOVE!!
2+#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
3+
4+fn main() {
5+ // WebKitGTK's DMABUF renderer crashes with "Error 71 (Protocol error)
6+ // dispatching to Wayland display" on many Wayland/driver combinations.
7+ // Users can override by exporting the variable themselves.
8+ // Safety: runs before any other thread is spawned.
9+ #[cfg(target_os = "linux")]
10+ if std::env::var_os("WEBKIT_DISABLE_DMABUF_RENDERER").is_none() {
11+ unsafe { std::env::set_var("WEBKIT_DISABLE_DMABUF_RENDERER", "1") };
12+ }
13+
14+ mutterbox_lib::run()
15+}
+216-0src-tauri/src/models.rs
@@ -0,0 +1,216 @@
1+use futures_util::StreamExt;
2+use serde::Serialize;
3+use std::fs;
4+use std::path::PathBuf;
5+use tauri::{AppHandle, Emitter, Manager};
6+
7+pub struct CatalogEntry {
8+ pub id: &'static str,
9+ pub label: &'static str,
10+ pub filename: &'static str,
11+ pub size_mb: u32,
12+ pub multilingual: bool,
13+ pub description: &'static str,
14+}
15+
16+const HF_BASE: &str = "https://huggingface.co/ggerganov/whisper.cpp/resolve/main";
17+
18+pub const CATALOG: &[CatalogEntry] = &[
19+ CatalogEntry {
20+ id: "tiny.en",
21+ label: "Tiny (English)",
22+ filename: "ggml-tiny.en.bin",
23+ size_mb: 75,
24+ multilingual: false,
25+ description: "Fastest, lowest accuracy. Good for quick notes on weak hardware.",
26+ },
27+ CatalogEntry {
28+ id: "base.en",
29+ label: "Base (English)",
30+ filename: "ggml-base.en.bin",
31+ size_mb: 142,
32+ multilingual: false,
33+ description: "Fast with decent accuracy. A sensible default for English dictation.",
34+ },
35+ CatalogEntry {
36+ id: "small.en",
37+ label: "Small (English)",
38+ filename: "ggml-small.en.bin",
39+ size_mb: 466,
40+ multilingual: false,
41+ description: "Noticeably better accuracy, still responsive on modern CPUs.",
42+ },
43+ CatalogEntry {
44+ id: "tiny",
45+ label: "Tiny (Multilingual)",
46+ filename: "ggml-tiny.bin",
47+ size_mb: 75,
48+ multilingual: true,
49+ description: "Fastest multilingual model.",
50+ },
51+ CatalogEntry {
52+ id: "base",
53+ label: "Base (Multilingual)",
54+ filename: "ggml-base.bin",
55+ size_mb: 142,
56+ multilingual: true,
57+ description: "Fast multilingual dictation.",
58+ },
59+ CatalogEntry {
60+ id: "small",
61+ label: "Small (Multilingual)",
62+ filename: "ggml-small.bin",
63+ size_mb: 466,
64+ multilingual: true,
65+ description: "Good multilingual accuracy for daily use.",
66+ },
67+ CatalogEntry {
68+ id: "medium",
69+ label: "Medium (Multilingual)",
70+ filename: "ggml-medium.bin",
71+ size_mb: 1530,
72+ multilingual: true,
73+ description: "High accuracy, slower. Best with a strong CPU.",
74+ },
75+ CatalogEntry {
76+ id: "large-v3-turbo-q5_0",
77+ label: "Large v3 Turbo Q5",
78+ filename: "ggml-large-v3-turbo-q5_0.bin",
79+ size_mb: 574,
80+ multilingual: true,
81+ description: "Quantized large-v3-turbo. Excellent accuracy for the size, the sweet spot for CPU inference.",
82+ },
83+ CatalogEntry {
84+ id: "large-v3-turbo",
85+ label: "Large v3 Turbo",
86+ filename: "ggml-large-v3-turbo.bin",
87+ size_mb: 1620,
88+ multilingual: true,
89+ description: "Near large-v3 accuracy at much higher speed.",
90+ },
91+ CatalogEntry {
92+ id: "large-v3",
93+ label: "Large v3",
94+ filename: "ggml-large-v3.bin",
95+ size_mb: 3100,
96+ multilingual: true,
97+ description: "Best accuracy whisper.cpp offers. Heavy; expect slower turnaround on CPU.",
98+ },
99+];
100+
101+#[derive(Serialize, Clone)]
102+pub struct ModelInfo {
103+ pub id: String,
104+ pub label: String,
105+ pub filename: String,
106+ pub size_mb: u32,
107+ pub multilingual: bool,
108+ pub description: String,
109+ pub installed: bool,
110+}
111+
112+#[derive(Serialize, Clone)]
113+pub struct DownloadProgress {
114+ pub id: String,
115+ pub downloaded: u64,
116+ pub total: u64,
117+ pub done: bool,
118+}
119+
120+pub fn models_dir(app: &AppHandle) -> Result<PathBuf, String> {
121+ let dir = app
122+ .path()
123+ .app_data_dir()
124+ .map_err(|e| format!("no data dir: {e}"))?
125+ .join("models");
126+ fs::create_dir_all(&dir).map_err(|e| format!("create models dir: {e}"))?;
127+ Ok(dir)
128+}
129+
130+pub fn model_path(app: &AppHandle, id: &str) -> Result<PathBuf, String> {
131+ let entry = CATALOG
132+ .iter()
133+ .find(|m| m.id == id)
134+ .ok_or_else(|| format!("unknown model id: {id}"))?;
135+ Ok(models_dir(app)?.join(entry.filename))
136+}
137+
138+pub fn list(app: &AppHandle) -> Result<Vec<ModelInfo>, String> {
139+ let dir = models_dir(app)?;
140+ Ok(CATALOG
141+ .iter()
142+ .map(|m| ModelInfo {
143+ id: m.id.into(),
144+ label: m.label.into(),
145+ filename: m.filename.into(),
146+ size_mb: m.size_mb,
147+ multilingual: m.multilingual,
148+ description: m.description.into(),
149+ installed: dir.join(m.filename).exists(),
150+ })
151+ .collect())
152+}
153+
154+pub async fn download(app: AppHandle, id: String) -> Result<(), String> {
155+ let entry = CATALOG
156+ .iter()
157+ .find(|m| m.id == id)
158+ .ok_or_else(|| format!("unknown model id: {id}"))?;
159+ let dest = models_dir(&app)?.join(entry.filename);
160+ let part = dest.with_extension("bin.part");
161+ let url = format!("{HF_BASE}/{}", entry.filename);
162+
163+ let resp = reqwest::get(&url)
164+ .await
165+ .map_err(|e| format!("download failed: {e}"))?
166+ .error_for_status()
167+ .map_err(|e| format!("download failed: {e}"))?;
168+
169+ let total = resp.content_length().unwrap_or(0);
170+ let mut file = tokio::fs::File::create(&part)
171+ .await
172+ .map_err(|e| format!("create file: {e}"))?;
173+
174+ let mut stream = resp.bytes_stream();
175+ let mut downloaded: u64 = 0;
176+ let mut last_emit: u64 = 0;
177+ while let Some(chunk) = stream.next().await {
178+ let chunk = chunk.map_err(|e| format!("download interrupted: {e}"))?;
179+ tokio::io::AsyncWriteExt::write_all(&mut file, &chunk)
180+ .await
181+ .map_err(|e| format!("write failed: {e}"))?;
182+ downloaded += chunk.len() as u64;
183+ if downloaded - last_emit > 2_000_000 {
184+ last_emit = downloaded;
185+ let _ = app.emit(
186+ "model-progress",
187+ DownloadProgress {
188+ id: id.clone(),
189+ downloaded,
190+ total,
191+ done: false,
192+ },
193+ );
194+ }
195+ }
196+ drop(file);
197+ fs::rename(&part, &dest).map_err(|e| format!("finalize download: {e}"))?;
198+ let _ = app.emit(
199+ "model-progress",
200+ DownloadProgress {
201+ id: id.clone(),
202+ downloaded,
203+ total,
204+ done: true,
205+ },
206+ );
207+ Ok(())
208+}
209+
210+pub fn delete(app: &AppHandle, id: &str) -> Result<(), String> {
211+ let path = model_path(app, id)?;
212+ if path.exists() {
213+ fs::remove_file(path).map_err(|e| format!("delete model: {e}"))?;
214+ }
215+ Ok(())
216+}
+247-0src-tauri/src/pipeline.rs
@@ -0,0 +1,247 @@
1+use crate::{audio, inject, llm, models, settings, transcribe};
2+use serde::Serialize;
3+use std::sync::atomic::AtomicU64;
4+use std::sync::Mutex;
5+use tauri::{AppHandle, Emitter, Manager};
6+use tauri_plugin_notification::NotificationExt;
7+
8+/// Anything shorter than this (0.5 s at 16 kHz) is treated as an accidental tap.
9+const MIN_SAMPLES: usize = 8_000;
10+
11+pub struct AppState {
12+ pub recorder: Mutex<audio::Recorder>,
13+ pub settings: Mutex<settings::Settings>,
14+ pub whisper: transcribe::WhisperCache,
15+ /// Generation counter used to debounce X11 key autorepeat in hold mode.
16+ pub hold_gen: AtomicU64,
17+}
18+
19+#[derive(Serialize, Clone)]
20+struct StatePayload {
21+ state: &'static str,
22+}
23+
24+#[derive(Serialize, Clone)]
25+struct TranscriptPayload {
26+ raw: String,
27+ text: String,
28+ enhanced: bool,
29+}
30+
31+#[derive(Serialize, Clone)]
32+struct ErrorPayload {
33+ message: String,
34+}
35+
36+fn set_state(app: &AppHandle, state: &'static str) {
37+ let _ = app.emit("recording-state", StatePayload { state });
38+}
39+
40+fn notify(app: &AppHandle, message: &str) {
41+ let _ = app
42+ .notification()
43+ .builder()
44+ .title("mutterbox")
45+ .body(message)
46+ .show();
47+ let _ = app.emit(
48+ "pipeline-error",
49+ ErrorPayload {
50+ message: message.to_string(),
51+ },
52+ );
53+}
54+
55+pub fn show_main(app: &AppHandle) {
56+ if let Some(window) = app.get_webview_window("main") {
57+ let _ = window.show();
58+ let _ = window.set_focus();
59+ }
60+}
61+
62+#[cfg(target_os = "linux")]
63+fn hyprctl_ok(args: &[&str]) -> bool {
64+ std::process::Command::new("hyprctl")
65+ .args(args)
66+ .output()
67+ .map(|o| o.status.success() && String::from_utf8_lossy(&o.stdout).trim() == "ok")
68+ .unwrap_or(false)
69+}
70+
71+/// Injects windowrules into a running Hyprland session so the overlay pill can
72+/// never steal focus from the field being dictated into. Re-applied on every
73+/// show so the rules survive `hyprctl reload`.
74+#[cfg(target_os = "linux")]
75+fn apply_hyprland_overlay_rules() {
76+ if std::env::var_os("HYPRLAND_INSTANCE_SIGNATURE").is_none() {
77+ return;
78+ }
79+ // Hyprland 0.53+ rule engine syntax
80+ if hyprctl_ok(&[
81+ "keyword",
82+ "windowrule",
83+ "match:title ^(mutterbox overlay)$, no_focus 1, float 1, pin 1",
84+ ]) {
85+ return;
86+ }
87+ // Older Hyprland releases: one rule per effect, best effort
88+ for keyword in ["windowrule", "windowrulev2"] {
89+ for rule in [
90+ "nofocus, title:^(mutterbox overlay)$",
91+ "float, title:^(mutterbox overlay)$",
92+ "pin, title:^(mutterbox overlay)$",
93+ ] {
94+ let _ = hyprctl_ok(&["keyword", keyword, rule]);
95+ }
96+ }
97+}
98+
99+fn show_overlay(app: &AppHandle) {
100+ #[cfg(target_os = "linux")]
101+ apply_hyprland_overlay_rules();
102+ if let Some(window) = app.get_webview_window("overlay") {
103+ if let (Ok(Some(monitor)), Ok(size)) = (window.primary_monitor(), window.outer_size()) {
104+ let msize = monitor.size();
105+ let mpos = monitor.position();
106+ let x = mpos.x + (msize.width as i32 - size.width as i32) / 2;
107+ let y = mpos.y + msize.height as i32 - size.height as i32 - 48;
108+ let _ = window.set_position(tauri::PhysicalPosition::new(x, y));
109+ }
110+ let _ = window.show();
111+ }
112+}
113+
114+fn hide_overlay(app: &AppHandle) {
115+ if let Some(window) = app.get_webview_window("overlay") {
116+ let _ = window.hide();
117+ }
118+}
119+
120+/// Hotkey (toggle mode), tray, `--toggle`, and the UI button land here.
121+pub fn toggle(app: &AppHandle) {
122+ let state = app.state::<AppState>();
123+ let recording = state.recorder.lock().unwrap().is_recording();
124+ if recording {
125+ stop(app);
126+ } else {
127+ start(app);
128+ }
129+}
130+
131+/// Begins recording. No-op when already recording.
132+pub fn start(app: &AppHandle) {
133+ let state = app.state::<AppState>();
134+ let mut recorder = state.recorder.lock().unwrap();
135+ if recorder.is_recording() {
136+ return;
137+ }
138+
139+ let cfg = state.settings.lock().unwrap().clone();
140+ let model_ready = models::model_path(app, &cfg.dictation_model)
141+ .map(|p| p.exists())
142+ .unwrap_or(false);
143+ if !model_ready {
144+ drop(recorder);
145+ notify(
146+ app,
147+ "No dictation model installed. Open mutterbox and download one under Models.",
148+ );
149+ show_main(app);
150+ return;
151+ }
152+ match recorder.start() {
153+ Ok(()) => {
154+ drop(recorder);
155+ set_state(app, "recording");
156+ show_overlay(app);
157+ }
158+ Err(e) => {
159+ drop(recorder);
160+ notify(app, &format!("could not start recording: {e}"));
161+ }
162+ }
163+}
164+
165+/// Stops recording and kicks off transcription. No-op when not recording.
166+pub fn stop(app: &AppHandle) {
167+ let state = app.state::<AppState>();
168+ let mut recorder = state.recorder.lock().unwrap();
169+ if !recorder.is_recording() {
170+ return;
171+ }
172+ let samples = recorder.stop();
173+ drop(recorder);
174+ match samples {
175+ Ok(samples) if samples.len() >= MIN_SAMPLES => {
176+ set_state(app, "processing");
177+ process(app.clone(), samples);
178+ }
179+ Ok(_) => {
180+ set_state(app, "idle");
181+ hide_overlay(app);
182+ }
183+ Err(e) => {
184+ set_state(app, "idle");
185+ hide_overlay(app);
186+ notify(app, &e);
187+ }
188+ }
189+}
190+
191+fn process(app: AppHandle, samples: Vec<f32>) {
192+ tauri::async_runtime::spawn(async move {
193+ if let Err(e) = process_inner(&app, samples).await {
194+ set_state(&app, "idle");
195+ hide_overlay(&app);
196+ notify(&app, &e);
197+ }
198+ });
199+}
200+
201+async fn process_inner(app: &AppHandle, samples: Vec<f32>) -> Result<(), String> {
202+ let cfg = app.state::<AppState>().settings.lock().unwrap().clone();
203+ let model_path = models::model_path(app, &cfg.dictation_model)?;
204+
205+ let task_app = app.clone();
206+ let language = cfg.language.clone();
207+ let raw = tauri::async_runtime::spawn_blocking(move || {
208+ let state = task_app.state::<AppState>();
209+ state.whisper.transcribe(&model_path, &samples, &language)
210+ })
211+ .await
212+ .map_err(|e| format!("transcription task: {e}"))??;
213+
214+ if raw.is_empty() {
215+ set_state(app, "idle");
216+ hide_overlay(app);
217+ notify(app, "Didn't catch anything.");
218+ return Ok(());
219+ }
220+
221+ let (text, enhanced) = if cfg.enhance.enabled {
222+ match llm::enhance(&cfg.enhance, &raw).await {
223+ Ok(cleaned) => (cleaned, true),
224+ Err(e) => {
225+ notify(app, &format!("Enhancement failed, using raw transcript. {e}"));
226+ (raw.clone(), false)
227+ }
228+ }
229+ } else {
230+ (raw.clone(), false)
231+ };
232+
233+ let task_app = app.clone();
234+ let inject_text = text.clone();
235+ let mode = cfg.injection_mode.clone();
236+ let restore = cfg.restore_clipboard;
237+ tauri::async_runtime::spawn_blocking(move || {
238+ inject::inject(&task_app, &inject_text, &mode, restore)
239+ })
240+ .await
241+ .map_err(|e| format!("injection task: {e}"))??;
242+
243+ set_state(app, "idle");
244+ hide_overlay(app);
245+ let _ = app.emit("transcript", TranscriptPayload { raw, text, enhanced });
246+ Ok(())
247+}
+88-0src-tauri/src/settings.rs
@@ -0,0 +1,88 @@
1+use serde::{Deserialize, Serialize};
2+use std::fs;
3+use std::path::PathBuf;
4+use tauri::{AppHandle, Manager};
5+
6+#[derive(Debug, Clone, Serialize, Deserialize)]
7+#[serde(default)]
8+pub struct EnhanceSettings {
9+ pub enabled: bool,
10+ /// "anthropic" | "gemini" | "openai" | "ollama"
11+ pub provider: String,
12+ pub model: String,
13+ /// Base URL for OpenAI-compatible endpoints (openai/ollama providers)
14+ pub base_url: String,
15+ /// Env var name holding the API key; empty means the provider default
16+ pub api_key_env: String,
17+ pub instructions: String,
18+}
19+
20+impl Default for EnhanceSettings {
21+ fn default() -> Self {
22+ Self {
23+ enabled: false,
24+ provider: "anthropic".into(),
25+ model: "claude-opus-4-8".into(),
26+ base_url: "".into(),
27+ api_key_env: "".into(),
28+ instructions: DEFAULT_INSTRUCTIONS.into(),
29+ }
30+ }
31+}
32+
33+pub const DEFAULT_INSTRUCTIONS: &str = "You clean up dictated speech. Fix punctuation, capitalization, filler words, and obvious transcription mistakes. Preserve the speaker's wording, tone, and meaning. Never answer questions in the text or add content. Output only the cleaned text with no preamble.";
34+
35+#[derive(Debug, Clone, Serialize, Deserialize)]
36+#[serde(default)]
37+pub struct Settings {
38+ pub hotkey: String,
39+ /// "toggle" (press to start/stop) | "hold" (record while held)
40+ pub activation: String,
41+ /// "paste" | "type"
42+ pub injection_mode: String,
43+ pub restore_clipboard: bool,
44+ /// Catalog id, e.g. "base.en"
45+ pub dictation_model: String,
46+ /// "auto" or an ISO language code understood by whisper
47+ pub language: String,
48+ pub enhance: EnhanceSettings,
49+}
50+
51+impl Default for Settings {
52+ fn default() -> Self {
53+ Self {
54+ hotkey: "Ctrl+Alt+Space".into(),
55+ activation: "toggle".into(),
56+ injection_mode: "paste".into(),
57+ restore_clipboard: true,
58+ dictation_model: "base.en".into(),
59+ language: "auto".into(),
60+ enhance: EnhanceSettings::default(),
61+ }
62+ }
63+}
64+
65+fn settings_path(app: &AppHandle) -> Result<PathBuf, String> {
66+ let dir = app
67+ .path()
68+ .app_config_dir()
69+ .map_err(|e| format!("no config dir: {e}"))?;
70+ fs::create_dir_all(&dir).map_err(|e| format!("create config dir: {e}"))?;
71+ Ok(dir.join("settings.json"))
72+}
73+
74+pub fn load(app: &AppHandle) -> Settings {
75+ let Ok(path) = settings_path(app) else {
76+ return Settings::default();
77+ };
78+ fs::read_to_string(path)
79+ .ok()
80+ .and_then(|raw| serde_json::from_str(&raw).ok())
81+ .unwrap_or_default()
82+}
83+
84+pub fn save(app: &AppHandle, settings: &Settings) -> Result<(), String> {
85+ let path = settings_path(app)?;
86+ let raw = serde_json::to_string_pretty(settings).map_err(|e| e.to_string())?;
87+ fs::write(path, raw).map_err(|e| format!("write settings: {e}"))
88+}
+68-0src-tauri/src/transcribe.rs
@@ -0,0 +1,68 @@
1+use std::path::{Path, PathBuf};
2+use std::sync::{Arc, Mutex};
3+use whisper_rs::{FullParams, SamplingStrategy, WhisperContext, WhisperContextParameters};
4+
5+/// Caches the loaded whisper context so repeated dictations skip model load time.
6+#[derive(Default)]
7+pub struct WhisperCache {
8+ loaded: Mutex<Option<(PathBuf, Arc<WhisperContext>)>>,
9+}
10+
11+impl WhisperCache {
12+ fn context(&self, model_path: &Path) -> Result<Arc<WhisperContext>, String> {
13+ let mut guard = self.loaded.lock().unwrap();
14+ if let Some((path, ctx)) = guard.as_ref() {
15+ if path == model_path {
16+ return Ok(ctx.clone());
17+ }
18+ }
19+ let ctx = WhisperContext::new_with_params(
20+ model_path
21+ .to_str()
22+ .ok_or("model path is not valid UTF-8".to_string())?,
23+ WhisperContextParameters::default(),
24+ )
25+ .map_err(|e| format!("load whisper model: {e}"))?;
26+ let ctx = Arc::new(ctx);
27+ *guard = Some((model_path.to_path_buf(), ctx.clone()));
28+ Ok(ctx)
29+ }
30+
31+ pub fn transcribe(
32+ &self,
33+ model_path: &Path,
34+ samples: &[f32],
35+ language: &str,
36+ ) -> Result<String, String> {
37+ let ctx = self.context(model_path)?;
38+ let mut state = ctx
39+ .create_state()
40+ .map_err(|e| format!("create whisper state: {e}"))?;
41+
42+ let mut params = FullParams::new(SamplingStrategy::Greedy { best_of: 1 });
43+ let lang = if language.is_empty() { "auto" } else { language };
44+ params.set_language(Some(lang));
45+ params.set_print_special(false);
46+ params.set_print_progress(false);
47+ params.set_print_realtime(false);
48+ params.set_print_timestamps(false);
49+ params.set_suppress_blank(true);
50+ let threads = std::thread::available_parallelism()
51+ .map(|n| n.get())
52+ .unwrap_or(4)
53+ .min(8) as i32;
54+ params.set_n_threads(threads);
55+
56+ state
57+ .full(params, samples)
58+ .map_err(|e| format!("transcription failed: {e}"))?;
59+
60+ let mut text = String::new();
61+ for segment in state.as_iter() {
62+ if let Ok(piece) = segment.to_str_lossy() {
63+ text.push_str(&piece);
64+ }
65+ }
66+ Ok(text.trim().to_string())
67+ }
68+}
+38-0src-tauri/tauri.conf.json
@@ -0,0 +1,38 @@
1+{
2+ "$schema": "https://schema.tauri.app/config/2",
3+ "productName": "mutterbox",
4+ "version": "0.1.0",
5+ "identifier": "dev.mutterbox.app",
6+ "build": {
7+ "beforeDevCommand": "npm run dev",
8+ "devUrl": "http://localhost:1420",
9+ "beforeBuildCommand": "npm run build",
10+ "frontendDist": "../dist"
11+ },
12+ "app": {
13+ "windows": [
14+ {
15+ "label": "main",
16+ "title": "mutterbox",
17+ "width": 960,
18+ "height": 660,
19+ "minWidth": 780,
20+ "minHeight": 540
21+ }
22+ ],
23+ "security": {
24+ "csp": null
25+ }
26+ },
27+ "bundle": {
28+ "active": true,
29+ "targets": "all",
30+ "icon": [
31+ "icons/32x32.png",
32+ "icons/128x128.png",
33+ "icons/128x128@2x.png",
34+ "icons/icon.icns",
35+ "icons/icon.ico"
36+ ]
37+ }
38+}
+123-0src/App.tsx
@@ -0,0 +1,123 @@
1+import { useCallback, useEffect, useState } from "react";
2+import { listen } from "@tauri-apps/api/event";
3+import Overlay from "./Overlay";
4+import GeneralPage from "./pages/General";
5+import ModelsPage from "./pages/Models";
6+import EnhancePage from "./pages/Enhance";
7+import { getSettings, setSettings as persistSettings, toggleDictation } from "./api";
8+import type { RecordingState, Settings, TranscriptPayload } from "./types";
9+
10+type Page = "general" | "models" | "enhance";
11+
12+const NAV: { id: Page; label: string }[] = [
13+ { id: "general", label: "general" },
14+ { id: "models", label: "models" },
15+ { id: "enhance", label: "enhance" },
16+];
17+
18+export default function App() {
19+ if (window.location.hash === "#overlay") {
20+ return <Overlay />;
21+ }
22+ return <SettingsApp />;
23+}
24+
25+function SettingsApp() {
26+ const [page, setPage] = useState<Page>("general");
27+ const [settings, setSettingsState] = useState<Settings | null>(null);
28+ const [saveError, setSaveError] = useState<string | null>(null);
29+ const [recState, setRecState] = useState<RecordingState>("idle");
30+ const [lastTranscript, setLastTranscript] = useState<TranscriptPayload | null>(null);
31+ const [pipelineError, setPipelineError] = useState<string | null>(null);
32+
33+ useEffect(() => {
34+ getSettings().then(setSettingsState).catch(console.error);
35+ const subs = [
36+ listen<{ state: RecordingState }>("recording-state", (e) =>
37+ setRecState(e.payload.state),
38+ ),
39+ listen<TranscriptPayload>("transcript", (e) => {
40+ setLastTranscript(e.payload);
41+ setPipelineError(null);
42+ }),
43+ listen<{ message: string }>("pipeline-error", (e) =>
44+ setPipelineError(e.payload.message),
45+ ),
46+ ];
47+ return () => {
48+ subs.forEach((s) => s.then((fn) => fn()));
49+ };
50+ }, []);
51+
52+ const update = useCallback((next: Settings) => {
53+ setSettingsState(next);
54+ setSaveError(null);
55+ persistSettings(next).catch((e) => setSaveError(String(e)));
56+ }, []);
57+
58+ return (
59+ <div className="shell">
60+ <aside className="sidebar">
61+ <div className="wordmark">
62+ <span className="wordmark-glyph" aria-hidden>
63+ ((•))
64+ </span>
65+ <h1>mutterbox</h1>
66+ <p className="tagline">speak anywhere, type nowhere</p>
67+ </div>
68+ <nav>
69+ {NAV.map((item) => (
70+ <button
71+ key={item.id}
72+ className={page === item.id ? "nav-item active" : "nav-item"}
73+ onClick={() => setPage(item.id)}
74+ >
75+ <span className="nav-marker">{page === item.id ? "▸" : " "}</span>
76+ {item.label}
77+ </button>
78+ ))}
79+ </nav>
80+ <div className="sidebar-foot">
81+ <button
82+ className={`dictate-btn state-${recState}`}
83+ onClick={() => toggleDictation()}
84+ >
85+ {recState === "recording"
86+ ? "■ stop"
87+ : recState === "processing"
88+ ? "… working"
89+ : "● dictate"}
90+ </button>
91+ <p className="hint">
92+ {settings ? `hotkey ${settings.hotkey}` : ""}
93+ </p>
94+ </div>
95+ </aside>
96+
97+ <main className="content">
98+ {saveError && <div className="banner error">save failed: {saveError}</div>}
99+ {pipelineError && (
100+ <div className="banner error">
101+ {pipelineError}
102+ <button className="banner-dismiss" onClick={() => setPipelineError(null)}>
103+ ✕
104+ </button>
105+ </div>
106+ )}
107+ {settings === null ? (
108+ <p className="hint">loading…</p>
109+ ) : page === "general" ? (
110+ <GeneralPage
111+ settings={settings}
112+ onChange={update}
113+ lastTranscript={lastTranscript}
114+ />
115+ ) : page === "models" ? (
116+ <ModelsPage settings={settings} onChange={update} />
117+ ) : (
118+ <EnhancePage settings={settings} onChange={update} />
119+ )}
120+ </main>
121+ </div>
122+ );
123+}
+29-0src/Overlay.tsx
@@ -0,0 +1,29 @@
1+import { useEffect, useState } from "react";
2+import { listen } from "@tauri-apps/api/event";
3+import type { RecordingState } from "./types";
4+
5+export default function Overlay() {
6+ const [state, setState] = useState<RecordingState>("recording");
7+
8+ useEffect(() => {
9+ document.documentElement.classList.add("overlay-mode");
10+ const unlisten = listen<{ state: RecordingState }>("recording-state", (e) => {
11+ setState(e.payload.state);
12+ });
13+ return () => {
14+ unlisten.then((fn) => fn());
15+ };
16+ }, []);
17+
18+ return (
19+ <div className={`overlay-pill overlay-${state}`}>
20+ <span className="overlay-dot" />
21+ <span className="overlay-label">
22+ {state === "recording" ? "listening" : state === "processing" ? "transcribing" : "idle"}
23+ </span>
24+ <span className="overlay-bars" aria-hidden>
25+ <i /><i /><i /><i /><i />
26+ </span>
27+ </div>
28+ );
29+}
+12-0src/api.ts
@@ -0,0 +1,12 @@
1+import { invoke } from "@tauri-apps/api/core";
2+import type { EnvironmentInfo, ModelInfo, Settings } from "./types";
3+
4+export const getSettings = () => invoke<Settings>("get_settings");
5+export const setSettings = (newSettings: Settings) =>
6+ invoke<void>("set_settings", { newSettings });
7+export const listModels = () => invoke<ModelInfo[]>("list_models");
8+export const downloadModel = (id: string) => invoke<void>("download_model", { id });
9+export const deleteModel = (id: string) => invoke<void>("delete_model", { id });
10+export const toggleDictation = () => invoke<void>("toggle_dictation");
11+export const enhanceKeyPresent = () => invoke<boolean>("enhance_key_present");
12+export const getEnvironment = () => invoke<EnvironmentInfo>("get_environment");
+10-0src/main.tsx
@@ -0,0 +1,10 @@
1+import React from "react";
2+import ReactDOM from "react-dom/client";
3+import App from "./App";
4+import "./styles.css";
5+
6+ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
7+ <React.StrictMode>
8+ <App />
9+ </React.StrictMode>,
10+);
+173-0src/pages/Enhance.tsx
@@ -0,0 +1,173 @@
1+import { useEffect, useState } from "react";
2+import { enhanceKeyPresent } from "../api";
3+import type { EnhanceSettings, Settings } from "../types";
4+
5+interface Props {
6+ settings: Settings;
7+ onChange: (next: Settings) => void;
8+}
9+
10+const PROVIDERS: {
11+ id: EnhanceSettings["provider"];
12+ label: string;
13+ keyVar: string;
14+ defaultModel: string;
15+ modelHint: string;
16+}[] = [
17+ {
18+ id: "anthropic",
19+ label: "claude",
20+ keyVar: "ANTHROPIC_API_KEY",
21+ defaultModel: "claude-opus-4-8",
22+ modelHint: "claude-opus-4-8, claude-sonnet-5, claude-haiku-4-5",
23+ },
24+ {
25+ id: "gemini",
26+ label: "gemini",
27+ keyVar: "GEMINI_API_KEY",
28+ defaultModel: "gemini-2.5-flash",
29+ modelHint: "gemini-2.5-flash, gemini-2.5-pro",
30+ },
31+ {
32+ id: "openai",
33+ label: "openai compatible",
34+ keyVar: "OPENAI_API_KEY",
35+ defaultModel: "gpt-4o-mini",
36+ modelHint: "any model id your endpoint serves",
37+ },
38+ {
39+ id: "ollama",
40+ label: "ollama (local)",
41+ keyVar: "",
42+ defaultModel: "llama3.2",
43+ modelHint: "any model pulled into ollama",
44+ },
45+];
46+
47+export default function EnhancePage({ settings, onChange }: Props) {
48+ const cfg = settings.enhance;
49+ const [keyOk, setKeyOk] = useState<boolean | null>(null);
50+ const provider = PROVIDERS.find((p) => p.id === cfg.provider) ?? PROVIDERS[0];
51+
52+ useEffect(() => {
53+ enhanceKeyPresent().then(setKeyOk).catch(() => setKeyOk(null));
54+ }, [cfg.provider, cfg.api_key_env]);
55+
56+ const patch = (partial: Partial<EnhanceSettings>) =>
57+ onChange({ ...settings, enhance: { ...cfg, ...partial } });
58+
59+ return (
60+ <section>
61+ <header className="page-head">
62+ <h2>enhance</h2>
63+ <p>
64+ Optionally pass the raw transcript through an LLM to fix punctuation and
65+ apply your instructions before it is typed.
66+ </p>
67+ </header>
68+
69+ <div className="field">
70+ <label className="check">
71+ <input
72+ type="checkbox"
73+ checked={cfg.enabled}
74+ onChange={(e) => patch({ enabled: e.currentTarget.checked })}
75+ />
76+ enable enhancement
77+ </label>
78+ <p className="hint">
79+ Off by default. Dictation stays fully local when this is off.
80+ </p>
81+ </div>
82+
83+ <div className={cfg.enabled ? "" : "dimmed"}>
84+ <div className="field">
85+ <label>provider</label>
86+ <div className="segmented">
87+ {PROVIDERS.map((p) => (
88+ <button
89+ key={p.id}
90+ className={cfg.provider === p.id ? "seg active" : "seg"}
91+ onClick={() => patch({ provider: p.id, model: p.defaultModel })}
92+ >
93+ {p.label}
94+ </button>
95+ ))}
96+ </div>
97+ {provider.keyVar ? (
98+ <p className="hint">
99+ Reads the key from{" "}
100+ <code>{cfg.api_key_env || provider.keyVar}</code>{" "}
101+ {keyOk === true ? (
102+ <span className="ok-text">— found</span>
103+ ) : keyOk === false ? (
104+ <span className="error-text">
105+ — not set. Export it in your shell profile and restart mutterbox.
106+ </span>
107+ ) : null}
108+ </p>
109+ ) : (
110+ <p className="hint">Talks to a local ollama server. No key needed.</p>
111+ )}
112+ </div>
113+
114+ <div className="field">
115+ <label>model</label>
116+ <input
117+ value={cfg.model}
118+ onChange={(e) => patch({ model: e.currentTarget.value })}
119+ spellCheck={false}
120+ />
121+ <p className="hint">e.g. {provider.modelHint}</p>
122+ </div>
123+
124+ {(cfg.provider === "openai" || cfg.provider === "ollama") && (
125+ <div className="field">
126+ <label>base url</label>
127+ <input
128+ value={cfg.base_url}
129+ placeholder={
130+ cfg.provider === "ollama"
131+ ? "http://localhost:11434/v1"
132+ : "https://api.openai.com/v1"
133+ }
134+ onChange={(e) => patch({ base_url: e.currentTarget.value })}
135+ spellCheck={false}
136+ />
137+ <p className="hint">
138+ Any OpenAI-compatible endpoint works: OpenAI, OpenRouter, llama.cpp
139+ server, vLLM, LM Studio.
140+ </p>
141+ </div>
142+ )}
143+
144+ <div className="field">
145+ <label>custom key variable (optional)</label>
146+ <input
147+ value={cfg.api_key_env}
148+ placeholder={provider.keyVar || "not needed"}
149+ onChange={(e) => patch({ api_key_env: e.currentTarget.value })}
150+ spellCheck={false}
151+ />
152+ <p className="hint">
153+ Name of an environment variable to read the API key from, if not the
154+ default. Keys are never stored by mutterbox.
155+ </p>
156+ </div>
157+
158+ <div className="field">
159+ <label>instructions</label>
160+ <textarea
161+ rows={7}
162+ value={cfg.instructions}
163+ onChange={(e) => patch({ instructions: e.currentTarget.value })}
164+ />
165+ <p className="hint">
166+ The system prompt for cleanup. Ask for summaries, bullet points, email
167+ tone, whatever fits how you dictate.
168+ </p>
169+ </div>
170+ </div>
171+ </section>
172+ );
173+}
+340-0src/pages/General.tsx
@@ -0,0 +1,340 @@
1+import { useEffect, useState } from "react";
2+import { writeText } from "@tauri-apps/plugin-clipboard-manager";
3+import { getEnvironment } from "../api";
4+import type { EnvironmentInfo, Settings, TranscriptPayload } from "../types";
5+
6+const LANGUAGES = [
7+ ["auto", "auto detect"],
8+ ["en", "english"],
9+ ["es", "spanish"],
10+ ["fr", "french"],
11+ ["de", "german"],
12+ ["it", "italian"],
13+ ["pt", "portuguese"],
14+ ["nl", "dutch"],
15+ ["ja", "japanese"],
16+ ["ko", "korean"],
17+ ["zh", "chinese"],
18+ ["ru", "russian"],
19+ ["hi", "hindi"],
20+ ["ar", "arabic"],
21+];
22+
23+/** Maps a KeyboardEvent to a tauri accelerator key token, or null for bare modifiers. */
24+function keyFromEvent(e: React.KeyboardEvent): string | null {
25+ const code = e.code;
26+ if (code.startsWith("Key")) return code.slice(3);
27+ if (code.startsWith("Digit")) return code.slice(5);
28+ if (/^F\d{1,2}$/.test(code)) return code;
29+ const map: Record<string, string> = {
30+ Space: "Space",
31+ Enter: "Enter",
32+ Tab: "Tab",
33+ Backspace: "Backspace",
34+ ArrowUp: "Up",
35+ ArrowDown: "Down",
36+ ArrowLeft: "Left",
37+ ArrowRight: "Right",
38+ Home: "Home",
39+ End: "End",
40+ PageUp: "PageUp",
41+ PageDown: "PageDown",
42+ Comma: "Comma",
43+ Period: "Period",
44+ Slash: "Slash",
45+ Backslash: "Backslash",
46+ Minus: "Minus",
47+ Equal: "Equal",
48+ Semicolon: "Semicolon",
49+ Quote: "Quote",
50+ BracketLeft: "BracketLeft",
51+ BracketRight: "BracketRight",
52+ Backquote: "Backquote",
53+ };
54+ return map[code] ?? null;
55+}
56+
57+/** Renders the hyprland.conf lines for the current hotkey and activation mode. */
58+function hyprlandBinds(hotkey: string, hold: boolean, exe: string): string {
59+ const parts = hotkey.split("+").map((s) => s.trim()).filter(Boolean);
60+ const mods: string[] = [];
61+ let key = "";
62+ for (const part of parts) {
63+ const up = part.toUpperCase();
64+ if (up === "CTRL" || up === "CONTROL") mods.push("CTRL");
65+ else if (up === "ALT" || up === "OPTION") mods.push("ALT");
66+ else if (up === "SHIFT") mods.push("SHIFT");
67+ else if (["SUPER", "META", "CMD", "COMMAND", "COMMANDORCONTROL"].includes(up))
68+ mods.push("SUPER");
69+ else key = up;
70+ }
71+ const KEY_NAMES: Record<string, string> = { ENTER: "RETURN" };
72+ const hyprKey = KEY_NAMES[key] ?? key;
73+ const m = mods.join(" ");
74+ return hold
75+ ? `bind = ${m}, ${hyprKey}, exec, ${exe} --start\nbindr = ${m}, ${hyprKey}, exec, ${exe} --stop`
76+ : `bind = ${m}, ${hyprKey}, exec, ${exe} --toggle`;
77+}
78+
79+function HotkeyCapture({
80+ value,
81+ onCapture,
82+}: {
83+ value: string;
84+ onCapture: (accel: string) => void;
85+}) {
86+ const [capturing, setCapturing] = useState(false);
87+
88+ const onKeyDown = (e: React.KeyboardEvent<HTMLButtonElement>) => {
89+ if (!capturing) return;
90+ e.preventDefault();
91+ e.stopPropagation();
92+ if (e.key === "Escape") {
93+ setCapturing(false);
94+ e.currentTarget.blur();
95+ return;
96+ }
97+ const key = keyFromEvent(e);
98+ if (!key) return; // modifier held alone; keep waiting
99+ const mods = [
100+ e.ctrlKey && "Ctrl",
101+ e.altKey && "Alt",
102+ e.shiftKey && "Shift",
103+ e.metaKey && "Super",
104+ ].filter(Boolean) as string[];
105+ if (mods.length === 0 && !/^F\d{1,2}$/.test(key)) return; // demand a modifier
106+ setCapturing(false);
107+ e.currentTarget.blur();
108+ onCapture([...mods, key].join("+"));
109+ };
110+
111+ return (
112+ <button
113+ type="button"
114+ className={capturing ? "hotkey-capture capturing" : "hotkey-capture"}
115+ onClick={() => setCapturing(true)}
116+ onKeyDown={onKeyDown}
117+ onBlur={() => setCapturing(false)}
118+ >
119+ {capturing ? "press shortcut… (esc to cancel)" : value}
120+ </button>
121+ );
122+}
123+
124+function HyprlandModal({
125+ hotkey,
126+ hold,
127+ exe,
128+ onClose,
129+}: {
130+ hotkey: string;
131+ hold: boolean;
132+ exe: string;
133+ onClose: () => void;
134+}) {
135+ const [copied, setCopied] = useState(false);
136+ const lines = hyprlandBinds(hotkey, hold, exe);
137+
138+ const copy = async () => {
139+ try {
140+ await writeText(lines);
141+ setCopied(true);
142+ setTimeout(() => setCopied(false), 1600);
143+ } catch (err) {
144+ console.error(err);
145+ }
146+ };
147+
148+ return (
149+ <div className="modal-backdrop" onClick={onClose}>
150+ <div className="modal" onClick={(e) => e.stopPropagation()}>
151+ <h3>hyprland keybind</h3>
152+ <p className="hint">
153+ Hyprland doesn't let apps grab global keys, so mutterbox is triggered
154+ from your compositor instead. Add this to{" "}
155+ <code>~/.config/hypr/hyprland.conf</code>:
156+ </p>
157+ <div className="code-block">
158+ <pre>{lines}</pre>
159+ <button className="copy-btn" onClick={copy} title="copy to clipboard">
160+ {copied ? "copied ✓" : "⧉ copy"}
161+ </button>
162+ </div>
163+ <p className="hint">
164+ Then run <code>hyprctl reload</code>. If mutterbox is on your PATH you
165+ can shorten the exec to just <code>mutterbox</code>.
166+ {hold &&
167+ " Hold mode uses bind for press and bindr for release, so dictation records only while the key is held."}{" "}
168+ mutterbox automatically makes its recording pill unfocusable while it
169+ runs. To make that permanent, also add:{" "}
170+ <code>
171+ windowrule = match:title ^(mutterbox overlay)$, no_focus 1, float 1,
172+ pin 1
173+ </code>
174+ </p>
175+ <button className="btn" onClick={onClose}>
176+ done
177+ </button>
178+ </div>
179+ </div>
180+ );
181+}
182+
183+interface Props {
184+ settings: Settings;
185+ onChange: (next: Settings) => void;
186+ lastTranscript: TranscriptPayload | null;
187+}
188+
189+export default function GeneralPage({ settings, onChange, lastTranscript }: Props) {
190+ const [env, setEnv] = useState<EnvironmentInfo | null>(null);
191+ const [showHypr, setShowHypr] = useState(false);
192+
193+ useEffect(() => {
194+ getEnvironment().then(setEnv).catch(console.error);
195+ }, []);
196+
197+ const isHyprland = env?.compositor === "hyprland";
198+ const hold = settings.activation === "hold";
199+
200+ const setHotkey = (hotkey: string) => {
201+ onChange({ ...settings, hotkey });
202+ if (isHyprland) setShowHypr(true);
203+ };
204+
205+ const setActivation = (activation: Settings["activation"]) => {
206+ if (activation === settings.activation) return;
207+ onChange({ ...settings, activation });
208+ if (isHyprland) setShowHypr(true);
209+ };
210+
211+ return (
212+ <section>
213+ <header className="page-head">
214+ <h2>general</h2>
215+ <p>Hotkey, language, and how text lands in the focused field.</p>
216+ </header>
217+
218+ <div className="field">
219+ <label>global hotkey</label>
220+ <div className="field-row">
221+ <HotkeyCapture value={settings.hotkey} onCapture={setHotkey} />
222+ {isHyprland && (
223+ <button className="btn ghost" onClick={() => setShowHypr(true)}>
224+ hyprland setup
225+ </button>
226+ )}
227+ </div>
228+ <p className="hint">
229+ Click, then press the shortcut you want.
230+ {isHyprland
231+ ? " Hyprland detected: the hotkey is bound in your compositor config, see hyprland setup."
232+ : env?.wayland
233+ ? ` On Wayland, bind a compositor key to run mutterbox ${hold ? "--start / --stop" : "--toggle"} instead.`
234+ : ""}
235+ </p>
236+ </div>
237+
238+ <div className="field">
239+ <label>activation</label>
240+ <div className="segmented">
241+ <button
242+ className={!hold ? "seg active" : "seg"}
243+ onClick={() => setActivation("toggle")}
244+ >
245+ toggle
246+ </button>
247+ <button
248+ className={hold ? "seg active" : "seg"}
249+ onClick={() => setActivation("hold")}
250+ >
251+ hold
252+ </button>
253+ </div>
254+ <p className="hint">
255+ Toggle: press once to start, again to stop. Hold: records while the
256+ hotkey is held, like push to talk.
257+ </p>
258+ </div>
259+
260+ <div className="field">
261+ <label>spoken language</label>
262+ <select
263+ value={settings.language}
264+ onChange={(e) => onChange({ ...settings, language: e.currentTarget.value })}
265+ >
266+ {LANGUAGES.map(([code, label]) => (
267+ <option key={code} value={code}>
268+ {label}
269+ </option>
270+ ))}
271+ </select>
272+ <p className="hint">Non-English languages need a multilingual model.</p>
273+ </div>
274+
275+ <div className="field">
276+ <label>text insertion</label>
277+ <div className="segmented">
278+ <button
279+ className={settings.injection_mode === "paste" ? "seg active" : "seg"}
280+ onClick={() => onChange({ ...settings, injection_mode: "paste" })}
281+ >
282+ paste
283+ </button>
284+ <button
285+ className={settings.injection_mode === "type" ? "seg active" : "seg"}
286+ onClick={() => onChange({ ...settings, injection_mode: "type" })}
287+ >
288+ keystrokes
289+ </button>
290+ </div>
291+ <p className="hint">
292+ Paste is fast and reliable. Keystrokes types character by character and
293+ works in fields that block pasting.
294+ </p>
295+ </div>
296+
297+ {settings.injection_mode === "paste" && (
298+ <div className="field">
299+ <label className="check">
300+ <input
301+ type="checkbox"
302+ checked={settings.restore_clipboard}
303+ onChange={(e) =>
304+ onChange({ ...settings, restore_clipboard: e.currentTarget.checked })
305+ }
306+ />
307+ restore previous clipboard after pasting
308+ </label>
309+ </div>
310+ )}
311+
312+ <div className="field">
313+ <label>last transcript</label>
314+ <div className="transcript-box">
315+ {lastTranscript ? (
316+ <>
317+ <p>{lastTranscript.text}</p>
318+ {lastTranscript.enhanced && (
319+ <p className="hint">raw: {lastTranscript.raw}</p>
320+ )}
321+ </>
322+ ) : (
323+ <p className="hint">
324+ Nothing yet. Press the hotkey, speak, press it again.
325+ </p>
326+ )}
327+ </div>
328+ </div>
329+
330+ {showHypr && env && (
331+ <HyprlandModal
332+ hotkey={settings.hotkey}
333+ hold={hold}
334+ exe={env.exe}
335+ onClose={() => setShowHypr(false)}
336+ />
337+ )}
338+ </section>
339+ );
340+}
+118-0src/pages/Models.tsx
@@ -0,0 +1,118 @@
1+import { useEffect, useState } from "react";
2+import { listen } from "@tauri-apps/api/event";
3+import { deleteModel, downloadModel, listModels } from "../api";
4+import type { DownloadProgress, ModelInfo, Settings } from "../types";
5+
6+interface Props {
7+ settings: Settings;
8+ onChange: (next: Settings) => void;
9+}
10+
11+export default function ModelsPage({ settings, onChange }: Props) {
12+ const [models, setModels] = useState<ModelInfo[]>([]);
13+ const [progress, setProgress] = useState<Record<string, DownloadProgress>>({});
14+ const [errors, setErrors] = useState<Record<string, string>>({});
15+
16+ const refresh = () => listModels().then(setModels).catch(console.error);
17+
18+ useEffect(() => {
19+ refresh();
20+ const sub = listen<DownloadProgress>("model-progress", (e) => {
21+ setProgress((p) => ({ ...p, [e.payload.id]: e.payload }));
22+ if (e.payload.done) refresh();
23+ });
24+ return () => {
25+ sub.then((fn) => fn());
26+ };
27+ }, []);
28+
29+ const start = (id: string) => {
30+ setErrors((e) => ({ ...e, [id]: "" }));
31+ setProgress((p) => ({ ...p, [id]: { id, downloaded: 0, total: 0, done: false } }));
32+ downloadModel(id)
33+ .then(refresh)
34+ .catch((err) => {
35+ setErrors((e) => ({ ...e, [id]: String(err) }));
36+ setProgress((p) => {
37+ const { [id]: _dropped, ...rest } = p;
38+ return rest;
39+ });
40+ });
41+ };
42+
43+ const remove = (id: string) => {
44+ deleteModel(id).then(refresh).catch(console.error);
45+ setProgress((p) => {
46+ const { [id]: _dropped, ...rest } = p;
47+ return rest;
48+ });
49+ };
50+
51+ return (
52+ <section>
53+ <header className="page-head">
54+ <h2>models</h2>
55+ <p>
56+ Dictation runs locally with whisper.cpp. Download a model once, then
57+ everything works offline.
58+ </p>
59+ </header>
60+
61+ <ul className="model-list">
62+ {models.map((m) => {
63+ const p = progress[m.id];
64+ const downloading = p !== undefined && !p.done && !m.installed;
65+ const active = settings.dictation_model === m.id;
66+ const pct =
67+ p && p.total > 0 ? Math.min(100, (p.downloaded / p.total) * 100) : 0;
68+ return (
69+ <li key={m.id} className={active ? "model active" : "model"}>
70+ <div className="model-main">
71+ <div className="model-title">
72+ <strong>{m.label}</strong>
73+ <span className="badge">{m.size_mb} MB</span>
74+ {m.multilingual && <span className="badge dim">multilingual</span>}
75+ {active && <span className="badge accent">in use</span>}
76+ </div>
77+ <p className="hint">{m.description}</p>
78+ {downloading && (
79+ <div className="progress">
80+ <div className="progress-fill" style={{ width: `${pct}%` }} />
81+ </div>
82+ )}
83+ {errors[m.id] && <p className="hint error-text">{errors[m.id]}</p>}
84+ </div>
85+ <div className="model-actions">
86+ {m.installed ? (
87+ <>
88+ {!active && (
89+ <button
90+ className="btn"
91+ onClick={() => onChange({ ...settings, dictation_model: m.id })}
92+ >
93+ use
94+ </button>
95+ )}
96+ <button className="btn ghost" onClick={() => remove(m.id)}>
97+ delete
98+ </button>
99+ </>
100+ ) : downloading ? (
101+ <span className="hint">
102+ {p.total > 0
103+ ? `${Math.round(pct)}%`
104+ : `${(p.downloaded / 1e6).toFixed(0)} MB`}
105+ </span>
106+ ) : (
107+ <button className="btn" onClick={() => start(m.id)}>
108+ install
109+ </button>
110+ )}
111+ </div>
112+ </li>
113+ );
114+ })}
115+ </ul>
116+ </section>
117+ );
118+}
+647-0src/styles.css
@@ -0,0 +1,647 @@
1+:root {
2+ --bg: #131110;
3+ --bg-raised: #1c1917;
4+ --bg-inset: #0d0c0b;
5+ --line: #2c2825;
6+ --text: #ece4d8;
7+ --text-dim: #93897c;
8+ --accent: #ff5c1f;
9+ --accent-soft: #b8410f;
10+ --ok: #7dbb6a;
11+ --danger: #e05646;
12+ --mono: "JetBrains Mono", "Fira Code", "Iosevka", ui-monospace, "Cascadia Code",
13+ monospace;
14+}
15+
16+* {
17+ margin: 0;
18+ padding: 0;
19+ box-sizing: border-box;
20+}
21+
22+html,
23+body,
24+#root {
25+ height: 100%;
26+}
27+
28+body {
29+ font-family: var(--mono);
30+ font-size: 13px;
31+ line-height: 1.55;
32+ background: var(--bg);
33+ color: var(--text);
34+ -webkit-font-smoothing: antialiased;
35+ user-select: none;
36+}
37+
38+code {
39+ color: var(--accent);
40+ font-size: 12px;
41+}
42+
43+/* ---------- shell ---------- */
44+
45+.shell {
46+ display: flex;
47+ height: 100%;
48+}
49+
50+.sidebar {
51+ width: 220px;
52+ flex-shrink: 0;
53+ display: flex;
54+ flex-direction: column;
55+ border-right: 1px solid var(--line);
56+ background: var(--bg-inset);
57+ padding: 24px 0;
58+}
59+
60+.wordmark {
61+ padding: 0 20px 24px;
62+ border-bottom: 1px solid var(--line);
63+}
64+
65+.wordmark-glyph {
66+ color: var(--accent);
67+ font-size: 15px;
68+ letter-spacing: 2px;
69+}
70+
71+.wordmark h1 {
72+ font-size: 19px;
73+ font-weight: 700;
74+ letter-spacing: -0.5px;
75+ margin-top: 6px;
76+}
77+
78+.tagline {
79+ color: var(--text-dim);
80+ font-size: 11px;
81+ margin-top: 2px;
82+}
83+
84+nav {
85+ display: flex;
86+ flex-direction: column;
87+ padding: 16px 8px;
88+ gap: 2px;
89+ flex: 1;
90+}
91+
92+.nav-item {
93+ display: flex;
94+ gap: 8px;
95+ align-items: center;
96+ background: none;
97+ border: none;
98+ color: var(--text-dim);
99+ font: inherit;
100+ text-align: left;
101+ padding: 8px 12px;
102+ border-radius: 6px;
103+ cursor: pointer;
104+}
105+
106+.nav-item:hover {
107+ color: var(--text);
108+ background: var(--bg-raised);
109+}
110+
111+.nav-item.active {
112+ color: var(--text);
113+ background: var(--bg-raised);
114+}
115+
116+.nav-marker {
117+ color: var(--accent);
118+ width: 10px;
119+ display: inline-block;
120+}
121+
122+.sidebar-foot {
123+ padding: 16px 20px 0;
124+ border-top: 1px solid var(--line);
125+}
126+
127+.dictate-btn {
128+ width: 100%;
129+ padding: 10px;
130+ font: inherit;
131+ font-weight: 700;
132+ border-radius: 8px;
133+ border: 1px solid var(--accent-soft);
134+ background: transparent;
135+ color: var(--accent);
136+ cursor: pointer;
137+ transition: background 120ms ease;
138+}
139+
140+.dictate-btn:hover {
141+ background: rgba(255, 92, 31, 0.12);
142+}
143+
144+.dictate-btn.state-recording {
145+ background: var(--accent);
146+ color: #170b05;
147+ animation: pulse-bg 1.4s ease-in-out infinite;
148+}
149+
150+.dictate-btn.state-processing {
151+ color: var(--text-dim);
152+ border-color: var(--line);
153+}
154+
155+@keyframes pulse-bg {
156+ 50% {
157+ filter: brightness(1.25);
158+ }
159+}
160+
161+/* ---------- content ---------- */
162+
163+.content {
164+ flex: 1;
165+ overflow-y: auto;
166+ padding: 36px 44px 60px;
167+}
168+
169+.page-head {
170+ margin-bottom: 28px;
171+}
172+
173+.page-head h2 {
174+ font-size: 17px;
175+ letter-spacing: -0.3px;
176+}
177+
178+.page-head h2::before {
179+ content: "# ";
180+ color: var(--accent);
181+}
182+
183+.page-head p {
184+ color: var(--text-dim);
185+ margin-top: 4px;
186+ max-width: 52ch;
187+}
188+
189+.field {
190+ margin-bottom: 22px;
191+ max-width: 560px;
192+}
193+
194+.field > label {
195+ display: block;
196+ font-size: 11px;
197+ text-transform: uppercase;
198+ letter-spacing: 1.5px;
199+ color: var(--text-dim);
200+ margin-bottom: 8px;
201+}
202+
203+.field-row {
204+ display: flex;
205+ gap: 8px;
206+}
207+
208+input[type="text"],
209+input:not([type]),
210+select,
211+textarea {
212+ width: 100%;
213+ font: inherit;
214+ color: var(--text);
215+ background: var(--bg-raised);
216+ border: 1px solid var(--line);
217+ border-radius: 6px;
218+ padding: 9px 12px;
219+ outline: none;
220+ user-select: text;
221+}
222+
223+input:focus,
224+select:focus,
225+textarea:focus {
226+ border-color: var(--accent-soft);
227+}
228+
229+/* WebKitGTK renders the native dropdown on a light surface, so option colors
230+ must be set explicitly or they inherit light text: white on white. */
231+select {
232+ appearance: none;
233+ -webkit-appearance: none;
234+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%2393897c' fill='none' stroke-width='1.5'/%3E%3C/svg%3E");
235+ background-repeat: no-repeat;
236+ background-position: right 12px center;
237+ padding-right: 32px;
238+ cursor: pointer;
239+}
240+
241+select option {
242+ background: #ffffff;
243+ color: #1c1917;
244+}
245+
246+textarea {
247+ resize: vertical;
248+ line-height: 1.6;
249+}
250+
251+.check {
252+ display: flex;
253+ align-items: center;
254+ gap: 10px;
255+ cursor: pointer;
256+ font-size: 13px;
257+ color: var(--text);
258+}
259+
260+.check input {
261+ accent-color: var(--accent);
262+ width: 14px;
263+ height: 14px;
264+}
265+
266+.btn {
267+ font: inherit;
268+ padding: 9px 16px;
269+ border-radius: 6px;
270+ border: 1px solid var(--accent-soft);
271+ background: transparent;
272+ color: var(--accent);
273+ cursor: pointer;
274+ white-space: nowrap;
275+}
276+
277+.btn:hover:not(:disabled) {
278+ background: rgba(255, 92, 31, 0.12);
279+}
280+
281+.btn:disabled {
282+ opacity: 0.4;
283+ cursor: default;
284+}
285+
286+.btn.ghost {
287+ border-color: var(--line);
288+ color: var(--text-dim);
289+}
290+
291+.btn.ghost:hover {
292+ color: var(--danger);
293+ border-color: var(--danger);
294+ background: transparent;
295+}
296+
297+.segmented {
298+ display: inline-flex;
299+ border: 1px solid var(--line);
300+ border-radius: 6px;
301+ overflow: hidden;
302+}
303+
304+.seg {
305+ font: inherit;
306+ background: transparent;
307+ color: var(--text-dim);
308+ border: none;
309+ padding: 8px 16px;
310+ cursor: pointer;
311+}
312+
313+.seg + .seg {
314+ border-left: 1px solid var(--line);
315+}
316+
317+.seg.active {
318+ background: var(--bg-raised);
319+ color: var(--accent);
320+}
321+
322+.hint {
323+ color: var(--text-dim);
324+ font-size: 11.5px;
325+ margin-top: 7px;
326+ max-width: 52ch;
327+}
328+
329+.ok-text {
330+ color: var(--ok);
331+}
332+
333+.error-text {
334+ color: var(--danger);
335+}
336+
337+.dimmed {
338+ opacity: 0.45;
339+ pointer-events: none;
340+}
341+
342+.banner {
343+ padding: 10px 14px;
344+ border-radius: 6px;
345+ margin-bottom: 20px;
346+ display: flex;
347+ justify-content: space-between;
348+ gap: 12px;
349+ align-items: baseline;
350+}
351+
352+.banner.error {
353+ border: 1px solid rgba(224, 86, 70, 0.5);
354+ color: var(--danger);
355+ background: rgba(224, 86, 70, 0.08);
356+}
357+
358+.banner-dismiss {
359+ background: none;
360+ border: none;
361+ color: inherit;
362+ cursor: pointer;
363+ font: inherit;
364+}
365+
366+.hotkey-capture {
367+ flex: 1;
368+ font: inherit;
369+ text-align: left;
370+ color: var(--text);
371+ background: var(--bg-raised);
372+ border: 1px solid var(--line);
373+ border-radius: 6px;
374+ padding: 9px 12px;
375+ cursor: pointer;
376+}
377+
378+.hotkey-capture:hover {
379+ border-color: var(--accent-soft);
380+}
381+
382+.hotkey-capture.capturing {
383+ border-color: var(--accent);
384+ color: var(--text-dim);
385+ animation: pulse-border 1.2s ease-in-out infinite;
386+}
387+
388+@keyframes pulse-border {
389+ 50% {
390+ border-color: var(--accent-soft);
391+ }
392+}
393+
394+/* ---------- modal ---------- */
395+
396+.modal-backdrop {
397+ position: fixed;
398+ inset: 0;
399+ background: rgba(0, 0, 0, 0.6);
400+ display: flex;
401+ align-items: center;
402+ justify-content: center;
403+ z-index: 50;
404+}
405+
406+.modal {
407+ width: min(560px, calc(100vw - 48px));
408+ background: var(--bg-raised);
409+ border: 1px solid var(--line);
410+ border-radius: 10px;
411+ padding: 24px;
412+ box-shadow: 0 16px 50px rgba(0, 0, 0, 0.55);
413+}
414+
415+.modal h3 {
416+ font-size: 15px;
417+ margin-bottom: 8px;
418+}
419+
420+.modal h3::before {
421+ content: "# ";
422+ color: var(--accent);
423+}
424+
425+.modal .btn {
426+ margin-top: 16px;
427+}
428+
429+.code-block {
430+ position: relative;
431+ background: var(--bg-inset);
432+ border: 1px solid var(--line);
433+ border-radius: 6px;
434+ padding: 14px;
435+ margin-top: 12px;
436+ user-select: text;
437+}
438+
439+.code-block pre {
440+ font: inherit;
441+ font-size: 12px;
442+ color: var(--accent);
443+ white-space: pre-wrap;
444+ word-break: break-all;
445+ padding-right: 72px;
446+}
447+
448+.copy-btn {
449+ position: absolute;
450+ top: 8px;
451+ right: 8px;
452+ font: inherit;
453+ font-size: 11px;
454+ color: var(--text-dim);
455+ background: var(--bg-raised);
456+ border: 1px solid var(--line);
457+ border-radius: 5px;
458+ padding: 4px 9px;
459+ cursor: pointer;
460+}
461+
462+.copy-btn:hover {
463+ color: var(--text);
464+ border-color: var(--accent-soft);
465+}
466+
467+.transcript-box {
468+ background: var(--bg-inset);
469+ border: 1px solid var(--line);
470+ border-radius: 6px;
471+ padding: 14px;
472+ min-height: 64px;
473+ user-select: text;
474+}
475+
476+.transcript-box p + p {
477+ margin-top: 8px;
478+}
479+
480+/* ---------- models ---------- */
481+
482+.model-list {
483+ list-style: none;
484+ max-width: 640px;
485+}
486+
487+.model {
488+ display: flex;
489+ gap: 16px;
490+ align-items: flex-start;
491+ justify-content: space-between;
492+ padding: 16px 18px;
493+ border: 1px solid var(--line);
494+ border-radius: 8px;
495+ margin-bottom: 10px;
496+ background: var(--bg-raised);
497+}
498+
499+.model.active {
500+ border-color: var(--accent-soft);
501+}
502+
503+.model-title {
504+ display: flex;
505+ align-items: baseline;
506+ gap: 8px;
507+ flex-wrap: wrap;
508+}
509+
510+.model-main {
511+ flex: 1;
512+}
513+
514+.model-actions {
515+ display: flex;
516+ gap: 8px;
517+ flex-shrink: 0;
518+ align-items: center;
519+}
520+
521+.badge {
522+ font-size: 10.5px;
523+ padding: 1px 7px;
524+ border-radius: 99px;
525+ border: 1px solid var(--line);
526+ color: var(--text-dim);
527+}
528+
529+.badge.accent {
530+ color: var(--accent);
531+ border-color: var(--accent-soft);
532+}
533+
534+.badge.dim {
535+ opacity: 0.8;
536+}
537+
538+.progress {
539+ height: 4px;
540+ border-radius: 2px;
541+ background: var(--bg-inset);
542+ margin-top: 10px;
543+ overflow: hidden;
544+}
545+
546+.progress-fill {
547+ height: 100%;
548+ background: var(--accent);
549+ border-radius: 2px;
550+ transition: width 300ms ease;
551+}
552+
553+/* ---------- overlay pill ---------- */
554+
555+html.overlay-mode,
556+html.overlay-mode body,
557+html.overlay-mode #root {
558+ background: transparent;
559+ overflow: hidden;
560+}
561+
562+.overlay-pill {
563+ position: fixed;
564+ inset: 8px;
565+ display: flex;
566+ align-items: center;
567+ justify-content: center;
568+ gap: 12px;
569+ background: rgba(19, 17, 16, 0.94);
570+ border: 1px solid var(--line);
571+ border-radius: 99px;
572+ box-shadow: 0 8px 30px rgba(0, 0, 0, 0.5);
573+}
574+
575+.overlay-dot {
576+ width: 9px;
577+ height: 9px;
578+ border-radius: 50%;
579+ background: var(--accent);
580+}
581+
582+.overlay-recording .overlay-dot {
583+ animation: blink 1.2s ease-in-out infinite;
584+}
585+
586+.overlay-processing .overlay-dot {
587+ background: var(--text-dim);
588+ animation: blink 0.5s ease-in-out infinite;
589+}
590+
591+@keyframes blink {
592+ 50% {
593+ opacity: 0.25;
594+ }
595+}
596+
597+.overlay-label {
598+ font-size: 12px;
599+ letter-spacing: 2px;
600+ text-transform: uppercase;
601+}
602+
603+.overlay-bars {
604+ display: flex;
605+ gap: 3px;
606+ align-items: center;
607+ height: 18px;
608+}
609+
610+.overlay-bars i {
611+ width: 3px;
612+ border-radius: 2px;
613+ background: var(--accent);
614+ animation: bounce 0.9s ease-in-out infinite;
615+}
616+
617+.overlay-bars i:nth-child(1) {
618+ height: 40%;
619+ animation-delay: 0s;
620+}
621+.overlay-bars i:nth-child(2) {
622+ height: 80%;
623+ animation-delay: 0.15s;
624+}
625+.overlay-bars i:nth-child(3) {
626+ height: 100%;
627+ animation-delay: 0.3s;
628+}
629+.overlay-bars i:nth-child(4) {
630+ height: 70%;
631+ animation-delay: 0.45s;
632+}
633+.overlay-bars i:nth-child(5) {
634+ height: 45%;
635+ animation-delay: 0.6s;
636+}
637+
638+@keyframes bounce {
639+ 50% {
640+ transform: scaleY(0.4);
641+ }
642+}
643+
644+.overlay-processing .overlay-bars i {
645+ background: var(--text-dim);
646+ animation-duration: 0.5s;
647+}
+49-0src/types.ts
@@ -0,0 +1,49 @@
1+export interface EnhanceSettings {
2+ enabled: boolean;
3+ provider: "anthropic" | "gemini" | "openai" | "ollama";
4+ model: string;
5+ base_url: string;
6+ api_key_env: string;
7+ instructions: string;
8+}
9+
10+export interface Settings {
11+ hotkey: string;
12+ activation: "toggle" | "hold";
13+ injection_mode: "paste" | "type";
14+ restore_clipboard: boolean;
15+ dictation_model: string;
16+ language: string;
17+ enhance: EnhanceSettings;
18+}
19+
20+export interface ModelInfo {
21+ id: string;
22+ label: string;
23+ filename: string;
24+ size_mb: number;
25+ multilingual: boolean;
26+ description: string;
27+ installed: boolean;
28+}
29+
30+export interface DownloadProgress {
31+ id: string;
32+ downloaded: number;
33+ total: number;
34+ done: boolean;
35+}
36+
37+export interface TranscriptPayload {
38+ raw: string;
39+ text: string;
40+ enhanced: boolean;
41+}
42+
43+export type RecordingState = "idle" | "recording" | "processing";
44+
45+export interface EnvironmentInfo {
46+ wayland: boolean;
47+ compositor: string;
48+ exe: string;
49+}
+1-0src/vite-env.d.ts
@@ -0,0 +1 @@
1+/// <reference types="vite/client" />
+25-0tsconfig.json
@@ -0,0 +1,25 @@
1+{
2+ "compilerOptions": {
3+ "target": "ES2020",
4+ "useDefineForClassFields": true,
5+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
6+ "module": "ESNext",
7+ "skipLibCheck": true,
8+
9+ /* Bundler mode */
10+ "moduleResolution": "bundler",
11+ "allowImportingTsExtensions": true,
12+ "resolveJsonModule": true,
13+ "isolatedModules": true,
14+ "noEmit": true,
15+ "jsx": "react-jsx",
16+
17+ /* Linting */
18+ "strict": true,
19+ "noUnusedLocals": true,
20+ "noUnusedParameters": true,
21+ "noFallthroughCasesInSwitch": true
22+ },
23+ "include": ["src"],
24+ "references": [{ "path": "./tsconfig.node.json" }]
25+}
+10-0tsconfig.node.json
@@ -0,0 +1,10 @@
1+{
2+ "compilerOptions": {
3+ "composite": true,
4+ "skipLibCheck": true,
5+ "module": "ESNext",
6+ "moduleResolution": "bundler",
7+ "allowSyntheticDefaultImports": true
8+ },
9+ "include": ["vite.config.ts"]
10+}
+32-0vite.config.ts
@@ -0,0 +1,32 @@
1+import { defineConfig } from "vite";
2+import react from "@vitejs/plugin-react";
3+
4+// @ts-expect-error process is a nodejs global
5+const host = process.env.TAURI_DEV_HOST;
6+
7+// https://vite.dev/config/
8+export default defineConfig(async () => ({
9+ plugins: [react()],
10+
11+ // Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
12+ //
13+ // 1. prevent Vite from obscuring rust errors
14+ clearScreen: false,
15+ // 2. tauri expects a fixed port, fail if that port is not available
16+ server: {
17+ port: 1420,
18+ strictPort: true,
19+ host: host || false,
20+ hmr: host
21+ ? {
22+ protocol: "ws",
23+ host,
24+ port: 1421,
25+ }
26+ : undefined,
27+ watch: {
28+ // 3. tell Vite to ignore watching `src-tauri`
29+ ignored: ["**/src-tauri/**"],
30+ },
31+ },
32+}));