From 1e9438e2dcc8445a61e13832172ac5c29991e114 Mon Sep 17 00:00:00 2001 From: Alejandro Perez Date: Wed, 1 Jul 2026 16:18:01 +0100 Subject: [PATCH 1/2] feat: Phase 2, projects, skills, custom agents, LSP, CI tab, and fixes Large delivery covering the 15-task program plus follow-up fixes. Whole workspace is green: cargo fmt/clippy/test (344 core + 13 CLI + 7 integration) and frontend npm ci + tsc. Core / Tauri: - Worktrees and agent logs now live under $HOME/.cockpit (config::cockpit_home, worktrees_dir, logs_dir); fixed the inside-worktree log + relative-fallback bugs. - Auth = the user's Claude Code login via the `claude` CLI (login-shell PATH resolution); no API key, no SDK. Removed dead config fields. - Full Phase 2: plan gate reuses the one Gated loop (no new GateState); planner generation + plan-doc ingestion; guarded plan-approve fans out N implementers (bounded by max_parallel_agents), one worktree each. - First-class Project concept (groups PRs; Linear is one optional source); ProjectId/ProjectSource/Project, ProjectStore, reviews_by_project. - Skills: ~/.cockpit/skills, install/sync via gh api (SHA-idempotent), now actually injected into every rework prompt; filtered by diff. - Customizable per-AgentMode prompt fragments (verbatim), agent_command made live. - CI visibility: gh pr checks + per-run logs; explicit Fix-CI into the rework loop. - LSP bridge (axum WS <-> stdio) for pyright / typescript-language-server, with a hand-written Monaco client (no monaco-languageclient coupling). - Hardened diff-gate Fix loop with a real end-to-end integration test; slashed worktree-branch fix. Frontend: - New IA: PRs grouped by project, Projects, Skills, Agents, Settings; removed Stacks and the batch-approve panel. - Shortcut registry + Kbd labels; settings rewrite; PR Info tab removed and its links/stack relocated to the DiffView header; Monaco first-load theme fix. - New views: PlanView, NewProjectView, SkillsView, AgentEditor, CiPanel. - External links routed through the opener plugin (with the URL scope), replacing no-op target=_blank anchors. Known follow-ups (tracked in cockpit-docs/PROGRAM_PLAN.md): per-project plan scoping (plan store still global), CLI loop daemon seam, two dangling backend commands, no FE unit-test harness, runtime verification with live claude/pyright/gh. Co-Authored-By: Claude Opus 4.8 (1M context) --- .gitignore | 3 + Cargo.lock | 201 +++- Cargo.toml | 2 +- app/package-lock.json | 10 + app/package.json | 1 + app/src-tauri/Cargo.toml | 1 + app/src-tauri/capabilities/default.json | 4 +- app/src-tauri/gen/schemas/acl-manifests.json | 2 +- app/src-tauri/gen/schemas/capabilities.json | 2 +- app/src-tauri/gen/schemas/desktop-schema.json | 233 +++++ app/src-tauri/gen/schemas/macOS-schema.json | 233 +++++ app/src-tauri/icons/Square107x107Logo.png | Bin 0 -> 4186 bytes app/src-tauri/icons/Square142x142Logo.png | Bin 0 -> 5463 bytes app/src-tauri/icons/Square150x150Logo.png | Bin 0 -> 5609 bytes app/src-tauri/icons/Square284x284Logo.png | Bin 0 -> 10786 bytes app/src-tauri/icons/Square30x30Logo.png | Bin 0 -> 923 bytes app/src-tauri/icons/Square310x310Logo.png | Bin 0 -> 12051 bytes app/src-tauri/icons/Square44x44Logo.png | Bin 0 -> 1454 bytes app/src-tauri/icons/Square71x71Logo.png | Bin 0 -> 2611 bytes app/src-tauri/icons/Square89x89Logo.png | Bin 0 -> 3255 bytes app/src-tauri/icons/StoreLogo.png | Bin 0 -> 1715 bytes .../android/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../icons/android/mipmap-hdpi/ic_launcher.png | Bin 0 -> 1637 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 6075 bytes .../android/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 1347 bytes .../icons/android/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1584 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 0 -> 4038 bytes .../android/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 1291 bytes .../android/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 3361 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 0 -> 8109 bytes .../mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 2753 bytes .../android/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 5408 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 0 -> 12524 bytes .../mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 4255 bytes .../android/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 7540 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 17506 bytes .../mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 5471 bytes .../android/values/ic_launcher_background.xml | 4 + app/src-tauri/icons/ios/AppIcon-20x20@1x.png | Bin 0 -> 561 bytes .../icons/ios/AppIcon-20x20@2x-1.png | Bin 0 -> 1177 bytes app/src-tauri/icons/ios/AppIcon-20x20@2x.png | Bin 0 -> 1177 bytes app/src-tauri/icons/ios/AppIcon-20x20@3x.png | Bin 0 -> 1901 bytes app/src-tauri/icons/ios/AppIcon-29x29@1x.png | Bin 0 -> 855 bytes .../icons/ios/AppIcon-29x29@2x-1.png | Bin 0 -> 1824 bytes app/src-tauri/icons/ios/AppIcon-29x29@2x.png | Bin 0 -> 1824 bytes app/src-tauri/icons/ios/AppIcon-29x29@3x.png | Bin 0 -> 2889 bytes app/src-tauri/icons/ios/AppIcon-40x40@1x.png | Bin 0 -> 1177 bytes .../icons/ios/AppIcon-40x40@2x-1.png | Bin 0 -> 2506 bytes app/src-tauri/icons/ios/AppIcon-40x40@2x.png | Bin 0 -> 2506 bytes app/src-tauri/icons/ios/AppIcon-40x40@3x.png | Bin 0 -> 3851 bytes app/src-tauri/icons/ios/AppIcon-512@2x.png | Bin 0 -> 26565 bytes app/src-tauri/icons/ios/AppIcon-60x60@2x.png | Bin 0 -> 3851 bytes app/src-tauri/icons/ios/AppIcon-60x60@3x.png | Bin 0 -> 5680 bytes app/src-tauri/icons/ios/AppIcon-76x76@1x.png | Bin 0 -> 2428 bytes app/src-tauri/icons/ios/AppIcon-76x76@2x.png | Bin 0 -> 4881 bytes .../icons/ios/AppIcon-83.5x83.5@2x.png | Bin 0 -> 5467 bytes app/src-tauri/src/commands/mod.rs | 956 +++++++++++++++++- app/src-tauri/src/error.rs | 16 + app/src-tauri/src/lib.rs | 128 ++- app/src-tauri/src/state.rs | 20 +- app/src-tauri/src/streaming.rs | 33 +- app/src/App.tsx | 568 ++++++----- app/src/bindings/AgentPrompts.ts | 28 + app/src/bindings/Artifact.ts | 11 - app/src/bindings/BatchApproveConfig.ts | 16 - app/src/bindings/BatchStatus.ts | 28 + app/src/bindings/BatchVerdict.ts | 17 - app/src/bindings/CiCheck.ts | 31 + app/src/bindings/CiSummary.ts | 25 + app/src/bindings/Config.ts | 43 +- app/src/bindings/LspServers.ts | 35 + app/src/bindings/Project.ts | 28 + app/src/bindings/ProjectId.ts | 7 + app/src/bindings/ProjectPlan.ts | 10 +- app/src/bindings/ProjectSource.ts | 9 + app/src/bindings/Review.ts | 8 +- app/src/bindings/Skill.ts | 33 + app/src/bindings/SkillSource.ts | 21 + app/src/bindings/SkillsGithub.ts | 30 + app/src/bindings/SyncReport.ts | 21 + app/src/components/AgentEditor.tsx | 239 +++++ app/src/components/BatchApprovePanel.tsx | 153 --- app/src/components/CiPanel.tsx | 483 +++++++++ app/src/components/CommandPalette.tsx | 117 ++- app/src/components/DiffView.tsx | 468 +++++++-- app/src/components/KickoffView.tsx | 189 ---- app/src/components/NewProjectView.tsx | 258 +++++ app/src/components/PlanView.tsx | 432 +++++--- app/src/components/ProjectCard.tsx | 126 +++ app/src/components/ReviewWorkspace.tsx | 205 ++++ app/src/components/SettingsView.tsx | 744 +++++++------- app/src/components/Sidebar.tsx | 79 +- app/src/components/SkillsView.tsx | 391 +++++++ app/src/components/Terminal.tsx | 29 +- app/src/components/ui/avatar.tsx | 109 -- app/src/components/ui/dropdown-menu.tsx | 266 ----- app/src/components/ui/scroll-area.tsx | 52 - app/src/components/ui/sheet.tsx | 136 --- app/src/lib/ci.ts | 116 +++ app/src/lib/lsp-client.ts | 543 ++++++++++ app/src/lib/open.ts | 31 + app/src/lib/shortcuts.tsx | 115 +++ app/src/store.ts | 419 ++++++-- cockpit-docs/PROGRAM_PLAN.md | 120 +++ crates/cockpit-cli/src/main.rs | 340 ++++++- crates/cockpit-core/Cargo.toml | 5 +- crates/cockpit-core/src/adapters/agent.rs | 219 +++- .../cockpit-core/src/adapters/agent_stream.rs | 55 +- crates/cockpit-core/src/adapters/git.rs | 101 +- crates/cockpit-core/src/adapters/github.rs | 358 ++++++- crates/cockpit-core/src/adapters/lsp.rs | 507 ++++++++++ crates/cockpit-core/src/adapters/mod.rs | 1 + crates/cockpit-core/src/batch.rs | 20 +- crates/cockpit-core/src/config.rs | 668 ++++++++++-- crates/cockpit-core/src/gate.rs | 81 ++ crates/cockpit-core/src/kickoff.rs | 385 +++++-- crates/cockpit-core/src/model.rs | 56 +- crates/cockpit-core/src/plan_parser.rs | 3 + crates/cockpit-core/src/prompt.rs | 650 +++++++++++- crates/cockpit-core/src/restack.rs | 90 +- crates/cockpit-core/src/skills.rs | 712 ++++++++++++- crates/cockpit-core/src/store.rs | 356 ++++++- .../cockpit-core/tests/batch_fan_out_e2e.rs | 325 ++++++ crates/cockpit-core/tests/e2e_round_trip.rs | 3 + crates/cockpit-core/tests/fix_loop_e2e.rs | 489 +++++++++ .../tests/golden/plan_generation.txt | 14 + .../golden/plan_generation_with_output.txt | 33 + .../tests/golden/rework_ci_failures.txt | 22 + .../tests/golden/rework_custom_preamble.txt | 21 + .../tests/golden/rework_with_skills.txt | 22 + 130 files changed, 11789 insertions(+), 2390 deletions(-) create mode 100644 app/src-tauri/icons/Square107x107Logo.png create mode 100644 app/src-tauri/icons/Square142x142Logo.png create mode 100644 app/src-tauri/icons/Square150x150Logo.png create mode 100644 app/src-tauri/icons/Square284x284Logo.png create mode 100644 app/src-tauri/icons/Square30x30Logo.png create mode 100644 app/src-tauri/icons/Square310x310Logo.png create mode 100644 app/src-tauri/icons/Square44x44Logo.png create mode 100644 app/src-tauri/icons/Square71x71Logo.png create mode 100644 app/src-tauri/icons/Square89x89Logo.png create mode 100644 app/src-tauri/icons/StoreLogo.png create mode 100644 app/src-tauri/icons/android/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 app/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png create mode 100644 app/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png create mode 100644 app/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png create mode 100644 app/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png create mode 100644 app/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png create mode 100644 app/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png create mode 100644 app/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png create mode 100644 app/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png create mode 100644 app/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png create mode 100644 app/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png create mode 100644 app/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png create mode 100644 app/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 app/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png create mode 100644 app/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png create mode 100644 app/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 app/src-tauri/icons/android/values/ic_launcher_background.xml create mode 100644 app/src-tauri/icons/ios/AppIcon-20x20@1x.png create mode 100644 app/src-tauri/icons/ios/AppIcon-20x20@2x-1.png create mode 100644 app/src-tauri/icons/ios/AppIcon-20x20@2x.png create mode 100644 app/src-tauri/icons/ios/AppIcon-20x20@3x.png create mode 100644 app/src-tauri/icons/ios/AppIcon-29x29@1x.png create mode 100644 app/src-tauri/icons/ios/AppIcon-29x29@2x-1.png create mode 100644 app/src-tauri/icons/ios/AppIcon-29x29@2x.png create mode 100644 app/src-tauri/icons/ios/AppIcon-29x29@3x.png create mode 100644 app/src-tauri/icons/ios/AppIcon-40x40@1x.png create mode 100644 app/src-tauri/icons/ios/AppIcon-40x40@2x-1.png create mode 100644 app/src-tauri/icons/ios/AppIcon-40x40@2x.png create mode 100644 app/src-tauri/icons/ios/AppIcon-40x40@3x.png create mode 100644 app/src-tauri/icons/ios/AppIcon-512@2x.png create mode 100644 app/src-tauri/icons/ios/AppIcon-60x60@2x.png create mode 100644 app/src-tauri/icons/ios/AppIcon-60x60@3x.png create mode 100644 app/src-tauri/icons/ios/AppIcon-76x76@1x.png create mode 100644 app/src-tauri/icons/ios/AppIcon-76x76@2x.png create mode 100644 app/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png create mode 100644 app/src/bindings/AgentPrompts.ts delete mode 100644 app/src/bindings/Artifact.ts delete mode 100644 app/src/bindings/BatchApproveConfig.ts create mode 100644 app/src/bindings/BatchStatus.ts delete mode 100644 app/src/bindings/BatchVerdict.ts create mode 100644 app/src/bindings/CiCheck.ts create mode 100644 app/src/bindings/CiSummary.ts create mode 100644 app/src/bindings/LspServers.ts create mode 100644 app/src/bindings/Project.ts create mode 100644 app/src/bindings/ProjectId.ts create mode 100644 app/src/bindings/ProjectSource.ts create mode 100644 app/src/bindings/Skill.ts create mode 100644 app/src/bindings/SkillSource.ts create mode 100644 app/src/bindings/SkillsGithub.ts create mode 100644 app/src/bindings/SyncReport.ts create mode 100644 app/src/components/AgentEditor.tsx delete mode 100644 app/src/components/BatchApprovePanel.tsx create mode 100644 app/src/components/CiPanel.tsx delete mode 100644 app/src/components/KickoffView.tsx create mode 100644 app/src/components/NewProjectView.tsx create mode 100644 app/src/components/ProjectCard.tsx create mode 100644 app/src/components/ReviewWorkspace.tsx create mode 100644 app/src/components/SkillsView.tsx delete mode 100644 app/src/components/ui/avatar.tsx delete mode 100644 app/src/components/ui/dropdown-menu.tsx delete mode 100644 app/src/components/ui/scroll-area.tsx delete mode 100644 app/src/components/ui/sheet.tsx create mode 100644 app/src/lib/ci.ts create mode 100644 app/src/lib/lsp-client.ts create mode 100644 app/src/lib/open.ts create mode 100644 app/src/lib/shortcuts.tsx create mode 100644 cockpit-docs/PROGRAM_PLAN.md create mode 100644 crates/cockpit-core/src/adapters/lsp.rs create mode 100644 crates/cockpit-core/tests/batch_fan_out_e2e.rs create mode 100644 crates/cockpit-core/tests/fix_loop_e2e.rs create mode 100644 crates/cockpit-core/tests/golden/plan_generation.txt create mode 100644 crates/cockpit-core/tests/golden/plan_generation_with_output.txt create mode 100644 crates/cockpit-core/tests/golden/rework_ci_failures.txt create mode 100644 crates/cockpit-core/tests/golden/rework_custom_preamble.txt create mode 100644 crates/cockpit-core/tests/golden/rework_with_skills.txt diff --git a/.gitignore b/.gitignore index 71e4991..4e324ee 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,6 @@ dist/ .env .DS_Store .claude/worktrees/ + +# cockpit runtime artifacts (should live in \$HOME/.cockpit, never in-tree) +.cockpit/ diff --git a/Cargo.lock b/Cargo.lock index 9cee59f..a6dbbe8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -270,6 +270,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90" dependencies = [ "axum-core", + "base64 0.22.1", "bytes", "form_urlencoded", "futures-util", @@ -288,8 +289,10 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded", + "sha1", "sync_wrapper", "tokio", + "tokio-tungstenite 0.29.0", "tower", "tower-layer", "tower-service", @@ -649,6 +652,7 @@ dependencies = [ "tauri-build", "tauri-plugin-dialog", "tauri-plugin-notification", + "tauri-plugin-opener", "tokio", "uuid", ] @@ -673,15 +677,18 @@ version = "0.0.0" dependencies = [ "axum", "dirs", + "futures-util", "git2", "http", "reqwest 0.12.28", "serde", "serde_json", "sha2 0.11.0", + "temp-env", "tempfile", "thiserror 2.0.18", "tokio", + "tokio-tungstenite 0.24.0", "toml 1.1.2+spec-1.1.0", "tower", "ts-rs", @@ -903,6 +910,12 @@ dependencies = [ "syn 2.0.118", ] +[[package]] +name = "data-encoding" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" + [[package]] name = "dbus" version = "0.9.11" @@ -1299,6 +1312,21 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "futures" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.32" @@ -1306,6 +1334,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -1373,6 +1402,7 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ + "futures-channel", "futures-core", "futures-io", "futures-macro", @@ -2031,6 +2061,25 @@ version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" +[[package]] +name = "is-docker" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3" +dependencies = [ + "once_cell", +] + +[[package]] +name = "is-wsl" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5" +dependencies = [ + "is-docker", + "once_cell", +] + [[package]] name = "is_terminal_polyfill" version = "1.70.2" @@ -2702,6 +2751,17 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" +[[package]] +name = "open" +version = "5.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd8d3b65c44123a56e0133d2cd06ce4361bd3ca99d41198b2f25e3c3db9b8b4a" +dependencies = [ + "dunce", + "is-wsl", + "libc", +] + [[package]] name = "option-ext" version = "0.2.0" @@ -3067,7 +3127,7 @@ dependencies = [ "bytes", "getrandom 0.3.4", "lru-slab", - "rand", + "rand 0.9.4", "ring", "rustc-hash", "rustls", @@ -3114,14 +3174,35 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" +[[package]] +name = "rand" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + [[package]] name = "rand" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ - "rand_chacha", - "rand_core", + "rand_chacha 0.9.0", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", ] [[package]] @@ -3131,7 +3212,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.17", ] [[package]] @@ -3690,6 +3780,17 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "digest 0.10.7", +] + [[package]] name = "sha2" version = "0.10.9" @@ -4169,7 +4270,7 @@ checksum = "01fc2c5ff41105bd1f7242d8201fdf3efd70749b82fa013a17f2126357d194cc" dependencies = [ "log", "notify-rust", - "rand", + "rand 0.9.4", "serde", "serde_json", "serde_repr", @@ -4180,6 +4281,28 @@ dependencies = [ "url", ] +[[package]] +name = "tauri-plugin-opener" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17e1bea14edce6b793a04e2417e3fd924b9bc4faae83cdee7d714156cceeed29" +dependencies = [ + "dunce", + "glob", + "objc2-app-kit", + "objc2-foundation", + "open", + "schemars 0.8.22", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "thiserror 2.0.18", + "url", + "windows", + "zbus", +] + [[package]] name = "tauri-runtime" version = "2.11.3" @@ -4292,6 +4415,16 @@ dependencies = [ "windows-version", ] +[[package]] +name = "temp-env" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96374855068f47402c3121c6eed88d29cb1de8f3ab27090e273e420bdabcf050" +dependencies = [ + "futures", + "parking_lot", +] + [[package]] name = "tempfile" version = "3.27.0" @@ -4456,6 +4589,30 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-tungstenite" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9" +dependencies = [ + "futures-util", + "log", + "tokio", + "tungstenite 0.24.0", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f72a05e828585856dacd553fba484c242c46e391fb0e58917c942ee9202915c" +dependencies = [ + "futures-util", + "log", + "tokio", + "tungstenite 0.29.0", +] + [[package]] name = "tokio-util" version = "0.7.18" @@ -4718,6 +4875,40 @@ dependencies = [ "termcolor", ] +[[package]] +name = "tungstenite" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a" +dependencies = [ + "byteorder", + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "rand 0.8.6", + "sha1", + "thiserror 1.0.69", + "utf-8", +] + +[[package]] +name = "tungstenite" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c01152af293afb9c7c2a57e4b559c5620b421f6d133261c60dd2d0cdb38e6b8" +dependencies = [ + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "rand 0.9.4", + "sha1", + "thiserror 2.0.18", +] + [[package]] name = "typeid" version = "1.0.3" diff --git a/Cargo.toml b/Cargo.toml index 5d891af..5140bd1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ anyhow = "1" thiserror = "2" serde = { version = "1", features = ["derive"] } serde_json = "1" -tokio = { version = "1", features = ["rt-multi-thread", "macros", "process", "fs"] } +tokio = { version = "1", features = ["rt-multi-thread", "macros", "process", "fs", "io-util"] } git2 = "0.21" tempfile = "3" sha2 = "0.11" diff --git a/app/package-lock.json b/app/package-lock.json index 85bfa7e..934cd87 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -15,6 +15,7 @@ "@tauri-apps/api": "^2.0.0", "@tauri-apps/plugin-dialog": "^2.7.1", "@tauri-apps/plugin-notification": "^2.2.2", + "@tauri-apps/plugin-opener": "^2.5.4", "@xterm/addon-fit": "^0.11.0", "@xterm/xterm": "^6.0.0", "class-variance-authority": "^0.7.1", @@ -2307,6 +2308,15 @@ "@tauri-apps/api": "^2.8.0" } }, + "node_modules/@tauri-apps/plugin-opener": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-opener/-/plugin-opener-2.5.4.tgz", + "integrity": "sha512-1HnPkb+AmgO29HBazm4uPLKB+r7zzcTBW1d0fyYp1uP+jwtpoiNDGKMMzz58SFp49nOIrxdE3aUJtT57lfO9CQ==", + "license": "MIT OR Apache-2.0", + "dependencies": { + "@tauri-apps/api": "^2.11.0" + } + }, "node_modules/@ts-morph/common": { "version": "0.27.0", "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.27.0.tgz", diff --git a/app/package.json b/app/package.json index b4327b5..63c8d56 100644 --- a/app/package.json +++ b/app/package.json @@ -16,6 +16,7 @@ "@tauri-apps/api": "^2.0.0", "@tauri-apps/plugin-dialog": "^2.7.1", "@tauri-apps/plugin-notification": "^2.2.2", + "@tauri-apps/plugin-opener": "^2.5.4", "@xterm/addon-fit": "^0.11.0", "@xterm/xterm": "^6.0.0", "class-variance-authority": "^0.7.1", diff --git a/app/src-tauri/Cargo.toml b/app/src-tauri/Cargo.toml index f1fba0d..e257b04 100644 --- a/app/src-tauri/Cargo.toml +++ b/app/src-tauri/Cargo.toml @@ -15,6 +15,7 @@ reqwest.workspace = true git2.workspace = true tauri-plugin-dialog = "2.7.1" tauri-plugin-notification = "2" +tauri-plugin-opener = "2" portable-pty = "0.9" base64 = "0.22" diff --git a/app/src-tauri/capabilities/default.json b/app/src-tauri/capabilities/default.json index d6004c5..98fb679 100644 --- a/app/src-tauri/capabilities/default.json +++ b/app/src-tauri/capabilities/default.json @@ -4,6 +4,8 @@ "windows": ["main"], "permissions": [ "core:default", - "notification:default" + "notification:default", + "opener:allow-open-url", + "opener:allow-default-urls" ] } diff --git a/app/src-tauri/gen/schemas/acl-manifests.json b/app/src-tauri/gen/schemas/acl-manifests.json index ed39bc9..365b4a2 100644 --- a/app/src-tauri/gen/schemas/acl-manifests.json +++ b/app/src-tauri/gen/schemas/acl-manifests.json @@ -1 +1 @@ -{"core":{"default_permission":{"identifier":"default","description":"Default core plugins set.","permissions":["core:path:default","core:event:default","core:window:default","core:webview:default","core:app:default","core:image:default","core:resources:default","core:menu:default","core:tray:default"]},"permissions":{},"permission_sets":{},"global_scope_schema":null},"core:app":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-version","allow-name","allow-tauri-version","allow-identifier","allow-bundle-type","allow-register-listener","allow-remove-listener","allow-supports-multiple-windows"]},"permissions":{"allow-app-hide":{"identifier":"allow-app-hide","description":"Enables the app_hide command without any pre-configured scope.","commands":{"allow":["app_hide"],"deny":[]}},"allow-app-show":{"identifier":"allow-app-show","description":"Enables the app_show command without any pre-configured scope.","commands":{"allow":["app_show"],"deny":[]}},"allow-bundle-type":{"identifier":"allow-bundle-type","description":"Enables the bundle_type command without any pre-configured scope.","commands":{"allow":["bundle_type"],"deny":[]}},"allow-default-window-icon":{"identifier":"allow-default-window-icon","description":"Enables the default_window_icon command without any pre-configured scope.","commands":{"allow":["default_window_icon"],"deny":[]}},"allow-fetch-data-store-identifiers":{"identifier":"allow-fetch-data-store-identifiers","description":"Enables the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":["fetch_data_store_identifiers"],"deny":[]}},"allow-identifier":{"identifier":"allow-identifier","description":"Enables the identifier command without any pre-configured scope.","commands":{"allow":["identifier"],"deny":[]}},"allow-name":{"identifier":"allow-name","description":"Enables the name command without any pre-configured scope.","commands":{"allow":["name"],"deny":[]}},"allow-register-listener":{"identifier":"allow-register-listener","description":"Enables the register_listener command without any pre-configured scope.","commands":{"allow":["register_listener"],"deny":[]}},"allow-remove-data-store":{"identifier":"allow-remove-data-store","description":"Enables the remove_data_store command without any pre-configured scope.","commands":{"allow":["remove_data_store"],"deny":[]}},"allow-remove-listener":{"identifier":"allow-remove-listener","description":"Enables the remove_listener command without any pre-configured scope.","commands":{"allow":["remove_listener"],"deny":[]}},"allow-set-app-theme":{"identifier":"allow-set-app-theme","description":"Enables the set_app_theme command without any pre-configured scope.","commands":{"allow":["set_app_theme"],"deny":[]}},"allow-set-dock-visibility":{"identifier":"allow-set-dock-visibility","description":"Enables the set_dock_visibility command without any pre-configured scope.","commands":{"allow":["set_dock_visibility"],"deny":[]}},"allow-supports-multiple-windows":{"identifier":"allow-supports-multiple-windows","description":"Enables the supports_multiple_windows command without any pre-configured scope.","commands":{"allow":["supports_multiple_windows"],"deny":[]}},"allow-tauri-version":{"identifier":"allow-tauri-version","description":"Enables the tauri_version command without any pre-configured scope.","commands":{"allow":["tauri_version"],"deny":[]}},"allow-version":{"identifier":"allow-version","description":"Enables the version command without any pre-configured scope.","commands":{"allow":["version"],"deny":[]}},"deny-app-hide":{"identifier":"deny-app-hide","description":"Denies the app_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["app_hide"]}},"deny-app-show":{"identifier":"deny-app-show","description":"Denies the app_show command without any pre-configured scope.","commands":{"allow":[],"deny":["app_show"]}},"deny-bundle-type":{"identifier":"deny-bundle-type","description":"Denies the bundle_type command without any pre-configured scope.","commands":{"allow":[],"deny":["bundle_type"]}},"deny-default-window-icon":{"identifier":"deny-default-window-icon","description":"Denies the default_window_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["default_window_icon"]}},"deny-fetch-data-store-identifiers":{"identifier":"deny-fetch-data-store-identifiers","description":"Denies the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":[],"deny":["fetch_data_store_identifiers"]}},"deny-identifier":{"identifier":"deny-identifier","description":"Denies the identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["identifier"]}},"deny-name":{"identifier":"deny-name","description":"Denies the name command without any pre-configured scope.","commands":{"allow":[],"deny":["name"]}},"deny-register-listener":{"identifier":"deny-register-listener","description":"Denies the register_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["register_listener"]}},"deny-remove-data-store":{"identifier":"deny-remove-data-store","description":"Denies the remove_data_store command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_data_store"]}},"deny-remove-listener":{"identifier":"deny-remove-listener","description":"Denies the remove_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_listener"]}},"deny-set-app-theme":{"identifier":"deny-set-app-theme","description":"Denies the set_app_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_app_theme"]}},"deny-set-dock-visibility":{"identifier":"deny-set-dock-visibility","description":"Denies the set_dock_visibility command without any pre-configured scope.","commands":{"allow":[],"deny":["set_dock_visibility"]}},"deny-supports-multiple-windows":{"identifier":"deny-supports-multiple-windows","description":"Denies the supports_multiple_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["supports_multiple_windows"]}},"deny-tauri-version":{"identifier":"deny-tauri-version","description":"Denies the tauri_version command without any pre-configured scope.","commands":{"allow":[],"deny":["tauri_version"]}},"deny-version":{"identifier":"deny-version","description":"Denies the version command without any pre-configured scope.","commands":{"allow":[],"deny":["version"]}}},"permission_sets":{},"global_scope_schema":null},"core:event":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-listen","allow-unlisten","allow-emit","allow-emit-to"]},"permissions":{"allow-emit":{"identifier":"allow-emit","description":"Enables the emit command without any pre-configured scope.","commands":{"allow":["emit"],"deny":[]}},"allow-emit-to":{"identifier":"allow-emit-to","description":"Enables the emit_to command without any pre-configured scope.","commands":{"allow":["emit_to"],"deny":[]}},"allow-listen":{"identifier":"allow-listen","description":"Enables the listen command without any pre-configured scope.","commands":{"allow":["listen"],"deny":[]}},"allow-unlisten":{"identifier":"allow-unlisten","description":"Enables the unlisten command without any pre-configured scope.","commands":{"allow":["unlisten"],"deny":[]}},"deny-emit":{"identifier":"deny-emit","description":"Denies the emit command without any pre-configured scope.","commands":{"allow":[],"deny":["emit"]}},"deny-emit-to":{"identifier":"deny-emit-to","description":"Denies the emit_to command without any pre-configured scope.","commands":{"allow":[],"deny":["emit_to"]}},"deny-listen":{"identifier":"deny-listen","description":"Denies the listen command without any pre-configured scope.","commands":{"allow":[],"deny":["listen"]}},"deny-unlisten":{"identifier":"deny-unlisten","description":"Denies the unlisten command without any pre-configured scope.","commands":{"allow":[],"deny":["unlisten"]}}},"permission_sets":{},"global_scope_schema":null},"core:image":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-from-bytes","allow-from-path","allow-rgba","allow-size"]},"permissions":{"allow-from-bytes":{"identifier":"allow-from-bytes","description":"Enables the from_bytes command without any pre-configured scope.","commands":{"allow":["from_bytes"],"deny":[]}},"allow-from-path":{"identifier":"allow-from-path","description":"Enables the from_path command without any pre-configured scope.","commands":{"allow":["from_path"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-rgba":{"identifier":"allow-rgba","description":"Enables the rgba command without any pre-configured scope.","commands":{"allow":["rgba"],"deny":[]}},"allow-size":{"identifier":"allow-size","description":"Enables the size command without any pre-configured scope.","commands":{"allow":["size"],"deny":[]}},"deny-from-bytes":{"identifier":"deny-from-bytes","description":"Denies the from_bytes command without any pre-configured scope.","commands":{"allow":[],"deny":["from_bytes"]}},"deny-from-path":{"identifier":"deny-from-path","description":"Denies the from_path command without any pre-configured scope.","commands":{"allow":[],"deny":["from_path"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-rgba":{"identifier":"deny-rgba","description":"Denies the rgba command without any pre-configured scope.","commands":{"allow":[],"deny":["rgba"]}},"deny-size":{"identifier":"deny-size","description":"Denies the size command without any pre-configured scope.","commands":{"allow":[],"deny":["size"]}}},"permission_sets":{},"global_scope_schema":null},"core:menu":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-append","allow-prepend","allow-insert","allow-remove","allow-remove-at","allow-items","allow-get","allow-popup","allow-create-default","allow-set-as-app-menu","allow-set-as-window-menu","allow-text","allow-set-text","allow-is-enabled","allow-set-enabled","allow-set-accelerator","allow-set-as-windows-menu-for-nsapp","allow-set-as-help-menu-for-nsapp","allow-is-checked","allow-set-checked","allow-set-icon"]},"permissions":{"allow-append":{"identifier":"allow-append","description":"Enables the append command without any pre-configured scope.","commands":{"allow":["append"],"deny":[]}},"allow-create-default":{"identifier":"allow-create-default","description":"Enables the create_default command without any pre-configured scope.","commands":{"allow":["create_default"],"deny":[]}},"allow-get":{"identifier":"allow-get","description":"Enables the get command without any pre-configured scope.","commands":{"allow":["get"],"deny":[]}},"allow-insert":{"identifier":"allow-insert","description":"Enables the insert command without any pre-configured scope.","commands":{"allow":["insert"],"deny":[]}},"allow-is-checked":{"identifier":"allow-is-checked","description":"Enables the is_checked command without any pre-configured scope.","commands":{"allow":["is_checked"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-items":{"identifier":"allow-items","description":"Enables the items command without any pre-configured scope.","commands":{"allow":["items"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-popup":{"identifier":"allow-popup","description":"Enables the popup command without any pre-configured scope.","commands":{"allow":["popup"],"deny":[]}},"allow-prepend":{"identifier":"allow-prepend","description":"Enables the prepend command without any pre-configured scope.","commands":{"allow":["prepend"],"deny":[]}},"allow-remove":{"identifier":"allow-remove","description":"Enables the remove command without any pre-configured scope.","commands":{"allow":["remove"],"deny":[]}},"allow-remove-at":{"identifier":"allow-remove-at","description":"Enables the remove_at command without any pre-configured scope.","commands":{"allow":["remove_at"],"deny":[]}},"allow-set-accelerator":{"identifier":"allow-set-accelerator","description":"Enables the set_accelerator command without any pre-configured scope.","commands":{"allow":["set_accelerator"],"deny":[]}},"allow-set-as-app-menu":{"identifier":"allow-set-as-app-menu","description":"Enables the set_as_app_menu command without any pre-configured scope.","commands":{"allow":["set_as_app_menu"],"deny":[]}},"allow-set-as-help-menu-for-nsapp":{"identifier":"allow-set-as-help-menu-for-nsapp","description":"Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_help_menu_for_nsapp"],"deny":[]}},"allow-set-as-window-menu":{"identifier":"allow-set-as-window-menu","description":"Enables the set_as_window_menu command without any pre-configured scope.","commands":{"allow":["set_as_window_menu"],"deny":[]}},"allow-set-as-windows-menu-for-nsapp":{"identifier":"allow-set-as-windows-menu-for-nsapp","description":"Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_windows_menu_for_nsapp"],"deny":[]}},"allow-set-checked":{"identifier":"allow-set-checked","description":"Enables the set_checked command without any pre-configured scope.","commands":{"allow":["set_checked"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-text":{"identifier":"allow-set-text","description":"Enables the set_text command without any pre-configured scope.","commands":{"allow":["set_text"],"deny":[]}},"allow-text":{"identifier":"allow-text","description":"Enables the text command without any pre-configured scope.","commands":{"allow":["text"],"deny":[]}},"deny-append":{"identifier":"deny-append","description":"Denies the append command without any pre-configured scope.","commands":{"allow":[],"deny":["append"]}},"deny-create-default":{"identifier":"deny-create-default","description":"Denies the create_default command without any pre-configured scope.","commands":{"allow":[],"deny":["create_default"]}},"deny-get":{"identifier":"deny-get","description":"Denies the get command without any pre-configured scope.","commands":{"allow":[],"deny":["get"]}},"deny-insert":{"identifier":"deny-insert","description":"Denies the insert command without any pre-configured scope.","commands":{"allow":[],"deny":["insert"]}},"deny-is-checked":{"identifier":"deny-is-checked","description":"Denies the is_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["is_checked"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-items":{"identifier":"deny-items","description":"Denies the items command without any pre-configured scope.","commands":{"allow":[],"deny":["items"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-popup":{"identifier":"deny-popup","description":"Denies the popup command without any pre-configured scope.","commands":{"allow":[],"deny":["popup"]}},"deny-prepend":{"identifier":"deny-prepend","description":"Denies the prepend command without any pre-configured scope.","commands":{"allow":[],"deny":["prepend"]}},"deny-remove":{"identifier":"deny-remove","description":"Denies the remove command without any pre-configured scope.","commands":{"allow":[],"deny":["remove"]}},"deny-remove-at":{"identifier":"deny-remove-at","description":"Denies the remove_at command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_at"]}},"deny-set-accelerator":{"identifier":"deny-set-accelerator","description":"Denies the set_accelerator command without any pre-configured scope.","commands":{"allow":[],"deny":["set_accelerator"]}},"deny-set-as-app-menu":{"identifier":"deny-set-as-app-menu","description":"Denies the set_as_app_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_app_menu"]}},"deny-set-as-help-menu-for-nsapp":{"identifier":"deny-set-as-help-menu-for-nsapp","description":"Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_help_menu_for_nsapp"]}},"deny-set-as-window-menu":{"identifier":"deny-set-as-window-menu","description":"Denies the set_as_window_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_window_menu"]}},"deny-set-as-windows-menu-for-nsapp":{"identifier":"deny-set-as-windows-menu-for-nsapp","description":"Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_windows_menu_for_nsapp"]}},"deny-set-checked":{"identifier":"deny-set-checked","description":"Denies the set_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["set_checked"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-text":{"identifier":"deny-set-text","description":"Denies the set_text command without any pre-configured scope.","commands":{"allow":[],"deny":["set_text"]}},"deny-text":{"identifier":"deny-text","description":"Denies the text command without any pre-configured scope.","commands":{"allow":[],"deny":["text"]}}},"permission_sets":{},"global_scope_schema":null},"core:path":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-resolve-directory","allow-resolve","allow-normalize","allow-join","allow-dirname","allow-extname","allow-basename","allow-is-absolute"]},"permissions":{"allow-basename":{"identifier":"allow-basename","description":"Enables the basename command without any pre-configured scope.","commands":{"allow":["basename"],"deny":[]}},"allow-dirname":{"identifier":"allow-dirname","description":"Enables the dirname command without any pre-configured scope.","commands":{"allow":["dirname"],"deny":[]}},"allow-extname":{"identifier":"allow-extname","description":"Enables the extname command without any pre-configured scope.","commands":{"allow":["extname"],"deny":[]}},"allow-is-absolute":{"identifier":"allow-is-absolute","description":"Enables the is_absolute command without any pre-configured scope.","commands":{"allow":["is_absolute"],"deny":[]}},"allow-join":{"identifier":"allow-join","description":"Enables the join command without any pre-configured scope.","commands":{"allow":["join"],"deny":[]}},"allow-normalize":{"identifier":"allow-normalize","description":"Enables the normalize command without any pre-configured scope.","commands":{"allow":["normalize"],"deny":[]}},"allow-resolve":{"identifier":"allow-resolve","description":"Enables the resolve command without any pre-configured scope.","commands":{"allow":["resolve"],"deny":[]}},"allow-resolve-directory":{"identifier":"allow-resolve-directory","description":"Enables the resolve_directory command without any pre-configured scope.","commands":{"allow":["resolve_directory"],"deny":[]}},"deny-basename":{"identifier":"deny-basename","description":"Denies the basename command without any pre-configured scope.","commands":{"allow":[],"deny":["basename"]}},"deny-dirname":{"identifier":"deny-dirname","description":"Denies the dirname command without any pre-configured scope.","commands":{"allow":[],"deny":["dirname"]}},"deny-extname":{"identifier":"deny-extname","description":"Denies the extname command without any pre-configured scope.","commands":{"allow":[],"deny":["extname"]}},"deny-is-absolute":{"identifier":"deny-is-absolute","description":"Denies the is_absolute command without any pre-configured scope.","commands":{"allow":[],"deny":["is_absolute"]}},"deny-join":{"identifier":"deny-join","description":"Denies the join command without any pre-configured scope.","commands":{"allow":[],"deny":["join"]}},"deny-normalize":{"identifier":"deny-normalize","description":"Denies the normalize command without any pre-configured scope.","commands":{"allow":[],"deny":["normalize"]}},"deny-resolve":{"identifier":"deny-resolve","description":"Denies the resolve command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve"]}},"deny-resolve-directory":{"identifier":"deny-resolve-directory","description":"Denies the resolve_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_directory"]}}},"permission_sets":{},"global_scope_schema":null},"core:resources":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-close"]},"permissions":{"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}}},"permission_sets":{},"global_scope_schema":null},"core:tray":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-get-by-id","allow-remove-by-id","allow-set-icon","allow-set-menu","allow-set-tooltip","allow-set-title","allow-set-visible","allow-set-temp-dir-path","allow-set-icon-as-template","allow-set-icon-with-as-template","allow-set-show-menu-on-left-click"]},"permissions":{"allow-get-by-id":{"identifier":"allow-get-by-id","description":"Enables the get_by_id command without any pre-configured scope.","commands":{"allow":["get_by_id"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-remove-by-id":{"identifier":"allow-remove-by-id","description":"Enables the remove_by_id command without any pre-configured scope.","commands":{"allow":["remove_by_id"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-icon-as-template":{"identifier":"allow-set-icon-as-template","description":"Enables the set_icon_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_as_template"],"deny":[]}},"allow-set-icon-with-as-template":{"identifier":"allow-set-icon-with-as-template","description":"Enables the set_icon_with_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_with_as_template"],"deny":[]}},"allow-set-menu":{"identifier":"allow-set-menu","description":"Enables the set_menu command without any pre-configured scope.","commands":{"allow":["set_menu"],"deny":[]}},"allow-set-show-menu-on-left-click":{"identifier":"allow-set-show-menu-on-left-click","description":"Enables the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":["set_show_menu_on_left_click"],"deny":[]}},"allow-set-temp-dir-path":{"identifier":"allow-set-temp-dir-path","description":"Enables the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":["set_temp_dir_path"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-tooltip":{"identifier":"allow-set-tooltip","description":"Enables the set_tooltip command without any pre-configured scope.","commands":{"allow":["set_tooltip"],"deny":[]}},"allow-set-visible":{"identifier":"allow-set-visible","description":"Enables the set_visible command without any pre-configured scope.","commands":{"allow":["set_visible"],"deny":[]}},"deny-get-by-id":{"identifier":"deny-get-by-id","description":"Denies the get_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["get_by_id"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-remove-by-id":{"identifier":"deny-remove-by-id","description":"Denies the remove_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_by_id"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-icon-as-template":{"identifier":"deny-set-icon-as-template","description":"Denies the set_icon_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_as_template"]}},"deny-set-icon-with-as-template":{"identifier":"deny-set-icon-with-as-template","description":"Denies the set_icon_with_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_with_as_template"]}},"deny-set-menu":{"identifier":"deny-set-menu","description":"Denies the set_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_menu"]}},"deny-set-show-menu-on-left-click":{"identifier":"deny-set-show-menu-on-left-click","description":"Denies the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":[],"deny":["set_show_menu_on_left_click"]}},"deny-set-temp-dir-path":{"identifier":"deny-set-temp-dir-path","description":"Denies the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":[],"deny":["set_temp_dir_path"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-tooltip":{"identifier":"deny-set-tooltip","description":"Denies the set_tooltip command without any pre-configured scope.","commands":{"allow":[],"deny":["set_tooltip"]}},"deny-set-visible":{"identifier":"deny-set-visible","description":"Denies the set_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible"]}}},"permission_sets":{},"global_scope_schema":null},"core:webview":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-webviews","allow-webview-position","allow-webview-size","allow-internal-toggle-devtools"]},"permissions":{"allow-clear-all-browsing-data":{"identifier":"allow-clear-all-browsing-data","description":"Enables the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":["clear_all_browsing_data"],"deny":[]}},"allow-create-webview":{"identifier":"allow-create-webview","description":"Enables the create_webview command without any pre-configured scope.","commands":{"allow":["create_webview"],"deny":[]}},"allow-create-webview-window":{"identifier":"allow-create-webview-window","description":"Enables the create_webview_window command without any pre-configured scope.","commands":{"allow":["create_webview_window"],"deny":[]}},"allow-get-all-webviews":{"identifier":"allow-get-all-webviews","description":"Enables the get_all_webviews command without any pre-configured scope.","commands":{"allow":["get_all_webviews"],"deny":[]}},"allow-internal-toggle-devtools":{"identifier":"allow-internal-toggle-devtools","description":"Enables the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":["internal_toggle_devtools"],"deny":[]}},"allow-print":{"identifier":"allow-print","description":"Enables the print command without any pre-configured scope.","commands":{"allow":["print"],"deny":[]}},"allow-reparent":{"identifier":"allow-reparent","description":"Enables the reparent command without any pre-configured scope.","commands":{"allow":["reparent"],"deny":[]}},"allow-set-webview-auto-resize":{"identifier":"allow-set-webview-auto-resize","description":"Enables the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":["set_webview_auto_resize"],"deny":[]}},"allow-set-webview-background-color":{"identifier":"allow-set-webview-background-color","description":"Enables the set_webview_background_color command without any pre-configured scope.","commands":{"allow":["set_webview_background_color"],"deny":[]}},"allow-set-webview-focus":{"identifier":"allow-set-webview-focus","description":"Enables the set_webview_focus command without any pre-configured scope.","commands":{"allow":["set_webview_focus"],"deny":[]}},"allow-set-webview-position":{"identifier":"allow-set-webview-position","description":"Enables the set_webview_position command without any pre-configured scope.","commands":{"allow":["set_webview_position"],"deny":[]}},"allow-set-webview-size":{"identifier":"allow-set-webview-size","description":"Enables the set_webview_size command without any pre-configured scope.","commands":{"allow":["set_webview_size"],"deny":[]}},"allow-set-webview-zoom":{"identifier":"allow-set-webview-zoom","description":"Enables the set_webview_zoom command without any pre-configured scope.","commands":{"allow":["set_webview_zoom"],"deny":[]}},"allow-webview-close":{"identifier":"allow-webview-close","description":"Enables the webview_close command without any pre-configured scope.","commands":{"allow":["webview_close"],"deny":[]}},"allow-webview-hide":{"identifier":"allow-webview-hide","description":"Enables the webview_hide command without any pre-configured scope.","commands":{"allow":["webview_hide"],"deny":[]}},"allow-webview-position":{"identifier":"allow-webview-position","description":"Enables the webview_position command without any pre-configured scope.","commands":{"allow":["webview_position"],"deny":[]}},"allow-webview-show":{"identifier":"allow-webview-show","description":"Enables the webview_show command without any pre-configured scope.","commands":{"allow":["webview_show"],"deny":[]}},"allow-webview-size":{"identifier":"allow-webview-size","description":"Enables the webview_size command without any pre-configured scope.","commands":{"allow":["webview_size"],"deny":[]}},"deny-clear-all-browsing-data":{"identifier":"deny-clear-all-browsing-data","description":"Denies the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":[],"deny":["clear_all_browsing_data"]}},"deny-create-webview":{"identifier":"deny-create-webview","description":"Denies the create_webview command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview"]}},"deny-create-webview-window":{"identifier":"deny-create-webview-window","description":"Denies the create_webview_window command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview_window"]}},"deny-get-all-webviews":{"identifier":"deny-get-all-webviews","description":"Denies the get_all_webviews command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_webviews"]}},"deny-internal-toggle-devtools":{"identifier":"deny-internal-toggle-devtools","description":"Denies the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_devtools"]}},"deny-print":{"identifier":"deny-print","description":"Denies the print command without any pre-configured scope.","commands":{"allow":[],"deny":["print"]}},"deny-reparent":{"identifier":"deny-reparent","description":"Denies the reparent command without any pre-configured scope.","commands":{"allow":[],"deny":["reparent"]}},"deny-set-webview-auto-resize":{"identifier":"deny-set-webview-auto-resize","description":"Denies the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_auto_resize"]}},"deny-set-webview-background-color":{"identifier":"deny-set-webview-background-color","description":"Denies the set_webview_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_background_color"]}},"deny-set-webview-focus":{"identifier":"deny-set-webview-focus","description":"Denies the set_webview_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_focus"]}},"deny-set-webview-position":{"identifier":"deny-set-webview-position","description":"Denies the set_webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_position"]}},"deny-set-webview-size":{"identifier":"deny-set-webview-size","description":"Denies the set_webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_size"]}},"deny-set-webview-zoom":{"identifier":"deny-set-webview-zoom","description":"Denies the set_webview_zoom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_zoom"]}},"deny-webview-close":{"identifier":"deny-webview-close","description":"Denies the webview_close command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_close"]}},"deny-webview-hide":{"identifier":"deny-webview-hide","description":"Denies the webview_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_hide"]}},"deny-webview-position":{"identifier":"deny-webview-position","description":"Denies the webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_position"]}},"deny-webview-show":{"identifier":"deny-webview-show","description":"Denies the webview_show command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_show"]}},"deny-webview-size":{"identifier":"deny-webview-size","description":"Denies the webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_size"]}}},"permission_sets":{},"global_scope_schema":null},"core:window":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-windows","allow-scale-factor","allow-inner-position","allow-outer-position","allow-inner-size","allow-outer-size","allow-is-fullscreen","allow-is-minimized","allow-is-maximized","allow-is-focused","allow-is-decorated","allow-is-resizable","allow-is-maximizable","allow-is-minimizable","allow-is-closable","allow-is-visible","allow-is-enabled","allow-title","allow-current-monitor","allow-primary-monitor","allow-monitor-from-point","allow-available-monitors","allow-cursor-position","allow-theme","allow-is-always-on-top","allow-activity-name","allow-scene-identifier","allow-internal-toggle-maximize"]},"permissions":{"allow-activity-name":{"identifier":"allow-activity-name","description":"Enables the activity_name command without any pre-configured scope.","commands":{"allow":["activity_name"],"deny":[]}},"allow-available-monitors":{"identifier":"allow-available-monitors","description":"Enables the available_monitors command without any pre-configured scope.","commands":{"allow":["available_monitors"],"deny":[]}},"allow-center":{"identifier":"allow-center","description":"Enables the center command without any pre-configured scope.","commands":{"allow":["center"],"deny":[]}},"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"allow-create":{"identifier":"allow-create","description":"Enables the create command without any pre-configured scope.","commands":{"allow":["create"],"deny":[]}},"allow-current-monitor":{"identifier":"allow-current-monitor","description":"Enables the current_monitor command without any pre-configured scope.","commands":{"allow":["current_monitor"],"deny":[]}},"allow-cursor-position":{"identifier":"allow-cursor-position","description":"Enables the cursor_position command without any pre-configured scope.","commands":{"allow":["cursor_position"],"deny":[]}},"allow-destroy":{"identifier":"allow-destroy","description":"Enables the destroy command without any pre-configured scope.","commands":{"allow":["destroy"],"deny":[]}},"allow-get-all-windows":{"identifier":"allow-get-all-windows","description":"Enables the get_all_windows command without any pre-configured scope.","commands":{"allow":["get_all_windows"],"deny":[]}},"allow-hide":{"identifier":"allow-hide","description":"Enables the hide command without any pre-configured scope.","commands":{"allow":["hide"],"deny":[]}},"allow-inner-position":{"identifier":"allow-inner-position","description":"Enables the inner_position command without any pre-configured scope.","commands":{"allow":["inner_position"],"deny":[]}},"allow-inner-size":{"identifier":"allow-inner-size","description":"Enables the inner_size command without any pre-configured scope.","commands":{"allow":["inner_size"],"deny":[]}},"allow-internal-toggle-maximize":{"identifier":"allow-internal-toggle-maximize","description":"Enables the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":["internal_toggle_maximize"],"deny":[]}},"allow-is-always-on-top":{"identifier":"allow-is-always-on-top","description":"Enables the is_always_on_top command without any pre-configured scope.","commands":{"allow":["is_always_on_top"],"deny":[]}},"allow-is-closable":{"identifier":"allow-is-closable","description":"Enables the is_closable command without any pre-configured scope.","commands":{"allow":["is_closable"],"deny":[]}},"allow-is-decorated":{"identifier":"allow-is-decorated","description":"Enables the is_decorated command without any pre-configured scope.","commands":{"allow":["is_decorated"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-is-focused":{"identifier":"allow-is-focused","description":"Enables the is_focused command without any pre-configured scope.","commands":{"allow":["is_focused"],"deny":[]}},"allow-is-fullscreen":{"identifier":"allow-is-fullscreen","description":"Enables the is_fullscreen command without any pre-configured scope.","commands":{"allow":["is_fullscreen"],"deny":[]}},"allow-is-maximizable":{"identifier":"allow-is-maximizable","description":"Enables the is_maximizable command without any pre-configured scope.","commands":{"allow":["is_maximizable"],"deny":[]}},"allow-is-maximized":{"identifier":"allow-is-maximized","description":"Enables the is_maximized command without any pre-configured scope.","commands":{"allow":["is_maximized"],"deny":[]}},"allow-is-minimizable":{"identifier":"allow-is-minimizable","description":"Enables the is_minimizable command without any pre-configured scope.","commands":{"allow":["is_minimizable"],"deny":[]}},"allow-is-minimized":{"identifier":"allow-is-minimized","description":"Enables the is_minimized command without any pre-configured scope.","commands":{"allow":["is_minimized"],"deny":[]}},"allow-is-resizable":{"identifier":"allow-is-resizable","description":"Enables the is_resizable command without any pre-configured scope.","commands":{"allow":["is_resizable"],"deny":[]}},"allow-is-visible":{"identifier":"allow-is-visible","description":"Enables the is_visible command without any pre-configured scope.","commands":{"allow":["is_visible"],"deny":[]}},"allow-maximize":{"identifier":"allow-maximize","description":"Enables the maximize command without any pre-configured scope.","commands":{"allow":["maximize"],"deny":[]}},"allow-minimize":{"identifier":"allow-minimize","description":"Enables the minimize command without any pre-configured scope.","commands":{"allow":["minimize"],"deny":[]}},"allow-monitor-from-point":{"identifier":"allow-monitor-from-point","description":"Enables the monitor_from_point command without any pre-configured scope.","commands":{"allow":["monitor_from_point"],"deny":[]}},"allow-outer-position":{"identifier":"allow-outer-position","description":"Enables the outer_position command without any pre-configured scope.","commands":{"allow":["outer_position"],"deny":[]}},"allow-outer-size":{"identifier":"allow-outer-size","description":"Enables the outer_size command without any pre-configured scope.","commands":{"allow":["outer_size"],"deny":[]}},"allow-primary-monitor":{"identifier":"allow-primary-monitor","description":"Enables the primary_monitor command without any pre-configured scope.","commands":{"allow":["primary_monitor"],"deny":[]}},"allow-request-user-attention":{"identifier":"allow-request-user-attention","description":"Enables the request_user_attention command without any pre-configured scope.","commands":{"allow":["request_user_attention"],"deny":[]}},"allow-scale-factor":{"identifier":"allow-scale-factor","description":"Enables the scale_factor command without any pre-configured scope.","commands":{"allow":["scale_factor"],"deny":[]}},"allow-scene-identifier":{"identifier":"allow-scene-identifier","description":"Enables the scene_identifier command without any pre-configured scope.","commands":{"allow":["scene_identifier"],"deny":[]}},"allow-set-always-on-bottom":{"identifier":"allow-set-always-on-bottom","description":"Enables the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":["set_always_on_bottom"],"deny":[]}},"allow-set-always-on-top":{"identifier":"allow-set-always-on-top","description":"Enables the set_always_on_top command without any pre-configured scope.","commands":{"allow":["set_always_on_top"],"deny":[]}},"allow-set-background-color":{"identifier":"allow-set-background-color","description":"Enables the set_background_color command without any pre-configured scope.","commands":{"allow":["set_background_color"],"deny":[]}},"allow-set-badge-count":{"identifier":"allow-set-badge-count","description":"Enables the set_badge_count command without any pre-configured scope.","commands":{"allow":["set_badge_count"],"deny":[]}},"allow-set-badge-label":{"identifier":"allow-set-badge-label","description":"Enables the set_badge_label command without any pre-configured scope.","commands":{"allow":["set_badge_label"],"deny":[]}},"allow-set-closable":{"identifier":"allow-set-closable","description":"Enables the set_closable command without any pre-configured scope.","commands":{"allow":["set_closable"],"deny":[]}},"allow-set-content-protected":{"identifier":"allow-set-content-protected","description":"Enables the set_content_protected command without any pre-configured scope.","commands":{"allow":["set_content_protected"],"deny":[]}},"allow-set-cursor-grab":{"identifier":"allow-set-cursor-grab","description":"Enables the set_cursor_grab command without any pre-configured scope.","commands":{"allow":["set_cursor_grab"],"deny":[]}},"allow-set-cursor-icon":{"identifier":"allow-set-cursor-icon","description":"Enables the set_cursor_icon command without any pre-configured scope.","commands":{"allow":["set_cursor_icon"],"deny":[]}},"allow-set-cursor-position":{"identifier":"allow-set-cursor-position","description":"Enables the set_cursor_position command without any pre-configured scope.","commands":{"allow":["set_cursor_position"],"deny":[]}},"allow-set-cursor-visible":{"identifier":"allow-set-cursor-visible","description":"Enables the set_cursor_visible command without any pre-configured scope.","commands":{"allow":["set_cursor_visible"],"deny":[]}},"allow-set-decorations":{"identifier":"allow-set-decorations","description":"Enables the set_decorations command without any pre-configured scope.","commands":{"allow":["set_decorations"],"deny":[]}},"allow-set-effects":{"identifier":"allow-set-effects","description":"Enables the set_effects command without any pre-configured scope.","commands":{"allow":["set_effects"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-focus":{"identifier":"allow-set-focus","description":"Enables the set_focus command without any pre-configured scope.","commands":{"allow":["set_focus"],"deny":[]}},"allow-set-focusable":{"identifier":"allow-set-focusable","description":"Enables the set_focusable command without any pre-configured scope.","commands":{"allow":["set_focusable"],"deny":[]}},"allow-set-fullscreen":{"identifier":"allow-set-fullscreen","description":"Enables the set_fullscreen command without any pre-configured scope.","commands":{"allow":["set_fullscreen"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-ignore-cursor-events":{"identifier":"allow-set-ignore-cursor-events","description":"Enables the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":["set_ignore_cursor_events"],"deny":[]}},"allow-set-max-size":{"identifier":"allow-set-max-size","description":"Enables the set_max_size command without any pre-configured scope.","commands":{"allow":["set_max_size"],"deny":[]}},"allow-set-maximizable":{"identifier":"allow-set-maximizable","description":"Enables the set_maximizable command without any pre-configured scope.","commands":{"allow":["set_maximizable"],"deny":[]}},"allow-set-min-size":{"identifier":"allow-set-min-size","description":"Enables the set_min_size command without any pre-configured scope.","commands":{"allow":["set_min_size"],"deny":[]}},"allow-set-minimizable":{"identifier":"allow-set-minimizable","description":"Enables the set_minimizable command without any pre-configured scope.","commands":{"allow":["set_minimizable"],"deny":[]}},"allow-set-overlay-icon":{"identifier":"allow-set-overlay-icon","description":"Enables the set_overlay_icon command without any pre-configured scope.","commands":{"allow":["set_overlay_icon"],"deny":[]}},"allow-set-position":{"identifier":"allow-set-position","description":"Enables the set_position command without any pre-configured scope.","commands":{"allow":["set_position"],"deny":[]}},"allow-set-progress-bar":{"identifier":"allow-set-progress-bar","description":"Enables the set_progress_bar command without any pre-configured scope.","commands":{"allow":["set_progress_bar"],"deny":[]}},"allow-set-resizable":{"identifier":"allow-set-resizable","description":"Enables the set_resizable command without any pre-configured scope.","commands":{"allow":["set_resizable"],"deny":[]}},"allow-set-shadow":{"identifier":"allow-set-shadow","description":"Enables the set_shadow command without any pre-configured scope.","commands":{"allow":["set_shadow"],"deny":[]}},"allow-set-simple-fullscreen":{"identifier":"allow-set-simple-fullscreen","description":"Enables the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":["set_simple_fullscreen"],"deny":[]}},"allow-set-size":{"identifier":"allow-set-size","description":"Enables the set_size command without any pre-configured scope.","commands":{"allow":["set_size"],"deny":[]}},"allow-set-size-constraints":{"identifier":"allow-set-size-constraints","description":"Enables the set_size_constraints command without any pre-configured scope.","commands":{"allow":["set_size_constraints"],"deny":[]}},"allow-set-skip-taskbar":{"identifier":"allow-set-skip-taskbar","description":"Enables the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":["set_skip_taskbar"],"deny":[]}},"allow-set-theme":{"identifier":"allow-set-theme","description":"Enables the set_theme command without any pre-configured scope.","commands":{"allow":["set_theme"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-title-bar-style":{"identifier":"allow-set-title-bar-style","description":"Enables the set_title_bar_style command without any pre-configured scope.","commands":{"allow":["set_title_bar_style"],"deny":[]}},"allow-set-visible-on-all-workspaces":{"identifier":"allow-set-visible-on-all-workspaces","description":"Enables the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":["set_visible_on_all_workspaces"],"deny":[]}},"allow-show":{"identifier":"allow-show","description":"Enables the show command without any pre-configured scope.","commands":{"allow":["show"],"deny":[]}},"allow-start-dragging":{"identifier":"allow-start-dragging","description":"Enables the start_dragging command without any pre-configured scope.","commands":{"allow":["start_dragging"],"deny":[]}},"allow-start-resize-dragging":{"identifier":"allow-start-resize-dragging","description":"Enables the start_resize_dragging command without any pre-configured scope.","commands":{"allow":["start_resize_dragging"],"deny":[]}},"allow-theme":{"identifier":"allow-theme","description":"Enables the theme command without any pre-configured scope.","commands":{"allow":["theme"],"deny":[]}},"allow-title":{"identifier":"allow-title","description":"Enables the title command without any pre-configured scope.","commands":{"allow":["title"],"deny":[]}},"allow-toggle-maximize":{"identifier":"allow-toggle-maximize","description":"Enables the toggle_maximize command without any pre-configured scope.","commands":{"allow":["toggle_maximize"],"deny":[]}},"allow-unmaximize":{"identifier":"allow-unmaximize","description":"Enables the unmaximize command without any pre-configured scope.","commands":{"allow":["unmaximize"],"deny":[]}},"allow-unminimize":{"identifier":"allow-unminimize","description":"Enables the unminimize command without any pre-configured scope.","commands":{"allow":["unminimize"],"deny":[]}},"deny-activity-name":{"identifier":"deny-activity-name","description":"Denies the activity_name command without any pre-configured scope.","commands":{"allow":[],"deny":["activity_name"]}},"deny-available-monitors":{"identifier":"deny-available-monitors","description":"Denies the available_monitors command without any pre-configured scope.","commands":{"allow":[],"deny":["available_monitors"]}},"deny-center":{"identifier":"deny-center","description":"Denies the center command without any pre-configured scope.","commands":{"allow":[],"deny":["center"]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}},"deny-create":{"identifier":"deny-create","description":"Denies the create command without any pre-configured scope.","commands":{"allow":[],"deny":["create"]}},"deny-current-monitor":{"identifier":"deny-current-monitor","description":"Denies the current_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["current_monitor"]}},"deny-cursor-position":{"identifier":"deny-cursor-position","description":"Denies the cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["cursor_position"]}},"deny-destroy":{"identifier":"deny-destroy","description":"Denies the destroy command without any pre-configured scope.","commands":{"allow":[],"deny":["destroy"]}},"deny-get-all-windows":{"identifier":"deny-get-all-windows","description":"Denies the get_all_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_windows"]}},"deny-hide":{"identifier":"deny-hide","description":"Denies the hide command without any pre-configured scope.","commands":{"allow":[],"deny":["hide"]}},"deny-inner-position":{"identifier":"deny-inner-position","description":"Denies the inner_position command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_position"]}},"deny-inner-size":{"identifier":"deny-inner-size","description":"Denies the inner_size command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_size"]}},"deny-internal-toggle-maximize":{"identifier":"deny-internal-toggle-maximize","description":"Denies the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_maximize"]}},"deny-is-always-on-top":{"identifier":"deny-is-always-on-top","description":"Denies the is_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["is_always_on_top"]}},"deny-is-closable":{"identifier":"deny-is-closable","description":"Denies the is_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_closable"]}},"deny-is-decorated":{"identifier":"deny-is-decorated","description":"Denies the is_decorated command without any pre-configured scope.","commands":{"allow":[],"deny":["is_decorated"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-is-focused":{"identifier":"deny-is-focused","description":"Denies the is_focused command without any pre-configured scope.","commands":{"allow":[],"deny":["is_focused"]}},"deny-is-fullscreen":{"identifier":"deny-is-fullscreen","description":"Denies the is_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["is_fullscreen"]}},"deny-is-maximizable":{"identifier":"deny-is-maximizable","description":"Denies the is_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximizable"]}},"deny-is-maximized":{"identifier":"deny-is-maximized","description":"Denies the is_maximized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximized"]}},"deny-is-minimizable":{"identifier":"deny-is-minimizable","description":"Denies the is_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimizable"]}},"deny-is-minimized":{"identifier":"deny-is-minimized","description":"Denies the is_minimized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimized"]}},"deny-is-resizable":{"identifier":"deny-is-resizable","description":"Denies the is_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_resizable"]}},"deny-is-visible":{"identifier":"deny-is-visible","description":"Denies the is_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["is_visible"]}},"deny-maximize":{"identifier":"deny-maximize","description":"Denies the maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["maximize"]}},"deny-minimize":{"identifier":"deny-minimize","description":"Denies the minimize command without any pre-configured scope.","commands":{"allow":[],"deny":["minimize"]}},"deny-monitor-from-point":{"identifier":"deny-monitor-from-point","description":"Denies the monitor_from_point command without any pre-configured scope.","commands":{"allow":[],"deny":["monitor_from_point"]}},"deny-outer-position":{"identifier":"deny-outer-position","description":"Denies the outer_position command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_position"]}},"deny-outer-size":{"identifier":"deny-outer-size","description":"Denies the outer_size command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_size"]}},"deny-primary-monitor":{"identifier":"deny-primary-monitor","description":"Denies the primary_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["primary_monitor"]}},"deny-request-user-attention":{"identifier":"deny-request-user-attention","description":"Denies the request_user_attention command without any pre-configured scope.","commands":{"allow":[],"deny":["request_user_attention"]}},"deny-scale-factor":{"identifier":"deny-scale-factor","description":"Denies the scale_factor command without any pre-configured scope.","commands":{"allow":[],"deny":["scale_factor"]}},"deny-scene-identifier":{"identifier":"deny-scene-identifier","description":"Denies the scene_identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["scene_identifier"]}},"deny-set-always-on-bottom":{"identifier":"deny-set-always-on-bottom","description":"Denies the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_bottom"]}},"deny-set-always-on-top":{"identifier":"deny-set-always-on-top","description":"Denies the set_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_top"]}},"deny-set-background-color":{"identifier":"deny-set-background-color","description":"Denies the set_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_background_color"]}},"deny-set-badge-count":{"identifier":"deny-set-badge-count","description":"Denies the set_badge_count command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_count"]}},"deny-set-badge-label":{"identifier":"deny-set-badge-label","description":"Denies the set_badge_label command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_label"]}},"deny-set-closable":{"identifier":"deny-set-closable","description":"Denies the set_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_closable"]}},"deny-set-content-protected":{"identifier":"deny-set-content-protected","description":"Denies the set_content_protected command without any pre-configured scope.","commands":{"allow":[],"deny":["set_content_protected"]}},"deny-set-cursor-grab":{"identifier":"deny-set-cursor-grab","description":"Denies the set_cursor_grab command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_grab"]}},"deny-set-cursor-icon":{"identifier":"deny-set-cursor-icon","description":"Denies the set_cursor_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_icon"]}},"deny-set-cursor-position":{"identifier":"deny-set-cursor-position","description":"Denies the set_cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_position"]}},"deny-set-cursor-visible":{"identifier":"deny-set-cursor-visible","description":"Denies the set_cursor_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_visible"]}},"deny-set-decorations":{"identifier":"deny-set-decorations","description":"Denies the set_decorations command without any pre-configured scope.","commands":{"allow":[],"deny":["set_decorations"]}},"deny-set-effects":{"identifier":"deny-set-effects","description":"Denies the set_effects command without any pre-configured scope.","commands":{"allow":[],"deny":["set_effects"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-focus":{"identifier":"deny-set-focus","description":"Denies the set_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focus"]}},"deny-set-focusable":{"identifier":"deny-set-focusable","description":"Denies the set_focusable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focusable"]}},"deny-set-fullscreen":{"identifier":"deny-set-fullscreen","description":"Denies the set_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_fullscreen"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-ignore-cursor-events":{"identifier":"deny-set-ignore-cursor-events","description":"Denies the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":[],"deny":["set_ignore_cursor_events"]}},"deny-set-max-size":{"identifier":"deny-set-max-size","description":"Denies the set_max_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_max_size"]}},"deny-set-maximizable":{"identifier":"deny-set-maximizable","description":"Denies the set_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_maximizable"]}},"deny-set-min-size":{"identifier":"deny-set-min-size","description":"Denies the set_min_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_min_size"]}},"deny-set-minimizable":{"identifier":"deny-set-minimizable","description":"Denies the set_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_minimizable"]}},"deny-set-overlay-icon":{"identifier":"deny-set-overlay-icon","description":"Denies the set_overlay_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_overlay_icon"]}},"deny-set-position":{"identifier":"deny-set-position","description":"Denies the set_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_position"]}},"deny-set-progress-bar":{"identifier":"deny-set-progress-bar","description":"Denies the set_progress_bar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_progress_bar"]}},"deny-set-resizable":{"identifier":"deny-set-resizable","description":"Denies the set_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_resizable"]}},"deny-set-shadow":{"identifier":"deny-set-shadow","description":"Denies the set_shadow command without any pre-configured scope.","commands":{"allow":[],"deny":["set_shadow"]}},"deny-set-simple-fullscreen":{"identifier":"deny-set-simple-fullscreen","description":"Denies the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_simple_fullscreen"]}},"deny-set-size":{"identifier":"deny-set-size","description":"Denies the set_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size"]}},"deny-set-size-constraints":{"identifier":"deny-set-size-constraints","description":"Denies the set_size_constraints command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size_constraints"]}},"deny-set-skip-taskbar":{"identifier":"deny-set-skip-taskbar","description":"Denies the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_skip_taskbar"]}},"deny-set-theme":{"identifier":"deny-set-theme","description":"Denies the set_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_theme"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-title-bar-style":{"identifier":"deny-set-title-bar-style","description":"Denies the set_title_bar_style command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title_bar_style"]}},"deny-set-visible-on-all-workspaces":{"identifier":"deny-set-visible-on-all-workspaces","description":"Denies the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible_on_all_workspaces"]}},"deny-show":{"identifier":"deny-show","description":"Denies the show command without any pre-configured scope.","commands":{"allow":[],"deny":["show"]}},"deny-start-dragging":{"identifier":"deny-start-dragging","description":"Denies the start_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_dragging"]}},"deny-start-resize-dragging":{"identifier":"deny-start-resize-dragging","description":"Denies the start_resize_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_resize_dragging"]}},"deny-theme":{"identifier":"deny-theme","description":"Denies the theme command without any pre-configured scope.","commands":{"allow":[],"deny":["theme"]}},"deny-title":{"identifier":"deny-title","description":"Denies the title command without any pre-configured scope.","commands":{"allow":[],"deny":["title"]}},"deny-toggle-maximize":{"identifier":"deny-toggle-maximize","description":"Denies the toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["toggle_maximize"]}},"deny-unmaximize":{"identifier":"deny-unmaximize","description":"Denies the unmaximize command without any pre-configured scope.","commands":{"allow":[],"deny":["unmaximize"]}},"deny-unminimize":{"identifier":"deny-unminimize","description":"Denies the unminimize command without any pre-configured scope.","commands":{"allow":[],"deny":["unminimize"]}}},"permission_sets":{},"global_scope_schema":null},"dialog":{"default_permission":{"identifier":"default","description":"This permission set configures the types of dialogs\navailable from the dialog plugin.\n\n#### Granted Permissions\n\nAll dialog types are enabled.\n\n\n","permissions":["allow-message","allow-save","allow-open"]},"permissions":{"allow-ask":{"identifier":"allow-ask","description":"Enables the ask command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `allow-message` and will be removed in v3)","commands":{"allow":["message"],"deny":[]}},"allow-confirm":{"identifier":"allow-confirm","description":"Enables the confirm command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `allow-message` and will be removed in v3)","commands":{"allow":["message"],"deny":[]}},"allow-message":{"identifier":"allow-message","description":"Enables the message command without any pre-configured scope.","commands":{"allow":["message"],"deny":[]}},"allow-open":{"identifier":"allow-open","description":"Enables the open command without any pre-configured scope.","commands":{"allow":["open"],"deny":[]}},"allow-save":{"identifier":"allow-save","description":"Enables the save command without any pre-configured scope.","commands":{"allow":["save"],"deny":[]}},"deny-ask":{"identifier":"deny-ask","description":"Denies the ask command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `deny-message` and will be removed in v3)","commands":{"allow":[],"deny":["message"]}},"deny-confirm":{"identifier":"deny-confirm","description":"Denies the confirm command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `deny-message` and will be removed in v3)","commands":{"allow":[],"deny":["message"]}},"deny-message":{"identifier":"deny-message","description":"Denies the message command without any pre-configured scope.","commands":{"allow":[],"deny":["message"]}},"deny-open":{"identifier":"deny-open","description":"Denies the open command without any pre-configured scope.","commands":{"allow":[],"deny":["open"]}},"deny-save":{"identifier":"deny-save","description":"Denies the save command without any pre-configured scope.","commands":{"allow":[],"deny":["save"]}}},"permission_sets":{},"global_scope_schema":null},"notification":{"default_permission":{"identifier":"default","description":"This permission set configures which\nnotification features are by default exposed.\n\n#### Granted Permissions\n\nIt allows all notification related features.\n\n","permissions":["allow-is-permission-granted","allow-request-permission","allow-notify","allow-register-action-types","allow-register-listener","allow-cancel","allow-get-pending","allow-remove-active","allow-get-active","allow-check-permissions","allow-show","allow-batch","allow-list-channels","allow-delete-channel","allow-create-channel","allow-permission-state"]},"permissions":{"allow-batch":{"identifier":"allow-batch","description":"Enables the batch command without any pre-configured scope.","commands":{"allow":["batch"],"deny":[]}},"allow-cancel":{"identifier":"allow-cancel","description":"Enables the cancel command without any pre-configured scope.","commands":{"allow":["cancel"],"deny":[]}},"allow-check-permissions":{"identifier":"allow-check-permissions","description":"Enables the check_permissions command without any pre-configured scope.","commands":{"allow":["check_permissions"],"deny":[]}},"allow-create-channel":{"identifier":"allow-create-channel","description":"Enables the create_channel command without any pre-configured scope.","commands":{"allow":["create_channel"],"deny":[]}},"allow-delete-channel":{"identifier":"allow-delete-channel","description":"Enables the delete_channel command without any pre-configured scope.","commands":{"allow":["delete_channel"],"deny":[]}},"allow-get-active":{"identifier":"allow-get-active","description":"Enables the get_active command without any pre-configured scope.","commands":{"allow":["get_active"],"deny":[]}},"allow-get-pending":{"identifier":"allow-get-pending","description":"Enables the get_pending command without any pre-configured scope.","commands":{"allow":["get_pending"],"deny":[]}},"allow-is-permission-granted":{"identifier":"allow-is-permission-granted","description":"Enables the is_permission_granted command without any pre-configured scope.","commands":{"allow":["is_permission_granted"],"deny":[]}},"allow-list-channels":{"identifier":"allow-list-channels","description":"Enables the list_channels command without any pre-configured scope.","commands":{"allow":["list_channels"],"deny":[]}},"allow-notify":{"identifier":"allow-notify","description":"Enables the notify command without any pre-configured scope.","commands":{"allow":["notify"],"deny":[]}},"allow-permission-state":{"identifier":"allow-permission-state","description":"Enables the permission_state command without any pre-configured scope.","commands":{"allow":["permission_state"],"deny":[]}},"allow-register-action-types":{"identifier":"allow-register-action-types","description":"Enables the register_action_types command without any pre-configured scope.","commands":{"allow":["register_action_types"],"deny":[]}},"allow-register-listener":{"identifier":"allow-register-listener","description":"Enables the register_listener command without any pre-configured scope.","commands":{"allow":["register_listener"],"deny":[]}},"allow-remove-active":{"identifier":"allow-remove-active","description":"Enables the remove_active command without any pre-configured scope.","commands":{"allow":["remove_active"],"deny":[]}},"allow-request-permission":{"identifier":"allow-request-permission","description":"Enables the request_permission command without any pre-configured scope.","commands":{"allow":["request_permission"],"deny":[]}},"allow-show":{"identifier":"allow-show","description":"Enables the show command without any pre-configured scope.","commands":{"allow":["show"],"deny":[]}},"deny-batch":{"identifier":"deny-batch","description":"Denies the batch command without any pre-configured scope.","commands":{"allow":[],"deny":["batch"]}},"deny-cancel":{"identifier":"deny-cancel","description":"Denies the cancel command without any pre-configured scope.","commands":{"allow":[],"deny":["cancel"]}},"deny-check-permissions":{"identifier":"deny-check-permissions","description":"Denies the check_permissions command without any pre-configured scope.","commands":{"allow":[],"deny":["check_permissions"]}},"deny-create-channel":{"identifier":"deny-create-channel","description":"Denies the create_channel command without any pre-configured scope.","commands":{"allow":[],"deny":["create_channel"]}},"deny-delete-channel":{"identifier":"deny-delete-channel","description":"Denies the delete_channel command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_channel"]}},"deny-get-active":{"identifier":"deny-get-active","description":"Denies the get_active command without any pre-configured scope.","commands":{"allow":[],"deny":["get_active"]}},"deny-get-pending":{"identifier":"deny-get-pending","description":"Denies the get_pending command without any pre-configured scope.","commands":{"allow":[],"deny":["get_pending"]}},"deny-is-permission-granted":{"identifier":"deny-is-permission-granted","description":"Denies the is_permission_granted command without any pre-configured scope.","commands":{"allow":[],"deny":["is_permission_granted"]}},"deny-list-channels":{"identifier":"deny-list-channels","description":"Denies the list_channels command without any pre-configured scope.","commands":{"allow":[],"deny":["list_channels"]}},"deny-notify":{"identifier":"deny-notify","description":"Denies the notify command without any pre-configured scope.","commands":{"allow":[],"deny":["notify"]}},"deny-permission-state":{"identifier":"deny-permission-state","description":"Denies the permission_state command without any pre-configured scope.","commands":{"allow":[],"deny":["permission_state"]}},"deny-register-action-types":{"identifier":"deny-register-action-types","description":"Denies the register_action_types command without any pre-configured scope.","commands":{"allow":[],"deny":["register_action_types"]}},"deny-register-listener":{"identifier":"deny-register-listener","description":"Denies the register_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["register_listener"]}},"deny-remove-active":{"identifier":"deny-remove-active","description":"Denies the remove_active command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_active"]}},"deny-request-permission":{"identifier":"deny-request-permission","description":"Denies the request_permission command without any pre-configured scope.","commands":{"allow":[],"deny":["request_permission"]}},"deny-show":{"identifier":"deny-show","description":"Denies the show command without any pre-configured scope.","commands":{"allow":[],"deny":["show"]}}},"permission_sets":{},"global_scope_schema":null}} \ No newline at end of file +{"core":{"default_permission":{"identifier":"default","description":"Default core plugins set.","permissions":["core:path:default","core:event:default","core:window:default","core:webview:default","core:app:default","core:image:default","core:resources:default","core:menu:default","core:tray:default"]},"permissions":{},"permission_sets":{},"global_scope_schema":null},"core:app":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-version","allow-name","allow-tauri-version","allow-identifier","allow-bundle-type","allow-register-listener","allow-remove-listener","allow-supports-multiple-windows"]},"permissions":{"allow-app-hide":{"identifier":"allow-app-hide","description":"Enables the app_hide command without any pre-configured scope.","commands":{"allow":["app_hide"],"deny":[]}},"allow-app-show":{"identifier":"allow-app-show","description":"Enables the app_show command without any pre-configured scope.","commands":{"allow":["app_show"],"deny":[]}},"allow-bundle-type":{"identifier":"allow-bundle-type","description":"Enables the bundle_type command without any pre-configured scope.","commands":{"allow":["bundle_type"],"deny":[]}},"allow-default-window-icon":{"identifier":"allow-default-window-icon","description":"Enables the default_window_icon command without any pre-configured scope.","commands":{"allow":["default_window_icon"],"deny":[]}},"allow-fetch-data-store-identifiers":{"identifier":"allow-fetch-data-store-identifiers","description":"Enables the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":["fetch_data_store_identifiers"],"deny":[]}},"allow-identifier":{"identifier":"allow-identifier","description":"Enables the identifier command without any pre-configured scope.","commands":{"allow":["identifier"],"deny":[]}},"allow-name":{"identifier":"allow-name","description":"Enables the name command without any pre-configured scope.","commands":{"allow":["name"],"deny":[]}},"allow-register-listener":{"identifier":"allow-register-listener","description":"Enables the register_listener command without any pre-configured scope.","commands":{"allow":["register_listener"],"deny":[]}},"allow-remove-data-store":{"identifier":"allow-remove-data-store","description":"Enables the remove_data_store command without any pre-configured scope.","commands":{"allow":["remove_data_store"],"deny":[]}},"allow-remove-listener":{"identifier":"allow-remove-listener","description":"Enables the remove_listener command without any pre-configured scope.","commands":{"allow":["remove_listener"],"deny":[]}},"allow-set-app-theme":{"identifier":"allow-set-app-theme","description":"Enables the set_app_theme command without any pre-configured scope.","commands":{"allow":["set_app_theme"],"deny":[]}},"allow-set-dock-visibility":{"identifier":"allow-set-dock-visibility","description":"Enables the set_dock_visibility command without any pre-configured scope.","commands":{"allow":["set_dock_visibility"],"deny":[]}},"allow-supports-multiple-windows":{"identifier":"allow-supports-multiple-windows","description":"Enables the supports_multiple_windows command without any pre-configured scope.","commands":{"allow":["supports_multiple_windows"],"deny":[]}},"allow-tauri-version":{"identifier":"allow-tauri-version","description":"Enables the tauri_version command without any pre-configured scope.","commands":{"allow":["tauri_version"],"deny":[]}},"allow-version":{"identifier":"allow-version","description":"Enables the version command without any pre-configured scope.","commands":{"allow":["version"],"deny":[]}},"deny-app-hide":{"identifier":"deny-app-hide","description":"Denies the app_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["app_hide"]}},"deny-app-show":{"identifier":"deny-app-show","description":"Denies the app_show command without any pre-configured scope.","commands":{"allow":[],"deny":["app_show"]}},"deny-bundle-type":{"identifier":"deny-bundle-type","description":"Denies the bundle_type command without any pre-configured scope.","commands":{"allow":[],"deny":["bundle_type"]}},"deny-default-window-icon":{"identifier":"deny-default-window-icon","description":"Denies the default_window_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["default_window_icon"]}},"deny-fetch-data-store-identifiers":{"identifier":"deny-fetch-data-store-identifiers","description":"Denies the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":[],"deny":["fetch_data_store_identifiers"]}},"deny-identifier":{"identifier":"deny-identifier","description":"Denies the identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["identifier"]}},"deny-name":{"identifier":"deny-name","description":"Denies the name command without any pre-configured scope.","commands":{"allow":[],"deny":["name"]}},"deny-register-listener":{"identifier":"deny-register-listener","description":"Denies the register_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["register_listener"]}},"deny-remove-data-store":{"identifier":"deny-remove-data-store","description":"Denies the remove_data_store command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_data_store"]}},"deny-remove-listener":{"identifier":"deny-remove-listener","description":"Denies the remove_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_listener"]}},"deny-set-app-theme":{"identifier":"deny-set-app-theme","description":"Denies the set_app_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_app_theme"]}},"deny-set-dock-visibility":{"identifier":"deny-set-dock-visibility","description":"Denies the set_dock_visibility command without any pre-configured scope.","commands":{"allow":[],"deny":["set_dock_visibility"]}},"deny-supports-multiple-windows":{"identifier":"deny-supports-multiple-windows","description":"Denies the supports_multiple_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["supports_multiple_windows"]}},"deny-tauri-version":{"identifier":"deny-tauri-version","description":"Denies the tauri_version command without any pre-configured scope.","commands":{"allow":[],"deny":["tauri_version"]}},"deny-version":{"identifier":"deny-version","description":"Denies the version command without any pre-configured scope.","commands":{"allow":[],"deny":["version"]}}},"permission_sets":{},"global_scope_schema":null},"core:event":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-listen","allow-unlisten","allow-emit","allow-emit-to"]},"permissions":{"allow-emit":{"identifier":"allow-emit","description":"Enables the emit command without any pre-configured scope.","commands":{"allow":["emit"],"deny":[]}},"allow-emit-to":{"identifier":"allow-emit-to","description":"Enables the emit_to command without any pre-configured scope.","commands":{"allow":["emit_to"],"deny":[]}},"allow-listen":{"identifier":"allow-listen","description":"Enables the listen command without any pre-configured scope.","commands":{"allow":["listen"],"deny":[]}},"allow-unlisten":{"identifier":"allow-unlisten","description":"Enables the unlisten command without any pre-configured scope.","commands":{"allow":["unlisten"],"deny":[]}},"deny-emit":{"identifier":"deny-emit","description":"Denies the emit command without any pre-configured scope.","commands":{"allow":[],"deny":["emit"]}},"deny-emit-to":{"identifier":"deny-emit-to","description":"Denies the emit_to command without any pre-configured scope.","commands":{"allow":[],"deny":["emit_to"]}},"deny-listen":{"identifier":"deny-listen","description":"Denies the listen command without any pre-configured scope.","commands":{"allow":[],"deny":["listen"]}},"deny-unlisten":{"identifier":"deny-unlisten","description":"Denies the unlisten command without any pre-configured scope.","commands":{"allow":[],"deny":["unlisten"]}}},"permission_sets":{},"global_scope_schema":null},"core:image":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-from-bytes","allow-from-path","allow-rgba","allow-size"]},"permissions":{"allow-from-bytes":{"identifier":"allow-from-bytes","description":"Enables the from_bytes command without any pre-configured scope.","commands":{"allow":["from_bytes"],"deny":[]}},"allow-from-path":{"identifier":"allow-from-path","description":"Enables the from_path command without any pre-configured scope.","commands":{"allow":["from_path"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-rgba":{"identifier":"allow-rgba","description":"Enables the rgba command without any pre-configured scope.","commands":{"allow":["rgba"],"deny":[]}},"allow-size":{"identifier":"allow-size","description":"Enables the size command without any pre-configured scope.","commands":{"allow":["size"],"deny":[]}},"deny-from-bytes":{"identifier":"deny-from-bytes","description":"Denies the from_bytes command without any pre-configured scope.","commands":{"allow":[],"deny":["from_bytes"]}},"deny-from-path":{"identifier":"deny-from-path","description":"Denies the from_path command without any pre-configured scope.","commands":{"allow":[],"deny":["from_path"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-rgba":{"identifier":"deny-rgba","description":"Denies the rgba command without any pre-configured scope.","commands":{"allow":[],"deny":["rgba"]}},"deny-size":{"identifier":"deny-size","description":"Denies the size command without any pre-configured scope.","commands":{"allow":[],"deny":["size"]}}},"permission_sets":{},"global_scope_schema":null},"core:menu":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-append","allow-prepend","allow-insert","allow-remove","allow-remove-at","allow-items","allow-get","allow-popup","allow-create-default","allow-set-as-app-menu","allow-set-as-window-menu","allow-text","allow-set-text","allow-is-enabled","allow-set-enabled","allow-set-accelerator","allow-set-as-windows-menu-for-nsapp","allow-set-as-help-menu-for-nsapp","allow-is-checked","allow-set-checked","allow-set-icon"]},"permissions":{"allow-append":{"identifier":"allow-append","description":"Enables the append command without any pre-configured scope.","commands":{"allow":["append"],"deny":[]}},"allow-create-default":{"identifier":"allow-create-default","description":"Enables the create_default command without any pre-configured scope.","commands":{"allow":["create_default"],"deny":[]}},"allow-get":{"identifier":"allow-get","description":"Enables the get command without any pre-configured scope.","commands":{"allow":["get"],"deny":[]}},"allow-insert":{"identifier":"allow-insert","description":"Enables the insert command without any pre-configured scope.","commands":{"allow":["insert"],"deny":[]}},"allow-is-checked":{"identifier":"allow-is-checked","description":"Enables the is_checked command without any pre-configured scope.","commands":{"allow":["is_checked"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-items":{"identifier":"allow-items","description":"Enables the items command without any pre-configured scope.","commands":{"allow":["items"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-popup":{"identifier":"allow-popup","description":"Enables the popup command without any pre-configured scope.","commands":{"allow":["popup"],"deny":[]}},"allow-prepend":{"identifier":"allow-prepend","description":"Enables the prepend command without any pre-configured scope.","commands":{"allow":["prepend"],"deny":[]}},"allow-remove":{"identifier":"allow-remove","description":"Enables the remove command without any pre-configured scope.","commands":{"allow":["remove"],"deny":[]}},"allow-remove-at":{"identifier":"allow-remove-at","description":"Enables the remove_at command without any pre-configured scope.","commands":{"allow":["remove_at"],"deny":[]}},"allow-set-accelerator":{"identifier":"allow-set-accelerator","description":"Enables the set_accelerator command without any pre-configured scope.","commands":{"allow":["set_accelerator"],"deny":[]}},"allow-set-as-app-menu":{"identifier":"allow-set-as-app-menu","description":"Enables the set_as_app_menu command without any pre-configured scope.","commands":{"allow":["set_as_app_menu"],"deny":[]}},"allow-set-as-help-menu-for-nsapp":{"identifier":"allow-set-as-help-menu-for-nsapp","description":"Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_help_menu_for_nsapp"],"deny":[]}},"allow-set-as-window-menu":{"identifier":"allow-set-as-window-menu","description":"Enables the set_as_window_menu command without any pre-configured scope.","commands":{"allow":["set_as_window_menu"],"deny":[]}},"allow-set-as-windows-menu-for-nsapp":{"identifier":"allow-set-as-windows-menu-for-nsapp","description":"Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_windows_menu_for_nsapp"],"deny":[]}},"allow-set-checked":{"identifier":"allow-set-checked","description":"Enables the set_checked command without any pre-configured scope.","commands":{"allow":["set_checked"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-text":{"identifier":"allow-set-text","description":"Enables the set_text command without any pre-configured scope.","commands":{"allow":["set_text"],"deny":[]}},"allow-text":{"identifier":"allow-text","description":"Enables the text command without any pre-configured scope.","commands":{"allow":["text"],"deny":[]}},"deny-append":{"identifier":"deny-append","description":"Denies the append command without any pre-configured scope.","commands":{"allow":[],"deny":["append"]}},"deny-create-default":{"identifier":"deny-create-default","description":"Denies the create_default command without any pre-configured scope.","commands":{"allow":[],"deny":["create_default"]}},"deny-get":{"identifier":"deny-get","description":"Denies the get command without any pre-configured scope.","commands":{"allow":[],"deny":["get"]}},"deny-insert":{"identifier":"deny-insert","description":"Denies the insert command without any pre-configured scope.","commands":{"allow":[],"deny":["insert"]}},"deny-is-checked":{"identifier":"deny-is-checked","description":"Denies the is_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["is_checked"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-items":{"identifier":"deny-items","description":"Denies the items command without any pre-configured scope.","commands":{"allow":[],"deny":["items"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-popup":{"identifier":"deny-popup","description":"Denies the popup command without any pre-configured scope.","commands":{"allow":[],"deny":["popup"]}},"deny-prepend":{"identifier":"deny-prepend","description":"Denies the prepend command without any pre-configured scope.","commands":{"allow":[],"deny":["prepend"]}},"deny-remove":{"identifier":"deny-remove","description":"Denies the remove command without any pre-configured scope.","commands":{"allow":[],"deny":["remove"]}},"deny-remove-at":{"identifier":"deny-remove-at","description":"Denies the remove_at command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_at"]}},"deny-set-accelerator":{"identifier":"deny-set-accelerator","description":"Denies the set_accelerator command without any pre-configured scope.","commands":{"allow":[],"deny":["set_accelerator"]}},"deny-set-as-app-menu":{"identifier":"deny-set-as-app-menu","description":"Denies the set_as_app_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_app_menu"]}},"deny-set-as-help-menu-for-nsapp":{"identifier":"deny-set-as-help-menu-for-nsapp","description":"Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_help_menu_for_nsapp"]}},"deny-set-as-window-menu":{"identifier":"deny-set-as-window-menu","description":"Denies the set_as_window_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_window_menu"]}},"deny-set-as-windows-menu-for-nsapp":{"identifier":"deny-set-as-windows-menu-for-nsapp","description":"Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_windows_menu_for_nsapp"]}},"deny-set-checked":{"identifier":"deny-set-checked","description":"Denies the set_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["set_checked"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-text":{"identifier":"deny-set-text","description":"Denies the set_text command without any pre-configured scope.","commands":{"allow":[],"deny":["set_text"]}},"deny-text":{"identifier":"deny-text","description":"Denies the text command without any pre-configured scope.","commands":{"allow":[],"deny":["text"]}}},"permission_sets":{},"global_scope_schema":null},"core:path":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-resolve-directory","allow-resolve","allow-normalize","allow-join","allow-dirname","allow-extname","allow-basename","allow-is-absolute"]},"permissions":{"allow-basename":{"identifier":"allow-basename","description":"Enables the basename command without any pre-configured scope.","commands":{"allow":["basename"],"deny":[]}},"allow-dirname":{"identifier":"allow-dirname","description":"Enables the dirname command without any pre-configured scope.","commands":{"allow":["dirname"],"deny":[]}},"allow-extname":{"identifier":"allow-extname","description":"Enables the extname command without any pre-configured scope.","commands":{"allow":["extname"],"deny":[]}},"allow-is-absolute":{"identifier":"allow-is-absolute","description":"Enables the is_absolute command without any pre-configured scope.","commands":{"allow":["is_absolute"],"deny":[]}},"allow-join":{"identifier":"allow-join","description":"Enables the join command without any pre-configured scope.","commands":{"allow":["join"],"deny":[]}},"allow-normalize":{"identifier":"allow-normalize","description":"Enables the normalize command without any pre-configured scope.","commands":{"allow":["normalize"],"deny":[]}},"allow-resolve":{"identifier":"allow-resolve","description":"Enables the resolve command without any pre-configured scope.","commands":{"allow":["resolve"],"deny":[]}},"allow-resolve-directory":{"identifier":"allow-resolve-directory","description":"Enables the resolve_directory command without any pre-configured scope.","commands":{"allow":["resolve_directory"],"deny":[]}},"deny-basename":{"identifier":"deny-basename","description":"Denies the basename command without any pre-configured scope.","commands":{"allow":[],"deny":["basename"]}},"deny-dirname":{"identifier":"deny-dirname","description":"Denies the dirname command without any pre-configured scope.","commands":{"allow":[],"deny":["dirname"]}},"deny-extname":{"identifier":"deny-extname","description":"Denies the extname command without any pre-configured scope.","commands":{"allow":[],"deny":["extname"]}},"deny-is-absolute":{"identifier":"deny-is-absolute","description":"Denies the is_absolute command without any pre-configured scope.","commands":{"allow":[],"deny":["is_absolute"]}},"deny-join":{"identifier":"deny-join","description":"Denies the join command without any pre-configured scope.","commands":{"allow":[],"deny":["join"]}},"deny-normalize":{"identifier":"deny-normalize","description":"Denies the normalize command without any pre-configured scope.","commands":{"allow":[],"deny":["normalize"]}},"deny-resolve":{"identifier":"deny-resolve","description":"Denies the resolve command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve"]}},"deny-resolve-directory":{"identifier":"deny-resolve-directory","description":"Denies the resolve_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_directory"]}}},"permission_sets":{},"global_scope_schema":null},"core:resources":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-close"]},"permissions":{"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}}},"permission_sets":{},"global_scope_schema":null},"core:tray":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-get-by-id","allow-remove-by-id","allow-set-icon","allow-set-menu","allow-set-tooltip","allow-set-title","allow-set-visible","allow-set-temp-dir-path","allow-set-icon-as-template","allow-set-icon-with-as-template","allow-set-show-menu-on-left-click"]},"permissions":{"allow-get-by-id":{"identifier":"allow-get-by-id","description":"Enables the get_by_id command without any pre-configured scope.","commands":{"allow":["get_by_id"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-remove-by-id":{"identifier":"allow-remove-by-id","description":"Enables the remove_by_id command without any pre-configured scope.","commands":{"allow":["remove_by_id"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-icon-as-template":{"identifier":"allow-set-icon-as-template","description":"Enables the set_icon_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_as_template"],"deny":[]}},"allow-set-icon-with-as-template":{"identifier":"allow-set-icon-with-as-template","description":"Enables the set_icon_with_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_with_as_template"],"deny":[]}},"allow-set-menu":{"identifier":"allow-set-menu","description":"Enables the set_menu command without any pre-configured scope.","commands":{"allow":["set_menu"],"deny":[]}},"allow-set-show-menu-on-left-click":{"identifier":"allow-set-show-menu-on-left-click","description":"Enables the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":["set_show_menu_on_left_click"],"deny":[]}},"allow-set-temp-dir-path":{"identifier":"allow-set-temp-dir-path","description":"Enables the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":["set_temp_dir_path"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-tooltip":{"identifier":"allow-set-tooltip","description":"Enables the set_tooltip command without any pre-configured scope.","commands":{"allow":["set_tooltip"],"deny":[]}},"allow-set-visible":{"identifier":"allow-set-visible","description":"Enables the set_visible command without any pre-configured scope.","commands":{"allow":["set_visible"],"deny":[]}},"deny-get-by-id":{"identifier":"deny-get-by-id","description":"Denies the get_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["get_by_id"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-remove-by-id":{"identifier":"deny-remove-by-id","description":"Denies the remove_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_by_id"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-icon-as-template":{"identifier":"deny-set-icon-as-template","description":"Denies the set_icon_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_as_template"]}},"deny-set-icon-with-as-template":{"identifier":"deny-set-icon-with-as-template","description":"Denies the set_icon_with_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_with_as_template"]}},"deny-set-menu":{"identifier":"deny-set-menu","description":"Denies the set_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_menu"]}},"deny-set-show-menu-on-left-click":{"identifier":"deny-set-show-menu-on-left-click","description":"Denies the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":[],"deny":["set_show_menu_on_left_click"]}},"deny-set-temp-dir-path":{"identifier":"deny-set-temp-dir-path","description":"Denies the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":[],"deny":["set_temp_dir_path"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-tooltip":{"identifier":"deny-set-tooltip","description":"Denies the set_tooltip command without any pre-configured scope.","commands":{"allow":[],"deny":["set_tooltip"]}},"deny-set-visible":{"identifier":"deny-set-visible","description":"Denies the set_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible"]}}},"permission_sets":{},"global_scope_schema":null},"core:webview":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-webviews","allow-webview-position","allow-webview-size","allow-internal-toggle-devtools"]},"permissions":{"allow-clear-all-browsing-data":{"identifier":"allow-clear-all-browsing-data","description":"Enables the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":["clear_all_browsing_data"],"deny":[]}},"allow-create-webview":{"identifier":"allow-create-webview","description":"Enables the create_webview command without any pre-configured scope.","commands":{"allow":["create_webview"],"deny":[]}},"allow-create-webview-window":{"identifier":"allow-create-webview-window","description":"Enables the create_webview_window command without any pre-configured scope.","commands":{"allow":["create_webview_window"],"deny":[]}},"allow-get-all-webviews":{"identifier":"allow-get-all-webviews","description":"Enables the get_all_webviews command without any pre-configured scope.","commands":{"allow":["get_all_webviews"],"deny":[]}},"allow-internal-toggle-devtools":{"identifier":"allow-internal-toggle-devtools","description":"Enables the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":["internal_toggle_devtools"],"deny":[]}},"allow-print":{"identifier":"allow-print","description":"Enables the print command without any pre-configured scope.","commands":{"allow":["print"],"deny":[]}},"allow-reparent":{"identifier":"allow-reparent","description":"Enables the reparent command without any pre-configured scope.","commands":{"allow":["reparent"],"deny":[]}},"allow-set-webview-auto-resize":{"identifier":"allow-set-webview-auto-resize","description":"Enables the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":["set_webview_auto_resize"],"deny":[]}},"allow-set-webview-background-color":{"identifier":"allow-set-webview-background-color","description":"Enables the set_webview_background_color command without any pre-configured scope.","commands":{"allow":["set_webview_background_color"],"deny":[]}},"allow-set-webview-focus":{"identifier":"allow-set-webview-focus","description":"Enables the set_webview_focus command without any pre-configured scope.","commands":{"allow":["set_webview_focus"],"deny":[]}},"allow-set-webview-position":{"identifier":"allow-set-webview-position","description":"Enables the set_webview_position command without any pre-configured scope.","commands":{"allow":["set_webview_position"],"deny":[]}},"allow-set-webview-size":{"identifier":"allow-set-webview-size","description":"Enables the set_webview_size command without any pre-configured scope.","commands":{"allow":["set_webview_size"],"deny":[]}},"allow-set-webview-zoom":{"identifier":"allow-set-webview-zoom","description":"Enables the set_webview_zoom command without any pre-configured scope.","commands":{"allow":["set_webview_zoom"],"deny":[]}},"allow-webview-close":{"identifier":"allow-webview-close","description":"Enables the webview_close command without any pre-configured scope.","commands":{"allow":["webview_close"],"deny":[]}},"allow-webview-hide":{"identifier":"allow-webview-hide","description":"Enables the webview_hide command without any pre-configured scope.","commands":{"allow":["webview_hide"],"deny":[]}},"allow-webview-position":{"identifier":"allow-webview-position","description":"Enables the webview_position command without any pre-configured scope.","commands":{"allow":["webview_position"],"deny":[]}},"allow-webview-show":{"identifier":"allow-webview-show","description":"Enables the webview_show command without any pre-configured scope.","commands":{"allow":["webview_show"],"deny":[]}},"allow-webview-size":{"identifier":"allow-webview-size","description":"Enables the webview_size command without any pre-configured scope.","commands":{"allow":["webview_size"],"deny":[]}},"deny-clear-all-browsing-data":{"identifier":"deny-clear-all-browsing-data","description":"Denies the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":[],"deny":["clear_all_browsing_data"]}},"deny-create-webview":{"identifier":"deny-create-webview","description":"Denies the create_webview command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview"]}},"deny-create-webview-window":{"identifier":"deny-create-webview-window","description":"Denies the create_webview_window command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview_window"]}},"deny-get-all-webviews":{"identifier":"deny-get-all-webviews","description":"Denies the get_all_webviews command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_webviews"]}},"deny-internal-toggle-devtools":{"identifier":"deny-internal-toggle-devtools","description":"Denies the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_devtools"]}},"deny-print":{"identifier":"deny-print","description":"Denies the print command without any pre-configured scope.","commands":{"allow":[],"deny":["print"]}},"deny-reparent":{"identifier":"deny-reparent","description":"Denies the reparent command without any pre-configured scope.","commands":{"allow":[],"deny":["reparent"]}},"deny-set-webview-auto-resize":{"identifier":"deny-set-webview-auto-resize","description":"Denies the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_auto_resize"]}},"deny-set-webview-background-color":{"identifier":"deny-set-webview-background-color","description":"Denies the set_webview_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_background_color"]}},"deny-set-webview-focus":{"identifier":"deny-set-webview-focus","description":"Denies the set_webview_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_focus"]}},"deny-set-webview-position":{"identifier":"deny-set-webview-position","description":"Denies the set_webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_position"]}},"deny-set-webview-size":{"identifier":"deny-set-webview-size","description":"Denies the set_webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_size"]}},"deny-set-webview-zoom":{"identifier":"deny-set-webview-zoom","description":"Denies the set_webview_zoom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_zoom"]}},"deny-webview-close":{"identifier":"deny-webview-close","description":"Denies the webview_close command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_close"]}},"deny-webview-hide":{"identifier":"deny-webview-hide","description":"Denies the webview_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_hide"]}},"deny-webview-position":{"identifier":"deny-webview-position","description":"Denies the webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_position"]}},"deny-webview-show":{"identifier":"deny-webview-show","description":"Denies the webview_show command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_show"]}},"deny-webview-size":{"identifier":"deny-webview-size","description":"Denies the webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_size"]}}},"permission_sets":{},"global_scope_schema":null},"core:window":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-windows","allow-scale-factor","allow-inner-position","allow-outer-position","allow-inner-size","allow-outer-size","allow-is-fullscreen","allow-is-minimized","allow-is-maximized","allow-is-focused","allow-is-decorated","allow-is-resizable","allow-is-maximizable","allow-is-minimizable","allow-is-closable","allow-is-visible","allow-is-enabled","allow-title","allow-current-monitor","allow-primary-monitor","allow-monitor-from-point","allow-available-monitors","allow-cursor-position","allow-theme","allow-is-always-on-top","allow-activity-name","allow-scene-identifier","allow-internal-toggle-maximize"]},"permissions":{"allow-activity-name":{"identifier":"allow-activity-name","description":"Enables the activity_name command without any pre-configured scope.","commands":{"allow":["activity_name"],"deny":[]}},"allow-available-monitors":{"identifier":"allow-available-monitors","description":"Enables the available_monitors command without any pre-configured scope.","commands":{"allow":["available_monitors"],"deny":[]}},"allow-center":{"identifier":"allow-center","description":"Enables the center command without any pre-configured scope.","commands":{"allow":["center"],"deny":[]}},"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"allow-create":{"identifier":"allow-create","description":"Enables the create command without any pre-configured scope.","commands":{"allow":["create"],"deny":[]}},"allow-current-monitor":{"identifier":"allow-current-monitor","description":"Enables the current_monitor command without any pre-configured scope.","commands":{"allow":["current_monitor"],"deny":[]}},"allow-cursor-position":{"identifier":"allow-cursor-position","description":"Enables the cursor_position command without any pre-configured scope.","commands":{"allow":["cursor_position"],"deny":[]}},"allow-destroy":{"identifier":"allow-destroy","description":"Enables the destroy command without any pre-configured scope.","commands":{"allow":["destroy"],"deny":[]}},"allow-get-all-windows":{"identifier":"allow-get-all-windows","description":"Enables the get_all_windows command without any pre-configured scope.","commands":{"allow":["get_all_windows"],"deny":[]}},"allow-hide":{"identifier":"allow-hide","description":"Enables the hide command without any pre-configured scope.","commands":{"allow":["hide"],"deny":[]}},"allow-inner-position":{"identifier":"allow-inner-position","description":"Enables the inner_position command without any pre-configured scope.","commands":{"allow":["inner_position"],"deny":[]}},"allow-inner-size":{"identifier":"allow-inner-size","description":"Enables the inner_size command without any pre-configured scope.","commands":{"allow":["inner_size"],"deny":[]}},"allow-internal-toggle-maximize":{"identifier":"allow-internal-toggle-maximize","description":"Enables the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":["internal_toggle_maximize"],"deny":[]}},"allow-is-always-on-top":{"identifier":"allow-is-always-on-top","description":"Enables the is_always_on_top command without any pre-configured scope.","commands":{"allow":["is_always_on_top"],"deny":[]}},"allow-is-closable":{"identifier":"allow-is-closable","description":"Enables the is_closable command without any pre-configured scope.","commands":{"allow":["is_closable"],"deny":[]}},"allow-is-decorated":{"identifier":"allow-is-decorated","description":"Enables the is_decorated command without any pre-configured scope.","commands":{"allow":["is_decorated"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-is-focused":{"identifier":"allow-is-focused","description":"Enables the is_focused command without any pre-configured scope.","commands":{"allow":["is_focused"],"deny":[]}},"allow-is-fullscreen":{"identifier":"allow-is-fullscreen","description":"Enables the is_fullscreen command without any pre-configured scope.","commands":{"allow":["is_fullscreen"],"deny":[]}},"allow-is-maximizable":{"identifier":"allow-is-maximizable","description":"Enables the is_maximizable command without any pre-configured scope.","commands":{"allow":["is_maximizable"],"deny":[]}},"allow-is-maximized":{"identifier":"allow-is-maximized","description":"Enables the is_maximized command without any pre-configured scope.","commands":{"allow":["is_maximized"],"deny":[]}},"allow-is-minimizable":{"identifier":"allow-is-minimizable","description":"Enables the is_minimizable command without any pre-configured scope.","commands":{"allow":["is_minimizable"],"deny":[]}},"allow-is-minimized":{"identifier":"allow-is-minimized","description":"Enables the is_minimized command without any pre-configured scope.","commands":{"allow":["is_minimized"],"deny":[]}},"allow-is-resizable":{"identifier":"allow-is-resizable","description":"Enables the is_resizable command without any pre-configured scope.","commands":{"allow":["is_resizable"],"deny":[]}},"allow-is-visible":{"identifier":"allow-is-visible","description":"Enables the is_visible command without any pre-configured scope.","commands":{"allow":["is_visible"],"deny":[]}},"allow-maximize":{"identifier":"allow-maximize","description":"Enables the maximize command without any pre-configured scope.","commands":{"allow":["maximize"],"deny":[]}},"allow-minimize":{"identifier":"allow-minimize","description":"Enables the minimize command without any pre-configured scope.","commands":{"allow":["minimize"],"deny":[]}},"allow-monitor-from-point":{"identifier":"allow-monitor-from-point","description":"Enables the monitor_from_point command without any pre-configured scope.","commands":{"allow":["monitor_from_point"],"deny":[]}},"allow-outer-position":{"identifier":"allow-outer-position","description":"Enables the outer_position command without any pre-configured scope.","commands":{"allow":["outer_position"],"deny":[]}},"allow-outer-size":{"identifier":"allow-outer-size","description":"Enables the outer_size command without any pre-configured scope.","commands":{"allow":["outer_size"],"deny":[]}},"allow-primary-monitor":{"identifier":"allow-primary-monitor","description":"Enables the primary_monitor command without any pre-configured scope.","commands":{"allow":["primary_monitor"],"deny":[]}},"allow-request-user-attention":{"identifier":"allow-request-user-attention","description":"Enables the request_user_attention command without any pre-configured scope.","commands":{"allow":["request_user_attention"],"deny":[]}},"allow-scale-factor":{"identifier":"allow-scale-factor","description":"Enables the scale_factor command without any pre-configured scope.","commands":{"allow":["scale_factor"],"deny":[]}},"allow-scene-identifier":{"identifier":"allow-scene-identifier","description":"Enables the scene_identifier command without any pre-configured scope.","commands":{"allow":["scene_identifier"],"deny":[]}},"allow-set-always-on-bottom":{"identifier":"allow-set-always-on-bottom","description":"Enables the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":["set_always_on_bottom"],"deny":[]}},"allow-set-always-on-top":{"identifier":"allow-set-always-on-top","description":"Enables the set_always_on_top command without any pre-configured scope.","commands":{"allow":["set_always_on_top"],"deny":[]}},"allow-set-background-color":{"identifier":"allow-set-background-color","description":"Enables the set_background_color command without any pre-configured scope.","commands":{"allow":["set_background_color"],"deny":[]}},"allow-set-badge-count":{"identifier":"allow-set-badge-count","description":"Enables the set_badge_count command without any pre-configured scope.","commands":{"allow":["set_badge_count"],"deny":[]}},"allow-set-badge-label":{"identifier":"allow-set-badge-label","description":"Enables the set_badge_label command without any pre-configured scope.","commands":{"allow":["set_badge_label"],"deny":[]}},"allow-set-closable":{"identifier":"allow-set-closable","description":"Enables the set_closable command without any pre-configured scope.","commands":{"allow":["set_closable"],"deny":[]}},"allow-set-content-protected":{"identifier":"allow-set-content-protected","description":"Enables the set_content_protected command without any pre-configured scope.","commands":{"allow":["set_content_protected"],"deny":[]}},"allow-set-cursor-grab":{"identifier":"allow-set-cursor-grab","description":"Enables the set_cursor_grab command without any pre-configured scope.","commands":{"allow":["set_cursor_grab"],"deny":[]}},"allow-set-cursor-icon":{"identifier":"allow-set-cursor-icon","description":"Enables the set_cursor_icon command without any pre-configured scope.","commands":{"allow":["set_cursor_icon"],"deny":[]}},"allow-set-cursor-position":{"identifier":"allow-set-cursor-position","description":"Enables the set_cursor_position command without any pre-configured scope.","commands":{"allow":["set_cursor_position"],"deny":[]}},"allow-set-cursor-visible":{"identifier":"allow-set-cursor-visible","description":"Enables the set_cursor_visible command without any pre-configured scope.","commands":{"allow":["set_cursor_visible"],"deny":[]}},"allow-set-decorations":{"identifier":"allow-set-decorations","description":"Enables the set_decorations command without any pre-configured scope.","commands":{"allow":["set_decorations"],"deny":[]}},"allow-set-effects":{"identifier":"allow-set-effects","description":"Enables the set_effects command without any pre-configured scope.","commands":{"allow":["set_effects"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-focus":{"identifier":"allow-set-focus","description":"Enables the set_focus command without any pre-configured scope.","commands":{"allow":["set_focus"],"deny":[]}},"allow-set-focusable":{"identifier":"allow-set-focusable","description":"Enables the set_focusable command without any pre-configured scope.","commands":{"allow":["set_focusable"],"deny":[]}},"allow-set-fullscreen":{"identifier":"allow-set-fullscreen","description":"Enables the set_fullscreen command without any pre-configured scope.","commands":{"allow":["set_fullscreen"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-ignore-cursor-events":{"identifier":"allow-set-ignore-cursor-events","description":"Enables the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":["set_ignore_cursor_events"],"deny":[]}},"allow-set-max-size":{"identifier":"allow-set-max-size","description":"Enables the set_max_size command without any pre-configured scope.","commands":{"allow":["set_max_size"],"deny":[]}},"allow-set-maximizable":{"identifier":"allow-set-maximizable","description":"Enables the set_maximizable command without any pre-configured scope.","commands":{"allow":["set_maximizable"],"deny":[]}},"allow-set-min-size":{"identifier":"allow-set-min-size","description":"Enables the set_min_size command without any pre-configured scope.","commands":{"allow":["set_min_size"],"deny":[]}},"allow-set-minimizable":{"identifier":"allow-set-minimizable","description":"Enables the set_minimizable command without any pre-configured scope.","commands":{"allow":["set_minimizable"],"deny":[]}},"allow-set-overlay-icon":{"identifier":"allow-set-overlay-icon","description":"Enables the set_overlay_icon command without any pre-configured scope.","commands":{"allow":["set_overlay_icon"],"deny":[]}},"allow-set-position":{"identifier":"allow-set-position","description":"Enables the set_position command without any pre-configured scope.","commands":{"allow":["set_position"],"deny":[]}},"allow-set-progress-bar":{"identifier":"allow-set-progress-bar","description":"Enables the set_progress_bar command without any pre-configured scope.","commands":{"allow":["set_progress_bar"],"deny":[]}},"allow-set-resizable":{"identifier":"allow-set-resizable","description":"Enables the set_resizable command without any pre-configured scope.","commands":{"allow":["set_resizable"],"deny":[]}},"allow-set-shadow":{"identifier":"allow-set-shadow","description":"Enables the set_shadow command without any pre-configured scope.","commands":{"allow":["set_shadow"],"deny":[]}},"allow-set-simple-fullscreen":{"identifier":"allow-set-simple-fullscreen","description":"Enables the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":["set_simple_fullscreen"],"deny":[]}},"allow-set-size":{"identifier":"allow-set-size","description":"Enables the set_size command without any pre-configured scope.","commands":{"allow":["set_size"],"deny":[]}},"allow-set-size-constraints":{"identifier":"allow-set-size-constraints","description":"Enables the set_size_constraints command without any pre-configured scope.","commands":{"allow":["set_size_constraints"],"deny":[]}},"allow-set-skip-taskbar":{"identifier":"allow-set-skip-taskbar","description":"Enables the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":["set_skip_taskbar"],"deny":[]}},"allow-set-theme":{"identifier":"allow-set-theme","description":"Enables the set_theme command without any pre-configured scope.","commands":{"allow":["set_theme"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-title-bar-style":{"identifier":"allow-set-title-bar-style","description":"Enables the set_title_bar_style command without any pre-configured scope.","commands":{"allow":["set_title_bar_style"],"deny":[]}},"allow-set-visible-on-all-workspaces":{"identifier":"allow-set-visible-on-all-workspaces","description":"Enables the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":["set_visible_on_all_workspaces"],"deny":[]}},"allow-show":{"identifier":"allow-show","description":"Enables the show command without any pre-configured scope.","commands":{"allow":["show"],"deny":[]}},"allow-start-dragging":{"identifier":"allow-start-dragging","description":"Enables the start_dragging command without any pre-configured scope.","commands":{"allow":["start_dragging"],"deny":[]}},"allow-start-resize-dragging":{"identifier":"allow-start-resize-dragging","description":"Enables the start_resize_dragging command without any pre-configured scope.","commands":{"allow":["start_resize_dragging"],"deny":[]}},"allow-theme":{"identifier":"allow-theme","description":"Enables the theme command without any pre-configured scope.","commands":{"allow":["theme"],"deny":[]}},"allow-title":{"identifier":"allow-title","description":"Enables the title command without any pre-configured scope.","commands":{"allow":["title"],"deny":[]}},"allow-toggle-maximize":{"identifier":"allow-toggle-maximize","description":"Enables the toggle_maximize command without any pre-configured scope.","commands":{"allow":["toggle_maximize"],"deny":[]}},"allow-unmaximize":{"identifier":"allow-unmaximize","description":"Enables the unmaximize command without any pre-configured scope.","commands":{"allow":["unmaximize"],"deny":[]}},"allow-unminimize":{"identifier":"allow-unminimize","description":"Enables the unminimize command without any pre-configured scope.","commands":{"allow":["unminimize"],"deny":[]}},"deny-activity-name":{"identifier":"deny-activity-name","description":"Denies the activity_name command without any pre-configured scope.","commands":{"allow":[],"deny":["activity_name"]}},"deny-available-monitors":{"identifier":"deny-available-monitors","description":"Denies the available_monitors command without any pre-configured scope.","commands":{"allow":[],"deny":["available_monitors"]}},"deny-center":{"identifier":"deny-center","description":"Denies the center command without any pre-configured scope.","commands":{"allow":[],"deny":["center"]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}},"deny-create":{"identifier":"deny-create","description":"Denies the create command without any pre-configured scope.","commands":{"allow":[],"deny":["create"]}},"deny-current-monitor":{"identifier":"deny-current-monitor","description":"Denies the current_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["current_monitor"]}},"deny-cursor-position":{"identifier":"deny-cursor-position","description":"Denies the cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["cursor_position"]}},"deny-destroy":{"identifier":"deny-destroy","description":"Denies the destroy command without any pre-configured scope.","commands":{"allow":[],"deny":["destroy"]}},"deny-get-all-windows":{"identifier":"deny-get-all-windows","description":"Denies the get_all_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_windows"]}},"deny-hide":{"identifier":"deny-hide","description":"Denies the hide command without any pre-configured scope.","commands":{"allow":[],"deny":["hide"]}},"deny-inner-position":{"identifier":"deny-inner-position","description":"Denies the inner_position command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_position"]}},"deny-inner-size":{"identifier":"deny-inner-size","description":"Denies the inner_size command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_size"]}},"deny-internal-toggle-maximize":{"identifier":"deny-internal-toggle-maximize","description":"Denies the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_maximize"]}},"deny-is-always-on-top":{"identifier":"deny-is-always-on-top","description":"Denies the is_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["is_always_on_top"]}},"deny-is-closable":{"identifier":"deny-is-closable","description":"Denies the is_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_closable"]}},"deny-is-decorated":{"identifier":"deny-is-decorated","description":"Denies the is_decorated command without any pre-configured scope.","commands":{"allow":[],"deny":["is_decorated"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-is-focused":{"identifier":"deny-is-focused","description":"Denies the is_focused command without any pre-configured scope.","commands":{"allow":[],"deny":["is_focused"]}},"deny-is-fullscreen":{"identifier":"deny-is-fullscreen","description":"Denies the is_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["is_fullscreen"]}},"deny-is-maximizable":{"identifier":"deny-is-maximizable","description":"Denies the is_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximizable"]}},"deny-is-maximized":{"identifier":"deny-is-maximized","description":"Denies the is_maximized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximized"]}},"deny-is-minimizable":{"identifier":"deny-is-minimizable","description":"Denies the is_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimizable"]}},"deny-is-minimized":{"identifier":"deny-is-minimized","description":"Denies the is_minimized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimized"]}},"deny-is-resizable":{"identifier":"deny-is-resizable","description":"Denies the is_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_resizable"]}},"deny-is-visible":{"identifier":"deny-is-visible","description":"Denies the is_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["is_visible"]}},"deny-maximize":{"identifier":"deny-maximize","description":"Denies the maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["maximize"]}},"deny-minimize":{"identifier":"deny-minimize","description":"Denies the minimize command without any pre-configured scope.","commands":{"allow":[],"deny":["minimize"]}},"deny-monitor-from-point":{"identifier":"deny-monitor-from-point","description":"Denies the monitor_from_point command without any pre-configured scope.","commands":{"allow":[],"deny":["monitor_from_point"]}},"deny-outer-position":{"identifier":"deny-outer-position","description":"Denies the outer_position command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_position"]}},"deny-outer-size":{"identifier":"deny-outer-size","description":"Denies the outer_size command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_size"]}},"deny-primary-monitor":{"identifier":"deny-primary-monitor","description":"Denies the primary_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["primary_monitor"]}},"deny-request-user-attention":{"identifier":"deny-request-user-attention","description":"Denies the request_user_attention command without any pre-configured scope.","commands":{"allow":[],"deny":["request_user_attention"]}},"deny-scale-factor":{"identifier":"deny-scale-factor","description":"Denies the scale_factor command without any pre-configured scope.","commands":{"allow":[],"deny":["scale_factor"]}},"deny-scene-identifier":{"identifier":"deny-scene-identifier","description":"Denies the scene_identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["scene_identifier"]}},"deny-set-always-on-bottom":{"identifier":"deny-set-always-on-bottom","description":"Denies the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_bottom"]}},"deny-set-always-on-top":{"identifier":"deny-set-always-on-top","description":"Denies the set_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_top"]}},"deny-set-background-color":{"identifier":"deny-set-background-color","description":"Denies the set_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_background_color"]}},"deny-set-badge-count":{"identifier":"deny-set-badge-count","description":"Denies the set_badge_count command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_count"]}},"deny-set-badge-label":{"identifier":"deny-set-badge-label","description":"Denies the set_badge_label command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_label"]}},"deny-set-closable":{"identifier":"deny-set-closable","description":"Denies the set_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_closable"]}},"deny-set-content-protected":{"identifier":"deny-set-content-protected","description":"Denies the set_content_protected command without any pre-configured scope.","commands":{"allow":[],"deny":["set_content_protected"]}},"deny-set-cursor-grab":{"identifier":"deny-set-cursor-grab","description":"Denies the set_cursor_grab command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_grab"]}},"deny-set-cursor-icon":{"identifier":"deny-set-cursor-icon","description":"Denies the set_cursor_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_icon"]}},"deny-set-cursor-position":{"identifier":"deny-set-cursor-position","description":"Denies the set_cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_position"]}},"deny-set-cursor-visible":{"identifier":"deny-set-cursor-visible","description":"Denies the set_cursor_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_visible"]}},"deny-set-decorations":{"identifier":"deny-set-decorations","description":"Denies the set_decorations command without any pre-configured scope.","commands":{"allow":[],"deny":["set_decorations"]}},"deny-set-effects":{"identifier":"deny-set-effects","description":"Denies the set_effects command without any pre-configured scope.","commands":{"allow":[],"deny":["set_effects"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-focus":{"identifier":"deny-set-focus","description":"Denies the set_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focus"]}},"deny-set-focusable":{"identifier":"deny-set-focusable","description":"Denies the set_focusable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focusable"]}},"deny-set-fullscreen":{"identifier":"deny-set-fullscreen","description":"Denies the set_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_fullscreen"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-ignore-cursor-events":{"identifier":"deny-set-ignore-cursor-events","description":"Denies the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":[],"deny":["set_ignore_cursor_events"]}},"deny-set-max-size":{"identifier":"deny-set-max-size","description":"Denies the set_max_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_max_size"]}},"deny-set-maximizable":{"identifier":"deny-set-maximizable","description":"Denies the set_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_maximizable"]}},"deny-set-min-size":{"identifier":"deny-set-min-size","description":"Denies the set_min_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_min_size"]}},"deny-set-minimizable":{"identifier":"deny-set-minimizable","description":"Denies the set_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_minimizable"]}},"deny-set-overlay-icon":{"identifier":"deny-set-overlay-icon","description":"Denies the set_overlay_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_overlay_icon"]}},"deny-set-position":{"identifier":"deny-set-position","description":"Denies the set_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_position"]}},"deny-set-progress-bar":{"identifier":"deny-set-progress-bar","description":"Denies the set_progress_bar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_progress_bar"]}},"deny-set-resizable":{"identifier":"deny-set-resizable","description":"Denies the set_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_resizable"]}},"deny-set-shadow":{"identifier":"deny-set-shadow","description":"Denies the set_shadow command without any pre-configured scope.","commands":{"allow":[],"deny":["set_shadow"]}},"deny-set-simple-fullscreen":{"identifier":"deny-set-simple-fullscreen","description":"Denies the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_simple_fullscreen"]}},"deny-set-size":{"identifier":"deny-set-size","description":"Denies the set_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size"]}},"deny-set-size-constraints":{"identifier":"deny-set-size-constraints","description":"Denies the set_size_constraints command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size_constraints"]}},"deny-set-skip-taskbar":{"identifier":"deny-set-skip-taskbar","description":"Denies the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_skip_taskbar"]}},"deny-set-theme":{"identifier":"deny-set-theme","description":"Denies the set_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_theme"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-title-bar-style":{"identifier":"deny-set-title-bar-style","description":"Denies the set_title_bar_style command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title_bar_style"]}},"deny-set-visible-on-all-workspaces":{"identifier":"deny-set-visible-on-all-workspaces","description":"Denies the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible_on_all_workspaces"]}},"deny-show":{"identifier":"deny-show","description":"Denies the show command without any pre-configured scope.","commands":{"allow":[],"deny":["show"]}},"deny-start-dragging":{"identifier":"deny-start-dragging","description":"Denies the start_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_dragging"]}},"deny-start-resize-dragging":{"identifier":"deny-start-resize-dragging","description":"Denies the start_resize_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_resize_dragging"]}},"deny-theme":{"identifier":"deny-theme","description":"Denies the theme command without any pre-configured scope.","commands":{"allow":[],"deny":["theme"]}},"deny-title":{"identifier":"deny-title","description":"Denies the title command without any pre-configured scope.","commands":{"allow":[],"deny":["title"]}},"deny-toggle-maximize":{"identifier":"deny-toggle-maximize","description":"Denies the toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["toggle_maximize"]}},"deny-unmaximize":{"identifier":"deny-unmaximize","description":"Denies the unmaximize command without any pre-configured scope.","commands":{"allow":[],"deny":["unmaximize"]}},"deny-unminimize":{"identifier":"deny-unminimize","description":"Denies the unminimize command without any pre-configured scope.","commands":{"allow":[],"deny":["unminimize"]}}},"permission_sets":{},"global_scope_schema":null},"dialog":{"default_permission":{"identifier":"default","description":"This permission set configures the types of dialogs\navailable from the dialog plugin.\n\n#### Granted Permissions\n\nAll dialog types are enabled.\n\n\n","permissions":["allow-message","allow-save","allow-open"]},"permissions":{"allow-ask":{"identifier":"allow-ask","description":"Enables the ask command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `allow-message` and will be removed in v3)","commands":{"allow":["message"],"deny":[]}},"allow-confirm":{"identifier":"allow-confirm","description":"Enables the confirm command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `allow-message` and will be removed in v3)","commands":{"allow":["message"],"deny":[]}},"allow-message":{"identifier":"allow-message","description":"Enables the message command without any pre-configured scope.","commands":{"allow":["message"],"deny":[]}},"allow-open":{"identifier":"allow-open","description":"Enables the open command without any pre-configured scope.","commands":{"allow":["open"],"deny":[]}},"allow-save":{"identifier":"allow-save","description":"Enables the save command without any pre-configured scope.","commands":{"allow":["save"],"deny":[]}},"deny-ask":{"identifier":"deny-ask","description":"Denies the ask command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `deny-message` and will be removed in v3)","commands":{"allow":[],"deny":["message"]}},"deny-confirm":{"identifier":"deny-confirm","description":"Denies the confirm command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `deny-message` and will be removed in v3)","commands":{"allow":[],"deny":["message"]}},"deny-message":{"identifier":"deny-message","description":"Denies the message command without any pre-configured scope.","commands":{"allow":[],"deny":["message"]}},"deny-open":{"identifier":"deny-open","description":"Denies the open command without any pre-configured scope.","commands":{"allow":[],"deny":["open"]}},"deny-save":{"identifier":"deny-save","description":"Denies the save command without any pre-configured scope.","commands":{"allow":[],"deny":["save"]}}},"permission_sets":{},"global_scope_schema":null},"notification":{"default_permission":{"identifier":"default","description":"This permission set configures which\nnotification features are by default exposed.\n\n#### Granted Permissions\n\nIt allows all notification related features.\n\n","permissions":["allow-is-permission-granted","allow-request-permission","allow-notify","allow-register-action-types","allow-register-listener","allow-cancel","allow-get-pending","allow-remove-active","allow-get-active","allow-check-permissions","allow-show","allow-batch","allow-list-channels","allow-delete-channel","allow-create-channel","allow-permission-state"]},"permissions":{"allow-batch":{"identifier":"allow-batch","description":"Enables the batch command without any pre-configured scope.","commands":{"allow":["batch"],"deny":[]}},"allow-cancel":{"identifier":"allow-cancel","description":"Enables the cancel command without any pre-configured scope.","commands":{"allow":["cancel"],"deny":[]}},"allow-check-permissions":{"identifier":"allow-check-permissions","description":"Enables the check_permissions command without any pre-configured scope.","commands":{"allow":["check_permissions"],"deny":[]}},"allow-create-channel":{"identifier":"allow-create-channel","description":"Enables the create_channel command without any pre-configured scope.","commands":{"allow":["create_channel"],"deny":[]}},"allow-delete-channel":{"identifier":"allow-delete-channel","description":"Enables the delete_channel command without any pre-configured scope.","commands":{"allow":["delete_channel"],"deny":[]}},"allow-get-active":{"identifier":"allow-get-active","description":"Enables the get_active command without any pre-configured scope.","commands":{"allow":["get_active"],"deny":[]}},"allow-get-pending":{"identifier":"allow-get-pending","description":"Enables the get_pending command without any pre-configured scope.","commands":{"allow":["get_pending"],"deny":[]}},"allow-is-permission-granted":{"identifier":"allow-is-permission-granted","description":"Enables the is_permission_granted command without any pre-configured scope.","commands":{"allow":["is_permission_granted"],"deny":[]}},"allow-list-channels":{"identifier":"allow-list-channels","description":"Enables the list_channels command without any pre-configured scope.","commands":{"allow":["list_channels"],"deny":[]}},"allow-notify":{"identifier":"allow-notify","description":"Enables the notify command without any pre-configured scope.","commands":{"allow":["notify"],"deny":[]}},"allow-permission-state":{"identifier":"allow-permission-state","description":"Enables the permission_state command without any pre-configured scope.","commands":{"allow":["permission_state"],"deny":[]}},"allow-register-action-types":{"identifier":"allow-register-action-types","description":"Enables the register_action_types command without any pre-configured scope.","commands":{"allow":["register_action_types"],"deny":[]}},"allow-register-listener":{"identifier":"allow-register-listener","description":"Enables the register_listener command without any pre-configured scope.","commands":{"allow":["register_listener"],"deny":[]}},"allow-remove-active":{"identifier":"allow-remove-active","description":"Enables the remove_active command without any pre-configured scope.","commands":{"allow":["remove_active"],"deny":[]}},"allow-request-permission":{"identifier":"allow-request-permission","description":"Enables the request_permission command without any pre-configured scope.","commands":{"allow":["request_permission"],"deny":[]}},"allow-show":{"identifier":"allow-show","description":"Enables the show command without any pre-configured scope.","commands":{"allow":["show"],"deny":[]}},"deny-batch":{"identifier":"deny-batch","description":"Denies the batch command without any pre-configured scope.","commands":{"allow":[],"deny":["batch"]}},"deny-cancel":{"identifier":"deny-cancel","description":"Denies the cancel command without any pre-configured scope.","commands":{"allow":[],"deny":["cancel"]}},"deny-check-permissions":{"identifier":"deny-check-permissions","description":"Denies the check_permissions command without any pre-configured scope.","commands":{"allow":[],"deny":["check_permissions"]}},"deny-create-channel":{"identifier":"deny-create-channel","description":"Denies the create_channel command without any pre-configured scope.","commands":{"allow":[],"deny":["create_channel"]}},"deny-delete-channel":{"identifier":"deny-delete-channel","description":"Denies the delete_channel command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_channel"]}},"deny-get-active":{"identifier":"deny-get-active","description":"Denies the get_active command without any pre-configured scope.","commands":{"allow":[],"deny":["get_active"]}},"deny-get-pending":{"identifier":"deny-get-pending","description":"Denies the get_pending command without any pre-configured scope.","commands":{"allow":[],"deny":["get_pending"]}},"deny-is-permission-granted":{"identifier":"deny-is-permission-granted","description":"Denies the is_permission_granted command without any pre-configured scope.","commands":{"allow":[],"deny":["is_permission_granted"]}},"deny-list-channels":{"identifier":"deny-list-channels","description":"Denies the list_channels command without any pre-configured scope.","commands":{"allow":[],"deny":["list_channels"]}},"deny-notify":{"identifier":"deny-notify","description":"Denies the notify command without any pre-configured scope.","commands":{"allow":[],"deny":["notify"]}},"deny-permission-state":{"identifier":"deny-permission-state","description":"Denies the permission_state command without any pre-configured scope.","commands":{"allow":[],"deny":["permission_state"]}},"deny-register-action-types":{"identifier":"deny-register-action-types","description":"Denies the register_action_types command without any pre-configured scope.","commands":{"allow":[],"deny":["register_action_types"]}},"deny-register-listener":{"identifier":"deny-register-listener","description":"Denies the register_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["register_listener"]}},"deny-remove-active":{"identifier":"deny-remove-active","description":"Denies the remove_active command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_active"]}},"deny-request-permission":{"identifier":"deny-request-permission","description":"Denies the request_permission command without any pre-configured scope.","commands":{"allow":[],"deny":["request_permission"]}},"deny-show":{"identifier":"deny-show","description":"Denies the show command without any pre-configured scope.","commands":{"allow":[],"deny":["show"]}}},"permission_sets":{},"global_scope_schema":null},"opener":{"default_permission":{"identifier":"default","description":"This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application\nas well as reveal file in directories using default file explorer","permissions":["allow-open-url","allow-reveal-item-in-dir","allow-default-urls"]},"permissions":{"allow-default-urls":{"identifier":"allow-default-urls","description":"This enables opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"url":"mailto:*"},{"url":"tel:*"},{"url":"http://*"},{"url":"https://*"}]}},"allow-open-path":{"identifier":"allow-open-path","description":"Enables the open_path command without any pre-configured scope.","commands":{"allow":["open_path"],"deny":[]}},"allow-open-url":{"identifier":"allow-open-url","description":"Enables the open_url command without any pre-configured scope.","commands":{"allow":["open_url"],"deny":[]}},"allow-reveal-item-in-dir":{"identifier":"allow-reveal-item-in-dir","description":"Enables the reveal_item_in_dir command without any pre-configured scope.","commands":{"allow":["reveal_item_in_dir"],"deny":[]}},"deny-open-path":{"identifier":"deny-open-path","description":"Denies the open_path command without any pre-configured scope.","commands":{"allow":[],"deny":["open_path"]}},"deny-open-url":{"identifier":"deny-open-url","description":"Denies the open_url command without any pre-configured scope.","commands":{"allow":[],"deny":["open_url"]}},"deny-reveal-item-in-dir":{"identifier":"deny-reveal-item-in-dir","description":"Denies the reveal_item_in_dir command without any pre-configured scope.","commands":{"allow":[],"deny":["reveal_item_in_dir"]}}},"permission_sets":{},"global_scope_schema":{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"properties":{"app":{"allOf":[{"$ref":"#/definitions/Application"}],"description":"An application to open this url with, for example: firefox."},"url":{"description":"A URL that can be opened by the webview when using the Opener APIs.\n\nWildcards can be used following the UNIX glob pattern.\n\nExamples:\n\n- \"https://*\" : allows all HTTPS origin\n\n- \"https://*.github.com/tauri-apps/tauri\": allows any subdomain of \"github.com\" with the \"tauri-apps/api\" path\n\n- \"https://myapi.service.com/users/*\": allows access to any URLs that begins with \"https://myapi.service.com/users/\"","type":"string"}},"required":["url"],"type":"object"},{"properties":{"app":{"allOf":[{"$ref":"#/definitions/Application"}],"description":"An application to open this path with, for example: xdg-open."},"path":{"description":"A path that can be opened by the webview when using the Opener APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.","type":"string"}},"required":["path"],"type":"object"}],"definitions":{"Application":{"anyOf":[{"description":"Open in default application.","type":"null"},{"description":"If true, allow open with any application.","type":"boolean"},{"description":"Allow specific application to open with.","type":"string"}],"description":"Opener scope application."}},"description":"Opener scope entry.","title":"OpenerScopeEntry"}}} \ No newline at end of file diff --git a/app/src-tauri/gen/schemas/capabilities.json b/app/src-tauri/gen/schemas/capabilities.json index a314e84..9f295d1 100644 --- a/app/src-tauri/gen/schemas/capabilities.json +++ b/app/src-tauri/gen/schemas/capabilities.json @@ -1 +1 @@ -{"default":{"identifier":"default","description":"Default capability for the main window","local":true,"windows":["main"],"permissions":["core:default","notification:default"]}} \ No newline at end of file +{"default":{"identifier":"default","description":"Default capability for the main window","local":true,"windows":["main"],"permissions":["core:default","notification:default","opener:allow-open-url","opener:allow-default-urls"]}} \ No newline at end of file diff --git a/app/src-tauri/gen/schemas/desktop-schema.json b/app/src-tauri/gen/schemas/desktop-schema.json index d0a8e4a..9eee418 100644 --- a/app/src-tauri/gen/schemas/desktop-schema.json +++ b/app/src-tauri/gen/schemas/desktop-schema.json @@ -134,6 +134,174 @@ "description": "Reference a permission or permission set by identifier and extends its scope.", "type": "object", "allOf": [ + { + "if": { + "properties": { + "identifier": { + "anyOf": [ + { + "description": "This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application\nas well as reveal file in directories using default file explorer\n#### This default permission set includes:\n\n- `allow-open-url`\n- `allow-reveal-item-in-dir`\n- `allow-default-urls`", + "type": "string", + "const": "opener:default", + "markdownDescription": "This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application\nas well as reveal file in directories using default file explorer\n#### This default permission set includes:\n\n- `allow-open-url`\n- `allow-reveal-item-in-dir`\n- `allow-default-urls`" + }, + { + "description": "This enables opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application.", + "type": "string", + "const": "opener:allow-default-urls", + "markdownDescription": "This enables opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application." + }, + { + "description": "Enables the open_path command without any pre-configured scope.", + "type": "string", + "const": "opener:allow-open-path", + "markdownDescription": "Enables the open_path command without any pre-configured scope." + }, + { + "description": "Enables the open_url command without any pre-configured scope.", + "type": "string", + "const": "opener:allow-open-url", + "markdownDescription": "Enables the open_url command without any pre-configured scope." + }, + { + "description": "Enables the reveal_item_in_dir command without any pre-configured scope.", + "type": "string", + "const": "opener:allow-reveal-item-in-dir", + "markdownDescription": "Enables the reveal_item_in_dir command without any pre-configured scope." + }, + { + "description": "Denies the open_path command without any pre-configured scope.", + "type": "string", + "const": "opener:deny-open-path", + "markdownDescription": "Denies the open_path command without any pre-configured scope." + }, + { + "description": "Denies the open_url command without any pre-configured scope.", + "type": "string", + "const": "opener:deny-open-url", + "markdownDescription": "Denies the open_url command without any pre-configured scope." + }, + { + "description": "Denies the reveal_item_in_dir command without any pre-configured scope.", + "type": "string", + "const": "opener:deny-reveal-item-in-dir", + "markdownDescription": "Denies the reveal_item_in_dir command without any pre-configured scope." + } + ] + } + } + }, + "then": { + "properties": { + "allow": { + "items": { + "title": "OpenerScopeEntry", + "description": "Opener scope entry.", + "anyOf": [ + { + "type": "object", + "required": [ + "url" + ], + "properties": { + "app": { + "description": "An application to open this url with, for example: firefox.", + "allOf": [ + { + "$ref": "#/definitions/Application" + } + ] + }, + "url": { + "description": "A URL that can be opened by the webview when using the Opener APIs.\n\nWildcards can be used following the UNIX glob pattern.\n\nExamples:\n\n- \"https://*\" : allows all HTTPS origin\n\n- \"https://*.github.com/tauri-apps/tauri\": allows any subdomain of \"github.com\" with the \"tauri-apps/api\" path\n\n- \"https://myapi.service.com/users/*\": allows access to any URLs that begins with \"https://myapi.service.com/users/\"", + "type": "string" + } + } + }, + { + "type": "object", + "required": [ + "path" + ], + "properties": { + "app": { + "description": "An application to open this path with, for example: xdg-open.", + "allOf": [ + { + "$ref": "#/definitions/Application" + } + ] + }, + "path": { + "description": "A path that can be opened by the webview when using the Opener APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.", + "type": "string" + } + } + } + ] + } + }, + "deny": { + "items": { + "title": "OpenerScopeEntry", + "description": "Opener scope entry.", + "anyOf": [ + { + "type": "object", + "required": [ + "url" + ], + "properties": { + "app": { + "description": "An application to open this url with, for example: firefox.", + "allOf": [ + { + "$ref": "#/definitions/Application" + } + ] + }, + "url": { + "description": "A URL that can be opened by the webview when using the Opener APIs.\n\nWildcards can be used following the UNIX glob pattern.\n\nExamples:\n\n- \"https://*\" : allows all HTTPS origin\n\n- \"https://*.github.com/tauri-apps/tauri\": allows any subdomain of \"github.com\" with the \"tauri-apps/api\" path\n\n- \"https://myapi.service.com/users/*\": allows access to any URLs that begins with \"https://myapi.service.com/users/\"", + "type": "string" + } + } + }, + { + "type": "object", + "required": [ + "path" + ], + "properties": { + "app": { + "description": "An application to open this path with, for example: xdg-open.", + "allOf": [ + { + "$ref": "#/definitions/Application" + } + ] + }, + "path": { + "description": "A path that can be opened by the webview when using the Opener APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.", + "type": "string" + } + } + } + ] + } + } + } + }, + "properties": { + "identifier": { + "description": "Identifier of the permission or permission set.", + "allOf": [ + { + "$ref": "#/definitions/Identifier" + } + ] + } + } + }, { "properties": { "identifier": { @@ -2455,6 +2623,54 @@ "type": "string", "const": "notification:deny-show", "markdownDescription": "Denies the show command without any pre-configured scope." + }, + { + "description": "This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application\nas well as reveal file in directories using default file explorer\n#### This default permission set includes:\n\n- `allow-open-url`\n- `allow-reveal-item-in-dir`\n- `allow-default-urls`", + "type": "string", + "const": "opener:default", + "markdownDescription": "This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application\nas well as reveal file in directories using default file explorer\n#### This default permission set includes:\n\n- `allow-open-url`\n- `allow-reveal-item-in-dir`\n- `allow-default-urls`" + }, + { + "description": "This enables opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application.", + "type": "string", + "const": "opener:allow-default-urls", + "markdownDescription": "This enables opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application." + }, + { + "description": "Enables the open_path command without any pre-configured scope.", + "type": "string", + "const": "opener:allow-open-path", + "markdownDescription": "Enables the open_path command without any pre-configured scope." + }, + { + "description": "Enables the open_url command without any pre-configured scope.", + "type": "string", + "const": "opener:allow-open-url", + "markdownDescription": "Enables the open_url command without any pre-configured scope." + }, + { + "description": "Enables the reveal_item_in_dir command without any pre-configured scope.", + "type": "string", + "const": "opener:allow-reveal-item-in-dir", + "markdownDescription": "Enables the reveal_item_in_dir command without any pre-configured scope." + }, + { + "description": "Denies the open_path command without any pre-configured scope.", + "type": "string", + "const": "opener:deny-open-path", + "markdownDescription": "Denies the open_path command without any pre-configured scope." + }, + { + "description": "Denies the open_url command without any pre-configured scope.", + "type": "string", + "const": "opener:deny-open-url", + "markdownDescription": "Denies the open_url command without any pre-configured scope." + }, + { + "description": "Denies the reveal_item_in_dir command without any pre-configured scope.", + "type": "string", + "const": "opener:deny-reveal-item-in-dir", + "markdownDescription": "Denies the reveal_item_in_dir command without any pre-configured scope." } ] }, @@ -2551,6 +2767,23 @@ ] } ] + }, + "Application": { + "description": "Opener scope application.", + "anyOf": [ + { + "description": "Open in default application.", + "type": "null" + }, + { + "description": "If true, allow open with any application.", + "type": "boolean" + }, + { + "description": "Allow specific application to open with.", + "type": "string" + } + ] } } } \ No newline at end of file diff --git a/app/src-tauri/gen/schemas/macOS-schema.json b/app/src-tauri/gen/schemas/macOS-schema.json index d0a8e4a..9eee418 100644 --- a/app/src-tauri/gen/schemas/macOS-schema.json +++ b/app/src-tauri/gen/schemas/macOS-schema.json @@ -134,6 +134,174 @@ "description": "Reference a permission or permission set by identifier and extends its scope.", "type": "object", "allOf": [ + { + "if": { + "properties": { + "identifier": { + "anyOf": [ + { + "description": "This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application\nas well as reveal file in directories using default file explorer\n#### This default permission set includes:\n\n- `allow-open-url`\n- `allow-reveal-item-in-dir`\n- `allow-default-urls`", + "type": "string", + "const": "opener:default", + "markdownDescription": "This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application\nas well as reveal file in directories using default file explorer\n#### This default permission set includes:\n\n- `allow-open-url`\n- `allow-reveal-item-in-dir`\n- `allow-default-urls`" + }, + { + "description": "This enables opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application.", + "type": "string", + "const": "opener:allow-default-urls", + "markdownDescription": "This enables opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application." + }, + { + "description": "Enables the open_path command without any pre-configured scope.", + "type": "string", + "const": "opener:allow-open-path", + "markdownDescription": "Enables the open_path command without any pre-configured scope." + }, + { + "description": "Enables the open_url command without any pre-configured scope.", + "type": "string", + "const": "opener:allow-open-url", + "markdownDescription": "Enables the open_url command without any pre-configured scope." + }, + { + "description": "Enables the reveal_item_in_dir command without any pre-configured scope.", + "type": "string", + "const": "opener:allow-reveal-item-in-dir", + "markdownDescription": "Enables the reveal_item_in_dir command without any pre-configured scope." + }, + { + "description": "Denies the open_path command without any pre-configured scope.", + "type": "string", + "const": "opener:deny-open-path", + "markdownDescription": "Denies the open_path command without any pre-configured scope." + }, + { + "description": "Denies the open_url command without any pre-configured scope.", + "type": "string", + "const": "opener:deny-open-url", + "markdownDescription": "Denies the open_url command without any pre-configured scope." + }, + { + "description": "Denies the reveal_item_in_dir command without any pre-configured scope.", + "type": "string", + "const": "opener:deny-reveal-item-in-dir", + "markdownDescription": "Denies the reveal_item_in_dir command without any pre-configured scope." + } + ] + } + } + }, + "then": { + "properties": { + "allow": { + "items": { + "title": "OpenerScopeEntry", + "description": "Opener scope entry.", + "anyOf": [ + { + "type": "object", + "required": [ + "url" + ], + "properties": { + "app": { + "description": "An application to open this url with, for example: firefox.", + "allOf": [ + { + "$ref": "#/definitions/Application" + } + ] + }, + "url": { + "description": "A URL that can be opened by the webview when using the Opener APIs.\n\nWildcards can be used following the UNIX glob pattern.\n\nExamples:\n\n- \"https://*\" : allows all HTTPS origin\n\n- \"https://*.github.com/tauri-apps/tauri\": allows any subdomain of \"github.com\" with the \"tauri-apps/api\" path\n\n- \"https://myapi.service.com/users/*\": allows access to any URLs that begins with \"https://myapi.service.com/users/\"", + "type": "string" + } + } + }, + { + "type": "object", + "required": [ + "path" + ], + "properties": { + "app": { + "description": "An application to open this path with, for example: xdg-open.", + "allOf": [ + { + "$ref": "#/definitions/Application" + } + ] + }, + "path": { + "description": "A path that can be opened by the webview when using the Opener APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.", + "type": "string" + } + } + } + ] + } + }, + "deny": { + "items": { + "title": "OpenerScopeEntry", + "description": "Opener scope entry.", + "anyOf": [ + { + "type": "object", + "required": [ + "url" + ], + "properties": { + "app": { + "description": "An application to open this url with, for example: firefox.", + "allOf": [ + { + "$ref": "#/definitions/Application" + } + ] + }, + "url": { + "description": "A URL that can be opened by the webview when using the Opener APIs.\n\nWildcards can be used following the UNIX glob pattern.\n\nExamples:\n\n- \"https://*\" : allows all HTTPS origin\n\n- \"https://*.github.com/tauri-apps/tauri\": allows any subdomain of \"github.com\" with the \"tauri-apps/api\" path\n\n- \"https://myapi.service.com/users/*\": allows access to any URLs that begins with \"https://myapi.service.com/users/\"", + "type": "string" + } + } + }, + { + "type": "object", + "required": [ + "path" + ], + "properties": { + "app": { + "description": "An application to open this path with, for example: xdg-open.", + "allOf": [ + { + "$ref": "#/definitions/Application" + } + ] + }, + "path": { + "description": "A path that can be opened by the webview when using the Opener APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.", + "type": "string" + } + } + } + ] + } + } + } + }, + "properties": { + "identifier": { + "description": "Identifier of the permission or permission set.", + "allOf": [ + { + "$ref": "#/definitions/Identifier" + } + ] + } + } + }, { "properties": { "identifier": { @@ -2455,6 +2623,54 @@ "type": "string", "const": "notification:deny-show", "markdownDescription": "Denies the show command without any pre-configured scope." + }, + { + "description": "This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application\nas well as reveal file in directories using default file explorer\n#### This default permission set includes:\n\n- `allow-open-url`\n- `allow-reveal-item-in-dir`\n- `allow-default-urls`", + "type": "string", + "const": "opener:default", + "markdownDescription": "This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application\nas well as reveal file in directories using default file explorer\n#### This default permission set includes:\n\n- `allow-open-url`\n- `allow-reveal-item-in-dir`\n- `allow-default-urls`" + }, + { + "description": "This enables opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application.", + "type": "string", + "const": "opener:allow-default-urls", + "markdownDescription": "This enables opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application." + }, + { + "description": "Enables the open_path command without any pre-configured scope.", + "type": "string", + "const": "opener:allow-open-path", + "markdownDescription": "Enables the open_path command without any pre-configured scope." + }, + { + "description": "Enables the open_url command without any pre-configured scope.", + "type": "string", + "const": "opener:allow-open-url", + "markdownDescription": "Enables the open_url command without any pre-configured scope." + }, + { + "description": "Enables the reveal_item_in_dir command without any pre-configured scope.", + "type": "string", + "const": "opener:allow-reveal-item-in-dir", + "markdownDescription": "Enables the reveal_item_in_dir command without any pre-configured scope." + }, + { + "description": "Denies the open_path command without any pre-configured scope.", + "type": "string", + "const": "opener:deny-open-path", + "markdownDescription": "Denies the open_path command without any pre-configured scope." + }, + { + "description": "Denies the open_url command without any pre-configured scope.", + "type": "string", + "const": "opener:deny-open-url", + "markdownDescription": "Denies the open_url command without any pre-configured scope." + }, + { + "description": "Denies the reveal_item_in_dir command without any pre-configured scope.", + "type": "string", + "const": "opener:deny-reveal-item-in-dir", + "markdownDescription": "Denies the reveal_item_in_dir command without any pre-configured scope." } ] }, @@ -2551,6 +2767,23 @@ ] } ] + }, + "Application": { + "description": "Opener scope application.", + "anyOf": [ + { + "description": "Open in default application.", + "type": "null" + }, + { + "description": "If true, allow open with any application.", + "type": "boolean" + }, + { + "description": "Allow specific application to open with.", + "type": "string" + } + ] } } } \ No newline at end of file diff --git a/app/src-tauri/icons/Square107x107Logo.png b/app/src-tauri/icons/Square107x107Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e379ce49391e6f11ae3cdc9918f5b0ab67404624 GIT binary patch literal 4186 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 N002ovPDHLkV1h@8SO)+A literal 0 HcmV?d00001 diff --git a/app/src-tauri/icons/Square150x150Logo.png b/app/src-tauri/icons/Square150x150Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..931e45a8a3d417ed961315f9a88cbbec9e8adabf GIT binary patch literal 5609 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 Dq%Npq literal 0 HcmV?d00001 diff --git a/app/src-tauri/icons/Square284x284Logo.png b/app/src-tauri/icons/Square284x284Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..6bf20d2b9a4f63a893595270622d386e1e894e6b GIT binary patch literal 10786 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 EAEkV^jsO4v literal 0 HcmV?d00001 diff --git a/app/src-tauri/icons/Square30x30Logo.png b/app/src-tauri/icons/Square30x30Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..d59e34ea0580496a7ee926435b60f6759a8bf423 GIT binary patch literal 923 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 E1Li$B761SM literal 0 HcmV?d00001 diff --git a/app/src-tauri/icons/Square44x44Logo.png b/app/src-tauri/icons/Square44x44Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..22941b8ad792346d59559b4b995966bdbcc93dda GIT binary patch literal 1454 zcmV;f1yTBmP)O^8+g-$2c5>7&Q(NDB6#tj!!!;Ef`|u2!Hd`j z85P8XFr(9hio3XPxLayj{r=Y(MYc}0rBzc?LI)(785#NF%NKvVc$sM?t=McflfhuH z;@D!byye{oK7Y^qH@pRqXUY|CtIYC=_rLr3`ThNn&7iNizrXjny}fPas%l?fUlXob ztybcCkI)*8MlzYCTe`WqL8rg@`1t(7^|y-Apo5LNySw{?8>I0bka!{^Uo(&g3-j1` zch8U}v)N4Sz<+q3$>#^cibn7(L;eX^ZeZamKk|-ZVJ1Hf`X_kWh+4?N3t>?JYth(R zMZ@gox2%`HFa%#m!}|(U35oK&dS_(V513$@X1%g#uqLpYwa_J#l)SeXHBY}cF!d$N zA;43i%axGFA@&NuHhM+HNUyB?0R92|+JVh(Oj_(&omw$f-h_~ZW7H%2!?DWBJPr&1 z6kdr0%+bSKUtbgF1kz4RAL%8DpxK4xQb7Fu{pI}V=!oX#=4g3&nU0T-r7j{Of)W!G zDJ3O^A|oU5VnCgpofH!jLnS38NV+@&46iEC$;nCT>guAgu`$}(+7i#{B>|7d#>P@n zQ4wu!Zc=Y=uhav)qM|}P{~UQd8yLxbKtKTP?CeloT^;rJ_lu`OLP97wI9NQdWC9S# zdbhJQ12JjqY5FQ>b?a$861U4ur zh@zsRq#Z^850aXi`XXSba|s2Dp)V~hmGiK$Fgs9jaWNGZ7E)STnjIJqvADQM_4W0% zw6r8L!b9O+y#Dm`^iXDICS6@!$+_Er;Te8|m0`@v%A)i0a~b}k;B}^c63=cxb81CxoY8eH{02&57qyihT1)KUlTn0wR=%}x+k48pDM6>7!VX3{n zUElx;Z>mX#doUs$9UU}2J}&nF8utti4pLrTo}8l|HZgJ0hnlP|NdjJiF?52-1|7mX z6B82@7Z>*^EGeyTY-~_QMuvDE@<1Gh{t<(>x3}dQJdOL))6;2qc-X1M#Q2nU0Xs7@ zL(|jK0(x?CLRD2&0t-FrVfFDD6Aj@D=KyPHXb{-b(^HC%j~6+?7Hq=y?Ch-c_0*fs zlfWobQ&Te0;B76>>m$ObkL9TpZA#5VeH zdD1C8!AnS7Fyt7{heM}=e`{+it*oqwTu|USghAvI(6V|!HIZQp$FL3gI1??LUg;1w zQ33-4AFWXO2g7whs1JM4uk!4}2Si(S-7QPAKK^3pP-<#w9(h6mpE*!5A60&RnLWZ&ZjDj!7999bK|#G zfVvYFY+z)Yt48eyh)Bwd-|p`<@K3MmgEk+&!%vsbeDG1r_$^+@Yth&~^78-r_5GBA zo^gO*OSpgr+E*H@?SIgS?Q5}uK?j?u{?$PeRt@?9Pr-WrRsB=o&EQNhcW3BApX#3r zSTxTb*nccK`gO~Ve&)Jd-rjJ1fQP($h0uj)z|bAq{Q8FN3oosr1Rk0*4gdfE07*qo IM6N<$f`Q_;00000 literal 0 HcmV?d00001 diff --git a/app/src-tauri/icons/Square71x71Logo.png b/app/src-tauri/icons/Square71x71Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..5a23dc6c5b7b0f7e71a051885256e6a31c3da0d7 GIT binary patch literal 2611 zcmV-33e5G1P)#V=pJ{HK2X`fCGF^7NFXScIjHB*ltOE>KWX0+7=6bB2$BJKGH~hD>#% z41j?tdK4%qDRl{$z}3REi}uk@m5j9tPzLP>hhoezpEJhj4fz3ELQ=<5;Bv4iS&5O} zph1HS!y{xLK7IQ1OT&f@&j#8e@c>K|K!O&1{`~o0jT$w|4sZ$QFI%=Otjhg|$xl21 z;}HQJBC`E~_BiGQqD!dGM11i@iPNM6%0r}8e}2<*mWj`=!8u9dJ036G_k>mW zU?@Ea6Yku(<9hqhp+oZG#S7|mNakPT-vs68*wwP8xVev8*@x>n>1-6&6+iHZU>4(d?+(#&XjZK&PmIbEgggGwG}@Ckw>HbYxF+9Hx~F{_@Kckbm#2Z zvktVhe(W6J@`0?ZJTC_G9djNI+{{1p|@Zd@X zs8Yb8L4;`{5K%>6N^sxJ9WeIYyLS$}88c?c?Afy=H8r)Ec-wCcNYkMmJ9fyNIddGd zN^&oLixAThCr+G@UcGu%nlM)w9HTcqHhlPSxpnK76Hj9d*IvDPB?AWzbi&-XZ(o;B z1AH;|wZgz=EHrG`Fz0H%rdT92fDHVeJ$uTTGiO{Um>bvV+{z4HvSf*K12n`32JM(O zZJL}sdC~y`tB5Z2EJsZ2A6*n(W@a+m#C=O<%~T ze(b;=->qu|9Bbs-wQGxoQ5b>nqCZ(#S&?W}o={Q-EWt(eogvpi-*sRSpdh>%85uHe z+&EW{>5FL*_W1TyJ2*z~Q>RYJ`Sa(U&e&7{%C~FRPBw1b7-2&!hT7zE)v8rayAWA( zTimf*w{Eg@=~BlM>Y;q0?7$xE!oG^Ir^1@EbLY;#L>lHiixw?%lSdjAOXRRQ z*p(|+WXqN<(yCRfh&$161boGc6)tL#Pq~zzo}TXN^Xs52?5dGy1$F6_r%#{CkRd~y z8`wMvU11hY@1ZZTOa={HTx#^_(GDO6e&kawgTaXtC(5o}yCPv48(y!QLlw}?7=SV^X;t`a7-lWVQYjRQW45n1QDYF<;IO0PG{DwTj%aKCczM<2MZT2 zbZmr`ewp@}`urh;=@0frPdlo7Ze>O>BDTSqv4(*dlfm*t7+`QC^kwnl#q#092d5|I zG6u|`L4#!O+_{b=(b`4%)I)t;x^#(%xD8DCUXiF3{t?#LkR8oIS1gR<0^PfJca8SP zCMCHNzhPiFfBt;e5TcH`h4nlQUA=m>%l8=?Juadw>NRbl4D4cl=4({7xRtSlDB(8< zHV{F|qp~$})22<47HZ5%|0$_+L?q;rAR-#^?S=fku6$1i2gpI{7P z3o~d;G;7Fbnoyp8Q4jS|FZE*w_FxzGVP`Buib`Fwu<^v{)2H3j1O{8vr%!idlJcl* zkqW^aHENU_z;U0kia{Ttn<+pngE%XX`?hc2?g9l1X)LJy=m4<7>p5oBk33+rdjV#_ zf(3H%;zb84c`#u8`t=T=ST%$4qG$XSeU??>#V-H9p3(oMjCIL_#6XZWXF@v9scb>) z@2u!WKhdb@YG94OYHQ)wf5Z#>EF9Nlsx|K++q10b7YAxG@#cDdZFqydwgBS4!Hz|_ z!SFiqCVTLgqCl&10p~#=q6u&Ud;&Zk08Wl&CUE&b4(jF?*{k4i;uW|OXAOt#53v7b zuL?aE*0n#_|J|JmbVw1_>Bes5^$50TNQy(&uq#25 zw*Rhr(LdO_AsqbkzDS4Nv&`q>EvyIa4F^-2S>O@bk$?|uQNUgf!S*Qy@dA*ymj!?6 zO!u~GaDza?R{owndy?4XLTU9on_d{z>bfh*_dP6NBo>{)S_T~CZLJ`OSM z*`-UA|JJPE>e8NFjAIDby579e6W{!pHZ&`3w>Qn35bR*kMSkMl-n66tEUle>`X4ao V;)4adqHO>G002ovPDHLkV1gk64lDow literal 0 HcmV?d00001 diff --git a/app/src-tauri/icons/Square89x89Logo.png b/app/src-tauri/icons/Square89x89Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..ff0347ad0412dcf25018cea356cacd00426b8c5a GIT binary patch literal 3255 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 literal 0 HcmV?d00001 diff --git a/app/src-tauri/icons/StoreLogo.png b/app/src-tauri/icons/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..3d835df9acda14112e35cf25526df06c1ae438a7 GIT binary patch literal 1715 zcmV;k22A;hP)dC=bSh1+12Tt0^^WUlMAiPQ$KNR_DJ_ccaWqy&AezMB z;9%CGMT^es7mucg&YnFD?@0Y8awI9#HO z(53{kB9RF5qdcP{C_iy1CRTA=F{Xq! zlvG#=q^foJSn9}_MR2FZix+oe3FQz`5+Rw#L&-#Ndo1(ub~s>#KcZ7{G8x6Q zOj+Rb=g&i$r_+B{orp)B(KLdi}-=0nAftBd_6@|(zSB0n6V1gFJG zEyeeqnQih6#T&RQtZatZ5;%a|V~@io%@s1{7A{<9bKGNY#wl2v$nkg(0F3S|Cx8R& z?c2AayE*YXY+1g1xv(+vk5{i=NqTy^9g1bfmYKChAi%0>^CoZJypi_ycIoKokVlUm zNq>Jodw+WllB-s&lA@v_*|~G4?Ay0bE?>SZ7cXA4`72kh$oB2qMLUfdS!PxiaaI@@ z7?7r>Cb@R)nmm90-0nGY4iwL_s{<%w!BO^mru3TyEftzqR;J6g-g$of!kRXNt4e7kRytxf_mt|01Utce$ zPoFkIYu2nWfbZVDGw{0ol$@L#J2RMn`SPU<4-ZRPTAGn?3j%Sh=dzcZODGY*0{qOG zGj`zLtg7yv<^B8jQd(Ln<>lqFW5*6zzka=0fiW^NVlmX*+$;?Z4YG9U(g}H3^1_7+ zMy9s5c1G?sEh1zheMuoLEiF=4S0}4iueOyN8XB^UMBr9bRD2UdF5U9IO`A5!ix)3! zj_lGFjPAh{=JI@gl_&Xq|5xCEtJ9mr( zt_5&b(hFWOmQ?3*9_jieOvbI*&|P$JTX$NG_FI&a|7APK-QKmTTC{w zf-Z_I_v1!{@$A_%a|s0FGR4KkcI{%o9}~n%V`HNnJa|w#J3Ea$av*Zz#0jh7T>IM> zWI+bmSPosiy}dEJS148@WF6eZRoo35HcV3DEJ5Le$chy!zG>4*yN3@Sp0Gr;4ky!l z6>2(TB@%P`#r&+6_p^ho@>HY&LD!3mu(A+fo@=Z?Kz|P$GW|NdpAO;^?9Tl7Iz_6l zug}iAckiAQ=&txto!6~fXKe{?#=-U4wQD6eH`ku=_fk#}D}Kz6@k!)XVGnaF z9DbQU4E!>G;Rr&43nsV$OCI$0+oSU#n}Go=-utgqFh-Gx1if55K?YMP+rJ1R{hXpl zFi|xi);a+Ouz*RiHG|PlV$z=k=IbBN^kjcL({l@fJ=Gu2{sYxrcU^Bui_QQ5002ov JPDHLkV1jD`KS}@q literal 0 HcmV?d00001 diff --git a/app/src-tauri/icons/android/mipmap-anydpi-v26/ic_launcher.xml b/app/src-tauri/icons/android/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..2ffbf24 --- /dev/null +++ b/app/src-tauri/icons/android/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png b/app/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..45e221847d0ac8408af2c8b5bd4a166675dbe057 GIT binary patch literal 1637 zcmV-r2AcVaP)nnk!lhlh!3ccfL*x}T)414LXa2`i7R!Z3u`4x zYowZum=lpv5 zA6$Ar2|tPRyNs?H#Ky*kEiNt=2L=Y-wOB0Q@T&;EbsofY!nfIIG|uep?e!-oC;zs- zzP|m%l6djr#kXr~YvTrkp_d=?`8U$T1aRpv&&kQjcf4>vVgAw4(Hr>C(a~XW*umLI zV`F3A-@JMAmz|v*3JMB3oOY6CuV0S|D&OS<$gLb32{xi*FSt>+gu>27?<&~& zG69G9{JE2#gr9`QELLmIqi#nzmZSH0b~hh8Hxlf><(E^He}FzdJ|?|he+twQ5q9ft z5iy>}>Vp7BdU;-6UZ%OZIhviFmH(Xc2(h@hI7&}Xr_9VuY5(}~V~UQBrt0cy`F?nK zC}h1(!j=GUoT#_Am!3U)MoUXer=YOHO2u$pzkZ#NK1@zd$}=Z*R8>`V`rWG}6fh9z z@9(GP=4M)0SfH@5FyaJ_K79BfL=-ra$%MQ|Bm`pd@$s~^wM9`;QMP*s?~zahIQ-MY zhYzWxrA2_p#Kh3%<|bhilarG}*REZYmEPUmrMGY2(wjGL)x-SlPkN_rtO5DGHU+e)ANJvPa!NEZxfM?}0 zaVz_P&0xO{a96KhrGbF~N=!@?A{eK!u~Ejw_?X8d5nD+ClRSO;RNSbF2~aB#0SKsu z(rdJbuJ`ox(94%E#b!VRs*{_WE2;?fL7&&JU(?Xgkc^LhT5LnFRSLKudUzYN*-WLS zrNpNqvf5A$r3SDANa5YPcVhT_enq@@r}FZ0DlRUT_JxIoR8mqR<6yku;o(n)s!%7SqHH37q+PKgk1>QRtb6>5fMR=k&*HY68MD#R#sN1t*uQA{L-aM0xl^jiTEt*?}@oRq=)|D z;o&kKo-w{w5=JeCjSKD)kru8KUInYHypd8Ve8*}-O#l}9t|GYYcp$AJ{Km$Hv_l`; z`OcMu@*1~q-=>C!2AY|f5ig_c0bT|-A3IW7S{mi$hwyi5wvL|75QXkN{vW>GQ15m7{0;kA2+b?L` zN1S|)cQQk_-ARoVL5u@{_;q&+3Ov^2(Cm@~H=I%N&Bx9IELMDfx+KAd_r#jJ9QzUj z-~lei*YA=9XO_ckIIq~x!&U722nW zs9T3&pLTu*%!~Pf19*VTzUX-7F}|u&qK?g(Ycc0ZciFJKTF2&m>j`JQ!(0a5c2qU} juhb&^r{aDR-oE|<+}&ybiACCX00000NkvXXu0mjftvMLS literal 0 HcmV?d00001 diff --git a/app/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png b/app/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..3aac9b4eb9fb4413b544a6d23f65f2c8752fa85d GIT binary patch literal 6075 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 FV1n(Te**vj literal 0 HcmV?d00001 diff --git a/app/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png b/app/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..89af1b72b3e03f02d31c06d2aa2787d5040d6697 GIT binary patch literal 1584 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 literal 0 HcmV?d00001 diff --git a/app/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png b/app/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..1f4932fb4cb9dab9c66fc9eb9f375f86eabddbe0 GIT binary patch literal 1291 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 B-HHGJ literal 0 HcmV?d00001 diff --git a/app/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png b/app/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..d2935530125bff34f3bd5316fc8db562710fa530 GIT binary patch literal 2753 zcmV;y3O@CTP)D3O<3a@y(?;BwKoPTU#DzJF;zGrQ z0mYniPXGTDUk&H>=XYo3Ix{_^r=huXXF8nozEyA4sna1Qeu;F6c?diKo&dji0*bwS z`SRswKDR&kTfi+A<42ME@jLsm^82@M-}EoX^8`2xKmiQEl`L7Z5I~=(W7$UzybaI=+Ptj{Q0wj#CEI( z7^LA5<`sBC?b@}aef##(vu97~)2EMG|FB`heZ`9mX=0B06>&4UtV6md?~YM&z6lFH!7(0>eW-=$aGvl_zi32e>?$V-0a4FNBdbV zrWkn^tli@wQ*1MS{CH{8rj2@r1^z#p06Go$_wV1Ai4!Nvp+kq%0s+n}KAi7E7-X?8 za)p;*xdc{AP05y6(Q$y}90q9EvW*z_C(x4#kwJa<@FD9YWHkt5y=e2jd-r6-h!Jw` z+&Kl(0cFR$~Js*kFu(NlPL1!i5WR%0YB041kKB1VoJ zDNUL*iDyBHNJifmE?lT9L={!W!1G9PyL9Oy+qP|!TD59rl!Sx?WCDB}?gKWmgS8Q8 zk&Cd^zkT~wL76&rs?3-%Ljf`ALh~(%{)z~WPs+-GZS?5Ta`Wa*B>+-fg54C>q=-xj z!&tX&ou1#$m1zQE*|-nNvX14;m&?|zTctsR266BWOn_lf#0Ylx?%is=NDtdt5Vh>b z&4S$g-(tdw6)WW8#fzGDy5L*(Wd>m+a1Po;+h`+g%~nd9Q3F|NgRO%^Imzt(pczw{VtBa3?_T+OXg8%L zZZHV!)~%aLQM$=U=mF_2s$prQc%++j1VAl)v_ME)7&>&QYB1olJpj2@nkc>iJ~g6c z%a&=@1nI8zvkk{vyLPQg4Z6=c!j)3aH)qZqZ3El8ZIyhQ6Sgt~o!qctgPb{YMygh= z8Xp|dQLGg3d-dw2mXEd3alTL1>fCZN$2fWNq-Iv(K^G}1ozj+pJkL*}s3kropUNuU^&S9I2}n=S+(D+^A6_Id<$=yf~PyN@-Rk$h05J+p=Yg z+_-V0kW~YUWi_~aalyCBCxLa*qD5-uNRfG&8+Zxo$Q%D-6r7WDTgk%GPBRY5A_Qgn zU}WZv1X-|SA>|C`?{tccXW+nrGHTSQxVIEH#vpNf_UuvVA#hsk07$fc?AWoI06+xi zF>UAE0|pGxwzySL%d{ZC;#8($K`c|&k7b@cdsfrIu=Qi@SR=r&9a%{#1XxCc^xVFE zTNW%>pfZ9~n8X1ZV~WO&8*2h!@xa<(nGkJ2_i0nu3urriV7p9tLB>3Qg*p$V1Q%Q^ zi&U?3=gvA=LdQ}8-{x`+jQR8DtBzCqvG2`-IrrSTb5;MtGhUn%!e|4dV9R=3FJ*uF z;Pxpi1pLlm%#|N%J(gj(qhWsU-MhC2I09a>1ejD|`B)`sE0Z@i$>I*kNJ)`6YECxC z>@FM!xguuJ763Pr+&0sPbji@KaE)b3{~1_O3UKwG&H*@D-KkTjq%RL~WsPHyA~I;B zRDtCixUTe2VI{~i7hqGF|8?m~$BrH2sjF>g85DES^d(bqAeL_Zx4?)t6Wm)~v4YVlnoq{! z&T_e6VeODGWy%yC;F0eaHOX$JZx(BlOPGz0U%YscKNsg(<4NAn zQcC8ADJ7HpTP(0alF1a=58K*RZixU(XM2ky;~Be8*viDXFjY!7(52cLjzw*T{iaW! zuJg85Ro{*JBkXjyH|+!zmjoM>S#ZN*?YrV!#%OcCn>KCI(J%uf7BreG zomu6d>xA%%ROKRF?M)?#$@sG(!XW%k5VN3e)`;X-fHo^mG`7fQd(%oluG}|fDWYAD zD9$A-R*H~6@o6c!c=MinWrgJF1Do>dCcRW{#`~im+UIX!jqsUqo`f8DYN98>Ke$!? z`UkgqFUWysM|%=-;OXi9{Q>?B8vYF${v9&@ElU0^O8z}!{!M!RO?v)alKyR~{%xxM zeZu~Y+Ww8&{+;r9Nj zV36LM^eRZddFHs@5! zH(C17fNx-UM8>b>kYJ?RomoN~BoY+)t+<``M?^$(D0PFcg~iaR&D^?h;0DaX&jMy~ zdyVft%;s`qwE5&>Zeq95#L1ojikf6%Wkbf$sA^H%s1F`^tOeN=HC*~kI3}-WhrwpgE1?1wzRZdfmC5f@&iwHF5z(a6)$6?chWl_eLlwR z<=}7*hL=OvCYR5kw_>&Gd$Z?y&ueerzI}bQoMdE9b4U7jr@vCm`es$D;p?4Ha%zzx zqipcA8hag{u@jV+z+k#;m0ec^16b}Oho|<+=NFx4hH26+5f_&H&(~-F2A#(ANp=<3 zr6`$^T@Epuc+y zGMozD&et=3bD6wcaq;=ryRFwdcGax6c>Hw;f@Nk&N(Op7!M`pF9_2Hf3W+fGy4TP6 z27R@jz19FvT2ix!P2Wo_QCBJBlzn9#JPdGN{r0JPIR9}^z{8jLm@oGmmlGoo>V{H8 zt*iqA0<0+p=Lc9@fdUYuoysjAA0GyJyS&K^4#-%!rBvbLIPl?}!-5>((GLxJ6!mjB z`6UX6_=EWDI#$`~>gsA@P#f|$c16SIRfT_IXV`N6+*`<;OL6A(*`G}orNeJhOM-?O z4f_ipxx~1n9QECENrZStirluwtM|uj1Km|&u+e*`<%joMFHG+nX=L6=lO#2~Lh>Ej z2!7X@IG*wt%J3+utW@#an{U5n0(ZZE>;oJJQK&Ku*E-}mEqUhi#>uau<=1~ z+d4N(o?^y`a>R4eOo+q>mBlxs{e#JDde+tajsv}Py;CY`Sv4W`@+Td9k4#Q?ns-&s ziO=Ggg>0;U5WQ`d0X^^GdY4@9I`--`_ahh)WxxNfH=5Ra^^?;vD)q{4I8eelNa$%4 z`HR%6;_SDGR_wScQ&{lnN~&2Q-%BO2T%GK^`fxa3*fZ{;-mt*!+Oc=<{)}2Q)`oP2 z&KcO2maJ7Ljwj~SAX8z`$W`m`NYt!NOw}tj+9+TN8TKsaa}_&3UY;_(i|)*oJLz^9 z>b)%UaH;XePcOQ=eT7GLF82-KR30xyRo!H*7@=tc&0Q_qDRB~#_-}qa8Ex{_#C*c)So`tOR2iQSMr2awjXTF-+eXU>C?f(JKzvTHJBK?b`|0UA@ zHT(xvs8vTurQGDgS=0P7!Xr4_dY$c_&|aYV-Xt_w?mE@Zr$YXC&J{Zs4lL0I=2ONv z1j~Iar#CuRZfk3wWeTzYCV-eg8PDmdjl8$l;wxDxa_smVL}&_5eI+mdF2!Btz$Dl^ z+MFZ2fNJN*+cRR#TZ?h_B>EZDH-UGng7AL=uGfpRn`qe|$Tj7IgZA1Dn|c)22Y&KB zA!fttl=8cxfKZiF@r&*HIo}bXfeKsPWQA4z_rAAQJH$xYWmBb`p6!xB9!y}nq-+(^ zo0Lzce{Q#4UzPJaQA6lKD9IqoJs|Ug)W&^0J13_xke|^ILETVR+0;+VCfOCH4SP{- zT0p*8ycw-C*~WpA7I$0eN9}a8Jo6q%y?>IZhEPJd;q_rwTJ%>GH?{fO2vyG> z`i{s9VoG*UGEI6kF!8L7O(|zyW>y8g^3`*I`b&*pgjYcv8+P&XqTkP=P(y-=dErlH? z`;b!5yru;E=lE?)Ttrv98x9A&K$2*6yg!+HHy6txKf>NWeyjaKx(izb8ITqEVIHiy zKHd1mLU^Xh=WwTXi*rF)2wjSohnv)q?N#%>HS*OwwgtE9WPEgW1OdKxBUOIqgiTL3 zdR;;Qi2Y}-B za{@7ux0dcV9QS)8*;WzFt+G!~7&YB_NRnz6vM6C*=%E1Z)>wAgGiYz#qv(svueAyg zOF+9d>wDVJ=pqxfC<55epz4cS;h5ufNt8sZ zlK{!KvIMh(Mly+-O1r}JBEhyT-}WalL)I#>2fFk(31Ow#DUvsYN&P?L43+jZJ*X4F z!=C?m13>2nuzV;9KzBmz^I&2*zhDS}YW{RF`hL)Rw$=UQB2yL+n7p4iPHC~S9Bafhk777>=O_-mag7=hbjRoizy}#)>h4iNP;3 z-Q>2|vUJac#^Xi&Egpjd3Id6K2DO>t8oZa|T zP0dE>`r>eBP^lqQNFcA%?fIp-Sx{IbG@R5VJV?51Dt&f;*vOun3#IC-yCCM;7FGdz+) zOOVPGo*EF^De#od`*2Y9yyPq1uZHSw0l@cmyBh z_YNm1Hl+HrgX9dy3;Y*^O_$|ADrdjT*}q>1=<~w%iIQ3zdkSF6>(yqq_JP@m6(old zeQ5N<$8V&;^`$7GU^E%rvEZbleimLbrc+y^7Twz0FY9}5<=XbLjRcGi?4*^wr~paW z+>95h(dz326pVltXJrHkteQdi@%`WEXm!!xSmwM-4VsVSNKgdS2yC>ka=x`xT3V{4 z@$~%t#s&=i0XXm{VygUUt%$TuE;(GAYx6;r-DD#kF*2IOWL;1&^Fg9+^@3K^`FIoRS+5_L=}Lt z(=yda_R%yXXJIx@ZZX1GQ9IUUHFQq6>jTZO`nSM@g;iv3EbY>=;9g1oKmGnPnr07J zjLwpU&4SX@^9R?VcAg9>``o2$oo)r*E1bdS#|Dip_vBBC4oxCXt3%0t5dZ%;5p9@L z`7P?sh~o_>(aa|RB#!jPUe4e2TKnzETD`#RJC_2h8u{;6wcD2+v|>W4-#@BLQ25sE zlpX8{=uZ}!`2lz#0?0MJ(Q7g`eP_MX$Cv?1!sGL#=liWVT^$RX8)lIUKU|igAeA>N z4Ei-e5)^pGA_19s?Z}Vhj8c3y2kgw(3obnscoiMP+g~*g=3R&tRqz$A=w_O(uSi2> z<7(Om2l>I;_OA$}gmc8*dtfpKYDs{Dw!h2^PKo3Y6bj`sz++8e;@DzT3gEr1ldN;s zl%IqFjzU%pp1LUephZ@_R=WVnxlei=3}ip)E2-7FdH=d=5W>{|byaJdYf;MIZ9;s$ zy1t_ycEnL&&5aKQNitTj{qd%8kDbbL>skcM77ywjG!l*r4(QVL*71pMl$Lx78u$&y z73i(91nciEm=n~6GEZ+`@LNfg_4G$EdN{`Z$9|27Mp!PUZFF+~m5)eFIHH6q)IAM2 zrV@U}w)WLLSk>RuprTZJg?tflIOA3_oU8G1H3(}(jwEz$%(b@0_07lT3VaRc*gcK8 zeq-ngfA=*dV)lbF;>h_oV+tKj+J`o+B}Fn|CmaEC$66Vf1bZs~h+&hu*r4>;WcX7~ z&AVG*tM8hnEehkOlZF#YJ~*P+O<67kB<`m182=1=GnK}qq0+Nimr^(=LVk1Rh_N68 zm={K|(=6un9dEy(t|qx&KkXS!zmX88XDe6*5e85{vbFz>L4Gs$=nVSDugsFYs9$o@`?AF@D1;R97uYlbzEAb?p=yj+?v z_KY>EGGX;*8L^rfPGVmvROrM1k$HcD)|symL9B(PZ5l03TVpeD=;3` z<=O^{(`R)|Wso{ges$T;>4n!}%bAwStYgH#ghvgXmxlT6iO)NbdU%0y90pSO?L9_7 zm|s)(l#_M~x6Jy%<-gi*&oHk$?9qWc^!z~{HkB3*LW9{4Th)D0n1pSv?5)Y#&DR)0 zG<9BuQh{95>Y`}?+xhSOxYYrQpzA{Hx6LMTOT?n=W+LY~eqey&#KPUAqPln<^I(4T z1JaKc>wWr!B}HG#>3d8pSXn{r`~zLQZTLW_jOiN)6yjDDUHf`;bd_}NU}6Y zNekcjP}wxW@&!hej~*NHc!bhZOexGyY)&t|vyzw7U;rP>&cdQ2ZF=08cI#`UOlK2- z#!(-X0^tq-#O;X)U`q$IF2vGnF$`)xpURi;0%t}E+Fi^F1Cyl);aerQYRywt=A=Ny zh)=r;);=bd-%cqKl-Ba<;*~n`o7~9XeYw+`a9P3l8}^3k;r3|Rn46_VZIyJT5;}<5 zD3nHop~QgHbf;7*UXJRGb3cDShh_b%84}_Dr*4w z$?I$pnkoPnWkAZ_sRmuTl@~l$xs_-T*Bf?+T4B2?c{a`ral9p8C1C^ttNtKh%y>t# z$XuYjoD)+zsl#3?OAMYzW1m4d zAkKlYsjpQ5mt%tbj)`djH;2@&v{ tym^IWHn!W{b#woJ6Y)RYMXzgW4voK44>2!`h@DS>&Lcz3O7-WV{{>Q&ZR!93 literal 0 HcmV?d00001 diff --git a/app/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png b/app/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..b8cefbff6935918c22d275403b91b5b8ce24ee04 GIT binary patch literal 12524 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%0Ax2dSo+x zymJwH`}4mDW~}(MPi#;of?d-!FI4B|NRBfl5A5x-&lWu$@f$G;%7W&h9l`FO1lzS~ zpdX1n++g%Qm0ftFtt|7y{oiylP3bBHoD;8WnZrNWrm^e6>+e@XsL(bw4bwL!`Qe>M_4E4AAQK)Xuqu?bi z=pMXCA%+ma86co!O%Qo+#^1cn+(PfSUnQc)_+Vy+32wbR9T+luIHk&5{2oiqCBBK2 zsCQhLX19p*@30ZPRRgnPDaHL9$9x}P=6@nDWIxSwcGdp4WcUiuKR&L*9s2i5n_F0K zj|5({hBE-*6W|eTMBU$BHNd}LgrKz$lD*&2JXo=9tp@#O4_*%#5}8TEX7rEKLm$_5 z$aMF2qgL~-XF>sg-Om=?MhvcqnaV>VC$q<*@o86rr@~O!PXG1cnYs3}SUG&6uuSyytW7Kt4=AncjLAGe1>=!aTYqevvRFR+)OjT7t` z*vSQ@A+W-RuT@?rs09sDaBeekG-`k>|Q2|iL_g5=o7Cli_ z=@xe}mbf7T#*{L{bk-x5yZFi+NYo@f_hi)8(Z@$WI&NqHkOz|8tJ=BFXA!D`ez6Wh zc-abQDb_F;sI+shqJ6pb^cVN^O9d|~Lj-#g*6O#H(mP)gOGEkygl67=44V7;7+Aok zC^F47e7?q?8g+7RZyJZm<;Zqn$6oEXCS7$fSeTOQ`*^SYS#!VRmuG`QA`|-@h}C+c zc!R^~vdp@3k9k%T>*m2PG1JC?F5MEnIgJ6^fsjp%EOSyq0k6Me?Kjacd$Z~lQ`6Jt z*F)w%0@SHTQ}7)BiUh08{6hQ~d=?EKlg6Nfhmp%Q527a9tb2JI7U4#6dFw(Zf3_`C zJS3*rR8wY$m)>U!@lMOzf@n3`?cqyBj1R|Qo6CMjbu^aj8fsr4Ab?!sfY-855ry2K zm30$2FEjz<6C_avkSjG$sIdM5eis*K>g`|oG)PML_m&~=2YNEK3hBMlntdJ?p0ZyT zy6CfI3x)k6bKD&m7$~!%RuEJ(TbpQ;{LHuZ`5kY{dC2a>j6z^CK~-OEh8e8o>UT@7 zZ?0-8-{zc6P8~O<4ml^1T#iJJ=Kxm_YUFdyO%O@ljHNXL8e@|=`S>1Nn;n4wh>|m{ zlLW;cg&)Pxs!}{L5hU*X#3ukC5Z3N?0GjMGyrf^XvumJkU2c<6OM6PXLbpP;S3H;{ zkvNd31K8TOix&`u^yn z>?r&j1|pISf^$WM&up%~el{#MQvQx$VAQc66ucXQYpwDv&DYvi-7pC2C_I6pVFOpy zF$!0pGjQ+U&z}9djq~8o3`Hr- zi#G1kN6T$e^6^2`j)Ks^J)@PsDeAdDX>lT`?L?`R31J46cYiMr?8_V1@a#!CC54BR zg#4)}hI4VFH2hF32x#{$`qV{cO#K{xw_vUUe=CIR0C6ND8aN}!p=5P59FCNe8V7u$^!b%^ zkS*?}E6d-Tk&jLce*1#lJm#G5f;jTMThM*3>3|-IpFe7Bn6btXKE;%ubX})(_0x-T zK1c$nzT%+`XhWdSy(=3UFYrku!PJsoPtgBnBXuYj9K3%;;ESu_7&&KgIiAG%x-@zC z>$BMh?nx@Pwa~PN2u{QIiuk;tjeUT`pbM{)ZmP_&0>zoe9`7IZrzw?7$hXPsw~M}e zWqA~UD2l~bIsT{0Eoz+8Bj(caL-derXkd%m)sojjQ-27-ru`l9K=QvJrdMIQxV;z1zJqf<>&FG7>!cfre#9jKE^L8>UOH~w^_!#yo9kE z*n&a_OoIP23AmUN6^NmRgHT$k?*yo*OIplvG0tI#ZW4;C#(D!jK)|H-nl<2(NP=35 zT8>&($#-?pJgUk-085ZOn2I^ro47C`ueA_RUTr83kYlBw&DeA2{#ApN-e4{8koUMF?3?X#$HPv z3W@C6gncC?QJ)jGKKqqNCo7CabVd_h!ADRv?6kr`-#AP`ILI50_1aW#b|;y28nx|4l)S*CmrAe9DZO*FbRH zNpDhHR1%CeuGKF%MGj&Zhbku@_m+>wKOHh1doeK5QX8>~t~Le{xMU6zgfg;xPdst{ zBh~M#AI_0op#mdR%OS0AJ1`bL4~SQ-hcWo}T{Z2B&s1vJ45pb&aaO&}q=a|yDKvhe z{*+d-f5n8dkt6tcS(DSPLx8XA_H7#U6aYsqhlpQZExN_>q7=6~kF>C$v=&-LX5%_v zm?%+_sNa5n;uZHL89wxszah}x^M1U)>eV1va#?6OY#wOP5akMmY0`l3fL^?1L9eG_^m{n+LbeB@k}mdU7I+E_aZT~_hqXTWA<}5(2YManQ#?02Tz*#dHV=MC zl31Nxmu_%gSuWoU^Zr`SZLtfJ!p@F~J3hAPNnrP5ib`vUv2M@mfZ&fcyvRg%bZ?p! zuw^hIpH36RBg{eeL{qv7??tU&XZGy z|2@lj+&6koXKX3uxi9c9y)>!fFNedvWym%DLgJhH?tB$VUvy|rST|nHTD|y?#eaYd zt_l}4MD7%jqo@tT`Zn`gJ7b}Ed`d{rVug`YQ@0_|rBvwk%*cpLSVrm3abm-}tO1{{ zrcMbu@%One!%TC;vU_m2Ne0TtRlYF!GBhr?`nV09i_1oQa?v)ImlpP%xjLlM|9tJx7NrsER9a9QFZGs5~ zJmKc-#!05cFL=*hE#eIztjSs;T+=Yr3EpPkTAghB&R-jwv^UF4XAfIdYXVjxr{aMsB5&3QZ&FkKO<~l0=soHrf02}>NA7eODzp1=4CQf z+|xkOMahxEO@WzA;4s@TXQ@V(1;0FAFJ7<1T(y;Fc|e}thc8SD!l4)cDwu%|ewQGR z@wizEd!juvH}8J7R7(@Lv^_P_R>t8nv)3=jqOmPf*~H0Ft-6l|q5C0JrpMChK~JJk zgegycGVi&(JEy(O=rSJWALg`Eafxv$Z7xEZXqmoin{XVZw zrVF&+ZSY(8De}ALbeY}n>PyT3r+e2MS3~KfbCiQdf|%g@aDw&QQO80i(X@7S6XP>6 zYa5f`Qi*9ED>xEat=qLq=)=_5uRehND}GQ-xli=kJddgqcwOhba~_ZJuODRP*vk zdk=}D;^e`Hl%8`UPy$1SOq@C|bAy1slp z^gi0yhTCQiI%<{Z^z!|p$nfCPm=wXi1Nh`Q!C>FZIh#z4Y{_mX!l-XEKx?-LmtiTd zLkHClt)7{JDY^iOhV-Dcvw8BPAGhWFjVtbif%se5ne3%?Iz)GwKnLr98%$r+7ZWf!n{~i0uxQoBf)R!D8JK z2m5;(A?viwp-jd4O@ReE3v}hTzfZy6Vz=J1CS~DJGbhJufe2%Ai(}kiq)sy(F;Nio zB*%XKBi35%38l7Ta1<6k<*eEkI?1yu12z8o;C}^~23q@(9nMtbnBaF0jG+DStY@qT z1Y9a~93^#md(?hpkcEXwLaF_)0}?`A*MS=eaN>+%L^+@S>91e7o-Q*g!vV8S!O!j6 zV$U6ue5By~dZBDY!Lz_*Nso*mKN&$8O(bgyyI4z@- zhKq4QSP(4sZx^x5^-t4Rrpb%8_p6*mS#Vhvu9EzBk8Lw%AD8e}UtTR*s>zPT42bbruZsC2}L}mu8^96 z&Ov%F8_i{2pffM_$RM;Kssm51*JB$jy6h{!z2bRH4DMRYEW61Rd516Th9%v%0e?ka zGljlSj2A}V_*O3B$-hBE8Qj!l933aFw2VEXJ>o(`Xe zTA17%=JZLlLQr;^Aq|iW*Z@-;DH1k^!(1vCMHod=ks>gP0?7nNGjJfWO^9hix=ibp zf^e7%s5f)#O=0ilDq0RD_cDB!?j`U?6^kaGa7@e!7E z?uodaNN^#|>xn=}V%fV&N6lDQT3PGNr)?wVG7wQ}I@9NR?=ctZ9W(ENhDdUhA^0`6 zM@1_&hn)dPk9;!|+t_Nd`sMkk-1G&p%8pjvEpQVPy%a=L(g-WvTG)q)93@$#nfEZt z9SK>7_WjJqhQoNF6z$JHdw0(C5X`Zc8rIoSY-e-@8z9k(c|K}`QPII}8JtKD46)7u zDE2dnXHtCg0(kkuo<9c@(}ipdRRuX*v>el1Ce+13@;56*!Km4v)F)ir<#l;nNJJ2f z``g;pd~;9;HLIAAJ~+%M!f7pyjE)sNsS+qK<7HPk7kl!=8Qq}4XGiY7U>Rk+yl|o7 zH6(8&TA2@|tH6#)u{9MleFYCeJHDsoxigfMJkZ8$^L^objO!jc=SlxCCWDIE zqGWFU(CXE4QAc?Lf*#}yW&Vssb`bRwfWxKl&(xHZ&=+ZCA`X2T@ItxK`O&=x^OYah zYmr)f4c|A+=AVxb(6Pfy(fSI2-7Dhh^uQ>rh8$CYIR? zL4|`gX8BrY?SddyAb2*>`hBo9XqP9svbXoH(y3tFGbYHk^(cH>5jc#f)g!C>0L~6B zV`H1`6_}a55mewn8bg>$q-tiq4FESiN`kWpI)8+;VM-WpazuIH!TZK&SWSa^zO$na z#^T8FR9M31rx~YFy0EQ?TS21xYXWrAxz)HHb2i!h({Ejsl^+3)`YE|E^Ibj*^f+@*tbcO{THIZq)Vm4d`P1nr zMbE6gJT~=O3GlLn;9tx9iOccdB-cwNM$D#KPJI2SKxH4>Ta!j2< zCnI0!l^R<%?Oc9~c=I+dNMB68zI=JIY~HRlHAE{2hrXrc9G^CuE#hbl0)~;JUN!Ng zWlR?+61TLnQ*w9SnPhwFqa*m^PBySY0*wsp`(?S0D+ik0l*#a!JU-mx%T&D%9LSC4PbwldMgo4GBL;4was;qqZwkA>Z@ujCp7~7AAf$ zh|lx>Vn*>YXiNMHQwCG_pg^uW(Tiul|6c43^+eOzPk(*o|11~)w$BzVbjjeL`msyP zE&F#Yb}))YXplq^sO{!L%ec7)A;2bPaG+}K#A3X#7;;ep3xhMBm#8b*w@j>Ql-J;| z0cxj-MgS~HZal_~qg2{&1f|i{*UVuckQvdhv@&H^-lN{$^4=fxuKpdImK>t zZ2SX3QUz|6-6aeoqPJu4KL*>=^k@@=o2R6w{Y+hZRm{#HGTtO>N}!%d$*|tWy$ebzH1?Xtml?D|8!{cQbSfTie~s)BNTi z1WLBi2{&0WSh8vuD0QlNAjFSA%c9CToqgNoAq4tMEG{Mkp@1&Q|1V(5niK@1zr3Ku z1)=^}CA<>hLE%yMl0pccVPXrngY;o2D@Yc1ni)+2(hJ5p2!8f! z&3dC>A)3~avf+ls#z*NNe65$UZM&j43i+<6c1Rh&_)|>?#M&c*+{h2{6Lz{5MdQPy z7GVG0#uSjrp>*{CCWuu7HbmCoV-U@hl9W`MlnYl;>tXJfw8$32PEhF zIn(NYA9^u1XruemTIP@lMLel3$K zVn*6WRCR}ahg%W-yNj75j^lfG|0buB4?XzyPW!u7dHi0 zlPrW+qgf-2kvrGL6FezS=pBq7Ru_1v5=;Dv)65MV?fl}$mxJ8onPwq{z~6inpC}7d z_Ij^fSl-IS{>Mp>EpkVc48pw6M-@4J5VYAOBCu2XTq{IkcZ?r^YMC3A4xvXVmb z*ZB0qGqcE}7dU9WvbGmwrhZhwklq*};n$cxV-q~%=(+2t>1el*=2a2q?5T4PRl+L% zP;&QJa(kgB2u`?;5RCQp<*W4ZbW>Zg0|MK17&umk|<6P;1vDuN=p zb@zGKvY<3;9Sw4d?#M_VAewoCZTL)`%<(qB5!CTW3gzvHKO`=Jf^*`3vMlE&ge3w< z;a*LohU^pPpGh2z4*2T&)2uX96&K#|pwZqvzF22a6wYI204aK=DEea0{@CXcOh3wK zy|nPh=v7hp+Nn5JRy^oS*U^ayRSzlTHEygFPo$on+f}7-zdBs9B1QUZS~n*}G%0hV zrRv}L;*OOsk;?9~_a_aZc`zP)8b`mxol~xWM`|AC=!xKvB&F}}wR>JM)YEqK47D_+ z_LnLw-&Otf2Z#Bx+R&t(xzePIe3RZtrvtAMmHvK+T4r0dS^eWG2n}D1ssJ~T<}N01 zZ!NGpw2Bn0q&-U||E>t^BJacPjV4$;sVCwF?!Bk29pJ3_K4_=@#O=5oFmKS(A9hz?4T1 zUF6zuBKc+8zef%BNbZ(wB`&XK2~C#Z?XszM{sv3Ti#Om=-3T7}S$u_VhvVROo=cCh zy4U!q<5l_<+3PK1jooPRh{PrIik@~H^%2!3^(IN{qh3RBIOC`bp^=rP+oC?w;PY*= zsp70fheSU-sg0yHf979OeJ({!DMFwxZ)>!3!7-GCL8210$!G5CmM?>olezUu0aR_4 zc^s!o>9m-6rTHABkUL5_=~uzI@}sP_ulZcMp5Zf#qoX;uRu0FHzvOfAQdWu)v;PGF z)`U2pho82OGTV~Ye*fV-oh#WX6Y%#7I?kmg(bI5WgvT=F_AiGc06DJ|nqajy5w@d` z!Ia=c+SAZ*X`T)J#O}EkucI8x-f}=)Ie@Aeu@wneGxt#sf72p8@kKe2dpA-05(-!n zG8hbW%`&JiNUa8j0oIbOkWWKx2OR`|@~O|{hQ9Lw(3l?%L#JmntOPoB;WI2I*`>+%rB*t*?S|KCR3v@HBn!AX5ZO z_m?(I8YWO+r}Ae#h*CgAc^>GSC0Nuz*y;-v-1d}0PMC(2*W1}9ubAW%i=q20iklR& zD?~ps7Mp|2yhB>J>xu~nt~G^hJMl!)dr}trs%3!Blljj=$n-7ca3D(c>6VRs3txi1 zGNJ$;p{C(^HbLL=w=>47anA7N$;SZsPw#(Ko+Ob$UR(&d`_eKewyHg?@Qv`Gqt}-sCm6S-E_)pe?}9qB5Y zk596nnF{irzhKaV8_RC;`N3EIgLwV|R^>2$)E z-4Wib#jgMNHc|HbTOT4&mBX-Bo+MMoF+$jGyKu-PkLE*oUIiuGk*^l`>4~cvLjvZg z?q{)tPaS8CEUe)1L|o`n0{GNFWY)k~SZ+Db@08&EZ+}skq@G z>ChjWOedRgBG4Gm*N!^gwJ`Bjh8v&OJ81^hkj|H$f9WV$cMRWi4+cC3h&8v}`Abn& zcXsHQf9Y0I66S$WK*WQ-zp=|Oeq2{kRTZNc=ORdAYQ}4dG)}jz{g08iotTr0t23}G z^ilQ24Mb@>flb$yo@%d-2Yy{@-0P+M?1q;Dg8Z7gA)H4FZJ=xOK3QY6iw2tSgRq^F zfRms#6)_QPofF!(>f?5-td-Nb*3pq!d!7~2(V+yyeO4{=YzW;D*H}z`q?5TCkZA+> z`_fhaCS2N-bJO$rmb37a#9VPwQfiV?J^N9T&LL)R&HTXH=AMukvQQ0x5S!`o?R=d* z9Xcoxk{{54jATiAt@&IK-g;7Bp}2UgpydjyHRM}JLN|`jcN}Kz(`w_?2^1uYd*q0) zSe}{-T&hl;P3D>eybk<-JZ?7Z2d#Tq>X=hnias=rTNy&j`k^_`MU{loQ|FK2oep2c z46A~;k)+9e&fQ&}lnbpph#;A%Igvl(jSH3i;bK!wG>Tm#^)c+iyFRPEpiVAyuMY4l zV^(4QN>ltuxr5b(LV6vUeM`dHeXsrvf1mV~@yESC2?kvJInQSnNO>N2KBpHdCo{3C zGIJuGDsu_y&!vbcxFT=s?=oS09%qmxi8_ zGM^rY-!1vhEhpGpg&4Cq-yM3jbGIMVFBFfzY^sC>$CIMe`0C1OvR5B7`;-ruWIdA~ z`4bc8=h=60%HJd^+Lz-H zw;~o!XZ!t45GzKsI*N{30i44v{j214J;)H z7Zfs;(n{Mm*Gg@1Y0v-vbMXw%VcwhV&2R2|b1n?(_~y;K_kP~@Ece_uS+QoVik7t@ zux0>RGk~laK-LT(Yt{^)SleHJ{k6|VA-rV_ig?>W2OX3#fD9Ics*wTm+3chZri?*j zFf}YdX>xFr3RA|wF_0PtphgO*lLAu4z%h_g3y>x8{0Avx@EAm?0?5Eg7DyR`#~?~P zKn6~7LCP3B22o-GGI){?QO3YAkP-!u!ILhCG6s)9ln8(fo^(Q#F?b9juK_Z6(hX6@ z;4z521jyiN42W!Bm^J?t$keBCR48Nc7)0IxWbiZ|MCJoo^Fx75eHv4RG6s)9WG2j7 za!r`2Ph+c4#^AA54Mb+btkuVanfjOtnF3j>j{=$cmj{=$c zm@P{_ns4?m#N^IWu9NHC3AZ zchmushB|ECyjiww+a^E#^ppJZ%P+EL&mPn_cl^NzA1oa^c9g>pKU|JH@<{h;)27V< zQ0nmtld4+Vwr$-xmn>N#n>KBdPMtbQzkdDX_~VbyDN|A*YH9?vVG>)lYL!!%UAuP4 zhaY|@t5&U&k3arczWVAb`SHge-TQz3`R4)VMw^-(&eOhqd+E}pivyrfpFVQtnP}>CmBr`~Ep|=E%5lLCya@jply-`DX{)V~;(SbE=c1LaFe9FeOYB6ZrY(pUcdd zGv&GGo^z9P*kOlB*REaNF={?)rGDx+;WXn9@$WELc~4E&mMvS{v8X10sxq1rUE@3s zgUyQxL;hcW`DMB9zWd~hFTQXlM1C(*M!KH!&D4d7$@i``ub8tTOUsNshJ5dP!R0UDrsuGps^Cz5ef&-uL)zm|h z*2oeQg(*Bt9)I3``|a|?6HmD43bUo=s+5V-FrV{~Jk)#;=8z;I8E4L`<^(gdd-raa zxB2b2-<)!&0^%%lO#o1Ce{`8+cA{W9JgGYTEpaHg% zPd-@&4H_huTylw=bka#qc{G1iYGcBQ{D}D8e*0~iHEWi8uiWJbg_L!;Yp%IQ9(?dY z_nvP)QDPH`!4-4N7E+H&aCa7iN5R2F@jBy-Gi3bu@ha_^Vx3+akH>NauWM42{iTF$rfWqqt{fP8>QClu55_~VZ|_37NX^8uOXs5_fu zSOdc}-Ezw<&eu@WpeyHkj&hw~OEFD0^W@xf&#lNTHYY$?pUW_Sg;nz#Zn(kS@kBjQ@bEs9z!C;E zH%~wPv{No7S0krt;o&)Z`B1u$&2F zviZL_CO{o`uIMlXUjkXUj`3z2tyHd4e^_ae$3~g1P$av(Mzp zE3b4Fh7^wRexaogt_xobbGLBeLbpao!P)!ozwd&9LZ1uftWYg#i-_|0o_?Oi)xtmPuj)xm&rz`}XbY?s&{r z+&+Uk@kB?XM~}{##zJuO-KgIWKm6eO@yaW&IM{#&CHdfk51dI;a~Ng<)v@L?6yzU$ z^wCbW>XBgdUV&77fP#WBl4`&d1p>zc*^C)896U&VvCmWrHt>)wX1Re$)M%*?JV1f+ zF!4l?zysKrKdzAie6E>mkMir(401z}eb)tCpHwL8Q&k~%ExRLLfBkj$_b?E2mj!n? z8DJ8Ggx0m#s27X~0ei)Y6>e)!*!r7BOaR1np)`7J9M7NpoBta=e7Ngxlw$Heuu_^! zgvq#QIg0_5XY-L};K4Z!E38rnlLz8tQ%}7H{3OPP z##rU=Tk{g2TK-^tzWU%duwUz=k3Nc29|n&BKjoBDWa!YL6_uNo0}vC76U^k1n<3 zQKLrXqLR1=Qj?in2V0R*9~|PSNker|6-?aZ$&+(_U0B4Vc_sRQKSZCx7EaZSGB%7+ zaPwrtn=qXy27|4}y4aaNI2zp$xpeQ|T`s)v!rbTM0!YEpvR3|$j|D`U%#8Xh5!Q9r zUFWjkx=AoWe((282oBW9fGyVfWyRam$Myu(xgcxm6mFBMIjjHD79pSYo`zNg+9?Y z`j`!QObq|e7%^79JfNzn6bGtS8R=k-g?;NpEQN})g60dK0jE>pt0pU}3dnhwM8J9E zkw=^}Ptp*lmK;pjovuzj$D%x_2>GFM7H_q$^ofw3H9f{4U-5L$KPtsol~QBW9M4E> zs<-+m0AGLob76f&vn%Q=*~E22tvzjx&z7?!Pa0GF1iX6MfUoi(z>t-e+lp?=5E+NL>M{ zRX#|g3-(*_1dXUlL*1D{@~xDb=u*@NcyLGwyZJW{eM055^fl_bFXiZP3;&MC1^s@Kkw`p3V~Y;2*#8xw>R$(>$p_#P}`fAPf^a}Q(C zve#ng)x}aK{LVY?bRbp=bTFK!Z}c&2kv16dF+;wp{Mpbu14RA!3aQnH+d#W(pp$8mo0b2;*w>jXs8{tELMWt8%wer~3E8f)6qXE8EmNKh9z*{0Nj!qnUD} zM?Q=BjjQPf!?0zX{O1of^lE%?K)CCQ6@sbb8mx1!HVYek{9L)u{!u@w+UNNMzgHiL zS8N>k&fr$;dS;`uwfQAW!-s$JBiFZeX|7>8yzVR1Xtx(|xFn0xNI$K6$ArO62M;_tl2|8Y#Q z{bA)O2$R6(L(T9O%c}&l!5qtHIfoXJC2btynBR(Eh;wZ$m?WgJ`+%}mT`*(|412Ix zY?MHaO|`PEWh9*M>Z`AIOBv*K2$2g#L27D_T z386xdMxI6AD^}_%6>imGF_f)3ixw?%3!1tHmj8%5{>?H1^*gg?&(2jS##PK;uW_ix zx_ALl{!bJHe+o%|x1v^$Inmu9RQs_P9Wa0bu<(my|MP?N!Qp^LF+9$pXSf3q=kks)> zXsSB;U`<-^ft$hK2$Kf;iSO6}O5-mYYK@RS{#O-Bms-*WPPLJBESi|spT&&hVd80q zN9;#;Uwvv0kU^Agc$x(ugDAc5G#fw$Q99viR)7qm^ug2Y02xH-f~PJ38AR!U zr)~flNXZAs3xEuwWW(bHKn78A;qe9_11WjncnOd}lq`6>1js;21~}dWWDxlekM{r> zNdAJ8D1aIfB;UbFBtVS-Qc}Q4G(c$tDQV!O0-&VBlvHR^2~bjCN&_^h2go;=(gsaK z0o2@3r5P3j$eP%`Flz>oH3P_+H3P_+0c5St?SEx$eV~Acfq4J`002ovPDHLkV1j6n B9-jaJ literal 0 HcmV?d00001 diff --git a/app/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png b/app/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..09e02ce090e0d7c32569116af66d4dcba9a051cb GIT binary patch literal 7540 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∨ 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 HGz|J5k%N@t literal 0 HcmV?d00001 diff --git a/app/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png b/app/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..2012ff9eb606e8f21f895ea979cdf4ffb1d5c01c GIT binary patch literal 5471 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 literal 0 HcmV?d00001 diff --git a/app/src-tauri/icons/android/values/ic_launcher_background.xml b/app/src-tauri/icons/android/values/ic_launcher_background.xml new file mode 100644 index 0000000..ea9c223 --- /dev/null +++ b/app/src-tauri/icons/android/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #fff + \ No newline at end of file diff --git a/app/src-tauri/icons/ios/AppIcon-20x20@1x.png b/app/src-tauri/icons/ios/AppIcon-20x20@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..fac2f175c06d9a97dd202536cd352a237b72055e GIT binary patch literal 561 zcmV-10?z%3P)FwW5Q$%*P^$a@Q7aTQ9-+ezP-xT=g+`%4;yriP$#-OO z&6O+nTZuSx&VH;}d!Id;Zs75F;C{cuSVB=0d;$pMq*uo793%6q?xWb|Qe^?-yr>!vP+T$1mUM;cyt+?G}MR;3cSH z^q>B{pE8*YhQlG+?KX0`+|xLfN@2ZTW53@c7K>pp7`*iFlOeC3%jLpoG(x}MN3+=! z!H&lxyk0MAwHju#8K%=IHk%EK#iFoHr_(r{PC|3bD))LlghC+{3I(Af#qV@FsMqT# zl}bn^lj03%L)#yVB55y|O9X>K!HSsA=g8;tLMLiT_FB9lZS zA)X_Vh>(V_SFKhp+s3je1jQ!!%u4c%8k_f}otfdwa3BLhiY(`yWGtP(+sWbZtMMh1 zy*npk7Ev)W>CDEvD(~*6W9uIw4rxXC-=Bal9L`LlU7P$000000NkvXXu0mjf+j0RH literal 0 HcmV?d00001 diff --git a/app/src-tauri/icons/ios/AppIcon-20x20@2x-1.png b/app/src-tauri/icons/ios/AppIcon-20x20@2x-1.png new file mode 100644 index 0000000000000000000000000000000000000000..479f8d928012e275bcf23a7b0deb2313f63dc590 GIT binary patch literal 1177 zcmV;K1ZMk*P)W!!Jm*|ZHwqaA4@FT>rMI^?dVhZ>FN(~o zswzcAMUg)iMgJ(=08j=vJvusC@d~IF*vrd{ZqyaD2`0q=prZmXGVuBN`2)T0E4*M4 zB_<}u^dPV>NYDqCfZ7KPfW1NX6)2D@04kVNA7Wj`{1!N$$1t~U#iYExzQXU!-Y;VN z;&QMESF2t{tCIq38qfl1q_8K!2}~%O$V()$2l6zE;KBk<5nlcS47X@*Z&%j!j*h6WuaCh2RBUXlnW|aGf;o%_7>onprKKfX z07GUF>j{%BE-q46R~Mb0o>F>xI=2HzLP7#FhXPl_mFUM(0QiT82P!HmGHtoapfEQ( zJIgKt7%cj$t1GIgsGydX7Ah?*rHqUW26S<8LF?=5>{1CLw4**aI7qFntqd48!e&sI z!y4-7=%D1}WM&7(M@L7gt*!0L_?(;^+S}Ws>+5SuOH1Pq!7@NZcXoDCc6K(Em6b8` z{!7CagZOH=0+ZI&)zSX`KIdsEDJe8RKTm~)g}k05`^6IQx9Xo&k@1GXk7C;2@|s~iCo1Jl#ftZmRTxVf^jlJ4*C%|nhHw4jS~b8{Ts2#}kb z8vHK1qe7=qD#9)X>mC zXJ=>3Zc|ee&CJYjK#1#WYis3rOUuj4R8mqBRCd&0y9LV5&JME$BgMtV3=VAhgBu`G+dU(AdgR3Q8<65=6Vau+L8A+IguvpvZ8cpieo=lCq+DQHG5s4? rz!80k{@u?I*s8qnv~|uvKSTThPcR?H9$6UN00000NkvXXu0mjf?4K(Q literal 0 HcmV?d00001 diff --git a/app/src-tauri/icons/ios/AppIcon-20x20@2x.png b/app/src-tauri/icons/ios/AppIcon-20x20@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..479f8d928012e275bcf23a7b0deb2313f63dc590 GIT binary patch literal 1177 zcmV;K1ZMk*P)W!!Jm*|ZHwqaA4@FT>rMI^?dVhZ>FN(~o zswzcAMUg)iMgJ(=08j=vJvusC@d~IF*vrd{ZqyaD2`0q=prZmXGVuBN`2)T0E4*M4 zB_<}u^dPV>NYDqCfZ7KPfW1NX6)2D@04kVNA7Wj`{1!N$$1t~U#iYExzQXU!-Y;VN z;&QMESF2t{tCIq38qfl1q_8K!2}~%O$V()$2l6zE;KBk<5nlcS47X@*Z&%j!j*h6WuaCh2RBUXlnW|aGf;o%_7>onprKKfX z07GUF>j{%BE-q46R~Mb0o>F>xI=2HzLP7#FhXPl_mFUM(0QiT82P!HmGHtoapfEQ( zJIgKt7%cj$t1GIgsGydX7Ah?*rHqUW26S<8LF?=5>{1CLw4**aI7qFntqd48!e&sI z!y4-7=%D1}WM&7(M@L7gt*!0L_?(;^+S}Ws>+5SuOH1Pq!7@NZcXoDCc6K(Em6b8` z{!7CagZOH=0+ZI&)zSX`KIdsEDJe8RKTm~)g}k05`^6IQx9Xo&k@1GXk7C;2@|s~iCo1Jl#ftZmRTxVf^jlJ4*C%|nhHw4jS~b8{Ts2#}kb z8vHK1qe7=qD#9)X>mC zXJ=>3Zc|ee&CJYjK#1#WYis3rOUuj4R8mqBRCd&0y9LV5&JME$BgMtV3=VAhgBu`G+dU(AdgR3Q8<65=6Vau+L8A+IguvpvZ8cpieo=lCq+DQHG5s4? rz!80k{@u?I*s8qnv~|uvKSTThPcR?H9$6UN00000NkvXXu0mjf?4K(Q literal 0 HcmV?d00001 diff --git a/app/src-tauri/icons/ios/AppIcon-20x20@3x.png b/app/src-tauri/icons/ios/AppIcon-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9c05c53e818102491abdb2b1e8ddc7a870fd66e5 GIT binary patch literal 1901 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 literal 0 HcmV?d00001 diff --git a/app/src-tauri/icons/ios/AppIcon-40x40@2x-1.png b/app/src-tauri/icons/ios/AppIcon-40x40@2x-1.png new file mode 100644 index 0000000000000000000000000000000000000000..5811d646a6eec3ca6441d87bcbdada9d4609b0c2 GIT binary patch literal 2506 zcmV;*2{rbKP)U7W9d+oJ<>$`sQ8g8PxrbvdOw}K#uuKoG*hwJ)S zz?Z;QXhg-(PG^EJ3|(LOo2mb)CCCIIm-WHFfB!0Q(xOF+s1DcpWEq17T@)+@j8auq z<$gD7)-3A3#Ud{N^#T3@Tq2Q(uK)i1JL0}vqti&ZF#1YgYWf-p6n(7$GEgki^|cOw zS`py*z;TR<9kr%htk^bh-dukD`sKJ0u0+}_x7GnrD*zl1DN8qX(6WK4DoZg*1u+89 zavl{yzA+n!I1LRr0ixL8ny4=>Q~-mdw~gCUt|t?AWV2@mS)j9I0UBZ-ER z8q$mq*>RRsqyms!mlI7ZrY;KNI?wSu-*rhwxeHTu)%6J)oz}%m^8fUzeEj%PK7al! zKY#vo*IKr0Dec?0myR7f)~O3nfZeK9EBW;4lRSU^T>A9sBON+)aL=c%Woh&P>I4=Y zmgL%-J9qBLwQJYp=FOY(@Zm#w{ra_h{rc5`LjmNrZQDxs?%ieJz=1My3|ynFXfx^(FxYu2oh1q&9G9mI+P2*tO$Ur-vH<7)2Fg++cr6JZ1 zSRq@tZgusn=r<}OV!3YDu3fTa%NBX{>Xp-Hh@|R5>g8*dwE!BTtsJWNbwzC@=6Vv9 z0Pp3?m$H2MayfbOq;%@kNxF6G<~nFW)8)3hXvYGQ>0Ua3s6)G5yLNTr?VQ~*>cB*~ z!MkV+Oe_yU&zwWFx z&t(j+k^_SKgRUJvetg;VVC(=|&YM1cy6XtsWS4~LB2Ik0QKLr5;>C+yT|msI+`fHV zX3Uu3+#JA4H>=1y7#Ki2apHt?eaZo1B5rG|IuEghU=+Otj}CnJ@WC07O`A5!qD6}$ zQ3Y(Z*qI`ccJ129fddDezt_2Q=UQ#+LU4^t7&y2WTF#$8@3=Z{mnK#Y)U|W7XU~>1 zXU;f>)`~6Qy?OISrc9Y4yLa!Fe*OA6E~1Xzmyxb0AQvxQbleA!mh*U4#nxWuoq#=c z>Qp&;^l0pBAj3FC7w~XZu(nvibl|~ph!o&qH1uA!PPsKGHFW@c_3G8NoNQ}(2M-?X zK(zPNB16;8ojVI3CmBBvS0xj8d-m*c_s~x&y19yO_Q3(aapQ)Ii&azs zlYtmIbf{dtdR6AnpD*v z7DO1@>3rM7-=m|aPoI|k`}f!KCsnVKaVCM9uIRfoy0NYe_n;M;;}GL8hAmJoY_sB^ zqC#Ao+JRiw9G!RU*fE(kYnDrrTCufOedWrPE@nn_>uf8~*>t*iTxpMB@ITtl(qE!cmc@IDVK#gFsNypf+V_iL) z-A25jIotDP2T-E}CV)`z>Mq!Oa7aF*jLuWe13=1h%l}K0lO6=)nf$j`2eW*_wL>60J6IxZK8npkX6CQLqxN2kG2U7&|;-P z+k*Cb6JhO~COS1+Y)4sB`MKJmE>;z>0>E@4uk~KMc;V_=e=}Qw23yxU_|RTzRFWvw zfH1oDs1Q5Knh=dE`=OIb`E*#{2@Sec-`>-?^ZYyobw1Hjdwrs|bSd@Qkt7}q^ zy6vvjP(h4N8}wWL3y;8@`qPCzoZRU3VBUGqK$E=*Wkt_{ zg`d3|rL(*dDcXqqe|{i8ba9Xurz?=5@V6 zsT)!THcuHH0cygMXrGzxRr8z}9YQNv51~zWhO|EhxxizPQ$f_tFaPR6+{$&T^U{Im zkAlx}6g-Dg>hHXdg7^Q7penj%*V7dA&j>OlG!-m!WL}f`cNodsV_;pBd=k3<0S8Zm UidaJe1^@s607*qoM6N<$f+#N7b^rhX literal 0 HcmV?d00001 diff --git a/app/src-tauri/icons/ios/AppIcon-40x40@2x.png b/app/src-tauri/icons/ios/AppIcon-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5811d646a6eec3ca6441d87bcbdada9d4609b0c2 GIT binary patch literal 2506 zcmV;*2{rbKP)U7W9d+oJ<>$`sQ8g8PxrbvdOw}K#uuKoG*hwJ)S zz?Z;QXhg-(PG^EJ3|(LOo2mb)CCCIIm-WHFfB!0Q(xOF+s1DcpWEq17T@)+@j8auq z<$gD7)-3A3#Ud{N^#T3@Tq2Q(uK)i1JL0}vqti&ZF#1YgYWf-p6n(7$GEgki^|cOw zS`py*z;TR<9kr%htk^bh-dukD`sKJ0u0+}_x7GnrD*zl1DN8qX(6WK4DoZg*1u+89 zavl{yzA+n!I1LRr0ixL8ny4=>Q~-mdw~gCUt|t?AWV2@mS)j9I0UBZ-ER z8q$mq*>RRsqyms!mlI7ZrY;KNI?wSu-*rhwxeHTu)%6J)oz}%m^8fUzeEj%PK7al! zKY#vo*IKr0Dec?0myR7f)~O3nfZeK9EBW;4lRSU^T>A9sBON+)aL=c%Woh&P>I4=Y zmgL%-J9qBLwQJYp=FOY(@Zm#w{ra_h{rc5`LjmNrZQDxs?%ieJz=1My3|ynFXfx^(FxYu2oh1q&9G9mI+P2*tO$Ur-vH<7)2Fg++cr6JZ1 zSRq@tZgusn=r<}OV!3YDu3fTa%NBX{>Xp-Hh@|R5>g8*dwE!BTtsJWNbwzC@=6Vv9 z0Pp3?m$H2MayfbOq;%@kNxF6G<~nFW)8)3hXvYGQ>0Ua3s6)G5yLNTr?VQ~*>cB*~ z!MkV+Oe_yU&zwWFx z&t(j+k^_SKgRUJvetg;VVC(=|&YM1cy6XtsWS4~LB2Ik0QKLr5;>C+yT|msI+`fHV zX3Uu3+#JA4H>=1y7#Ki2apHt?eaZo1B5rG|IuEghU=+Otj}CnJ@WC07O`A5!qD6}$ zQ3Y(Z*qI`ccJ129fddDezt_2Q=UQ#+LU4^t7&y2WTF#$8@3=Z{mnK#Y)U|W7XU~>1 zXU;f>)`~6Qy?OISrc9Y4yLa!Fe*OA6E~1Xzmyxb0AQvxQbleA!mh*U4#nxWuoq#=c z>Qp&;^l0pBAj3FC7w~XZu(nvibl|~ph!o&qH1uA!PPsKGHFW@c_3G8NoNQ}(2M-?X zK(zPNB16;8ojVI3CmBBvS0xj8d-m*c_s~x&y19yO_Q3(aapQ)Ii&azs zlYtmIbf{dtdR6AnpD*v z7DO1@>3rM7-=m|aPoI|k`}f!KCsnVKaVCM9uIRfoy0NYe_n;M;;}GL8hAmJoY_sB^ zqC#Ao+JRiw9G!RU*fE(kYnDrrTCufOedWrPE@nn_>uf8~*>t*iTxpMB@ITtl(qE!cmc@IDVK#gFsNypf+V_iL) z-A25jIotDP2T-E}CV)`z>Mq!Oa7aF*jLuWe13=1h%l}K0lO6=)nf$j`2eW*_wL>60J6IxZK8npkX6CQLqxN2kG2U7&|;-P z+k*Cb6JhO~COS1+Y)4sB`MKJmE>;z>0>E@4uk~KMc;V_=e=}Qw23yxU_|RTzRFWvw zfH1oDs1Q5Knh=dE`=OIb`E*#{2@Sec-`>-?^ZYyobw1Hjdwrs|bSd@Qkt7}q^ zy6vvjP(h4N8}wWL3y;8@`qPCzoZRU3VBUGqK$E=*Wkt_{ zg`d3|rL(*dDcXqqe|{i8ba9Xurz?=5@V6 zsT)!THcuHH0cygMXrGzxRr8z}9YQNv51~zWhO|EhxxizPQ$f_tFaPR6+{$&T^U{Im zkAlx}6g-Dg>hHXdg7^Q7penj%*V7dA&j>OlG!-m!WL}f`cNodsV_;pBd=k3<0S8Zm UidaJe1^@s607*qoM6N<$f+#N7b^rhX literal 0 HcmV?d00001 diff --git a/app/src-tauri/icons/ios/AppIcon-40x40@3x.png b/app/src-tauri/icons/ios/AppIcon-40x40@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..961ccd4b5df81edbeda0c85529747976c70fd1e2 GIT binary patch literal 3851 zcmV+m5A^VfP)pRZexpU6*J`N#2|@8sUw(3{Z6BaHsbOQDnNx}o%r(wss8=63Uk1XQl; zuDhL zUF@uDfSg>1Zr5LbefINz{`p69GnYyKsC114u=zkh<&sWhKuudP>ksq{ogD!hZWhrU z735HWm26trpanz!rwei0^a;XsxfKfE)<032ugK(;0E>SYRs;G#J3mTwx&l z0xVxd9E+mo!4}xc11;Pv*aU%`7vNlQJ-wT@zD{C5PG@wngSrd@`5J&tv5Z1Txff%e z+gAUa3?_InK_I(9;Np*2aFgppi_Z+WU?%V71vuBB@`4y?3vRMO1|!e9&I__@-s~yv zthH=)ZdHJ+vBK~Y#x!BmIyl#;vet6-TGzSy*p(Ojg~e^F?k33|!PGTBz#_BUTfO=i z?7+}uRM(6#+g3YVETC&0EN&5r18Z1Se-MNOg<$H6?}NLyD^Ll}#jl(O|wwav+{kxjDlxyB4FF|r)X#kI-3Sq>)1VGXR> zifVa*tF-0d+OFYpQkHXTo0DBjhT3ixU<fz_wX{ZLrzj z1=uzVux%D#+bqDgS%59TwpoB}tHPF24Pb96znU{CS1Pn@Nh%g|Hx0D_t9TYa>vGWy z;bpThKLBOFO)lBrLf0|*fF_INZ@A%x>@!*NW9}uEwB~qwO;&A_-E7%2%G?;0cInb3 zb?)3beO%f5n>iF^F>g?IG8eCSt%OZDxU_T2$ zZq=%ly5o*JROil}RgWG$RL`D0^=tFFTuquZQGfpVrwr<_3KK=AlwPni|4e%d-{85LaO);HsJ7g}C zW8r83e(bTw)Q}-V)FY2Pq9+5NKl98pYQu&Ns!f|V*^N$^JUnCd>ecG`=buj;Csz%? z5Ew3^oj7qqefZ&r`r5N+k0vUha|xINqMxB<8d!1(=sb@LUE8f&H}%p>FRA_e_pABy z=c~4D+h%wF6LAm7x88cI`u5vzRm+wwvy;UF98t#t8r%r5ix)4}+;a5jQ4Kg^7O^PX z9hb#-^fut;d5C4iJClds%l8|A{M&E8srTQ1Up@ESbBW^OR5frdAiwwCd+ObH-_^h( zMsK<0mO94?l-nAYXJSa*c;k(s+f4EKFTeZ}=$2W4bG9D<-0#2tUQL}kRekf#H>!E_ z<{DT47mGNqzC`i2+qG+_lD3z2Dv2Ul{LF<57pmE_XKN7|H?W1Q|3M^o>eNX+`skxs zAKU^QAd=C07&dFxtWm97x7L6c0&H%;BG=$D4XfM$Niq5wBMT{mb$#K&1+A}>BBm2# zWC^(VuEU29SKod2o#tBE(m2veIuB4d9L~*s){P zi!Z)d2UIgOnVU7r4Sq%tCZ2Ak!z}(;GK#R5#yzbH&4#6$4nTO|GY( zep-F?)mNGzVPY8~5?{vnnmBQy8aHm7cAu1&To932sH-B@yYvN-Ud#rq=yN7)-@bjd zBoLpvQm&I*N$v%#S6+EVZQ8Uc6kM@-PoF-m1`i&rzW(}aHF@%69mzu9nP&+VN=&#F zHL+sF3iZVoUugYb?C!gafw3?q#>N;cxes?mI9QCTk3RZHjT$v7l%R4z2pl?n`gBb= z8oCz(mckvPCNQx2^y#CGCAcuGNFXd?#Y98W5LSKRg%>Jjbj1#^5R|wwx(*`Xp7_mj zZ<}NNcj?ll+R8?+LELf}FkyJE&Kpu zOgx)0zWL^x6^l{F%E3a=&6_uCV}>BUAGngfgNURB2MidX!OgAOC}pAvNEk$<1JURC z`eUAH!DOH);Iq#@QzJ%<(9$R0c}3VVc4)? z+TZmvtPsgq%jiW?gyl9+q%RZ;^zYw4>sICCLWwow+hV!P(KTEciW4SGP)n99(Q)W7 z@s3eRX-}M7?8cdOp)FgsER@R;Y4_iMznVLDZoO123KvbAHcf*kd z11`kpWdfmh{lJwxFEMT^Df4k2ed8YbI&|nz-S?oeF?MJWwUD4H0G9Iu(4**Izq%%q z)6r}7>7oG`NsXYqtpGwvEHQ5SA0&ban+9>FOfIZ%o)r{KsVaaaB)Mb94qdD42QUOZ zfBw8SdLDY{AsrMbr|y+-WK^G*h!zQuF=NJPQS2v4BvnbD`}OOm$B?hz0x$^`Xu>gzAxe|hzlSB`mUTo0iH>)1n!bhXVAov&9u?2Z@u+aBylQz9XWDj;Ju6;?u8a{ ziD@@3-*?-#ZN9VCtZO3ZAg6YftG-K0Yq5BD@7^8R=f#o-kT6LiCARdPG5F<@r63<# z#N`vaap+%ah7r$xI!b1CuU@^h=q%N8mij70@((}!pk90JHTC%8kE=zC7G(?5{eVL6 zvV>*Ilqr#2G_k1ZJ7e(E*J5Kp3uqFD9(Lo%`BKZwf~}wdF?f;>rHW^Xkl_juX#&^< z3l?biBnnvheBMG-QSaWpeWim;cxVAl3N0u|B)~LktR$e|2QFfhfI+FEONjW!8*k`J zN1jEL2{9c+%pjk)5LE>Chp7N)0ZrmaK*Rzt85O^iUF29jKfiV!%LH5(wgs zMJ>5S9Fx|I;`0WLgE6oWEo>Y?G^rYZWq|mUe!+Yp46{BcfgaW0#zLhG)-UxJB-Xoj z?OKwGkVWEBG~j1R^FC3pIO5W=a4;MZG!O=j-YP|8$@li|-5cs}`{_lB?aSex%3`%J zm7r>6=}K4un~2wPH1e~>Hlk4FusNbw>v65IO2uJh-FDk;zNMp*5a*t97#-x9EAd^k z@6=xf8I|Q6Zz6OsnHGs+nW9ttKtAK1Qgo7h@7{aw4XpDDs-L>=zWd73hd9QY2!JIJ zkMmEqg|$HZUuv9r&3k;tJ*6ZVq(F~7HCU4rQzjrV zQ^k-`A~S+p;e!u8(5v&qj2*zlq9xh|$fW=r z=XeuUlO;qZd`PVK@ZrPy|E$8p;=~6n*I*^yOC*bI5dO8SE-=>zOELYaQ>S$4&a7Fp z%2u}==XeuWHY-~j$^V(j%(4w%l9WT%0oeLyL3`VVm8D z3}q~9X04%B8wM6wO4>8kPy+z9-XsL;=9GzA7OoKkOPJO*%Uv?8?N~8g_2StvbIxwH zoWW;X;o@0Bm36k>v&L3!7*}=tU@29p<-~VGY39LTI+A57Wa~0jJ@=-Cd+QikW-{C} zxY8cT7UkrFn-*|04C>^rmPqBUZ}nz?Xf6|CZgP{S2z20L}$j4yBME^y;b|3wHTIWjx%+khOd6=6MC}qjb{{Yw?F!fhF;PL4 zhK!M+jLDRF+V+0exx0VQbHDHJ^W69I{PDh@_n++Pysq+xn-pH?wVL z!!T^~@nf2&F^mabGGVMN@P{NMbpyj3?i|-tH@en6(Yx_soL!gN50`T+IGkKtWk78} z;eJL1F=E3$ky_%)gyCf+o#A>tPBGmh?-!0m=zo+k?a`O#YtyXdk-7Zxd+5JH~p(uQAUZjHw@NPn!8qR&~O9KYVHQK`ux< z3jdIsh+$u6FRz7bui&thZnwJ@f-Gi=p%|uWCq{B!ZEX##-Hl;N-MjP)m)A3widnJr zv5@^(-_cH;##>(} zFkq=h;gpM08!+!^pp5K47H`cnqJs@JTITc_$9T?k2p%IyZ`9KaS|?>NW@` zPIj)qt+!-vJ?Y25tH(^h2+q?^v;hxN09>=JT9fEIoveZRF)(3m%@1iC1di~4n>z1h zJ(kQXv^ia#69&xsMD$Zu<`mX3tWtZHtksGI!5r>BH6Y2#V;KHKu~Ow%_@Hr_5yKQj zL$IB2G0iJ?R%P9&3RDau=DBGTy#rDRM2u)OvX!RQK=M`U9oc|kd9@4IUl#9$d!z)l z6l>M5??*qE%jUS~)?Z$B^9V*P4&)4MrU)#+k5i4-aHnZcHgIBiaiJwsR+vmGkqJBh z9?VYUb`e!##=_O`So6(_BHjbE?Ia9KxyQ@AC!Qt!gb4YZ7Dkk&8IndRIE?Jf%Fyx^ zoF`AinPP~gtiZ)z4Hb~nv$H!tvSN!&jx-_+e%R@y%M=IKhp0OjAZ>VX0~hxDNC6FcIwYDBp5wb;Zh!Qn@QMSXjf- zvEA4)b&P@hxz+r^2<_<%%$Aj%K?e85X|CeekvVXdKVt!gx!=EjU?Li=e6G-fm1FgL zgf?Dsw!rXNh43!4NA09;4cv}Z8+&zO$Vvo0OTE&`bcoBEfgq{!Tt{!cmG6}d+z+eo zwSC?vDYUWKW+Nt9zrmEU@(TRHaqu?TOOVJ)z(RGltt?f6@$ricMsIw@Lx+8SCr7Ni zP?5#H`QhF+g#;OUpWkR5W7k?S0_#uNFG4)zo3!K804p)ZdH$b(ug|+*LI@<6Vdoi$ zX!=AC-`xGNlRgC){jI)$O1ws}80IROw4i5YR(%3yB`M1ayHhB*_ax?s?j*WYkINOq z1-oFjN{Z{U<<1On!Lah3dk?=&ienVT9Ph>uibvquDb5 zwNeU3h+CrSkN*Tye&d$!K!31PM3vLDp zje`u)z1xZ%hpbrPmiQHw-;-TeBlIx;X3APSTuh%)#yTJ%;H=EFpH$oGBeWIH9|l|) zbg^Li&DttuaN#>~uvOP)(b9)jC9Y*I1~0^^p}{A3t!RB&XG{0u@GAkc70V%DCxWx@ zt}~f3A+l{P_i6JCowL>2@Y8{hXR$GyhfD|-V&OZRja>MLng)5q;t{uOo5tL9ExKMZ z7ekv&JVW|zd`dL9SUj3doCwqB^+_y5*=jQS91;07R_`fDn8p#$UfweO$+8F8hSINYP**k2wD}WN-JJqTP5-D*ph#2xU`Z)9*Z^RgbY5 zdrtLVK?c=iR(+G@0#3q0&^q08kZnyExlznMRzCWb$y)BnRH;!Lfb)htPj9=d=6W` z|D^__@?5t>@BGe;<;>5Zi-i7GWotg;wC?)8gZ{Qal}&#a7OE$_o;`nfD_o55YTksb z!5l#yN0=`I_-Pc(9UFWvxS5`VvsQU&{Co06p9Wm`HW70yLd1b z;+cHw4cb2P=OvBG2@|rXFtbF=inL}f`W05l02W-fp6@q>i(?8RLW~ll24oE-(!iA+ zG_>mc%iJl6h8VLR4b4TTfIa(+AzXC*f(m`z&R%ROf*e)s!`D{f9+<)48V08g#uclv zH7AZ^DKB5vzTN~Mgr8!JDbd~&9VqH64yg5_A4#uiRQ_hi!cZ;(oPtAQb#U`Ej^bEBr(e?6X@UbLI6aW{_UlMi1JECR%c!yB-MhK6%8@ZPMv zucRSiyrh8gKv6-#Cl)?RiO6&BSCw>QAPloM&`nCzI`xgO+jGS#=_7s8uKDaKGVV+g zc|T{>{#sdbPLUk+cSXe&oGJP*m$pK@(h4$1sIwBwAM^W^h2$$#H1E(ef{YUU^d3qMt=I^%T*@JZ1o!~X z^*SfH#EuQ)l{SlxV|hsbEWJ^S{Ibw$#09x9`SbJ^ves3W?etqpE*{Se_z#QsSTX+s zFaSFrA%r`&@%lQNF22~3$*dxe6GmbwtL;+gujUjVu0z)K1OZ;_uj7d4Yb(%8jJ%x{ zlg3bf{X8sM>C298M{pk9PW6%2993jP9Xm+6&>Tmh?ADP1tXASIjfJ5rqwivN?=I9(Y0Mk8hR1{u(4v z825$=-D0+h9#S~-)0GuWz){veydX!H-VEX)r5Lw83Equ-NA z|A4;P|LNs_KaRe}f4jv0V%&dw>wg66rhlU)}ouyQTi!sQ-T~_1{+g zUzvyr(?MqZPd;FD!&e+5*U7tdWH?^Dc&97Zp~lj^EH*%TWw1&Zg;J%F-_121 zmUHiWcWt_C>8)^6vKmc{)_Ao);K15iTw8g-nwduxkJ{=;O1bKxt5bqPhrB`~g$~=R zog!IvW}VHgh*QnZYtiY_E_CaC8#O=5OS?84YZ_^6VqO()_OzvQESW|bUH;xr<&`a8 zw%Nab|EDjHFW=>#w+8$CrX$oS zKRISTu*+&*o|`Qz%Xs}de6!*=f_InQgXPuEiXCOX3w0kPP(;<2J4aeyn7HlWJ6pUw z7;Ad&_E>A0Lj#SZdOiEfZi!@HBc?!e&_J? zJNdrAwaHZKQi<0Xm)}H=_C#)z>ete%?oT+$uzjf)^pulH)Rl*dt`^EmJ(s(-HdX18 zwwI+%J{#N+&Ujtc|0jFSOtnDGO#wH40oObOMU7KVGQR!%73-7kwmn52U7aMQXW1c) z9LjrdZrV1RGbn|D*Q6M?@CQ0iCHss#T3+j?JyuwIIp#C={K4B@DKUDb-jg zvA(zr10GLirE88Yf4;rzF~8qbaT*^x5ey*wAZ}WPx;!X%<#$^~7iqS3S8iJ3kX}i# z_4-0*lg4!+?{6Y&$L=#aeHBdJGnvJ&y9CokW_Uy_^;GkMJ8SC zE8aQ%L{Iztse?a*i+;a){c3eIhelniNjG@!**A{rs)%=3%5{UgCaj}IV`;+aQWvMihn_W;2OVLpnpcm?^oq1 zIB-IvT+;fumHEeH)u{>^HMRf9Dc5n>BSoR;os6dm(I2iW_i81(74R!xyR!WBB4^E$_YOH%T2C=3yFL83o#HomD~gEo4M1m#}N4eHM%Q zlv&uf{r*nfut)L^l5E8fs+%F$Eq!yzE_-XqTvx1lY3TD^5AgfWq47(VxDB6Prak`6 z&IQ4kD5rvsq#<>lX-|^MO^fziho*_p$^#WE4bqz=p6_QNwHau)d#yLYF`rmwB!fG5 z>mNCCq~lVLXT8i!6p3;~{fFAcqMtYAtSiYGBD$R&JcbsForUiG4^{lUbvyl^$C}i| zg})Hnj;3q2Wp1RQzH#0Pg4s+ZBgcjMb@KD?5G!qH>q}8(OMQn?45{KLB`f>9)sSsT z(@Tz5VZp)fSQo3T&$pVllE9cXFqx->W*wo!-d`TKrR}vIO}grKKY?lIsYL#dH#Zyh zh*KcMHOB1+)dci3*JsP!F4+;_3XLoziJ*l}E49VmtNqJ;OXZ!vr6#ru2;}bS%e8Mf z-7KC_w%FaJsd;OQ5H};Tj(>G4HC(p*VBp&KetXj}TvcpV)_2#!UJC`Dz5dI8ibmpH zxM#Lf=F`+7z`ak3AcP}52AffrHB~y_a$<0rL@NyEjJr2|| z!?aTo>Ni-rs%Cb#7*!qNP>B&LMW9xH?s33k*Mt+Pdr0l-)EVaMY+qj*rcEr8Z)`av zq1bide$@KH{-oTssnVJ}r&jK9c?xAzEec|zKK1~)Q7!)9%stonrFp#M z_brDf@Ee5vFTr8o@fFmoiKZloP9AWGb~m2RDD3lYeerwOeQNlg z5{btost@yZ$=s=u@oEV1e5Dg_Pxy}>?yt=nzA)Az+Ip_ccQ=Zd1ZSHB()PKE**YoP z#zZAH2IH*qa@CQh{j9R=1t@I=j64zDA1um9Z9aD$Kr=3;#JE z@_M>12||wzWqGEns3I+xc#z7?q5Ow9Kl$BM4jFdk&o|pBJKL2VO(@ES^N>^5kB0#gQ+Mo)R$EAMK`A#!SdYc4kGF&i8oK2+29OrC*#7CKt?& zB)Cg5fRR%uJN*B=KR6s?IPl2fvB4&?M57ntfaJGMj*g-C^;DJq8bBh|XKrLS8bPR= z{pWWO`<_s%_1~s5019@)d0@cE?~d!O=|Nb3s2WgWgT)-Hi4@{NbHj_5-dO##RqspV z8l%2N(xEG->2vZ>P*A8^o*5hjJ4AxsVtG1Nyf!$|$wLVSxM|4_Ev8`*n5} zE1Flq0f)xKgX0;w18?j1gom*6NwN|jE&Td=gcI$i>-bUyEr2q#OYOGlIUg-KO!Cvt zgo~+vN6K9u`GOMPARr8*O=Py*u@?z+BUrCMqI2ysq#fw@H-s@K&z?Pdv3zBO4aEq@ zGO+9Jqj&f@Ar*ju*zy5ZXrt|hN)*=Y>6Fv2#dkJFW;NmP)vO@Q=ne8;x@m_I1UfkK z(AH*ls5T6z&%8Q6_LP;F#S??2O!mTde9g83t(O@4tL6ELiM-ZRY`9>c!Ev?keCBMv zJe2dO6@MVXLgeX!*pPbU))xA7%u048`|pc9^gI39&k#Ot#+15EJCw~h$(NWgvRQX( z1qv)ITLjZrHl%AHsOUc|Wo5uh05Rat%X2=%vHXe`&6H<9i@|)JZ#ncUCH?hlLsr7l zzwo1D@ptzMmB_T7{*1-V*YD zI3kQ(*#G3ALD~&r3gLxr!V7-P*e&Tw$8Epqvd%>kK^n*OLu?Ap7s?>}X_(U87sdN& zP^`czZ4k&yY*zp)OR*3e+uGZ!04MLKfvcr-0Av>1qB7rnZQ%AUZbrf_0E%1y znoU>KIP9XwL1s;t{suXJk$M_rsRBPhbH8SnUWGXeB)Y8^OGYAu+oCj z$9~RK9FEL|<-dY}5I7TV^$8G?5EL!h7@}=W&t5TJR8b3<-T);l%vsxcIZ9>mTM;-K z4`a&BP22ZNG#(th;|Mhx8~Ra8fGk)rAq#bflttt?9^eW`fmhJ;%TW6X*)r}8f|rQO zG|C+8^GC&Q$EQUDVNx~?3Z1Zr6Cln!QUffSv()DYrL0h=))!TU0F1Bwewp_761C5c z-?xEeAAwRo3-+kfilkD$);nDdDK3*Aj6>kqQ@%Vf@rBk?e3^%l9CdA}_v&EukuA4R z>?ziiL!wZMj*QtG!YS32p(4mx@SEqW?>PeTyAm&HaI-zW3w1?u`U@8-^5o^->A*C8 zOgcA@??>Y0Mh{&A#F=y!r#9M~k6XfP@9&ag!DKoBwif*eVn-(-3>{3#_KB|CLCE)a zYIgXYl*1hJ`^x+r{BS_NGU!v3yp%8p8!+fjT1&8rmI4R9Gu2zF-Sk)`x9N4pTb+z| zvvptdT{?etWLjp>shO|EBdR~Z{L~W<_T+qElhOnvu1Zvk9{Q z>UZOzyu&H!GevtL(GLQ|2#16xwRTLza@A$5sRA}`1|n=VIC|XrwZ3;g=cGO19IogT zXzyJ2MRCI@6!=gLr0&!wPt@hoC0~kIxn$K=uR#_XYQahFW`uWN=z#%r( zcec&cNo8M1w(=c&&Otl4-t7;-%a%%6Ip_7N4p^W7ggZOl0%VsuX$9W?wZ5gdI~gU7 zqjsp+JdIGSQ&sG_^wG>A>52`|gD60#^1sK&pPIy7et{>f#|O+*@eQtwCP#rM*aF+>piO@9N+;zhteCIyL)8=D1CDpfo?DuNbwXK&a{GzJZcWv<7h5Ne7DrdsH zp8WuD;)&q#$NvX@&1O2(m!=dUl}O0%Ja;$?Fx7-S zI;EPYw?;Qon&K5s$VoiPBfCQ|3YCSNZ{C``otl>tB{8Ou>~x3_f&*~W;6^#t%BU~t z#6Zwxc=m<^&E*0e9{|^?FNiuK_k6A#NNkwU)gHO;ERU;K#()3jei8I6f$cGXn`?*$ z!?BIf-r@64>0K;rz3e9>rpBFQ1icO3?V^o+sTfI?Xu0AywvpC&cv=tzv5UYH4J5d^ zU(`_ms)Qj5?a`#NbRl_?Gljq9N+O)CfP!yZVJ>)A(g+Doox-AC-om54!1YzF{_=p_ zG>X%0;T5DjT$F@$jEVJXU|(<6;2``~Pnd8(-XrGq7SN^xmr8l5IXx{~*S!KONHnVX zV6x);Rs{vEm>_cLbopUR>2Ey~uK1iDk%3RQxAty9{G?l>L|$2embGf@6Hk>57&|f3 z;2tQy_UCBQKa*?^m3=&WU}ro4M{64z-cN0o9M7%@1W(#L1H|+k0#HO3-DFjj^0}nx zPXNJQ@#g{A`M$bg6aQbja*j_`_mG8GjnLIk4F~!Yd!?=Sk>k1{mJgPUXN9}Hb#e&?vZgQ0OaP- z5Ty@Om#&XJ<8=BTncH43k{t(=aDbOwd%#Jv_%1wpW|s=k%E#+>+i^7K%9eKkb?L-& zFiI_p-~ZL(L$Im;pbn39(fs@9AfIlUT znVt6&r?wy`(5`9j8_P{0fxz8dHVGZtzq&XnFxj1N$gML4G(94>@z4noGkeAjTkc$L zRNA$+16j%JLsQ^lZqd-a6Wl=@SEhQDz7Hh7&}i{g3*C24yBl_#p5U5AZ|(4POuY1A zBOA_$N&Yxd3rO+1kz|fcL_=Ds0K{cYAXqRznK&9L_;Mx9I1nIojfG1l&xRe>Qf#1# zjHUYk?W=nn4FOJH&bcSf(rugC>er|Nf&S&2awN%Wa39-mZ_cx+zkWXLz<1WmV1B$) z4_Q{f6dij0{f_ztE6LsYKwmy_kd{AA_><0_O$ySNL$oMj3eloXaVG#F(!F4^;QJ~1 zV83$^-M#@_umuPkW)NP1lX0Fm{76%y&8g)yD1Mh<<#Ag6^V0*;m;}>Tlfs9HF6Mws zNFwt%*CZ-k9yr{;a!Pq^A~($729l)?P8ALAryAt}-Lc=Q)6mc-`PI8cqcy>;WOvDx z@fRphgvJ-0I4pC`540!lr_~b>Og-kmYS-{uUVOrDL|J<26}5&)(G7{Ctg8wAl%3s$ z?%Djro>&~xd?8ULB8c+#s6MIM9uY1|FM)IYcQ2Mv_S@mX{$5w%+X__JI>4JUBg= zTwRfr)==R!dd0V7VbY!S-Gub2k-9c5jIb!H&f853$Xl*6ZlGIWRxE;&c9}MIMrI|y zMMtU%x!MLHFMY3H&FbpuhqmrIHLn?W&*FRt&j5t2NC*=eLYFdEr8p_=vWBo zvv7iI!J{Dk_7|s;wr|~eQlGVM1Qf5(`=<^aMM^B-0G{Th#$iEdnat@SPO&WDQ zB-SWKp~FlJ{A-J!F@oRejtIp9?K?e}ECvP&I2pfxH{i}|4Qj>moC4YrW1PvbpzMVRY7+NULwehiV-M2L-a7);dC zF?}xtau=`DFtH+V9kGO|XFChwSUuHCR?S*}`nEq^*5a-2S1rCOx6(MGyK5w$g(-jVs+wLclUcj5(0DgRf;7*TL!w=%A5HX~vpvSe)p9*;+-4;nwO1 z0lwB3x`wQ;8X+Ad2r*-Tjme%!#V(L`Tb$?$GYDCP3mpUn#}<@ylTFSVpdrmq_xIiliITD#nIjc&-7hD>oKM?DXqDw(&=hA zrB7C}MIri!LpD+cTy4{!rr-p5C7vYeUT7}pGjw+bz=Q+}a$%!DrSI^ayQVJkN)t%v zV3<@^D2g&&S4jFUEe6jwZrv%tbhqYtT-sybR~l#~2d7}$Cbo;d`iSB<_`c-?Q0Fl9 zw%>*=oMJ~cFXy&K4jHmtYt2MFp3uDtoqQi}NomF&J3)1WKxGEN6jq|()>DMoxJI-K z;O&d=K!yOH6eklCj&*LHEbI?N0+Hm=kk{GSQ3g+sRsr(nxskpw^DA$;C7;w51e>9d zz;daL9e85p>~@rsD%g#w3#u=h zx~?x}re+ZEw-KHBSq#CgnvT+1TlY)00*uYIPYYOE48w(=Ogf~%vU&SZx0-V|?90Qm zn~Ol?l0^KJZ089i(wQn{)IFP6t&DJOgPK2d`ygfE$x7PDb6dZ$<;Pa+kdVxFg3fvs z0WUU#>!&}G`g}&Kz&CBH$l`ZEkwVlO|K?ap@hAw8#;g#r{0rb$!P`^K4 zb9i}FjrM3V3TbXc6pHNhXsrqsMmHa;_}MqmKxt3m|FaRLp&KllJ=@J=0=GH&##7Au z6I!NsuT2(O(Ous}D_a2VYc~L`U5-?#j1@f)U=42Q#g$t{@XKk;S+Rg>Z25cX1?1F& zpslZhJKYM>8Wx;e>uL&ofrpKD?nMea#F1zX&EY%iX`J0xI?tNQ{V;syVXqyhBdb6~ zLZS3{@f^s^d)6KwwJVw~UmM6OojT15!SK_l{!`HX5@ecvfeiA9N!tFj+PidOU#p^{icnXNy|X(obD17hUd4D^vuX{h@3 zz0my~#KABFdq~m^k12@Jh2dtpuEwXy|I(~wtOGXhkZd{reuMBGV2W#jO)oJZ=3mY= z<#$+|kVE>C!oaipr)H04X!M1i1w0r}G7Ix6q(Fs;JN0CRm9*Ym^8b)L))psu^1ie% zH8hc^mqQRrkZNhE0H&rbQYT%;dFtsy5VD@yRGz-GL*OUyZ|Cv|bKs7`|q!B6_ihj16eH5YI zhA@WpH2^2eVI1Y7P?|22-Oz0v-Y;tcWSekSYX_iB&dYWK-7}d+_nJh<#7Eb>9ddv zK@2t#(aFfl+T*gRm6I$n>-ip{u<`qPN6-`G0x8#!$)XQrmn~WpTz@p%WfLy*Hti9w z_4~Kmpj@a}tQq64^Ag;~AWSQL_rpFQQ#>klYnQA6owMN}Rp`;N8>*Y&?OL8{M@^Je z>^WN^!6JR*_SRk1F}n?6+AUW|K>p6uQvJXoBBZj4L=kRWwwndST;nsEl!nJcACcz( zRKFd(*H2r#&>DOGLd~`86l94O1w}>s8oM)VroJyZ1rJ`buBDZt$XOt$uP zUBy6ngXCEET#5#~xqr9jqeRcT-AIuQA=~YTO@>NfkVcG|#q!l|r!+fu?CG5or(11^ zb%T&n!a&bEB?6JxD7RHlO@(*QnRL9}UVzyXjG=acY)UqtLLJ?_59PGo+$<1xcHPvi zAL?!xI4Beg({uptRh-AQjHQ=kM|qy&h%Qhk0&sJ>+$3?6e=Te^&5mP9tI0* zkQU5a)t#B`2W!+tY5jv(5D@}wuh#EOx1;&_`4ES&s{xu%+KI=8g7af=ec_`fxK1h?wq_g=~^BD_AG?7r>BM(HMOYDhKCV^-NhEpWM93G8+C=d33Di&bIqP zxO9^-8Yx1dJ2ZaD z^74gF8SbY{P&0pBG#qD{N{2}@&3`em$E4M^XK5p#aeOg0j1N@RQ(bw+cR)wpXXe+_ zsFK_8)BvWBtBw-RUXi`aV|qsJaB0TMtvEWTtk`s#s0^jyGwX>hOF!nz%#K)WhkWL3 zw+rpn9~4@QP0vEK_iQ=7t9X{f;yje>wukOJ#!fqRcrx!I&bkj(D7#cQ>I@Eq%SJ-O zvJ~28&l2kD_#h!>;e2>TR0{p=ZQ$g5I*j#TA~{@X%LWOgSZ$Q)zlOo0O8pB|cW6A1YecMerug#w}! zl#U%0@4NKRTxL{?)I}o%HBPg#oCD55JM<&|Mr$-}Bhe|ZLisyGwb^%>5p)A*^Ei&t0 zK+OnQ!Yr_rPzH>;inLkO@^X~Z6^MlgfGLM1T}B!Ce^tFxKlv{F=0VEcp6qo?Uc{%} z1I8_9zQ{K%+eoCIN;*_!8>M2uA_{dKg3jfIN}LrACrSINdVYanWxxos@|w2suI z<)uA`Z9oi&WZZJFl27yQS?Hw-Ou7MW5d~21ZVu?y>HuF`?x(F=g^*4754a^x8`wo} zr+ws5J0qfs>fzM@FnvNKQb&_XstJowz9n)W@JK5PTy0H03OF0WWcrgQB0w--!(JVw zw%&d2#YCpHBB$XB87P5*HxC+=^A5bx0}3lrnw$Zse+CK}-`Q}Pdp(CfBdJd#<{K&? zK!RqQ5eD876QGxN4OoA{Lj{*O4KhslW}cB$Qnq+lf%5Md!&5KEm@S$uoJ79;=ggd_ z@oAUd(PvVet*1>>9S^Iu*w}!L@^bPVN5MG^Lq)eA@^ZXb&}GktlWF_cR_{Bu*^Ldi ze8JK+-x!r2MZzS`9^MGfthfkgw;BRbI$rDE)IQbKUr%AR=Yh*slj~Cei9 z=K8K~nKn@8_*MOjG&E;+81+Cpqv!5B9a_(2LsvTr%b$Y>{ZFRlULXv#%A1KCw+$c* zy^hQoDH#M6tzQSaqSUBG8r;WARO`1{I2J>iwYP1L>G;<+evLm+7M{hppIKiyN_qC! z$z;{D$THGVNUtnqh%P7ulxpvwaXs#T=ny*6GLpJa#4}NI%yOM+c`Du@aXieuc$gOj zBz(OOHF@A56w`Td7U`hl9gW!j9B+3Cg~iN&y6vxvR(XKvCy4@4hwtiGn#?!Jd(`zc zhXYcWj6Ae=(OoIV3;@&sE&r-4(IR$Ks4{u|TkMJG@Kkbex>FUq3AbFycoJ9D$%{E{ zzg{W)e&#LTezB#IbxUibiFB#FLTh7;h_223Y#5Q`_&ogW=C7;J@*&ImO%It(`rJD+JWt#v%J{Eed$a%1`OZwxYub~7 zVb7`|wacU$lo!&V3>ieQR`c@qu7(O`!#^*BIyyQA+DV$n-N_)*US{GPe#AMj#3X@X zYfdY(!#UoQ7V0tYM^%@UL@EO<@*MAq9XF1?NU^lAVB##n-VT69b=i*-{d^om9bS!X z5Vpl$oO~q88oFK@=>-imL7{cRrq1r}vO91DFI+ILn#_O=oi;T!?E%F*NP^LUcAnOd za6q=etyeOX&Be_v^2Ljt>cNq3GFHAu1rG6JaPfczbiP2jW-_n=Df2}k4ZlWuyaa5D zTQfwwbG_k_yf)rW(X~5ofbV&%;CX)#9q4AVLWOE>jcxvmxyd{X6SpD+4phTKuFM9^ zuCA_CqS)|ND7vtT)U`6B+pItN$#A>0{X9`KmCUnbq-Z_S8?Pr>ynyc{S8=kaKOuM%~D4-=FNK zPd`q-)=}NW$2Rk*$^R%`d=a=yH6UpjRv52Qe?|-CBKyX~-K@W!Ha0dsgwBe>tH#aU z-4^dwqv}u{#uh?K5UcifbtuG3OwyiT1>jnfqJD!37m(-pHPx)x^Ep9Mx@);GFOM~q z4HSdzNOora`G|!ZT76MVr%n4S;~q&loelx6C z`(17f5U^+{mk!%)*$T>A0uhIOyPpglCK{nFg;yeh>EoNV0b7M$(4qB49W3J6+YglsCeE=Uu4b&dWpzxC zB*_GZ=yM1C6M-SN)Zj+dwTmC2nyKj4!#_9L#HY!Vm!HoQjv4g}Q-2DV>?`;bCu_AM z;eb0Ya@kVL5-%r@S;gmbe54sZ4YH~QkdAjiGlSCKR99D{Lrpk61QHcqW20+-xeAn( zk~cDdWtv4z6$fjgqCl%*XIT9Kvd`_Ra6b0b5BIK{yBV4%oi8{m*#Ed`Q{@U z7&DfB7Uf9gxi9iT5}fWGghihhK2tr#Q-fJS7y2|j7lgY8`H5qcCK^TWV&6M+G^PA8 zr09WYpdK^u!2HP%kZQNAF!-&n&u!M{rtZVNBA}~DhD!9x{R0Pr8)KD;*H?wp zb9wL>4>Y}^A~WFwr+nb}&s)O0@Z1n_vg@tgi5Y1@#siMcDNsmyL9mvE#%S->!qvREkRwt3)s56G zEiH3ciHkx|v+{t>Y4%j60{8wMQYIOAI6cI+9*n3n2rX`ShKZ^mX7&N7Ttj#TF~V7( zume8=zJ=*OTRmGcM(d`XpXTTa=ac1y@XJU$bm-8@$fif2#NJnJg+*epNav%T8w#tk z_n$g6_Kg3qcLw1{z&){}mq#0AsO3-IT3A|!o6_#e!ra24rAi&ohDAFqh?46p^PP=n z&g@~l3hM7h+(2PS6?AxrpM#>sK(gBMdk&l7y4awXU|af*B*sHoM0sWCeh`1k!gyy* zy=;Xb@XVsUFoD@=B!=L1miMycJ3^JA>U?Ug^4$wZW+`(`H9#1c4YiK@UHcpFR_3AF zqg=jRCCiqo*`&dSAs1bUD36D>XeehL$F~K$elMW+g8^5T2`q!w9*yIVMn*>9=~^z$ zNZrTE#YKx5=DA1t#jo*}p!f$#8h;4;b$_l&&5BjCuW3f@PbDKlwKb^Tg1TFR@13r_ zLV~6;PR-5Gz2)mam(b50>>vUmFjdce=AOw}7E~1HVYu6=BvLz1oer4x%W>;Hbo~O6 zzLBsU0pQ?GpP-5_^a#g{eJ*rJ4k%bQiMqZG>iLP_0zrgXZ`b|@<@3*%A-X#Il5Xx- zRIG-1G8u^7v)xhqLZRy&7vt|sIyd8XfM)lB3=iK8bwEj<#`c8iUIPsP8k73ad0!gH zfLnpv(jO8*qQqRXNbS)#kkHouC|rP&INhB-$a4m7!K{;^7VabxQ;E_i(?0jwd*U;C zw0XT5U~n77p8nl=1ItD@oMz?z#RP7Q;00><=No}ei6Cle5OVKrq@os_GoZ5u?z&+1 zcE;Vwi8ELs^v`J~jSbkJz{B1Xd$Bi6Am(j_l1v8SbE1r8!6%u*9xki3?#{3Zj?Y=o zhAYa-da>N?3)-Z4Z8<=6*MQmtb217r6@d>*aKF1B+>FCk=70uQLmw0~C!-o|`kjn< z?!~URsMd!12Xj`MuEQ1&>^z6;LkV0}$Dsot0u@T}pJ*J}3< zRGFUf(4zb{t>8Mg<)8n6Bpsq6!AclD62ttSuJ<3|Gq~Itcn+G|t6pb)jw&c9u;CV6)32gQO^8?M-svTJ+pnt zMVO1XSYq%y>0{8b+^nputa5*(?m?@TI2stdNa}kEsScHb)uRuMcVvd6 zhK4BUwjjc|Jj$*EO8;nM)>omXe|yzeK7WHVoNW}m-xST9s}a0>a?`ebn)qiro_V89 z)QP4ucCohb0QJ|lwtrXyo1n}V?y~i#_(qgiTl;vsX|+ix0t`Q}+5u8G@6l8Lf`!4h z*yFnp4}QrD1WO!$E&i+ul-sSaSs@!b6J1C0 z=-Iayp=Eq%-pMsRmJd#AO@;r$5X;2-yYzTJU}aDd&>({!6+;Qz{Syi*au~=D-s`+C zqkBd?py#aS28XJ|9l;YU)GJX)L=abj{)H|8^vX4larHGVi*K*`gJN(O?dAqU00~f=*%p=Ek5`W(60`Q859px!Lirok@Xibdlpv4~LDhs+G>>*) z1*+5GmtQInwk>yl{c0eHv7X;TG)BY*6g_%szVt%oOf7TlB0A!5pDXHZM*MX2nyd^C*W-faQA=6Zge{MKMg_`e9u*-#N$BPBIX+Wa&{wEtcl zZEYpRAR`Q1O$r3f|^G1ymYp#WtH^-W|E zGK_gtc>W`cNU(hDg_;UVeFdw?Z0kV90U$6_u4zM&2M1V1AbUT=VNa4GsEDqA9hjMs}IV&L81N} zOc&|QkldWl>omoHeb|J3P6d+2cAkv%aS?rQXapf&Pg1%H4_Ig+m?ZJ~$QC6{R>pad zu-I{s4=&tOEV#Z6^xaLus%P*qy-?~A4^9+N@_dF*|J?Lw&sJu{&X}>)^FU2CQYH#q zzw@fC)ao&Du1wD!i}WQH3&EoR8vJB{9NMffM>gz9ELYvYlUqAxE4Ss(n9Lwh#`NS` zCLEd1du3FnyCwA2^yAB=Ekf2`jMSJx1*bbR`Z1>mwKtHJ=3^7$C-t~RT0*a$(F z8>xu8%_Fue=&(LcLV)Qj^hF7XY^n_96bmMr ztAK{2kuHaX6THN0^h^pX;~${dY&b}m2?ZCsL?M9@eW734R^!j38~OFQTifpVauQb% z)7Ym#9m!o-a!A6EYb6XiLaXK-2`Hg_A87!nE2UjUy7_xAP%5pk%y zn;D=RK}&W13CG6kZ&%v01MN;}w~dfamv!E*-339E}ac zl8fI9bdlY=^1z8i;Ihxp1uPhgEKfWc0!pZn*2ab*`=w?D>u$s49Vq>A#kK7H+bp>&x@(1%WmsD=Jj z4mji&MiR#iw1vb&ztK95J9uq$zy3dGC>{|Jp%J~U@fVlHot!ukd9Xp^VR#TOgdi`P za;djHgqE9!&5`*h?O~^5YM_E=?*HSN`%Mnv9UxSf5JGhl6%34Ou=mqp%T7|`a?dsY_ zqSTNCUz=odRlBLq-i`XSzSQr&Dr@{TcMI>XkM0mc`IQtw1V_(hp#FJ&WG6U|_xv2zZOt9bvUT4rb$gNbmzZ zMzy4bA-#PoGzg9zIQl+3VTAv}lZZO2}Q_>QnUgw|w%-9fGLe5kXgK4#d6dfRN1>KMGU#();Ri?R6z-fzaz3iePRO zQZZDeJ#7Kp%>WC3_iZzARTo-F(F1r(cm5S015{{b)#!YD0;$q=eRbjG@?n&>J$kQn zRzbOU8;Y_Vw|kIYv;)zEUf1H2xf)OOl`s3l<2`JQ|6x{t6;{fR4QioU;k;FKu~M&R zuO6iQ`8Wtd>>jr}kZwkfh;(*$cMm|BtDpI<4SGmn=F5I`(16kmwSbU52*5zHFDD_d z%&qU8Qk}{f7w8L-^ZUOVd-ixJv-i&ogOr*=wz5p3tlG$Sk(PNE6}1(WY!?ld)s3l; zH1WP&Y`(UQP<>mKQ7R>uE|Tl0R*@~*Xh@loglLLkTxRC|KIhebKHq0yw7d=yFe6RQ?~2ShN$+H)2sRLWq!{+9k!PTq*_XDRsXX;Z)>~O)AO#H zvG>EbG}yA{zCQV`b!>M+jN-yBaG{)dIemuGa2$O6G}L9l(VG5~Hg+?LJ#K-Gns@#5 z$6fLZK6Tf?{%{c-@Z)PhPFezUUorI;pySNV-=yq^i+%Qh91cteP=0u;99t7zV&j>H+E;0`#@b4oHR z&d6OSkrA_F*$DDFd9$GEK`*G4CM+>lSEZ>uR39Xotecfg>APpJnMpT=t(fIowDv3S zouFVb$#o0sV`TY6qt%)Me&3Z<6%Y}?>Zrcso5O}J#WHp1{&rXM2|8E~PXz5~$eTJF zIs!R%|9roZ4Vtc~$YQes}qS}K0~87_zS@HG)- zmIYeB!cGw_ec>q&I3}C8GVma80f#H25#;uPDYTLN65SQdpAr!f!S1+hS&R+UG~F`I zw>sm@W^oZ5&?rNCBdGd(e*QcVFU&aFAh{b)gS^ocbjv0q?aap)Ld{Sv?TBqr{1ta` zqyxdw->2da8MCluHM$W15gRJ9K4{v6n(6wS<)QnDY8uQ@)|^oYA*P}uLcC`<3ILY$ zmcZ)1*YJ4GLsLW8dc*KuH8P&cBk;*&boqr0I}Lz0>mN@7+H2D*{Qp&zCkfnZ!Aw|T zFMPkcfh-JLU(Op;*MJg7^Vyu91K!Sd{4os7pz>y#`kKS%vUR^|gGPE@DEO&kBjo4- zra1pSIQcKeu3;x<`%aEJ`;m^d-G8?}hAFf>ha*dXnr;HN2)dA!HM2KajZFet!s(26 z=J>h|#7G?6(lRydT3KqkPnN!W#?VcbeYgnWB8H)^bi)r!Xw5%|5x_^3deNu zKeRW33e)QU+wXtD{dcQOMIuKZy>j{!V?B7HOZ`ElxdtC+I82rAZf!yr=eM4L7^&c= zDfu{5PaO zK%_2&L)<~gPkk_pO~OsPl`TU09=g|)UH;#;Tb$G8%z0yp&!AT6H&8-{YtyHxp}!$G20S>`_Sv=k(tA| z>wpC%;JFR?mC%z30O0MGYRpB8*m;-z8TdV;@x}%)3`20EOxX<^ksY=WLl!1l=j6S%2u91;y}#+f|uH+MT5(cJB9GY=^0jR$sGSI-ndB zc4fulq`SmLa8+-l-@u+BN&AQKRQr9)AE1c0I!Y~2|xDcBWgG>YS}HQ%~^{dG@f&bDp!` z<1~*mo|1a~rqPGGIN`?TRnmcHN?tS?D!HCk8f{*F+Z& zuR)m!_61DF#b+{>IyTcY3r~cnQ*6w-DFI-(^EaSK=`ZVVQAd9xXqRW)1^VC-LZrkH zTCRkkjS8~G@2o$CvrbIbED%o{?DLAfibuv(cRWale}Z;Sg9KXpoY3tVmx(+D0`p_c zY^M~fB_f`X*4>2Kokobh{s`^;ZgRPjwhCuJ){jP7&W8ko$20K^P)EbR%w|Wk>eQ`& zhH~WyeK8B!)fVeP9jeEy*fyod*~J%k%C!;=3*fmylU6g4rSYiy2w=p4!(B;bLAG0E zF(8X$)^Z$6qLzPb{P~pPTTygMnai7GU{%Up8X}6_t+I+>kQo!$L;6A_&?>v~R{4i% zm@+Y?KgplC=@RFIm!*f{4r?W#gzc}3wLj-wi&qD_PTr> z{fyyg11-E}+IzG26}NQ;Wue6O!keDsajgJZGM&sO78*bDEwz?5;+En}S7>bCH_i+uVdlE9TZQ=zgYcAI*#k+q_ub4qh!%Ca)L-%WEq?G~#s> zXOyPSz2$Pk#`FcGke-kZ+l1V&nmR3Ib(&&m-nN~e1o^+T)-OG=;p;JAFAF(&eUiyS z`oiR|(VGnfz?`2i(=3=fcWpN**~XzV-lcEw#v4uCWCvwhJev@XCrluTytIV$_9B$G zohP=y>B45!43TVG){soR;n_GmkE@59TeCXJgt>>WZ`V6G9|P?U0wbNH>xQ8~U-SH}nf3T{FUa_ihkuc0l96AyHHoMpP(DpOtl{F2Ow)*(uiD!00e zPKyEV{K<{<&7DU}6JzZn&!#inL~KxA(??!K+v2lWF#fm{-$9f0TQ}6y4Gw|w+DD5G zlfHG~jdK^Lbm_0xkMzl7CMnJ)@@iyo_t20_pnON{0Sek~NNp=ciD$CiU(EW88Qj(I zcY=w=HwI3vytlHf$Q$!}=IdHXpzR+eDNoK9%@UqB;NZC&qplX}mVbN`{H_Skwneoo zZ9m+`H{npNTJ4ic{LCN|c|Cbf2g*vn~ut@ck+K+rZ3#G#SXq0AYlA_`jv;z-fSC)DxP4bgBz-QV3v1D z#+KF()$gq;NP9WP&yENDT-K!7UOKwuwQlQ8Kj8m^P`R?I zO%kk0JxjKuIH$+j?pIy5VOlggcb@I)-l1{TB^2p~yurUMpr^#b$7G~^S52QhU5hu= zFv`=~C>$fupqhzVeeEqR2GgJ76Fu?w+w?h;!uj+YJwjsT%8Kl2c;f(YMEnA}YWd5I zPUU`g__ZBpY27*qF$X4#86 zo-bkX9xXJ@JCXw{iLxmZuehX6t#8vK7KcYf7)w;;(7#(n&fxOtYEf@4;)dcA!LB21 zr?%L1fwtwd>Be|%KN@b6Wze;(#EBj=C~K&)jBFNE0}b4hGbW!<`PtxMxm|fOY@*x% z(rS14CMxtTh8rTA`Hcfjsv~2mTQ!{at*fqtdGi2~$52-<3;?hOHHtK-*GH!zWQw<{ zM+>eJ+~y&l<6iMznm5$vrbgtEz8Ig>e&dFxrveh(g;%#&-Df594fKF}yO^5qSMz46GE;aN{oW3epn^Q!)d9$DnsFzDABuX7z$ zIyBsE!@e^IQtiDD_+A2mupF-V`Y;{DW~(WrNQZ-Vuhz4(2D0syw1!C5ksM@^_8og) z&RA9Vkz9PU@yZHTi6jt>UPqr*D!^4ezgwgJ%}^bp0(_r#3RW$pmct&%dsw4#su_Bf z)9cEj>}EjCo~F*U9YaoUFQ9TW(nDcp0C^TS52=%Er;tV{u56FC!ia4O8bTMqXFevx+r! zm}P>>?g^#8NS=7|q2;+Rd7i5Do@yY>vKt+;h)c567$f8^45k7AR6#yV3vYNXm5$ct zAR~-<@O@QL$dDIYr}t$0-SGipq{bMkyx?9O(^!$yak2D}w)&nH{82?sc~z^%mweu+ zxB!1Vp|O9dUI+B3e0qtF6o_GyD%_l>Tpk4C@LBnN%9yBXz)^7@B6^-z2G`@u)!%m6 z{Ki$?WmWRRoK0Yhg+g@6jfHNkHEM`1E0@O%L_oDV#T0e3f#zdPY;)HI2w+_=GWPFTE-7%R z6`fmt00#JMib`2hA&a))TjQ;?rD&u7YbRI1z9ZxNHN6?$JAAzS6HaJxIEadt9GCg- vZYzt_3zzrS4R2ILl21BcwTnI;bQr@TvTR literal 0 HcmV?d00001 diff --git a/app/src-tauri/icons/ios/AppIcon-60x60@2x.png b/app/src-tauri/icons/ios/AppIcon-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..961ccd4b5df81edbeda0c85529747976c70fd1e2 GIT binary patch literal 3851 zcmV+m5A^VfP)pRZexpU6*J`N#2|@8sUw(3{Z6BaHsbOQDnNx}o%r(wss8=63Uk1XQl; zuDhL zUF@uDfSg>1Zr5LbefINz{`p69GnYyKsC114u=zkh<&sWhKuudP>ksq{ogD!hZWhrU z735HWm26trpanz!rwei0^a;XsxfKfE)<032ugK(;0E>SYRs;G#J3mTwx&l z0xVxd9E+mo!4}xc11;Pv*aU%`7vNlQJ-wT@zD{C5PG@wngSrd@`5J&tv5Z1Txff%e z+gAUa3?_InK_I(9;Np*2aFgppi_Z+WU?%V71vuBB@`4y?3vRMO1|!e9&I__@-s~yv zthH=)ZdHJ+vBK~Y#x!BmIyl#;vet6-TGzSy*p(Ojg~e^F?k33|!PGTBz#_BUTfO=i z?7+}uRM(6#+g3YVETC&0EN&5r18Z1Se-MNOg<$H6?}NLyD^Ll}#jl(O|wwav+{kxjDlxyB4FF|r)X#kI-3Sq>)1VGXR> zifVa*tF-0d+OFYpQkHXTo0DBjhT3ixU<fz_wX{ZLrzj z1=uzVux%D#+bqDgS%59TwpoB}tHPF24Pb96znU{CS1Pn@Nh%g|Hx0D_t9TYa>vGWy z;bpThKLBOFO)lBrLf0|*fF_INZ@A%x>@!*NW9}uEwB~qwO;&A_-E7%2%G?;0cInb3 zb?)3beO%f5n>iF^F>g?IG8eCSt%OZDxU_T2$ zZq=%ly5o*JROil}RgWG$RL`D0^=tFFTuquZQGfpVrwr<_3KK=AlwPni|4e%d-{85LaO);HsJ7g}C zW8r83e(bTw)Q}-V)FY2Pq9+5NKl98pYQu&Ns!f|V*^N$^JUnCd>ecG`=buj;Csz%? z5Ew3^oj7qqefZ&r`r5N+k0vUha|xINqMxB<8d!1(=sb@LUE8f&H}%p>FRA_e_pABy z=c~4D+h%wF6LAm7x88cI`u5vzRm+wwvy;UF98t#t8r%r5ix)4}+;a5jQ4Kg^7O^PX z9hb#-^fut;d5C4iJClds%l8|A{M&E8srTQ1Up@ESbBW^OR5frdAiwwCd+ObH-_^h( zMsK<0mO94?l-nAYXJSa*c;k(s+f4EKFTeZ}=$2W4bG9D<-0#2tUQL}kRekf#H>!E_ z<{DT47mGNqzC`i2+qG+_lD3z2Dv2Ul{LF<57pmE_XKN7|H?W1Q|3M^o>eNX+`skxs zAKU^QAd=C07&dFxtWm97x7L6c0&H%;BG=$D4XfM$Niq5wBMT{mb$#K&1+A}>BBm2# zWC^(VuEU29SKod2o#tBE(m2veIuB4d9L~*s){P zi!Z)d2UIgOnVU7r4Sq%tCZ2Ak!z}(;GK#R5#yzbH&4#6$4nTO|GY( zep-F?)mNGzVPY8~5?{vnnmBQy8aHm7cAu1&To932sH-B@yYvN-Ud#rq=yN7)-@bjd zBoLpvQm&I*N$v%#S6+EVZQ8Uc6kM@-PoF-m1`i&rzW(}aHF@%69mzu9nP&+VN=&#F zHL+sF3iZVoUugYb?C!gafw3?q#>N;cxes?mI9QCTk3RZHjT$v7l%R4z2pl?n`gBb= z8oCz(mckvPCNQx2^y#CGCAcuGNFXd?#Y98W5LSKRg%>Jjbj1#^5R|wwx(*`Xp7_mj zZ<}NNcj?ll+R8?+LELf}FkyJE&Kpu zOgx)0zWL^x6^l{F%E3a=&6_uCV}>BUAGngfgNURB2MidX!OgAOC}pAvNEk$<1JURC z`eUAH!DOH);Iq#@QzJ%<(9$R0c}3VVc4)? z+TZmvtPsgq%jiW?gyl9+q%RZ;^zYw4>sICCLWwow+hV!P(KTEciW4SGP)n99(Q)W7 z@s3eRX-}M7?8cdOp)FgsER@R;Y4_iMznVLDZoO123KvbAHcf*kd z11`kpWdfmh{lJwxFEMT^Df4k2ed8YbI&|nz-S?oeF?MJWwUD4H0G9Iu(4**Izq%%q z)6r}7>7oG`NsXYqtpGwvEHQ5SA0&ban+9>FOfIZ%o)r{KsVaaaB)Mb94qdD42QUOZ zfBw8SdLDY{AsrMbr|y+-WK^G*h!zQuF=NJPQS2v4BvnbD`}OOm$B?hz0x$^`Xu>gzAxe|hzlSB`mUTo0iH>)1n!bhXVAov&9u?2Z@u+aBylQz9XWDj;Ju6;?u8a{ ziD@@3-*?-#ZN9VCtZO3ZAg6YftG-K0Yq5BD@7^8R=f#o-kT6LiCARdPG5F<@r63<# z#N`vaap+%ah7r$xI!b1CuU@^h=q%N8mij70@((}!pk90JHTC%8kE=zC7G(?5{eVL6 zvV>*Ilqr#2G_k1ZJ7e(E*J5Kp3uqFD9(Lo%`BKZwf~}wdF?f;>rHW^Xkl_juX#&^< z3l?biBnnvheBMG-QSaWpeWim;cxVAl3N0u|B)~LktR$e|2QFfhfI+FEONjW!8*k`J zN1jEL2{9c+%pjk)5LE>Chp7N)0ZrmaK*Rzt85O^iUF29jKfiV!%LH5(wgs zMJ>5S9Fx|I;`0WLgE6oWEo>Y?G^rYZWq|mUe!+Yp46{BcfgaW0#zLhG)-UxJB-Xoj z?OKwGkVWEBG~j1R^FC3pIO5W=a4;MZG!O=j-YP|8$@li|-5cs}`{_lB?aSex%3`%J zm7r>6=}K4un~2wPH1e~>Hlk4FusNbw>v65IO2uJh-FDk;zNMp*5a*t97#-x9EAd^k z@6=xf8I|Q6Zz6OsnHGs+nW9ttKtAK1Qgo7h@7{aw4XpDDs-L>=zWd73hd9QY2!JIJ zkMmEqg|$HZUuv9r&3k;tJ*6ZVq(F~7HCU4rQzjrV zQ^k-`A~S+p;e!u8(5v&qj2*zlq9xh|$fW=r z=XeuUlO;qZd`PVK@ZrPy|E$8p;=~6n*I*^yOC*bI5dO8SE-=>zOELYaQ>S$4&a7Fp z%2u}==XeuWHY-~j$^V(j%(4w%l9WT%0oeLyL3`VVm8D z3}q~9X04%B8wM6wO4>8kPy+z9-XsL;=9GzA7OoKkOPJO*%Uv?8?N~8g_2StvbIxwH zoWW;X;o@0Bm36k>v&L3!7*}=tU@29p<-~VGY39LTI+A57Wa~0jJ@=-Cd+QikW-{C} zxY8cT7UkrFn-*|04C>^rmPqBUZ}nz?Xf6|CZgP{S2z20L}$j4yBME^y;b|3wHTIWjx%+khOd6=6MC}qjb{{Yw?F!fhF;PLz3yj(p)f)=l9X9<=q6n{=pMJ&N32~>TsjEEO!&jW z2m+088{PZJ-u_x)jeBR}l<-vky0+fi$-A`vMPbw0WuCQnV4?ca7u&XzO;gjB@9zh- zXHn&5T*v3(*O!6Qi>HBql%rL%FFus8>+p{k>!n_ooEMgJ@m86Df!Mj6=d>1{#d3Ja zIBahr{OZ(s9a*@f)1JT~;}qMbmwo^HjopCUe&#>02>lPm?H=FeUA#I0lvZ-8to1`q z7+v@Bm~BBo?=8w*(bx;t`uQMq4#(&p;joWj-8pup01rLZvz@l<4@-CCO@H3@Jqljv zj1$(&T)9?b2+7WACCee_@R`Zv-`eoF=>0;X+>SoKhAfWNHvFJGmgwLGjqWig(cY?$ zWR?^6*mP`J&h7&LbIH@E@Si{F;3V@K65#49w5#;h@KFc6fV85dM)#t+%cVu$7un*$<(;q9MX8q~?xzgRa z+pXw~-{mC~nxV%IGg|uP2R$~^EH;#}A4(s@Yi^PV0X&48=$(v>u*a}(P9owws7N@4 zrkR$bABCtX>W%b@zG2{yUl$TjS=|pRK0xFrq}fA7tmt(|GOUcogPuX)UN>*so1Hq# z-(gBAvE{j&W0hEJ?Ty{X6Wr2c*9|%g%lzlCQt*6lY0QJaW&ZE!$nlC<1J4R>Fs7K{ zctz&Rs!QTjQQ5zX<9Ftzwmih%V2+P8be=s=Q{U|gca_Er>By4@vE()uQ`BZS8@tk> zl<~?EgB`p3Ua@MhLV-peDcU9)hEEOsav1~L0TbXR`_dd>j#BV0NRVdy^Fm}xLq z5~+#DGM|8QxR~dG{!hWv*=t>`q6S3{}(t$g;Pj8rT+(H zvyReOJ>mZWGz&&q(@(VffAIgA|F_Hk%;U}EqS^+XTbfrOUnJ$!oi47cKU~(<4jqM8 z`)a-;@!aIK0x+dJ^u!T^w#8lRR8?lAesbm@i=U3d`m+>F>2FPEn40UD(6#(99xX>7 zWiSc+WzKf@#zNN{=7mJHtMxEqE}abCZEIKzJI7xhP1%O2xGhfWO_O-_a5($Rj3`&1 zFJ51*)eF7kjtbqd&*1z8P+IUGKfNYq?a4wfU-+Lyg`MUD93mCoa~*$qdy$dy5dAQ& zCxK_{R%+`hf$L(WK>e6j0U2He~PB`PKQ(!k4zI%?GKdxF&$P&M`%o z3?7n_6?#0g5ORQDW3>(Otv?*oZCXvW9KOzWuV{=W8Eg$1Wsb5urVU`%J9Cw{|3-e&#cc3zN&yW3=aM{!!y?2!E7YRg$xWC-;12NT2~kHs?V{-CCoR4I zPQsmeu9b!{4z~W^HMW060gty|wW>+P|G1!AJD+jRZCnUkT!`mW``N@tc?gJzJNKFM ztZ!7>X&!I6I@{uvkPr!{N@`HcnX|Z6PNiXXOeA?1$SBz#Fz2~;{PTtP&QFhq-_f1C zrTR-vw&9nxO?y3D3&Tn~e@@`tP+x3>e&oge;N2#ozhjn;A&&e`Wa$le=M%eq(1`~W z9`m^xY}ONasZP4>aRap@ua_a0`b+2JpUux+Y&RBFnFZTL^dyp-9nQLcX*?KK8i|T) z)256B7>0Sh>+0-|*8SFqB14Aw>V)_%p($9+vB`#0RNuvr%n_#tBWi)pxuJF8^kn-I z)k8~!bO(m;Wl%my*3PtY_AgnHzu?qqCs6G<7IPwp6}Q8DX+3kx<>5EaL`}jMJgV_# zE=fvY2*(+ZRpRrr?{IL8I6{@fJmNGb@Tc#bM|Hf?ZaZ0vfx=ogvJTH+;%lT6ITu98 z=*6pDUsRNCH9h5ZL7g-Gvkt#J@>-6U4@gu!E2her3V=)OyJ&DR!n|-Bg+CK1y=ZB4 zH=i*=dHnirZ4+V-wsqVia0T!H>%V)`pdlA#f`>*hI!M3snQ|g#*nifd^_2+iB5X0wJ!S(_6?~3Q&v)8h1im$Y_7+@MEHr^3 zwU8oa|6i}g&=a20q(OnGTU)Ud6m+~U;bN8Y@*@| z8D&%7Ym``EOwhC38?`Gbp)FyWzyK_y$T}*Twm0(zNu9i;<$067;w-%y3l^`5tf)Au zm^yItH8L@=xRF6jceIJDCn)W8F^2-3QiJ>+-~$H1^$mFW#b#;4G+vhunElQ6J@0mQ z`XOaHK-W4mX^G0o{J3Q(P2`enziW(cqa-CurESGpH=FI@J?NzD?LWEo44x?Bg*BR* z!3&rS(>Pt|RXz$kr0B`{+J>DLw4J(^XUx-HSn?*f9M2B&_>VsLX`uP9l~i?y>M%}b z*heJWCvsbZKjB#;Y7nlHO(NzBpJm<5)~r1Zu|eOQa>N z`bjE(!`Pd%tzq4VWNhO#dIFst=~69bFjdC_nuvU#mWQ$p54-JF-D zML5nMx>XyuIJ8b{lP1<)``OdMcy-~C72~I4IYn4$vo^}Woc}W>p_*IJ-ljU^0tPTw$_BcSU9PSSPFL8Hjrh1!2m?zCt8pG%f8krfkDQ z)ug#{WhNBK!15QBoeT#VbT-uk!iVCz4Z3(u`Cc)oXqN^s7+q&^{lPp4N{S)Fqd(US$@V? zF(>)bqhAc%DZ0NpFrs__3y-&QU$=}|9=--dWTM z`%hJQGljm|N;$tnni&p~btFkkhyzN^UfQue6^5ws@i7|K-CQz)m&xFWDjFI<#`w^y zSw|!&{t2Rx%j_k!s^>8Lz~fgKk54;^D#PedQRe2`h<5)em_P98vx7Erw!7_%c~qnrX*Yz7 zYMRe8bX-q9sIrj?(HHy(@pX7U1j|r6Oq0o=a%h-aza1Du;zL5Eutt>QALpO*q_#4( z6e_;u1 zQeX-@*Sc?0;~)9xk%!TOYm!d9ZwM*jg~i&k-G$#i#Ihx8*yrZUu)!T~=I$B(e)=wS zqjVUiLdf zNP^rir5bIQi}uE`cc#%Gz{ihM9#Xnj#EObJJFtgyKZmGg&5ZH_iP^~dsr-@Ox-n;e z26U0Y2DSx#23KgktJdLeCy$#$zz zzwpv|mI2AB+nCfDC)B9qK?G{KJ#4fDY1W3d_|&bF)CSORBz`OvQ4rqC)*Kh zgd8(^w?H4Fw_kf}J6hmHs`a|__WJ|SP|#YoI`T|{pQVa3b)KOj>ctbsdOJ`Ltq+E29=s&c#ywYmm*Q-HC19Y7ZJ0hv!eN`>fX`+ z6#=8QV@5_rVW@IhgNK@*r~wijg0FJ$32OQ-yqgKxIGRIx*Qm~4H!L1Fg1g{R+W zNF9nb-cBh5W+54T*VYyCU#mHCIB!#&ygcH_u*rK3dVcf~$JGwSNs_x@l%ItLgW}zD zn0Oyj&Mb)^NF_T9C+RH9Ckn64dmg`*`&f<(br&6faF+0bY*fSQ(`_-a(VdnP8^a1y zM#JUGE+*Z>d;(PdJ^Bp;_Y=2l8BnMnX3R-wjF8;` zj=n|;@;rvSvqHsJwOTa(TixX-eJjVT)L`u=3xe7*FJe+Wo&}^Zmek*B+Sb8h5o8Hm z(4w4+9`=FMVgr7^Vmo$iRd%nhwVf5quTX~~y-jvaA!@iJ)=cOtO4^O?Cm-J16|td& z^9jWtbd`|CMX}0?lIAPLY)4G_fBmzQ>IgqsP%O_)CVXG!vFb=tp;uk=C^(k6?xc>m zMH{XL&4@tPGBgb5TC<6ESOPZNNMbCO*&zh zn!;kMm*wXAw}8;Vd%hiU>0UE_vC(J5}Vg z=Z=d(=fxV{YXgAtynUElUu5b8B<_%g;2jb@vY*p@P*2La)x3?{a+0$#LNUdO+Aju? zSsw;em>3o(>y}Pwfn6v0)$u zi)IO1OOCiaD4hoVuYbUV?vryrW!Iqz>_gQLGfVn~bQ?Lp5Nnp$RSsp&C$`)psY!*M z-cC5_NW6_@n?OBsl@K#ooTATaILLJJsRGJhsVa{|?^-yOr+Src16b4dbTisAy!`RE z#(;LQ^TQac5zye`IT#gh}J)%OV_)i z&#fuja^o5$Bd?<*5ls^pulU9r=FHDET2UsxD6E8lc}bQ26?48vXXiY=k@;WyK0%J7 zb05ioSp$=#)J9AS%>VlzU|84eyI>PGHez#G4F`KVmnLH>G-|Ie=w-eaj&ZtPmStUg zlqSEb=%uNP_b_&ao7u6G)C{nJr63qt{)x)kVp${G&P`uE1V);heGL~)o&huMQ=eLe zS*D~9log^X=#N#sd0jxlGhTh@6!i`&9CvL1EDXx&u zz;?GW>Z#?=T6^P)<}gI8eyagOam#q@}Oo}db4JzQg~$>Qh@27NZgoEY~&Qw zhkUwgH(*E54m4ux=BsrAeth7$DL%w*hHEGy+Z4BUrg3cBd)u(1R3NF*R`U^4s6(FgPVzXQWmF zX&6qesx62YP~d*e5{qh2uNrphb55`%SVaVsuY%qKB{roS3-?zuEInjRma~;c_he5j zwq8M~IW2W9r*|J2yM2yR`iyd2%3k%#Tc&a#;l@sGb<8swi}qF2KJjcG7Xqu7STp3j zXP}w3_&m}s_X;iXIoq*RM6y@Q&|N`BqXb;Z_0_i_;4u~3k|ym+CUjEt4u~_Jl>kF~ zQPoM``onc?!J54|Lt_+G|DLDfB^K1ThvKXTC?K&Zt*8)$X~>^Kx4ms7_#p>Zq>W6U zF8$7EXxv>n&XLG|&fe3$vk%TR{vwr#JPd@&=W4z}^^xRT)NI2yw%I_=swvV2qpY$! zswq@`jid|sH@zge7vH0Y3!EgiORQow#qV=c`Y6c@7$g;3lQB9@CNdnl9}$0o0ooe+ Kk18J8MgAY$fBdTe literal 0 HcmV?d00001 diff --git a/app/src-tauri/icons/ios/AppIcon-76x76@1x.png b/app/src-tauri/icons/ios/AppIcon-76x76@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..afb5bc0155ed88fe05936a4f9d7eafb7cc302af6 GIT binary patch literal 2428 zcmV-?34`{DP)jziQR0mGF!KSeX)Ss!^jx z0w_Oz{7AU(wm%SHE~5adX3d)V`}_CriWUD$S70S#nco&8LacpdG0-9amlMO{j4F#p zqY($FN()d>03il#gmFd^uy9qj9ANzX`SYj#p{fIw4mcPW15F8&+;%UCqWYkL#lzJF zEF%UNZI59Pi4mtP8BEXp0}sT|jTl(fHKhYh^RQJsfPu%@Rd=wGRTT9!Z20ZjFp6=j zY%W4Yfo9l%m1iRXcFX*cF#WHZHe!O2Z^NKmm@+5BC=&ak(}d7=1+!(IQ7!KEhA9nZ z2At;r71Aq%IWxeb;pmv#EFc=UW1;=ZGFn<>ChCSW!jzd|z8@B*;3)(w1S|wB1S|wB z1T0J;U?E^3U?E^tF-1!$X6`O^S)O~JKxcB0z>OB$GgS^S+m}J(YS*rv(|^Bx`}QZ0 z7YC+JojT?6iwRovUjRiTZ9l`aXV2u$ojY>(?p=BK@S(hV^-4Z}{;YZR>eZ7LEm}zX z_U)xxw{FtCdv|HmrcFYb2M!#NBS((tv$JQy?dwkDF<*~zI-X;#*LFhhYl5uWzmXY6(DTdv`IE>*dR}zK9xp|8mX!o zgY3#GYz&yjjTF+hpuo7UUAy`KR|*?uU}1a#3x@F9WfTnoi1+W`Oa1!w zrDxBcGGM>}>CvNyv}@N+8a8aG&wcptLG9k{+qdQN<;%*}bgFBt0_2@Lcgp0+lhxh< zV#xw#U>!exT&7K%ri_3w{xW;qv3&dXtu$}mTt_;tzJ2=!YS`w@n`Qa(1 zmK{5GC|KMx+XV~EJ#a4)WvyGcPA*-#Bn=ugNC1mE@!{OTf#;C{S;(i}LM@eLQzm5NCDj)TusD0F=pBqFhuQR&Cj`MawW%) zU?u~{+_`h5fB*jK^)oV3m#cclZe&a4ic~nmj9oWx-c)wc5P#D~>^uI~;>C+)?b@|D zfo0_~D;PFxn7SWUHVlC&ZQHh$^XJbikdzIJmn~bSvk7Jqt{X#nr%s)c-o1P0%`z`v zbtLWEw@-a0V;8D`o$Au1i!5Eb)SvI=%G#AHSIUzoPZT`Yqo?dut5!+VrcHgLP94w4rizm$O_C{7ruYK~W%Hf7sFS*_^N`7WLmR2{QO&#nLs*Rc{rmT|kqBqPXM5)XkdZGrSsm0#-PTEziEPM-tghLpP{52$SFT*qo-={55A-mj z7QsGLCL6oVW?|&cX}SA3j`Vuzd3aku_hn z^zzwcM!I$DR=HQ^5D1}zj7$a=kyqw_%n}YBJgDI<=*L)DP%qCM&7-qveD)8pb8-E0}t&Ic-E%u(NHw}nAd-f<;s1x?f z1c!2>=N6F2*~kQ0LB_^Y_80 zOBNT)rcTsJ-LCy}J2+oIESm40Pm9@GLo6`pMk=z|K^)IaKu|tTa1g*ORBf*#+w+uR zjH~cb(&A3ge&E1?+87Hn^PONIc|4O%B}q(ecs5nfbB{b6(rhD~D;F{(%Z02#z<@y_--j*XDluV2@tG5jTLjXOHhI8=#AHcM>TRH_hi z6@4y=kTjY^qs(~?Vk<20$OL`SqD2alt!4uh`5QNGR1ZFAAg~Z}6*atrAkLfl2}}98 z08dn6>(;Gu@7_JV&s=oDf(7cE<=W6f$W_!3wHpP^C&W!+zDQznEqU&j$XBj^wpAb~ zXt2VhH;X>ZJjDf65c(4wh!^@S<@ti*H9 zN(m{JSKUE#484D>VR)opmLvTD ziv!n^+n)B&NDeXL4^j;ejYJKNSy>N_Ob)kjxk0$9d@QMrhB+Tgn(E+N8)B>K!MC

>cV-^t?V7Nl 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

fW6jwVBx6D*~0CS_jWy^!KQ{au=)Ks4_0F9 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 `Dispatched`). /// -/// Requires at least one comment to be present. The actual agent dispatch -/// is handled by the `Gated::request_changes` transition; the agent spawn -/// is not yet wired (Phase 1 prerequisite). +/// Requires at least one comment to be present. After transitioning the gate +/// state, assembles a rework prompt from the review's issue, diff, and +/// comments, then spawns the fixer agent in the review's worktree. The +/// agent's stdout is streamed to the frontend via Tauri events. #[tauri::command] -pub fn request_changes( +pub async fn request_changes( state: State<'_, Arc>, + app_handle: tauri::AppHandle, pr: String, ) -> Result { let pr_ref = PrRef::new(&pr); @@ -158,11 +159,113 @@ pub fn request_changes( return Err(CommandError::from(e)); } + // Spawn the fixer agent via the shared Fix-loop path (no CI logs here). + // Spawn failure is non-fatal — the gate transition already succeeded so we + // return the Dispatched review regardless and log the spawn error. + dispatch_fix_agent(&state, &app_handle, &pr, &pr_ref, None).await; + state.reviews.get(&pr_ref).ok_or_else(|| CommandError { message: format!("Review not found: {pr}"), }) } +/// Dispatch the diff-gate Fix loop for a review already transitioned to +/// `Dispatched`, spawning the fixer agent with a rework prompt. +/// +/// This is the shared spawn path for both `request_changes` and `fix_ci`: +/// assemble the rework prompt (optionally carrying `ci_failures` verbatim), +/// spawn the fixer agent in the review's worktree, and attach the running +/// agent. Spawn failure is non-fatal — the gate transition already stands, so +/// the error is logged and surfaced as an `agent-event` rather than blocking +/// the loop (Invariant 1). +async fn dispatch_fix_agent( + state: &State<'_, Arc>, + app_handle: &tauri::AppHandle, + pr: &str, + pr_ref: &PrRef, + ci_failures: Option<&str>, +) { + let Some(review) = state.reviews.get(pr_ref) else { + return; + }; + + // Load config once so the per-mode custom preamble and agent command are + // both honored. A load failure is non-fatal — fall back to defaults (no + // preamble, builtin command) so rework still dispatches. + let config = Config::load().ok(); + let preamble = config + .as_ref() + .and_then(|c| c.agent_prompts.for_mode(AgentMode::Fix).map(str::to_owned)); + // Skills relevant to the diff under review; discovery failures are non-fatal + // (fall back to no skills — never block the loop). + let skills = cockpit_core::skills::relevant_for_diff(&review.diff.raw); + let artifact = Artifact::Diff(review.diff.clone()); + let rework_input = cockpit_core::prompt::ReworkInput { + intent: review.issue.as_str(), + custom_preamble: preamble.as_deref(), + approved_plan: None, + artifact: &artifact, + comments: &review.comments, + ci_failures, + skills: &skills, + }; + let assembled = cockpit_core::prompt::assemble_rework(&rework_input); + + match try_spawn_agent(state, app_handle, pr, pr_ref, &review.worktree, &assembled).await { + Ok(agent_run) => { + state.reviews.update(pr_ref, |r| { + r.agent = Some(agent_run); + }); + } + Err(e) => { + eprintln!("dispatch_fix_agent: agent spawn failed: {e}"); + use tauri::Emitter; + let error_event = cockpit_core::adapters::agent_stream::Event::Error { + message: format!("Agent spawn failed: {e}"), + }; + let _ = app_handle.emit("agent-event", &error_event); + } + } +} + +/// Attempt to spawn a fixer agent. Factored out so the caller can treat +/// failure as non-fatal. +async fn try_spawn_agent( + state: &AppState, + app_handle: &tauri::AppHandle, + pr: &str, + pr_ref: &PrRef, + worktree: &std::path::Path, + prompt: &cockpit_core::prompt::AssembledPrompt, +) -> Result { + let config = Config::load().map_err(|e| format!("config: {e}"))?; + let spawn_config = SpawnConfig::from_config(&config); + let hook_url = format!("http://127.0.0.1:{}/hook/stop", config.hook_port); + + let spawn_result = cockpit_core::adapters::agent::spawn_agent( + worktree, + prompt, + cockpit_core::model::AgentMode::Fix, + pr_ref.as_str(), + &state.sessions, + &hook_url, + &spawn_config, + ) + .await + .map_err(|e| format!("spawn: {e}"))?; + + let stream_ctx = crate::streaming::StreamContext { + object_id: pr.to_string(), + mode: cockpit_core::model::AgentMode::Fix, + completion_tx: state.completion_tx.clone(), + }; + Ok(crate::streaming::start_stream_forwarding( + spawn_result, + app_handle.clone(), + stream_ctx, + )) +} + // --------------------------------------------------------------------------- // Comment mirroring // --------------------------------------------------------------------------- @@ -192,6 +295,240 @@ pub async fn mirror_comments( Ok(result) } +// --------------------------------------------------------------------------- +// CI visibility + dispatch-to-fix +// --------------------------------------------------------------------------- + +/// Parse a PR number from a review's PR reference. +/// +/// Accepts URL form (`https://.../pull/42`) and `owner/repo#42` form; returns +/// `None` when no number can be parsed. +fn pr_number_from_ref(pr: &str) -> Option { + if let Some(tail) = pr.rsplit('/').next() + && let Ok(n) = tail.parse::() + { + return Some(n); + } + if let Some(tail) = pr.rsplit('#').next() + && let Ok(n) = tail.parse::() + { + return Some(n); + } + None +} + +/// Fetch CI checks for a review's PR and return their rollup (STATUS tier). +/// +/// Reads checks via `gh pr checks` (using the review's `repo_slug` when set), +/// emits a `ci-updated` event carrying the full [`CiCheck`] list so the +/// frontend updates via events (not polling), and returns the [`CiSummary`] +/// rollup for the badge. +/// +/// This never blocks the review loop and never mutates review state: any `gh` +/// error (including a PR with no checks) is treated as non-fatal and yields an +/// empty summary with an empty checks event (Invariant 1). +#[tauri::command] +pub async fn fetch_ci_checks( + state: State<'_, Arc>, + app_handle: tauri::AppHandle, + pr: String, +) -> Result { + use tauri::Emitter; + + let pr_ref = PrRef::new(&pr); + let repo_slug = state.reviews.get(&pr_ref).and_then(|r| r.repo_slug.clone()); + + let empty = github::CiSummary { + passed: 0, + total: 0, + failed: 0, + pending: 0, + }; + + let Some(pr_number) = pr_number_from_ref(&pr) else { + // No parseable PR number — nothing to fetch. Emit an empty update so + // the badge clears rather than hanging. + let _ = app_handle.emit("ci-updated", (&pr, Vec::::new())); + return Ok(empty); + }; + + match github::pr_checks(repo_slug.as_deref(), pr_number).await { + Ok(checks) => { + let summary = github::summarize(&checks); + // Push the full checks list to the frontend via event (§4). + let _ = app_handle.emit("ci-updated", (&pr, &checks)); + Ok(summary) + } + Err(e) => { + // Non-fatal: a PR may legitimately have no checks (gh exits + // non-zero). Report an empty summary; never block the loop. + eprintln!("fetch_ci_checks: {e}"); + let _ = app_handle.emit("ci-updated", (&pr, Vec::::new())); + Ok(empty) + } + } +} + +/// List the CI checks for a review's PR (STATUS tier, best-effort query). +/// +/// Resolves the PR number and `repo_slug` from the stored review and reads +/// checks via `gh pr checks`. Unlike [`fetch_ci_checks`], this returns the full +/// [`CiCheck`] list directly (for the CI tab) and emits no event. +/// +/// Per Invariant 1 this is a best-effort UI query that must never block the +/// review loop: any `gh` error (including a PR with no checks, or a +/// non-parseable PR reference) is treated as non-fatal and yields an EMPTY +/// list, with the error logged to stderr. +#[tauri::command] +pub async fn list_ci_checks( + state: State<'_, Arc>, + pr: String, +) -> Result, CommandError> { + let pr_ref = PrRef::new(&pr); + let repo_slug = state.reviews.get(&pr_ref).and_then(|r| r.repo_slug.clone()); + + let Some(pr_number) = pr_number_from_ref(&pr) else { + return Ok(Vec::new()); + }; + + match github::pr_checks(repo_slug.as_deref(), pr_number).await { + Ok(checks) => Ok(checks), + Err(e) => { + eprintln!("list_ci_checks: {e}"); + Ok(Vec::new()) + } + } +} + +/// Fetch the failed-job logs for a single CI run, identified by a check `link` +/// (LOG tier, best-effort, per-pipeline). +/// +/// The `link` is a check's details URL (e.g. +/// `https://github.com/owner/repo/actions/runs/123/job/456`); the run id is +/// extracted server-side via [`github::run_id_from_link`] and the logs are read +/// via `gh run view --log-failed`, scoped to the review's `repo_slug`. +/// +/// Per Invariant 1 this is non-fatal: a `link` with no parseable run id, or any +/// `gh` error, yields an EMPTY string with the error logged to stderr, never a +/// hard failure that could block the UI. The CI panel calls this per pipeline, +/// so passing pipelines run no subprocess at all (only failed pipelines fetch). +#[tauri::command] +pub async fn ci_run_logs_by_link( + state: State<'_, Arc>, + pr: String, + link: String, +) -> Result { + let pr_ref = PrRef::new(&pr); + let repo_slug = state.reviews.get(&pr_ref).and_then(|r| r.repo_slug.clone()); + + let Some(run_id) = github::run_id_from_link(&link) else { + return Ok(String::new()); + }; + + match github::run_logs(repo_slug.as_deref(), run_id).await { + Ok(logs) => Ok(logs), + Err(e) => { + eprintln!("ci_run_logs_by_link: {e}"); + Ok(String::new()) + } + } +} + +/// Dispatch the Fix loop to address a PR's CI failures (LOG tier). +/// +/// This is an EXPLICIT user action (Invariant 5): it never auto-fires. It +/// fetches the failed-CI logs on demand, reuses the diff-gate Fix loop +/// (`request_changes` spawn path via [`dispatch_fix_agent`]) — ensuring the +/// review is `InReview`, adding a synthetic local comment summarizing the CI +/// failure so the gate's ≥1-comment rule is met, transitioning +/// `request_changes` (→ `Dispatched`), and spawning the fixer agent with a +/// rework prompt carrying the CI logs verbatim. +/// +/// The CI-log fetch is best-effort: a failure yields no logs but the Fix loop +/// still dispatches (the synthetic comment still tells the agent CI failed), +/// so a GitHub read never blocks the loop. +#[tauri::command] +pub async fn fix_ci( + state: State<'_, Arc>, + app_handle: tauri::AppHandle, + pr: String, +) -> Result { + let pr_ref = PrRef::new(&pr); + let review = state.reviews.get(&pr_ref).ok_or_else(|| CommandError { + message: format!("Review not found: {pr}"), + })?; + + // On-demand LOG-tier fetch. Best-effort: failure yields empty logs. + let ci_logs = match pr_number_from_ref(&pr) { + Some(n) => github::failed_ci_logs(review.repo_slug.as_deref(), n) + .await + .unwrap_or_else(|e| { + eprintln!("fix_ci: failed_ci_logs: {e}"); + String::new() + }), + None => String::new(), + }; + + // Ensure the review is InReview before adding the comment + requesting + // changes. Reworked -> InReview via open(); a wrong starting state surfaces + // as a transition error below. + let mut transition_err: Option = None; + state.reviews.update(&pr_ref, |r| { + if r.gate_state == GateState::Reworked + && let Err(e) = r.open() + { + transition_err = Some(e); + return; + } + if r.gate_state == GateState::Pending + && let Err(e) = r.open() + { + transition_err = Some(e); + return; + } + + // Synthetic Local comment so the gate's ≥1-comment rule is satisfied. + // Anchored to the PR (no specific line) via a zero-length diff anchor. + let summary = if ci_logs.trim().is_empty() { + "CI is failing on this PR. Investigate and fix the failing checks.".to_string() + } else { + "CI is failing on this PR. See the CI Failures section for the failed \ + job logs; fix the failing checks." + .to_string() + }; + r.comments.push(Comment { + id: CommentId::new(format!("ci-{}", uuid::Uuid::new_v4())), + anchor: Anchor::DiffLine { + path: PathBuf::from("CI"), + range: (0, 0), + }, + body: summary, + origin: CommentOrigin::Local, + }); + + if let Err(e) = r.request_changes() { + transition_err = Some(e); + } + }); + + if let Some(e) = transition_err { + return Err(CommandError::from(e)); + } + + // Reuse the shared Fix-loop spawn path, carrying the CI logs into the + // rework prompt verbatim. + let ci_arg = if ci_logs.trim().is_empty() { + None + } else { + Some(ci_logs.as_str()) + }; + dispatch_fix_agent(&state, &app_handle, &pr, &pr_ref, ci_arg).await; + + state.reviews.get(&pr_ref).ok_or_else(|| CommandError { + message: format!("Review not found: {pr}"), + }) +} + // --------------------------------------------------------------------------- // Plan gate commands // --------------------------------------------------------------------------- @@ -220,6 +557,7 @@ pub fn load_plan( gate_state: GateState::Pending, comments: vec![], agent: None, + plan_path: Some(PathBuf::from(file)), }; state.plan.set(plan.clone()); Ok(plan) @@ -258,43 +596,318 @@ pub fn add_plan_comment( }) } -/// Transition the plan to `Dispatched` (request changes from the planner agent). +/// Generate the initial project plan by spawning a planner agent. +/// +/// This is an artifact-filling spawn: it does **not** move the gate. The plan +/// stays `Pending` while the planner (`AgentMode::Plan`) runs in the repo +/// working directory; on Stop-hook completion the plan is left `Pending` and +/// ready for the user to `plan_open`. Mirrors how implementers fill a review's +/// diff while the review stays `Pending`. +/// +/// Requires a loaded plan (see `load_plan`/`kickoff`) and a configured repo +/// path. Spawn failure is surfaced as an error; the plan state is unchanged. +#[tauri::command] +pub async fn generate_plan( + state: State<'_, Arc>, + app_handle: tauri::AppHandle, +) -> Result { + let plan = state.plan.get().ok_or_else(|| CommandError { + message: "No project plan loaded".into(), + })?; + + // Resolve the on-disk destination the planner writes to, and ensure the + // parent directory exists so the agent's write succeeds. This path is + // read back and parsed on completion (see the Plan completion arm). + let plan_path = cockpit_core::config::plan_file_path(plan.project.as_str())?; + if let Some(parent) = plan_path.parent() { + std::fs::create_dir_all(parent)?; + } + + // Assemble the initial plan-generation prompt (intent = the project goal; + // no comments — the plan does not exist yet). The Plan-mode custom preamble + // is injected verbatim; a config load failure falls back to the builtin. + let preamble = Config::load() + .ok() + .and_then(|c| c.agent_prompts.for_mode(AgentMode::Plan).map(str::to_owned)); + let intent = format!("Produce a project plan for {}.", plan.project); + // Plan generation has no diff yet — surface universal (untagged) skills. + // Discovery failures are non-fatal. + let skills = cockpit_core::skills::relevant_for_diff(""); + let plan_input = cockpit_core::prompt::PlanInput { + intent: &intent, + custom_preamble: preamble.as_deref(), + issues: &[], + current_plan: Some(&plan.doc), + output_path: Some(&plan_path), + skills: &skills, + }; + let assembled = cockpit_core::prompt::assemble_plan_prompt(&plan_input); + + let object_id = plan.project.as_str().to_string(); + let run = spawn_plan_agent(&state, &app_handle, &object_id, &assembled).await?; + + // Attach the running agent and record the write destination; the plan + // stays Pending (artifact-fill). + state.plan.update(|p| { + p.agent = Some(run); + p.plan_path = Some(plan_path); + }); + + state.plan.get().ok_or_else(|| CommandError { + message: "Plan disappeared after update".into(), + }) +} + +/// Transition the plan to `Dispatched` and spawn a planner agent for rework. /// /// Requires that the plan is in `InReview` state with at least one comment. +/// The gate transition happens first; then a planner (`AgentMode::Plan`) is +/// spawned with the rework prompt (approved-plan-absent, artifact = the plan +/// doc, plus the gathered comments) — exactly like `request_changes` does for +/// reviews. Spawn failure is non-fatal: the gate already advanced, so the +/// `Dispatched` plan is returned and the error is logged. +/// /// This is an explicit user action (Invariant 5). #[tauri::command] -pub fn plan_request_changes(state: State<'_, Arc>) -> Result { +pub async fn plan_request_changes( + state: State<'_, Arc>, + app_handle: tauri::AppHandle, +) -> Result { let mut plan = state.plan.get().ok_or_else(|| CommandError { message: "No project plan loaded".into(), })?; plan.request_changes()?; - state.plan.set(plan); + + // Resolve (and record) the on-disk destination for the revised plan so the + // completion arm can read + parse it back. Reuse an existing path when the + // plan already has one (e.g. loaded from a file); otherwise derive it. + let plan_path = match plan.plan_path.clone() { + Some(p) => p, + None => cockpit_core::config::plan_file_path(plan.project.as_str())?, + }; + if let Some(parent) = plan_path.parent() { + std::fs::create_dir_all(parent)?; + } + plan.plan_path = Some(plan_path.clone()); + state.plan.set(plan.clone()); + + // Assemble the rework prompt over the plan artifact + comments. Plan-mode + // custom preamble injected verbatim (builtin fallback on load failure). + let preamble = Config::load() + .ok() + .and_then(|c| c.agent_prompts.for_mode(AgentMode::Plan).map(str::to_owned)); + // Plan rework operates on the plan doc, not a file diff — surface universal + // (untagged) skills. Discovery failures are non-fatal. + let skills = cockpit_core::skills::relevant_for_diff(""); + let artifact = Artifact::Plan(plan.doc.clone()); + // Instruct the planner to persist the revised plan to the recorded path, + // in the pinned format, so cockpit can parse it back on completion. + let intent = format!( + "Revise the project plan for {}. Write the finished plan as markdown to `{}` in the same pinned format.", + plan.project, + plan_path.display() + ); + let rework_input = cockpit_core::prompt::ReworkInput { + intent: &intent, + custom_preamble: preamble.as_deref(), + approved_plan: None, + artifact: &artifact, + comments: &plan.comments, + ci_failures: None, + skills: &skills, + }; + let assembled = cockpit_core::prompt::assemble_rework(&rework_input); + + let object_id = plan.project.as_str().to_string(); + match spawn_plan_agent(&state, &app_handle, &object_id, &assembled).await { + Ok(run) => { + state.plan.update(|p| p.agent = Some(run)); + } + Err(e) => { + eprintln!("plan_request_changes: planner spawn failed: {e}"); + use tauri::Emitter; + let error_event = cockpit_core::adapters::agent_stream::Event::Error { + message: format!("Planner spawn failed: {e}"), + }; + let _ = app_handle.emit("agent-event", &error_event); + } + } state.plan.get().ok_or_else(|| CommandError { message: "Plan disappeared after update".into(), }) } -/// Approve the plan, transitioning it to `Approved`. +/// Spawn a planner agent (`AgentMode::Plan`) in the repo working directory. +/// +/// Factored out so both initial generation and rework share one spawn path. +/// Uses the configured repo path as the agent's working directory (the plan +/// is a document produced against the repo). Returns the [`AgentRun`] with +/// stdout streaming wired to the frontend. +async fn spawn_plan_agent( + state: &AppState, + app_handle: &tauri::AppHandle, + object_id: &str, + prompt: &cockpit_core::prompt::AssembledPrompt, +) -> Result { + let config = Config::load()?; + let repo_path = config + .repo_path + .clone() + .unwrap_or_else(|| PathBuf::from(".")); + let spawn_config = SpawnConfig::from_config(&config); + let hook_url = format!("http://127.0.0.1:{}/hook/stop", config.hook_port); + + let spawn_result = cockpit_core::adapters::agent::spawn_agent( + &repo_path, + prompt, + cockpit_core::model::AgentMode::Plan, + object_id, + &state.sessions, + &hook_url, + &spawn_config, + ) + .await?; + + let stream_ctx = crate::streaming::StreamContext { + object_id: object_id.to_string(), + mode: cockpit_core::model::AgentMode::Plan, + completion_tx: state.completion_tx.clone(), + }; + Ok(crate::streaming::start_stream_forwarding( + spawn_result, + app_handle.clone(), + stream_ctx, + )) +} + +/// Approve the plan (`InReview` -> `Approved`) and fan out implementers. /// -/// Requires that the plan is in `InReview` state. This is an explicit user -/// action that triggers the batch build (Invariant 5: side effects require -/// explicit confirmation). +/// This is the guarded side effect of the plan gate (Invariant 5 / `SPEC.md` +/// §12): it only ever runs from this explicit user command, never from agent +/// output. On approval it spawns one implementer agent (`AgentMode::Implement`) +/// per frontier review of the plan's project — a dedicated worktree each, +/// bounded by `max_parallel_agents`. Each implementer builds the initial code +/// in its worktree; the reviews stay `Pending` (ready for human review) — +/// nothing auto-advances. +/// +/// The gate transition happens first and is authoritative. Fan-out failure is +/// reported as an error but the plan remains `Approved`. #[tauri::command] -pub fn plan_approve(state: State<'_, Arc>) -> Result { +pub async fn plan_approve(state: State<'_, Arc>) -> Result { let mut plan = state.plan.get().ok_or_else(|| CommandError { message: "No project plan loaded".into(), })?; plan.approve()?; - state.plan.set(plan); + state.plan.set(plan.clone()); + + // Fan out implementers for the project's frontier reviews. The plan's + // ProjectRef and the first-class ProjectId share the same string (see + // kickoff::project_from_linear), so reviews are selected by that id. + let project_id = ProjectId::new(plan.project.as_str()); + // The approval stands regardless; a fan-out failure is surfaced to the + // caller but does not roll back the (authoritative) gate transition. + fan_out_implementers(&state, &plan.project, &project_id).await?; state.plan.get().ok_or_else(|| CommandError { message: "Plan disappeared after update".into(), }) } +/// Spawn implementer agents for a project's frontier reviews after approval. +/// +/// Loads the project's reviews from the store, selects the frontier (roots of +/// the stack), and runs [`kickoff::spawn_batch`] with the configured +/// concurrency bound. Updates each spawned review's `base_sha` and `agent` in +/// the store; the reviews stay `Pending`. +async fn fan_out_implementers( + state: &AppState, + project: &ProjectRef, + project_id: &ProjectId, +) -> Result<(), CommandError> { + let config = Config::load()?; + let repo_path = config + .repo_path + .clone() + .unwrap_or_else(|| PathBuf::from(".")); + + // Collect this project's reviews, then narrow to the frontier (roots). + let mut reviews = cockpit_core::store::reviews_by_project(&state.reviews, Some(project_id)); + let frontier_ids = kickoff::select_frontier_reviews(&reviews); + reviews.retain(|r| frontier_ids.contains(&r.id)); + + if reviews.is_empty() { + // Nothing to build (e.g. plan-only project); approval already stands. + return Ok(()); + } + + // Phase 1 (synchronous): prepare worktrees. `git2::Repository` is not + // `Send`, so it must not live across the `.await` below — scope it here so + // it is dropped before spawning. + // Implement-mode custom preamble, injected verbatim into every implementer + // prompt (builtin fallback when unset). + let implement_preamble = config + .agent_prompts + .for_mode(AgentMode::Implement) + .map(str::to_owned); + let prepared = { + let repo = git2::Repository::discover(&repo_path).map_err(|e| CommandError { + message: format!("could not open git repo at {}: {e}", repo_path.display()), + })?; + kickoff::prepare_batch_worktrees( + &mut reviews, + &repo, + project, + implement_preamble.as_deref(), + ) + .map_err(CommandError::from)? + }; + + let spawn_config = SpawnConfig::from_config(&config); + let hook_url = format!("http://127.0.0.1:{}/hook/stop", config.hook_port); + + let kickoff_config = kickoff::KickoffConfig { + session_map: &state.sessions, + hook_url: &hook_url, + spawn_config: &spawn_config, + max_parallel_agents: config.max_parallel_agents, + }; + + // Phase 2 (async): bounded agent fan-out. No repo handle in scope. + kickoff::spawn_batch(&mut reviews, &prepared, &kickoff_config) + .await + .map_err(CommandError::from)?; + + // Persist the spawned agents + base SHAs back into the store. + for review in &reviews { + state.reviews.update(&review.pr, |r| { + r.base_sha = review.base_sha.clone(); + r.agent = review.agent.clone(); + }); + } + + Ok(()) +} + +/// Return the [`BatchStatus`] for the plan's project (or ungrouped reviews). +/// +/// Aggregates the project's reviews into building / ready / approved counts so +/// the frontend can show batch progress after a fan-out without polling each +/// review individually. +#[tauri::command] +pub fn batch_status( + state: State<'_, Arc>, + project_id: Option, +) -> Result { + let id = project_id.map(ProjectId::new); + Ok(cockpit_core::store::batch_status( + &state.reviews, + id.as_ref(), + )) +} + /// Open the plan for review (`Pending | Reworked` -> `InReview`). #[tauri::command] pub fn plan_open(state: State<'_, Arc>) -> Result { @@ -310,30 +923,11 @@ pub fn plan_open(state: State<'_, Arc>) -> Result>, -) -> Result, CommandError> { - let config = batch::Config::default(); - let results = batch::evaluate_frontier(&state.reviews, &config); - Ok(results) -} - /// Approve a single review by PR reference string (`InReview` -> `Approved`). /// /// If the review is in `Reworked` state, it is first opened to `InReview` -/// before approving. This is used by the batch-approve UI to approve -/// individual eligible reviews (explicit user action per Invariant 5). +/// before approving. The frontend calls this per review as an explicit user +/// action (Invariant 5: side effects require explicit confirmation). #[tauri::command] pub fn approve_review(state: State<'_, Arc>, pr: String) -> Result { let pr_ref = PrRef::new(&pr); @@ -389,6 +983,97 @@ pub fn save_config(config: Config) -> Result<(), CommandError> { Ok(()) } +// --------------------------------------------------------------------------- +// Agent prompt customization +// --------------------------------------------------------------------------- + +/// Return the stored custom prompt override for `mode`, if any. +/// +/// `None` means the mode uses its builtin default (see +/// [`get_builtin_agent_prompt`] for that text). Thin: reads config and returns +/// the [`AgentPrompts`](cockpit_core::config::AgentPrompts) entry. +#[tauri::command] +pub fn get_agent_prompt(mode: AgentMode) -> Result, CommandError> { + let config = Config::load()?; + Ok(config.agent_prompts.for_mode(mode).map(str::to_owned)) +} + +/// Return the builtin default prompt fragment for `mode`. +/// +/// Used by the settings editor as the placeholder and the "reset to default" +/// value. This is the canonical builtin intent, never a stored override. +#[tauri::command] +pub fn get_builtin_agent_prompt(mode: AgentMode) -> Result { + Ok(cockpit_core::prompt::builtin_intent(mode).to_string()) +} + +/// Persist a custom prompt override for `mode`. +/// +/// An empty or whitespace-only `text` clears the override, resetting the mode +/// to its builtin default. The override is injected verbatim into that mode's +/// prompt at dispatch time. +#[tauri::command] +pub fn save_agent_prompt(mode: AgentMode, text: String) -> Result<(), CommandError> { + let mut config = Config::load()?; + config.agent_prompts.set_mode(mode, Some(text)); + config.save()?; + Ok(()) +} + +// --------------------------------------------------------------------------- +// Skills commands +// --------------------------------------------------------------------------- + +/// List installed skills from `/skills`. +/// +/// Thin: delegates to [`cockpit_core::skills::discover_installed_skills`]. +#[tauri::command] +pub fn list_skills() -> Result, CommandError> { + let skills = cockpit_core::skills::discover_installed_skills()?; + Ok(skills) +} + +/// Install or overwrite a local skill by name. +/// +/// Writes `SKILL.md` (+ `.meta.json`) marking the skill [`SkillSource::Local`] +/// so a later GitHub sync never clobbers a hand edit. Explicit user action. +#[tauri::command] +pub fn save_skill(name: String, contents: String) -> Result<(), CommandError> { + cockpit_core::skills::install_skill( + &name, + &contents, + cockpit_core::skills::SkillSource::Local, + )?; + Ok(()) +} + +/// Delete an installed skill by name (Invariant 5: explicit user action). +#[tauri::command] +pub fn delete_skill(name: String) -> Result<(), CommandError> { + cockpit_core::skills::delete_skill(&name)?; + Ok(()) +} + +/// Sync skills from the configured GitHub source via the `gh` CLI. +/// +/// Requires `[skills_github]` in config. Uses the user's `gh auth` (no PAT). +/// Returns a [`SyncReport`](cockpit_core::skills::SyncReport) of counts. +#[tauri::command] +pub async fn sync_skills() -> Result { + let config = Config::load()?; + let source = config.skills_github.ok_or_else(|| CommandError { + message: "No skills GitHub source configured. Set it in Settings.".into(), + })?; + let report = cockpit_core::skills::sync_from_github( + &source.owner, + &source.repo, + &source.branch, + &source.path, + ) + .await?; + Ok(report) +} + // --------------------------------------------------------------------------- // Kickoff command // --------------------------------------------------------------------------- @@ -440,21 +1125,30 @@ pub async fn kickoff( gate_state: GateState::Pending, comments: vec![], agent: None, + plan_path: None, }; state.plan.set(plan); } - // 4. Build reviews for frontier issues. - let worktree_base = config - .repo_path - .as_ref() - .map(|p| p.join(".cockpit/worktrees")) - .unwrap_or_else(|| PathBuf::from(".cockpit/worktrees")); - - let reviews = - kickoff::build_reviews_for_frontier(&frontier, &data, &issue_dag, &worktree_base, "main"); + // 4. Build reviews for frontier issues. Kickoff creates a first-class + // Linear-backed project that groups the reviews; worktrees live under + // the cockpit home (outside the managed repo) and are keyed via the + // unified `review_worktree_path` scheme so projects never collide. + let cockpit_project = kickoff::project_from_linear(&project, format!("Project {project}")); + + let mut reviews = kickoff::build_reviews_for_frontier( + &frontier, + &data, + &issue_dag, + "main", + Some(&cockpit_project.id), + ); + for review in &mut reviews { + review.worktree = kickoff::review_worktree_path(review)?; + } - // 5. Store reviews in the in-memory store. + // 5. Store the project and its reviews in the in-memory stores. + state.projects.insert(cockpit_project); for review in &reviews { state.reviews.insert(review.clone()); } @@ -469,6 +1163,65 @@ pub async fn kickoff( Ok(result) } +// --------------------------------------------------------------------------- +// Project commands +// --------------------------------------------------------------------------- + +/// List all first-class projects currently in the store. +#[tauri::command] +pub fn list_projects(state: State<'_, Arc>) -> Result, CommandError> { + Ok(state.projects.list()) +} + +/// Create a new ad-hoc project with the given name. +/// +/// This is an explicit user action (Invariant 5): ad-hoc projects only ever +/// come from a deliberate UI action, never from agent output. Returns the +/// created [`Project`]. +#[tauri::command] +pub fn create_project( + state: State<'_, Arc>, + name: String, +) -> Result { + let project = kickoff::create_ad_hoc_project(name); + state.projects.insert(project.clone()); + Ok(project) +} + +/// Attach an existing review to a project. +/// +/// Looks up the review by PR reference and sets its `project` field. Returns +/// the updated [`Review`]. Errors if either the review or the project is +/// unknown. +#[tauri::command] +pub fn attach_review( + state: State<'_, Arc>, + pr: String, + project_id: String, +) -> Result { + let pr_ref = PrRef::new(&pr); + let project_id = ProjectId::new(&project_id); + + if state.projects.get(&project_id).is_none() { + return Err(CommandError { + message: format!("Project not found: {project_id}"), + }); + } + + let updated = state.reviews.update(&pr_ref, |r| { + r.project = Some(project_id.clone()); + }); + if !updated { + return Err(CommandError { + message: format!("Review not found: {pr}"), + }); + } + + state.reviews.get(&pr_ref).ok_or_else(|| CommandError { + message: format!("Review not found after attach: {pr}"), + }) +} + // --------------------------------------------------------------------------- // Restack command // --------------------------------------------------------------------------- @@ -503,7 +1256,10 @@ pub async fn restack_pr( } let config = Config::load()?; - let repo_path = config.repo_path.unwrap_or_else(|| PathBuf::from(".")); + let repo_path = config + .repo_path + .clone() + .unwrap_or_else(|| PathBuf::from(".")); let parent_branch = review.base.clone(); // Phase 1: synchronous git restack. git2::Repository is not Send, so @@ -525,11 +1281,17 @@ pub async fn restack_pr( // Phase 2: if conflicts, spawn the conflict-resolver agent (async). if !clean { - let spawn_config = SpawnConfig::default(); + let spawn_config = SpawnConfig::from_config(&config); let hook_url = format!("http://127.0.0.1:{}/hook/stop", config.hook_port); let worktree_path = review.worktree.clone(); - let prompt = restack::assemble_conflict_prompt(&review, &parent_branch); + // Restack-mode custom preamble, injected verbatim (builtin fallback). + let preamble = config + .agent_prompts + .for_mode(AgentMode::Restack) + .map(str::to_owned); + let prompt = + restack::assemble_conflict_prompt(&review, &parent_branch, preamble.as_deref()); let spawn_result = cockpit_core::adapters::agent::spawn_agent( &worktree_path, &prompt, @@ -545,7 +1307,13 @@ pub async fn restack_pr( })?; // Start streaming agent stdout to the frontend. - let agent_run = crate::streaming::start_stream_forwarding(spawn_result, app_handle); + let stream_ctx = crate::streaming::StreamContext { + object_id: review.id.as_str().to_string(), + mode: cockpit_core::model::AgentMode::Restack, + completion_tx: state.completion_tx.clone(), + }; + let agent_run = + crate::streaming::start_stream_forwarding(spawn_result, app_handle, stream_ctx); review.agent = Some(agent_run); } @@ -591,6 +1359,11 @@ pub async fn fetch_review_requests( } /// Shared implementation for fetching PRs by filter. +/// +/// When a review already exists in the store (matched by PR URL), only the +/// diff, branch, and base are refreshed — comments, gate state, agent run, +/// and stale flag are preserved. This prevents re-fetching from GitHub from +/// blowing away in-progress review work. async fn fetch_prs_by_filter( state: State<'_, Arc>, filter: github::PrFilter, @@ -620,9 +1393,25 @@ async fn fetch_prs_by_filter( .await .unwrap_or_default() }; - let review = github::build_review_from_pr(pr, diff, &repo_path, source); - state.reviews.insert(review.clone()); - reviews.push(review); + + let pr_ref = PrRef::new(&pr.url); + + if state.reviews.get(&pr_ref).is_some() { + let branch = pr.head_ref_name.clone(); + let base = pr.base_ref_name.clone(); + state.reviews.update(&pr_ref, |r| { + r.diff = cockpit_core::model::DiffData { raw: diff }; + r.branch = branch; + r.base = base; + }); + if let Some(updated) = state.reviews.get(&pr_ref) { + reviews.push(updated); + } + } else { + let review = github::build_review_from_pr(pr, diff, &repo_path, source); + state.reviews.insert(review.clone()); + reviews.push(review); + } } Ok(reviews) @@ -651,6 +1440,7 @@ pub fn load_plan_from_path( gate_state: GateState::Pending, comments: vec![], agent: None, + plan_path: Some(PathBuf::from(path)), }; state.plan.set(plan.clone()); Ok(plan) @@ -708,3 +1498,61 @@ pub async fn open_in_editor( Ok(()) } + +/// Start (or reuse) a Monaco LSP bridge for the given Monaco `languageId`. +/// +/// Returns the localhost WebSocket URL the frontend language client should +/// connect to, or `None` when LSP is disabled or the language has no +/// configured server. The bridge is lazily started per language and cached in +/// [`AppState::lsp_bridges`], so repeated calls for the same language reuse the +/// existing bridge and URL. +/// +/// The bridge only spawns the actual language-server child when the webview +/// opens a WebSocket, so an unavailable binary (pyright/tsserver not installed) +/// surfaces at connect time as a closed socket, not here — keeping this command +/// thin and non-fatal (Invariant 1). +#[tauri::command] +pub async fn start_lsp_bridge( + state: State<'_, Arc>, + language_id: String, +) -> Result, CommandError> { + use cockpit_core::adapters::lsp::LspBridge; + use cockpit_core::config::LspLanguage; + + let Some(language) = LspLanguage::from_language_id(&language_id) else { + return Ok(None); + }; + + let config = Config::load()?; + if !config.lsp_servers.enabled { + return Ok(None); + } + + // Fast path: an existing bridge for this language. Take the URL under the + // lock and drop it immediately — never hold the lock across `.await`. + { + let bridges = state.lsp_bridges.lock().map_err(|_| CommandError { + message: "LSP bridge registry lock poisoned".to_string(), + })?; + if let Some(existing) = bridges.get(&language) { + return Ok(Some(existing.url())); + } + } + + // Start a new bridge (async) with the lock released. + let command = config.lsp_servers.command_for(language); + let bridge = LspBridge::start(language, command).await?; + let url = bridge.url(); + + // Re-acquire the lock to insert. Double-check: another task may have + // started one concurrently; if so, keep the first and drop ours (its + // Drop aborts the just-started serve task, no orphan). + let mut bridges = state.lsp_bridges.lock().map_err(|_| CommandError { + message: "LSP bridge registry lock poisoned".to_string(), + })?; + if let Some(existing) = bridges.get(&language) { + return Ok(Some(existing.url())); + } + bridges.insert(language, bridge); + Ok(Some(url)) +} diff --git a/app/src-tauri/src/error.rs b/app/src-tauri/src/error.rs index 1aaf268..d5e7404 100644 --- a/app/src-tauri/src/error.rs +++ b/app/src-tauri/src/error.rs @@ -92,3 +92,19 @@ impl From for CommandError { } } } + +impl From for CommandError { + fn from(e: cockpit_core::skills::Error) -> Self { + Self { + message: e.to_string(), + } + } +} + +impl From for CommandError { + fn from(e: cockpit_core::adapters::lsp::Error) -> Self { + Self { + message: e.to_string(), + } + } +} diff --git a/app/src-tauri/src/lib.rs b/app/src-tauri/src/lib.rs index 7217016..7e729e5 100644 --- a/app/src-tauri/src/lib.rs +++ b/app/src-tauri/src/lib.rs @@ -65,6 +65,7 @@ pub fn run() { tauri::Builder::default() .plugin(tauri_plugin_dialog::init()) .plugin(tauri_plugin_notification::init()) + .plugin(tauri_plugin_opener::init()) .manage(app_state) .manage(shell_sessions) .setup(move |app| { @@ -97,16 +98,38 @@ pub fn run() { refresh_review_diff(&app_state_ref, &pr_ref).await; } AgentMode::Plan => { - // Clear the plan's agent run and transition - // to Reworked so the user can re-review. - app_state_ref.plan.update(|plan| { - plan.agent = None; - let _ = plan.mark_reworked(); - }); + // Two planner spawns land here (both AgentMode::Plan): + // * initial generation — the plan is still + // `Pending`; leave it `Pending` (artifact-fill) + // so the user opens it when ready. + // * rework — the plan is `Dispatched`; transition + // to `Reworked` (clears ephemeral comments). + // In both cases, if the planner wrote its output to + // the recorded `plan_path`, ingest it: read + parse + // the markdown into `doc`. Read/parse failure is + // non-fatal (Invariant 1) — we log and keep the + // prior doc rather than block the loop. + ingest_plan_output(&app_state_ref); } AgentMode::Implement => { - // TODO: implementation agent completion - // reconciliation (Phase 2). + // An implementer finished building a review's + // initial code in its worktree. Clear the agent + // run and re-fetch the diff so the review is ready + // for human review — but do NOT auto-advance the + // gate: the review stays `Pending` until a human + // opens it (Invariant 5). + // + // Fan-out (kickoff::spawn_batch) keys the session by + // ReviewId, so resolve the review by id and act on + // its PrRef. + if let Some(pr_ref) = + resolve_review_pr(&app_state_ref, &event.object_id) + { + app_state_ref.reviews.update(&pr_ref, |review| { + review.agent = None; + }); + refresh_review_diff(&app_state_ref, &pr_ref).await; + } } } @@ -144,17 +167,32 @@ pub fn run() { commands::add_comment, commands::request_changes, commands::mirror_comments, + commands::fetch_ci_checks, + commands::list_ci_checks, + commands::ci_run_logs_by_link, + commands::fix_ci, commands::get_plan, commands::load_plan, commands::add_plan_comment, + commands::generate_plan, commands::plan_request_changes, commands::plan_approve, commands::plan_open, - commands::batch_approve_preview, + commands::batch_status, commands::approve_review, commands::get_config, commands::save_config, + commands::get_agent_prompt, + commands::get_builtin_agent_prompt, + commands::save_agent_prompt, + commands::list_skills, + commands::save_skill, + commands::delete_skill, + commands::sync_skills, commands::kickoff, + commands::list_projects, + commands::create_project, + commands::attach_review, commands::restack_pr, commands::load_plan_from_path, commands::fetch_authored_prs, @@ -164,6 +202,7 @@ pub fn run() { commands::shell::shell_resize, commands::shell::shell_kill, commands::open_in_editor, + commands::start_lsp_bridge, ]) .run(tauri::generate_context!()) // INVARIANT: if Tauri fails to start there is nothing to recover -- @@ -171,6 +210,77 @@ pub fn run() { .expect("error running tauri application"); } +/// Settle plan state after a planner (`AgentMode::Plan`) completion. +/// +/// Clears the running agent, ingests the planner's written markdown (when a +/// `plan_path` is recorded and the file is present and non-empty) by parsing it +/// into the plan's `doc`, and settles the gate: +/// * `Dispatched` (rework) -> `Reworked` (also clears ephemeral comments). +/// * `Pending` (initial artifact-fill) stays `Pending`. +/// +/// Read/parse failures are non-fatal (Invariant 1): the prior doc is kept and +/// the failure is logged rather than blocking the loop. +fn ingest_plan_output(state: &AppState) { + use cockpit_core::gate::Gated; + use cockpit_core::model::GateState; + + // Read + parse outside the store lock; only touch on-disk state here. + let parsed = state.plan.get().and_then(|plan| { + let path = plan.plan_path.clone()?; + match std::fs::read_to_string(&path) { + Ok(raw) if !raw.trim().is_empty() => match cockpit_core::plan_parser::parse(&raw) { + Ok(doc) => Some(doc), + Err(e) => { + eprintln!( + "ingest_plan_output: parse failed for {}: {e}", + path.display() + ); + None + } + }, + Ok(_) => None, + Err(e) => { + eprintln!( + "ingest_plan_output: read failed for {}: {e}", + path.display() + ); + None + } + } + }); + + state.plan.update(|plan| { + plan.agent = None; + if let Some(doc) = parsed { + plan.doc = doc; + } + if plan.gate_state == GateState::Dispatched { + // `mark_reworked` clears ephemeral comments (Invariant 4). A wrong + // starting state cannot occur here (guarded above), so the error is + // ignored deliberately. + let _ = plan.mark_reworked(); + } + }); +} + +/// Resolve a review's [`PrRef`] from a completion event's `object_id`. +/// +/// The object id may be a [`PrRef`] string (the Fix/Restack path keys sessions +/// by PR) or a `ReviewId` string (the implementer fan-out keys sessions by +/// review id). Tries the PR key first, then falls back to a scan by review id. +fn resolve_review_pr(state: &AppState, object_id: &str) -> Option { + let pr_ref = PrRef::new(object_id); + if state.reviews.get(&pr_ref).is_some() { + return Some(pr_ref); + } + state + .reviews + .list() + .into_iter() + .find(|r| r.id.as_str() == object_id) + .map(|r| r.pr) +} + /// Re-fetch the PR diff from GitHub after an agent completion. /// /// Snapshots the `repo_slug` and PR number from the review, then calls diff --git a/app/src-tauri/src/state.rs b/app/src-tauri/src/state.rs index 746818a..5303aba 100644 --- a/app/src-tauri/src/state.rs +++ b/app/src-tauri/src/state.rs @@ -2,11 +2,16 @@ //! //! Background tasks (hook server, agent runs) access this from spawned tasks. +use std::collections::HashMap; +use std::sync::Mutex; + use tokio::sync::broadcast; use cockpit_core::adapters::agent::SessionMap; +use cockpit_core::adapters::lsp::LspBridge; +use cockpit_core::config::LspLanguage; use cockpit_core::hook_server::CompletionEvent; -use cockpit_core::store::{PlanStore, ReviewStore}; +use cockpit_core::store::{PlanStore, ProjectStore, ReviewStore}; /// Holds core handles shared across the Tauri app. /// @@ -15,6 +20,8 @@ use cockpit_core::store::{PlanStore, ReviewStore}; pub struct AppState { /// In-memory store of active reviews. pub reviews: ReviewStore, + /// In-memory store of first-class projects that group reviews. + pub projects: ProjectStore, /// In-memory store for the optional project plan. pub plan: PlanStore, /// Maps agent session IDs to their reviewed objects. @@ -27,6 +34,15 @@ pub struct AppState { /// The hook server sends events here; the Tauri setup listener forwards /// them to the frontend via Tauri events. pub completion_tx: broadcast::Sender, + + /// Running Monaco LSP bridges, one per language, started lazily. + /// + /// Held here so their lifetime is tied to the app: dropping `AppState` + /// drops each [`LspBridge`], aborting its serve task and killing any + /// spawned language-server child (no orphan pids). The `std::sync::Mutex` + /// is only ever held for trivial map lookups/inserts — never across an + /// `.await`. + pub lsp_bridges: Mutex>, } impl AppState { @@ -34,9 +50,11 @@ impl AppState { pub fn new_with_completion_tx(completion_tx: broadcast::Sender) -> Self { Self { reviews: ReviewStore::new(), + projects: ProjectStore::new(), plan: PlanStore::new(), sessions: SessionMap::new(), completion_tx, + lsp_bridges: Mutex::new(HashMap::new()), } } } diff --git a/app/src-tauri/src/streaming.rs b/app/src-tauri/src/streaming.rs index e3b4661..3daa651 100644 --- a/app/src-tauri/src/streaming.rs +++ b/app/src-tauri/src/streaming.rs @@ -5,6 +5,10 @@ //! is piped. This module reads that pipe line by line, writes each raw line //! to the log file, parses it into a [`cockpit_core::adapters::agent_stream::Event`], //! and emits it as a `"agent-event"` Tauri event for the frontend to render. +//! +//! When the stream ends (agent process exits), a [`CompletionEvent`] is +//! emitted on the broadcast channel so the completion handler in `lib.rs` +//! can reconcile the review state. use std::path::PathBuf; @@ -12,9 +16,23 @@ use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader}; use cockpit_core::adapters::agent::SpawnResult; use cockpit_core::adapters::agent_stream; +use cockpit_core::hook_server::CompletionEvent; +use cockpit_core::model::AgentMode; + +/// Context needed by the streaming task to emit a completion event +/// when the agent stream ends. +pub struct StreamContext { + /// PR ref or object identifier for the reviewed object. + pub object_id: String, + /// Agent mode (Fix, Plan, etc.). + pub mode: AgentMode, + /// Completion channel sender. + pub completion_tx: tokio::sync::broadcast::Sender, +} /// Spawn a background task that reads agent stdout, tees to the log file, -/// and emits parsed events to the frontend. +/// emits parsed events to the frontend, and fires a completion event when +/// the stream ends. /// /// Takes ownership of the child process from the [`SpawnResult`]. Returns /// the [`cockpit_core::model::AgentRun`] for the caller to store on the @@ -22,12 +40,25 @@ use cockpit_core::adapters::agent_stream; pub fn start_stream_forwarding( mut spawn_result: SpawnResult, app_handle: tauri::AppHandle, + ctx: StreamContext, ) -> cockpit_core::model::AgentRun { let agent_run = spawn_result.run.clone(); let log_path = spawn_result.log_path.clone(); tauri::async_runtime::spawn(async move { stream_agent_output(&mut spawn_result.child, &log_path, &app_handle).await; + + // Wait for the child process to fully exit. + let _ = spawn_result.child.wait().await; + + // Emit a completion event so the handler in lib.rs reconciles + // the review state (Dispatched → Reworked). + let event = CompletionEvent { + session_id: String::new(), + object_id: ctx.object_id, + mode: ctx.mode, + }; + let _ = ctx.completion_tx.send(event); }); agent_run diff --git a/app/src/App.tsx b/app/src/App.tsx index 681e723..423c4c6 100644 --- a/app/src/App.tsx +++ b/app/src/App.tsx @@ -1,19 +1,22 @@ import { useState, useEffect, useCallback, useMemo } from "react"; +import { invoke } from "@tauri-apps/api/core"; import { listen } from "@tauri-apps/api/event"; import { sendNotification } from "@tauri-apps/plugin-notification"; import { useAppStore } from "./store"; import type { ViewState } from "./store"; import { useKeyboardShortcuts } from "./hooks/useKeyboardShortcuts"; import type { ShortcutMap } from "./hooks/useKeyboardShortcuts"; +import { SHORTCUTS } from "./lib/shortcuts"; +import type { ShortcutId } from "./lib/shortcuts"; import { Sidebar } from "./components/Sidebar"; import { ReviewCard } from "./components/ReviewCard"; -import { DiffView } from "./components/DiffView"; +import { ProjectCard } from "./components/ProjectCard"; +import { ReviewWorkspace } from "./components/ReviewWorkspace"; import { PlanView } from "./components/PlanView"; -import { BatchApprovePanel } from "./components/BatchApprovePanel"; -import { buildStackTrees, computeHealth } from "./lib/stack-tree"; -import type { StackTreeNode } from "./lib/stack-tree"; +import { NewProjectView } from "./components/NewProjectView"; +import { SkillsView } from "./components/SkillsView"; +import { AgentEditor } from "./components/AgentEditor"; import { SettingsView } from "./components/SettingsView"; -import { KickoffView } from "./components/KickoffView"; import { CommandPalette } from "./components/CommandPalette"; import { SkeletonList } from "./components/SkeletonCard"; import { EmptyState } from "./components/EmptyState"; @@ -21,12 +24,20 @@ import { StateFilter } from "./components/StateFilter"; import { TooltipProvider } from "@/components/ui/tooltip"; import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"; import { Button } from "@/components/ui/button"; -import { cn } from "@/lib/utils"; import { Search } from "lucide-react"; import type { GateState } from "./bindings/GateState"; import type { Review } from "./bindings/Review"; +import type { Project } from "./bindings/Project"; +import type { AgentMode } from "./bindings/AgentMode"; + +/** Payload emitted by the Tauri backend on "agent-completed" events. */ +interface CompletionEventPayload { + readonly session_id: string; + readonly object_id: string; + readonly mode: AgentMode; +} -type ReviewTab = "my-prs" | "review-requests" | "frontier"; +type ReviewTab = "my-prs" | "review-requests" | "all"; const SIDEBAR_COLLAPSED_KEY = "cockpit-sidebar-collapsed"; @@ -34,76 +45,69 @@ function assertNever(x: never): never { throw new Error(`unreachable: ${String(x)}`); } -function FrontierStackNode({ - node, - depth, - onAction, -}: { - readonly node: StackTreeNode; - readonly depth: number; - readonly onAction: (pr: string) => void; -}) { - return ( -

- ); +/** Build a desktop notification title from the agent mode. */ +function notificationTitleForMode(mode: AgentMode): string { + switch (mode) { + case "Fix": + case "Restack": + return "Rework Complete"; + case "Plan": + return "Plan Rework Complete"; + case "Implement": + return "Implementation Complete"; + default: + return assertNever(mode); + } } -function FrontierStackGroup({ - root, - onAction, -}: { - readonly root: StackTreeNode; - readonly onAction: (pr: string) => void; -}) { - const health = useMemo(() => computeHealth(root), [root]); +/** Build a desktop notification body from the agent mode and branch name. */ +function notificationBodyForMode(mode: AgentMode, branch: string): string { + switch (mode) { + case "Fix": + return `Fix agent finished on ${branch}`; + case "Restack": + return `Restack agent finished on ${branch}`; + case "Plan": + return `Plan agent finished reworking`; + case "Implement": + return `Implementation agent finished on ${branch}`; + default: + return assertNever(mode); + } +} - return ( -
-
- - Stack: {root.review.branch} - - - - {health.approved}/{health.total} approved - - {health.stale > 0 && ( - {health.stale} stale - )} - -
+/** A named group of reviews for the grouped-by-project PRs list. */ +interface ReviewGroup { + readonly key: string; + readonly title: string; + readonly reviews: readonly Review[]; +} - -
- ); +/** + * Group reviews by their project, preserving project order from `projects` + * and collecting reviews with no project into a trailing "Ungrouped" section. + * Empty groups are omitted. + */ +function groupReviewsByProject( + reviews: readonly Review[], + projects: readonly Project[], +): readonly ReviewGroup[] { + const groups: ReviewGroup[] = []; + for (const project of projects) { + const members = reviews.filter((r) => r.project === project.id); + if (members.length > 0) { + groups.push({ key: project.id, title: project.name, reviews: members }); + } + } + const ungrouped = reviews.filter((r) => r.project === null); + if (ungrouped.length > 0) { + groups.push({ key: "__ungrouped__", title: "Ungrouped", reviews: ungrouped }); + } + return groups; } function App() { const reviews = useAppStore((s) => s.reviews); - const frontier = useAppStore((s) => s.frontier); const plan = useAppStore((s) => s.plan); const loading = useAppStore((s) => s.loading); const error = useAppStore((s) => s.error); @@ -112,6 +116,7 @@ function App() { const activeDiff = useAppStore((s) => s.activeDiff); const authoredPrs = useAppStore((s) => s.authoredPrs); const reviewRequests = useAppStore((s) => s.reviewRequests); + const projects = useAppStore((s) => s.projects); const prFetchLoading = useAppStore((s) => s.prFetchLoading); const fetchAuthoredPrs = useAppStore((s) => s.fetchAuthoredPrs); const fetchReviewRequests = useAppStore((s) => s.fetchReviewRequests); @@ -119,6 +124,7 @@ function App() { const fetchFrontier = useAppStore((s) => s.fetchFrontier); const fetchPlan = useAppStore((s) => s.fetchPlan); const fetchConfig = useAppStore((s) => s.fetchConfig); + const listProjects = useAppStore((s) => s.listProjects); const [reviewTab, setReviewTab] = useState("my-prs"); const [stateFilter, setStateFilter] = useState(null); @@ -127,25 +133,21 @@ function App() { const openReview = useAppStore((s) => s.openReview); const navigateToDiff = useAppStore((s) => s.navigateToDiff); const navigateToPlan = useAppStore((s) => s.navigateToPlan); - const navigateToFrontier = useAppStore((s) => s.navigateToFrontier); + const navigateToPrs = useAppStore((s) => s.navigateToPrs); + const navigateToProjects = useAppStore((s) => s.navigateToProjects); + const navigateToNewProject = useAppStore((s) => s.navigateToNewProject); + const navigateToSkills = useAppStore((s) => s.navigateToSkills); + const navigateToAgents = useAppStore((s) => s.navigateToAgents); const navigateToSettings = useAppStore((s) => s.navigateToSettings); - const navigateToKickoff = useAppStore((s) => s.navigateToKickoff); const addComment = useAppStore((s) => s.addComment); const requestChanges = useAppStore((s) => s.requestChanges); const mirrorComments = useAppStore((s) => s.mirrorComments); const refreshActiveReview = useAppStore((s) => s.refreshActiveReview); const addPlanComment = useAppStore((s) => s.addPlanComment); - const requestPlanChanges = useAppStore((s) => s.requestPlanChanges); - const approvePlan = useAppStore((s) => s.approvePlan); + const planRequestChanges = useAppStore((s) => s.planRequestChanges); + const planApprove = useAppStore((s) => s.planApprove); const openPlan = useAppStore((s) => s.openPlan); - const batchVerdicts = useAppStore((s) => s.batchVerdicts); - const showBatchPanel = useAppStore((s) => s.showBatchPanel); - const fetchBatchApprovePreview = useAppStore( - (s) => s.fetchBatchApprovePreview, - ); - const approveReview = useAppStore((s) => s.approveReview); - const approveAllEligible = useAppStore((s) => s.approveAllEligible); - const toggleBatchPanel = useAppStore((s) => s.toggleBatchPanel); + const batchStatus = useAppStore((s) => s.batchStatus); const [sidebarCollapsed, setSidebarCollapsed] = useState(() => { return localStorage.getItem(SIDEBAR_COLLAPSED_KEY) === "true"; @@ -161,47 +163,75 @@ function App() { }); }, []); - const shortcuts: ShortcutMap = useMemo( + // Handlers keyed by shortcut id; the registry supplies the key bindings so + // there is exactly one source of truth for both the combo and the handler. + const shortcutHandlers = useMemo void>>>( () => ({ - "meta+k": () => { + "command-palette": () => { setCommandPaletteOpen(true); }, - "meta+1": () => { - navigateToFrontier(); + "nav-prs": () => { + navigateToPrs(); }, - "meta+2": () => { - navigateToPlan(); + "nav-projects": () => { + navigateToProjects(); + }, + "nav-skills": () => { + navigateToSkills(); }, - "meta+comma": () => { + "nav-agents": () => { + navigateToAgents(); + }, + "nav-settings": () => { navigateToSettings(); }, - "meta+r": () => { + refresh: () => { void fetchReviews(); void fetchFrontier(); void fetchAuthoredPrs(); }, - "meta+b": () => { + "toggle-sidebar": () => { toggleSidebar(); }, + "open-in-ide": () => { + if (view.kind === "diff" && activeReview !== null) { + void invoke("open_in_editor", { + filePath: ".", + repoSlug: activeReview.repo_slug, + branch: activeReview.branch, + }); + } + }, escape: () => { - // Only navigate back when viewing a diff or plan, not from the frontier. + // Only navigate back when viewing a diff or plan, not from the list. if (view.kind === "diff" || view.kind === "plan") { - navigateToFrontier(); + navigateToPrs(); } }, }), [ - navigateToFrontier, - navigateToPlan, + navigateToPrs, + navigateToProjects, + navigateToSkills, + navigateToAgents, navigateToSettings, fetchReviews, fetchFrontier, fetchAuthoredPrs, toggleSidebar, view.kind, + activeReview, ], ); + const shortcuts: ShortcutMap = useMemo(() => { + const map: Record void> = {}; + for (const shortcut of SHORTCUTS) { + map[shortcut.combo] = shortcutHandlers[shortcut.id]; + } + return map; + }, [shortcutHandlers]); + useKeyboardShortcuts(shortcuts); useEffect(() => { @@ -210,20 +240,22 @@ function App() { void fetchPlan(); void fetchConfig(); void fetchAuthoredPrs(); + void listProjects(); - const unlisten = listen("agent-completed", () => { + const unlisten = listen("agent-completed", (event) => { void fetchReviews(); void fetchFrontier(); void fetchPlan(); void refreshActiveReview(); - // Best-effort desktop notification. The active review may be stale - // at this point, so we read the current value from the store. + // Best-effort desktop notification. Use the event payload's mode + // to differentiate the notification title and body. + const { mode } = event.payload; const current = useAppStore.getState().activeReview; const branch = current !== null ? current.branch : "a review"; void sendNotification({ - title: "Rework Complete", - body: `Agent finished on ${branch}`, + title: notificationTitleForMode(mode), + body: notificationBodyForMode(mode, branch), }); }); @@ -232,7 +264,15 @@ function App() { f(); }); }; - }, [fetchReviews, fetchFrontier, fetchPlan, fetchConfig, fetchAuthoredPrs, refreshActiveReview]); + }, [ + fetchReviews, + fetchFrontier, + fetchPlan, + fetchConfig, + fetchAuthoredPrs, + listProjects, + refreshActiveReview, + ]); const filterReviews = useCallback( (items: readonly Review[]): readonly Review[] => { @@ -258,24 +298,22 @@ function App() { [stateFilter, showStale, searchQuery], ); - const unfilteredReviewsForTab: readonly Review[] = useMemo(() => { + const reviewsForTab: readonly Review[] = useMemo(() => { switch (reviewTab) { case "my-prs": return authoredPrs; case "review-requests": return reviewRequests; - case "frontier": + case "all": return reviews; - default: { - const _exhaustive: never = reviewTab; - throw new Error(`unreachable: ${String(_exhaustive)}`); - } + default: + return assertNever(reviewTab); } }, [reviewTab, authoredPrs, reviewRequests, reviews]); const handleReviewAction = useCallback( (pr: string) => { - const allReviews = [...authoredPrs, ...reviewRequests, ...frontier, ...reviews]; + const allReviews = [...authoredPrs, ...reviewRequests, ...reviews]; const review = allReviews.find((r) => r.pr === pr); if (review === undefined) return; @@ -293,14 +331,39 @@ function App() { assertNever(review.gate_state); } }, - [openReview, navigateToDiff, authoredPrs, reviewRequests, frontier, reviews], + [openReview, navigateToDiff, authoredPrs, reviewRequests, reviews], + ); + + // Opening a project routes to its plan gate when a plan exists, otherwise to + // the project-grouped PRs list. + const handleOpenProject = useCallback( + (project: Project) => { + if (project.plan !== null) { + navigateToPlan(); + } else { + navigateToPrs(); + } + }, + [navigateToPlan, navigateToPrs], ); const handleNavigate = useCallback( (kind: ViewState["kind"]) => { switch (kind) { - case "frontier": - navigateToFrontier(); + case "prs": + navigateToPrs(); + break; + case "projects": + navigateToProjects(); + break; + case "new-project": + navigateToNewProject(); + break; + case "skills": + navigateToSkills(); + break; + case "agents": + navigateToAgents(); break; case "plan": navigateToPlan(); @@ -308,31 +371,45 @@ function App() { case "settings": navigateToSettings(); break; - case "kickoff": - navigateToKickoff(); - break; case "diff": break; default: assertNever(kind); } }, - [navigateToFrontier, navigateToPlan, navigateToSettings, navigateToKickoff], + [ + navigateToPrs, + navigateToProjects, + navigateToNewProject, + navigateToSkills, + navigateToAgents, + navigateToPlan, + navigateToSettings, + ], ); - // Justified cast: value is constrained to the three TabsTrigger values below const handleTabChange = useCallback( (value: unknown) => { if (value === null || typeof value !== "string") return; - const tab = value as ReviewTab; + let tab: ReviewTab; + switch (value) { + case "my-prs": + case "review-requests": + case "all": + tab = value; + break; + default: + return; + } setReviewTab(tab); setStateFilter(null); setShowStale(false); setSearchQuery(""); if (tab === "my-prs") void fetchAuthoredPrs(); if (tab === "review-requests") void fetchReviewRequests(); + if (tab === "all") void fetchReviews(); }, - [fetchAuthoredPrs, fetchReviewRequests], + [fetchAuthoredPrs, fetchReviewRequests, fetchReviews], ); const errorBanner = @@ -342,9 +419,55 @@ function App() { ) : null; + function renderProjectGroupedList(items: readonly Review[]) { + const filtered = filterReviews(items); + const groups = groupReviewsByProject(filtered, projects); + + if (groups.length === 0) { + return null; + } + + return groups.map((group) => ( +
+

+ {group.title}{" "} + + ({group.reviews.length}) + +

+
+ {group.reviews.map((review) => ( + + ))} +
+
+ )); + } + + function renderPrsContent(items: readonly Review[], emptyIcon: string, emptyTitle: string, emptyDescription: string) { + if (prFetchLoading && items.length === 0) { + return ; + } + const grouped = renderProjectGroupedList(items); + if (grouped === null) { + return ( + + ); + } + return grouped; + } + function renderContent() { switch (view.kind) { - case "frontier": + case "prs": return (
{errorBanner} @@ -353,7 +476,7 @@ function App() {
- My PRs + Mine {authoredPrs.length > 0 && ( {authoredPrs.length} @@ -368,29 +491,19 @@ function App() { )} - - Frontier - {frontier.length > 0 && ( + + All + {reviews.length > 0 && ( - {frontier.length} + {reviews.length} )}
- {reviewTab === "frontier" && frontier.length > 0 && ( - - )} - - {(reviewTab === "my-prs" || reviewTab === "review-requests") && ( + {(reviewTab === "my-prs" || + reviewTab === "review-requests") && (
- {showBatchPanel && batchVerdicts !== null && reviewTab === "frontier" && ( - { - void approveAllEligible(); - }} - onClose={toggleBatchPanel} - /> - )} -
@@ -430,7 +532,7 @@ function App() { />
-
- {prFetchLoading && authoredPrs.length === 0 && } - {filterReviews(authoredPrs).map((review) => ( - - ))} - {!prFetchLoading && authoredPrs.length === 0 && ( - - )} -
+ {renderPrsContent( + authoredPrs, + "📝", + "No open PRs", + "Click Refresh to fetch your open PRs from GitHub. Make sure your repo path is configured in Settings.", + )}
-
- {prFetchLoading && reviewRequests.length === 0 && } - {filterReviews(reviewRequests).map((review) => ( - - ))} - {!prFetchLoading && reviewRequests.length === 0 && ( - - )} -
+ {renderPrsContent( + reviewRequests, + "👀", + "No review requests", + "No PRs are waiting for your review. Click Refresh to check again.", + )}
- -
- {loading && frontier.length === 0 && } - {(() => { - const filtered = filterReviews(frontier); - const trees = buildStackTrees(filtered); - - if (trees.length === 0 && !loading && filtered.length === 0) { - return ( - - ); - } - - return trees.map((root) => ( - - )); - })()} -
- - {reviews.length > 0 && ( -
-

- All Reviews ({filterReviews(reviews).length}) -

-
- {filterReviews(reviews).map((review) => ( - - ))} -
-
+ + {loading && reviews.length === 0 ? ( + + ) : ( + (renderProjectGroupedList(reviews) ?? ( + + )) )} @@ -542,7 +589,7 @@ function App() {
Failed to load review.{" "}
+ ); + + case "projects": + return ( +
+ {errorBanner} +
+

Projects

+ +
+ {projects.length === 0 ? ( + + ) : ( +
+ {projects.map((project) => ( + r.project === project.id).length + } + onOpen={handleOpenProject} + /> + ))} +
)}
); + case "new-project": + return ; + + case "skills": + return ; + + case "agents": + return ; + case "settings": return ; - case "kickoff": - return ; - default: return assertNever(view); } @@ -614,14 +701,11 @@ function App() { -
- {renderContent()} -
+
{renderContent()}
, } | { "kind": "Ineligible", -/** - * Human-readable reasons why this review does not qualify. - */ -reasons: Array, }; diff --git a/app/src/bindings/CiCheck.ts b/app/src/bindings/CiCheck.ts new file mode 100644 index 0000000..1d12ab0 --- /dev/null +++ b/app/src/bindings/CiCheck.ts @@ -0,0 +1,31 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * A single CI check as returned by `gh pr checks --json`. + * + * `gh pr checks` reports each check's `bucket` — a normalized rollup of the + * raw state that groups the many possible GitHub statuses into a handful of + * outcomes (`pass`, `fail`, `pending`, `skipping`, `cancel`). The bucket is + * the reliable signal for summarizing pass/fail; `state` is the raw value. + */ +export type CiCheck = { +/** + * Name of the check (e.g. "build", "lint"). + */ +name: string, +/** + * Raw check state (e.g. "SUCCESS", "FAILURE", "PENDING", "SKIPPED"). + */ +state: string, +/** + * Normalized outcome bucket from `gh` (e.g. "pass", "fail", "pending"). + */ +bucket: string, +/** + * Deep link to the check run's details page (used to extract the run id). + */ +link: string, +/** + * Workflow name the check belongs to, when available. + */ +workflow: string, }; diff --git a/app/src/bindings/CiSummary.ts b/app/src/bindings/CiSummary.ts new file mode 100644 index 0000000..32267e3 --- /dev/null +++ b/app/src/bindings/CiSummary.ts @@ -0,0 +1,25 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Rollup of a set of [`CiCheck`]s into pass/fail/pending counts. + * + * Drives the diff-gate CI badge. Neutral and skipped checks count as passing: + * they do not indicate a failure and should not block or alarm the reviewer. + */ +export type CiSummary = { +/** + * Checks that passed (includes neutral/skipped/cancelled). + */ +passed: number, +/** + * Total number of checks. + */ +total: number, +/** + * Checks that failed. + */ +failed: number, +/** + * Checks still pending (queued or in progress). + */ +pending: number, }; diff --git a/app/src/bindings/Config.ts b/app/src/bindings/Config.ts index 0876718..2e5d254 100644 --- a/app/src/bindings/Config.ts +++ b/app/src/bindings/Config.ts @@ -1,4 +1,7 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { AgentPrompts } from "./AgentPrompts"; +import type { LspServers } from "./LspServers"; +import type { SkillsGithub } from "./SkillsGithub"; /** * Persistent application configuration stored at `~/.cockpit/config.toml`. @@ -30,21 +33,14 @@ agent_command: string, */ hook_port: number, /** - * Anthropic API key for direct model access. - */ -anthropic_api_key: string | null, -/** - * Model identifier to use for agent runs (default: `"claude-sonnet-4-6"`). - */ -model: string | null, -/** - * Optional daily spend cap in US dollars. `None` means unlimited. - */ -daily_budget_usd: number | null, -/** - * GitHub personal access token for API operations. + * Maximum number of implementer agents to run concurrently during a + * plan-approval fan-out (default: `3`). + * + * Bounds resource use when a project's frontier is large: `spawn_batch` + * spawns at most this many agents at once and waits for a slot before + * starting the next. */ -github_token: string | null, +max_parallel_agents: number, /** * Shell command to launch the preferred IDE (e.g. `"cursor"`, `"code"`). */ @@ -58,10 +54,21 @@ app_theme: string | null, */ editor_theme: string | null, /** - * Terminal font family name (default: `"SF Mono"`). + * Per-[`AgentMode`] custom prompt fragment overrides. + * + * Each present override is injected verbatim into the corresponding + * mode's prompt; absent modes fall back to the builtin intent. + */ +agent_prompts: AgentPrompts, +/** + * Optional GitHub source for installable skills. + * + * `None` means no remote source is configured; skills are then local-only. */ -terminal_font: string | null, +skills_github: SkillsGithub | null, /** - * Terminal font size in points (default: `13`). + * Language-server command configuration for the Monaco LSP bridge. + * + * Controls whether the bridge runs and which binaries back each language. */ -terminal_font_size: number | null, }; +lsp_servers: LspServers, }; diff --git a/app/src/bindings/LspServers.ts b/app/src/bindings/LspServers.ts new file mode 100644 index 0000000..125d5e1 --- /dev/null +++ b/app/src/bindings/LspServers.ts @@ -0,0 +1,35 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Language-server command configuration for the Monaco LSP bridge. + * + * Cockpit does not bundle language servers. The user installs them (for + * example `npm i -g pyright typescript-language-server`) and cockpit resolves + * each command via the login-shell `PATH` at spawn time. These fields let a + * user point at a non-default binary or a wrapper script; when a field is + * `None`, the built-in default command name is used and looked up on `PATH`. + */ +export type LspServers = { +/** + * Whether the Monaco LSP bridge is active at all (default: `true`). + * + * When `false`, cockpit never starts a language-server bridge and the + * diff editor falls back to plain syntax highlighting only. + */ +enabled: boolean, +/** + * Override for the Python language-server command + * (default: `pyright-langserver`). + * + * The command is invoked with `--stdio`. `None` uses the default name, + * resolved on `PATH`. + */ +pyright_command: string | null, +/** + * Override for the TypeScript/JavaScript language-server command + * (default: `typescript-language-server`). + * + * The command is invoked with `--stdio`. `None` uses the default name, + * resolved on `PATH`. + */ +typescript_command: string | null, }; diff --git a/app/src/bindings/Project.ts b/app/src/bindings/Project.ts new file mode 100644 index 0000000..aa95a5d --- /dev/null +++ b/app/src/bindings/Project.ts @@ -0,0 +1,28 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { ProjectId } from "./ProjectId"; +import type { ProjectPlan } from "./ProjectPlan"; +import type { ProjectSource } from "./ProjectSource"; + +/** + * A first-class project that groups reviews. + * + * Reviews may belong to a project (via [`Review::project`]) or be ungrouped + * (`None`). Linear is one optional [`ProjectSource`], not the entry point. + */ +export type Project = { +/** + * Locally-unique project identifier. + */ +id: ProjectId, +/** + * Human-readable project name. + */ +name: string, +/** + * Where this project came from (Linear or ad-hoc). + */ +source: ProjectSource, +/** + * The optional project-level plan reviewed at the plan gate. + */ +plan: ProjectPlan | null, }; diff --git a/app/src/bindings/ProjectId.ts b/app/src/bindings/ProjectId.ts new file mode 100644 index 0000000..3866e98 --- /dev/null +++ b/app/src/bindings/ProjectId.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Locally-unique identifier for a first-class [`Project`] that groups + * reviews. Distinct from [`ProjectRef`], which references a Linear project. + */ +export type ProjectId = string; diff --git a/app/src/bindings/ProjectPlan.ts b/app/src/bindings/ProjectPlan.ts index 03f7e93..d8d69d8 100644 --- a/app/src/bindings/ProjectPlan.ts +++ b/app/src/bindings/ProjectPlan.ts @@ -30,4 +30,12 @@ comments: Array, /** * The agent run responsible for producing / revising the plan. */ -agent: AgentRun | null, }; +agent: AgentRun | null, +/** + * On-disk markdown file the planner agent writes its finished plan to. + * + * Set before spawning a planner (`AgentMode::Plan`); on completion the + * file is read back and parsed into [`Self::doc`]. `None` for plans that + * were loaded directly from a document rather than produced by an agent. + */ +plan_path?: string, }; diff --git a/app/src/bindings/ProjectSource.ts b/app/src/bindings/ProjectSource.ts new file mode 100644 index 0000000..00484d1 --- /dev/null +++ b/app/src/bindings/ProjectSource.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Where a first-class [`Project`] came from. + * + * Linear is one *optional* source, not the entry point: a project may be + * created ad-hoc with no Linear backing at all. + */ +export type ProjectSource = { "Linear": string } | "AdHoc"; diff --git a/app/src/bindings/Review.ts b/app/src/bindings/Review.ts index 00239d7..88c5608 100644 --- a/app/src/bindings/Review.ts +++ b/app/src/bindings/Review.ts @@ -5,6 +5,7 @@ import type { DiffData } from "./DiffData"; import type { GateState } from "./GateState"; import type { IssueRef } from "./IssueRef"; import type { PrRef } from "./PrRef"; +import type { ProjectId } from "./ProjectId"; import type { ReviewId } from "./ReviewId"; import type { ReviewSource } from "./ReviewSource"; @@ -87,4 +88,9 @@ agent: AgentRun | null, * operations like fetching diffs via `gh --repo`. `None` for reviews * created from the local repo context (kickoff). */ -repo_slug: string | null, }; +repo_slug: string | null, +/** + * The first-class [`Project`] this review belongs to, if any. `None` for + * ungrouped reviews (e.g. GitHub-imported PRs with no project attached). + */ +project: ProjectId | null, }; diff --git a/app/src/bindings/Skill.ts b/app/src/bindings/Skill.ts new file mode 100644 index 0000000..1c39fdb --- /dev/null +++ b/app/src/bindings/Skill.ts @@ -0,0 +1,33 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { SkillSource } from "./SkillSource"; + +/** + * A parsed skill definition loaded from a markdown file with YAML frontmatter. + */ +export type Skill = { +/** + * Short identifier from frontmatter. + */ +name: string, +/** + * One-line description from frontmatter. + */ +description: string, +/** + * Optional tags for filtering by relevance (e.g. `["rust", "testing"]`). + */ +tags: Array, +/** + * The full markdown body (after frontmatter). + */ +body: string, +/** + * Source file path. + */ +path: string, +/** + * Provenance of the skill (local vs. GitHub), read from the `.meta.json` + * sidecar. Defaults to [`SkillSource::Local`] when no sidecar exists so + * hand-authored skills surface a Local badge in the UI. + */ +source: SkillSource, }; diff --git a/app/src/bindings/SkillSource.ts b/app/src/bindings/SkillSource.ts new file mode 100644 index 0000000..315b93e --- /dev/null +++ b/app/src/bindings/SkillSource.ts @@ -0,0 +1,21 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Where a locally-installed skill came from. + * + * Recorded in each skill's `.meta.json` sidecar so sync can decide whether a + * remote update should overwrite a local edit and so the UI can label origin. + */ +export type SkillSource = { "kind": "Local" } | { "kind": "GitHub", +/** + * Repository owner (user or org). + */ +owner: string, +/** + * Repository name. + */ +repo: string, +/** + * The blob SHA of the `SKILL.md` last fetched, for idempotency. + */ +sha: string, }; diff --git a/app/src/bindings/SkillsGithub.ts b/app/src/bindings/SkillsGithub.ts new file mode 100644 index 0000000..a1b96cc --- /dev/null +++ b/app/src/bindings/SkillsGithub.ts @@ -0,0 +1,30 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * GitHub source configuration for syncing installable skills. + * + * Points at a directory in a repo that holds one skill per subdirectory + * (`/SKILL.md`). Authentication is the user's existing `gh auth` — there + * is deliberately no token field here (see PROGRAM_PLAN #3/#8). + */ +export type SkillsGithub = { +/** + * Repository owner (user or org). + */ +owner: string, +/** + * Repository name. + */ +repo: string, +/** + * Branch to sync from (e.g. `"main"`). + */ +branch: string, +/** + * Repo-relative path to the directory that holds the skills. + */ +path: string, +/** + * Whether cockpit should sync on relevant triggers automatically. + */ +auto_sync: boolean, }; diff --git a/app/src/bindings/SyncReport.ts b/app/src/bindings/SyncReport.ts new file mode 100644 index 0000000..03b09c7 --- /dev/null +++ b/app/src/bindings/SyncReport.ts @@ -0,0 +1,21 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Outcome counts from a [`sync_from_github`] run. + * + * Serializable so the CLI and Tauri surfaces can report progress without + * re-deriving the numbers. + */ +export type SyncReport = { +/** + * Skills newly written (no prior local copy). + */ +installed: number, +/** + * Skills whose SHA changed and were overwritten. + */ +updated: number, +/** + * Skills skipped because the stored SHA already matched (idempotent). + */ +skipped: number, }; diff --git a/app/src/components/AgentEditor.tsx b/app/src/components/AgentEditor.tsx new file mode 100644 index 0000000..c5ea60a --- /dev/null +++ b/app/src/components/AgentEditor.tsx @@ -0,0 +1,239 @@ +import { useState, useEffect, useCallback } from "react"; +import { useAppStore } from "../store"; +import type { AgentMode } from "../bindings/AgentMode"; +import { + Card, + CardHeader, + CardTitle, + CardDescription, + CardContent, +} from "@/components/ui/card"; +import { Button } from "@/components/ui/button"; +import { Textarea } from "@/components/ui/textarea"; +import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"; +import { Bot, Save, Undo2, Loader2 } from "lucide-react"; +import { cn } from "@/lib/utils"; + +function assertNever(x: never): never { + throw new Error(`unreachable: ${String(x)}`); +} + +/** The agent modes, in display order, as an exhaustive literal table. */ +const AGENT_MODES = ["Implement", "Plan", "Fix", "Restack"] as const; + +/** Human-facing label for an agent mode. */ +function modeLabel(mode: AgentMode): string { + switch (mode) { + case "Implement": + return "Implement"; + case "Plan": + return "Plan"; + case "Fix": + return "Fix"; + case "Restack": + return "Restack"; + default: + return assertNever(mode); + } +} + +/** One-line description of what each agent mode does. */ +function modeDescription(mode: AgentMode): string { + switch (mode) { + case "Implement": + return "Runs when a plan is approved to build each PR in the batch."; + case "Plan": + return "Revises the project plan during the plan gate's rework loop."; + case "Fix": + return "Applies your diff-gate comments and pushes the rework."; + case "Restack": + return "Rebases a descendant PR after its base branch changed."; + default: + return assertNever(mode); + } +} + +/** Narrow an unknown tab value to an `AgentMode`, or null if unrecognized. */ +function toAgentMode(value: unknown): AgentMode | null { + switch (value) { + case "Implement": + case "Plan": + case "Fix": + case "Restack": + return value; + default: + return null; + } +} + +/** + * Per-`AgentMode` prompt-fragment editor. + * + * For the selected mode it loads the stored override and the builtin default. + * The custom fragment (a `