From 296843215f28dcf1f4fc366e10fa3a42f54dffb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?AgentDock=20=E6=96=BD=E5=B7=A5=E5=91=98?= Date: Tue, 25 Aug 2026 00:21:13 +0800 Subject: [PATCH] chore: wave-0 baseline (Tauri2+React shell, platform detect, fake catalog) --- .gitignore | 22 + Cargo.toml | 26 + README.md | 51 + adapters/catalog.yaml | 33 + adapters/schema/adapter.schema.json | 33 + adapters/tools/aider.yaml | 6 + adapters/tools/claude-code.yaml | 6 + adapters/tools/cline.yaml | 6 + adapters/tools/codebuddy.yaml | 6 + adapters/tools/codex.yaml | 6 + adapters/tools/copilot.yaml | 6 + adapters/tools/crush.yaml | 6 + adapters/tools/cursor.yaml | 6 + adapters/tools/gemini.yaml | 6 + adapters/tools/goose.yaml | 6 + adapters/tools/kimi.yaml | 6 + adapters/tools/opencode.yaml | 6 + adapters/tools/qwen.yaml | 6 + adapters/tools/warp.yaml | 6 + apps/desktop/index.html | 12 + apps/desktop/package-lock.json | 2137 +++++++++++++++++ apps/desktop/package.json | 26 + apps/desktop/src-tauri/Cargo.toml | 21 + apps/desktop/src-tauri/build.rs | 3 + .../src-tauri/capabilities/default.json | 7 + apps/desktop/src-tauri/icon-source.png | Bin 0 -> 8452 bytes apps/desktop/src-tauri/icons/128x128.png | Bin 0 -> 4126 bytes apps/desktop/src-tauri/icons/128x128@2x.png | Bin 0 -> 7674 bytes apps/desktop/src-tauri/icons/32x32.png | Bin 0 -> 1041 bytes apps/desktop/src-tauri/icons/64x64.png | Bin 0 -> 2063 bytes .../src-tauri/icons/Square107x107Logo.png | Bin 0 -> 3462 bytes .../src-tauri/icons/Square142x142Logo.png | Bin 0 -> 4546 bytes .../src-tauri/icons/Square150x150Logo.png | Bin 0 -> 4745 bytes .../src-tauri/icons/Square284x284Logo.png | Bin 0 -> 9026 bytes .../src-tauri/icons/Square30x30Logo.png | Bin 0 -> 887 bytes .../src-tauri/icons/Square310x310Logo.png | Bin 0 -> 9886 bytes .../src-tauri/icons/Square44x44Logo.png | Bin 0 -> 1421 bytes .../src-tauri/icons/Square71x71Logo.png | Bin 0 -> 2353 bytes .../src-tauri/icons/Square89x89Logo.png | Bin 0 -> 2905 bytes apps/desktop/src-tauri/icons/StoreLogo.png | Bin 0 -> 1597 bytes .../android/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../icons/android/mipmap-hdpi/ic_launcher.png | Bin 0 -> 1494 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 5147 bytes .../android/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 1658 bytes .../icons/android/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1492 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 0 -> 3491 bytes .../android/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 1699 bytes .../android/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 3174 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 0 -> 6832 bytes .../mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 3533 bytes .../android/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 4819 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 0 -> 10311 bytes .../mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 5338 bytes .../android/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 6524 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 13987 bytes .../mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 7343 bytes .../android/values/ic_launcher_background.xml | 4 + apps/desktop/src-tauri/icons/icon.icns | Bin 0 -> 62551 bytes apps/desktop/src-tauri/icons/icon.ico | Bin 0 -> 14386 bytes apps/desktop/src-tauri/icons/icon.png | Bin 0 -> 14421 bytes .../src-tauri/icons/ios/AppIcon-20x20@1x.png | Bin 0 -> 622 bytes .../icons/ios/AppIcon-20x20@2x-1.png | Bin 0 -> 1276 bytes .../src-tauri/icons/ios/AppIcon-20x20@2x.png | Bin 0 -> 1276 bytes .../src-tauri/icons/ios/AppIcon-20x20@3x.png | Bin 0 -> 1858 bytes .../src-tauri/icons/ios/AppIcon-29x29@1x.png | Bin 0 -> 973 bytes .../icons/ios/AppIcon-29x29@2x-1.png | Bin 0 -> 1908 bytes .../src-tauri/icons/ios/AppIcon-29x29@2x.png | Bin 0 -> 1908 bytes .../src-tauri/icons/ios/AppIcon-29x29@3x.png | Bin 0 -> 2970 bytes .../src-tauri/icons/ios/AppIcon-40x40@1x.png | Bin 0 -> 1276 bytes .../icons/ios/AppIcon-40x40@2x-1.png | Bin 0 -> 2642 bytes .../src-tauri/icons/ios/AppIcon-40x40@2x.png | Bin 0 -> 2642 bytes .../src-tauri/icons/ios/AppIcon-40x40@3x.png | Bin 0 -> 3926 bytes .../src-tauri/icons/ios/AppIcon-512@2x.png | Bin 0 -> 8220 bytes .../src-tauri/icons/ios/AppIcon-60x60@2x.png | Bin 0 -> 3926 bytes .../src-tauri/icons/ios/AppIcon-60x60@3x.png | Bin 0 -> 5752 bytes .../src-tauri/icons/ios/AppIcon-76x76@1x.png | Bin 0 -> 2495 bytes .../src-tauri/icons/ios/AppIcon-76x76@2x.png | Bin 0 -> 4816 bytes .../icons/ios/AppIcon-83.5x83.5@2x.png | Bin 0 -> 5208 bytes .../desktop/src-tauri/src/commands/catalog.rs | 11 + apps/desktop/src-tauri/src/commands/env.rs | 10 + apps/desktop/src-tauri/src/commands/mod.rs | 2 + apps/desktop/src-tauri/src/lib.rs | 42 + apps/desktop/src-tauri/src/main.rs | 6 + apps/desktop/src-tauri/tauri.conf.json | 37 + apps/desktop/src/App.tsx | 65 + apps/desktop/src/components/CliMonogram.tsx | 19 + apps/desktop/src/components/Header.tsx | 34 + apps/desktop/src/components/KpiCard.tsx | 39 + apps/desktop/src/components/MonoChip.tsx | 6 + apps/desktop/src/components/Sidebar.tsx | 79 + apps/desktop/src/components/StatusBadge.tsx | 18 + apps/desktop/src/hooks/useCatalog.ts | 38 + apps/desktop/src/hooks/useEnv.ts | 38 + apps/desktop/src/ipc/index.ts | 58 + apps/desktop/src/ipc/types.ts | 54 + apps/desktop/src/main.tsx | 30 + apps/desktop/src/pages/Backup.tsx | 19 + apps/desktop/src/pages/Catalog.tsx | 113 + apps/desktop/src/pages/ConfigCenter.tsx | 19 + apps/desktop/src/pages/MyCli.tsx | 19 + apps/desktop/src/pages/Overview.tsx | 254 ++ apps/desktop/src/pages/Settings.tsx | 44 + apps/desktop/src/styles/global.css | 1009 ++++++++ apps/desktop/src/tokens/color.css | 57 + apps/desktop/src/tokens/effects.css | 39 + apps/desktop/src/tokens/motion.css | 21 + apps/desktop/src/tokens/space.css | 24 + apps/desktop/src/tokens/tiers.css | 59 + apps/desktop/src/tokens/typography.css | 31 + apps/desktop/tsconfig.json | 20 + apps/desktop/vite.config.ts | 28 + crates/agentdock-adapter/Cargo.toml | 10 + crates/agentdock-adapter/src/catalog.rs | 110 + crates/agentdock-adapter/src/error.rs | 20 + crates/agentdock-adapter/src/lib.rs | 11 + crates/agentdock-config/Cargo.toml | 7 + crates/agentdock-config/src/lib.rs | 18 + crates/agentdock-core/Cargo.toml | 7 + crates/agentdock-core/src/lib.rs | 17 + crates/agentdock-diag/Cargo.toml | 7 + crates/agentdock-diag/src/lib.rs | 17 + crates/agentdock-exec/Cargo.toml | 7 + crates/agentdock-exec/src/lib.rs | 17 + crates/agentdock-platform/Cargo.toml | 12 + crates/agentdock-platform/src/detect.rs | 315 +++ crates/agentdock-platform/src/lib.rs | 10 + crates/agentdock-platform/src/model.rs | 56 + crates/agentdock-secrets/Cargo.toml | 7 + crates/agentdock-secrets/src/lib.rs | 17 + crates/agentdock-store/Cargo.toml | 11 + crates/agentdock-store/src/error.rs | 32 + crates/agentdock-store/src/lib.rs | 11 + crates/agentdock-store/src/migrations.rs | 26 + crates/agentdock-store/src/schema.rs | 33 + crates/agentdock-store/src/store.rs | 105 + docs/architecture.md | 559 +++++ docs/visual-spec-v1.2.md | 448 ++++ 137 files changed, 6696 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 README.md create mode 100644 adapters/catalog.yaml create mode 100644 adapters/schema/adapter.schema.json create mode 100644 adapters/tools/aider.yaml create mode 100644 adapters/tools/claude-code.yaml create mode 100644 adapters/tools/cline.yaml create mode 100644 adapters/tools/codebuddy.yaml create mode 100644 adapters/tools/codex.yaml create mode 100644 adapters/tools/copilot.yaml create mode 100644 adapters/tools/crush.yaml create mode 100644 adapters/tools/cursor.yaml create mode 100644 adapters/tools/gemini.yaml create mode 100644 adapters/tools/goose.yaml create mode 100644 adapters/tools/kimi.yaml create mode 100644 adapters/tools/opencode.yaml create mode 100644 adapters/tools/qwen.yaml create mode 100644 adapters/tools/warp.yaml create mode 100644 apps/desktop/index.html create mode 100644 apps/desktop/package-lock.json create mode 100644 apps/desktop/package.json create mode 100644 apps/desktop/src-tauri/Cargo.toml create mode 100644 apps/desktop/src-tauri/build.rs create mode 100644 apps/desktop/src-tauri/capabilities/default.json create mode 100644 apps/desktop/src-tauri/icon-source.png create mode 100644 apps/desktop/src-tauri/icons/128x128.png create mode 100644 apps/desktop/src-tauri/icons/128x128@2x.png create mode 100644 apps/desktop/src-tauri/icons/32x32.png create mode 100644 apps/desktop/src-tauri/icons/64x64.png create mode 100644 apps/desktop/src-tauri/icons/Square107x107Logo.png create mode 100644 apps/desktop/src-tauri/icons/Square142x142Logo.png create mode 100644 apps/desktop/src-tauri/icons/Square150x150Logo.png create mode 100644 apps/desktop/src-tauri/icons/Square284x284Logo.png create mode 100644 apps/desktop/src-tauri/icons/Square30x30Logo.png create mode 100644 apps/desktop/src-tauri/icons/Square310x310Logo.png create mode 100644 apps/desktop/src-tauri/icons/Square44x44Logo.png create mode 100644 apps/desktop/src-tauri/icons/Square71x71Logo.png create mode 100644 apps/desktop/src-tauri/icons/Square89x89Logo.png create mode 100644 apps/desktop/src-tauri/icons/StoreLogo.png create mode 100644 apps/desktop/src-tauri/icons/android/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 apps/desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png create mode 100644 apps/desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png create mode 100644 apps/desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png create mode 100644 apps/desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png create mode 100644 apps/desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png create mode 100644 apps/desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png create mode 100644 apps/desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png create mode 100644 apps/desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png create mode 100644 apps/desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png create mode 100644 apps/desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png create mode 100644 apps/desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png create mode 100644 apps/desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 apps/desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png create mode 100644 apps/desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png create mode 100644 apps/desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 apps/desktop/src-tauri/icons/android/values/ic_launcher_background.xml create mode 100644 apps/desktop/src-tauri/icons/icon.icns create mode 100644 apps/desktop/src-tauri/icons/icon.ico create mode 100644 apps/desktop/src-tauri/icons/icon.png create mode 100644 apps/desktop/src-tauri/icons/ios/AppIcon-20x20@1x.png create mode 100644 apps/desktop/src-tauri/icons/ios/AppIcon-20x20@2x-1.png create mode 100644 apps/desktop/src-tauri/icons/ios/AppIcon-20x20@2x.png create mode 100644 apps/desktop/src-tauri/icons/ios/AppIcon-20x20@3x.png create mode 100644 apps/desktop/src-tauri/icons/ios/AppIcon-29x29@1x.png create mode 100644 apps/desktop/src-tauri/icons/ios/AppIcon-29x29@2x-1.png create mode 100644 apps/desktop/src-tauri/icons/ios/AppIcon-29x29@2x.png create mode 100644 apps/desktop/src-tauri/icons/ios/AppIcon-29x29@3x.png create mode 100644 apps/desktop/src-tauri/icons/ios/AppIcon-40x40@1x.png create mode 100644 apps/desktop/src-tauri/icons/ios/AppIcon-40x40@2x-1.png create mode 100644 apps/desktop/src-tauri/icons/ios/AppIcon-40x40@2x.png create mode 100644 apps/desktop/src-tauri/icons/ios/AppIcon-40x40@3x.png create mode 100644 apps/desktop/src-tauri/icons/ios/AppIcon-512@2x.png create mode 100644 apps/desktop/src-tauri/icons/ios/AppIcon-60x60@2x.png create mode 100644 apps/desktop/src-tauri/icons/ios/AppIcon-60x60@3x.png create mode 100644 apps/desktop/src-tauri/icons/ios/AppIcon-76x76@1x.png create mode 100644 apps/desktop/src-tauri/icons/ios/AppIcon-76x76@2x.png create mode 100644 apps/desktop/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png create mode 100644 apps/desktop/src-tauri/src/commands/catalog.rs create mode 100644 apps/desktop/src-tauri/src/commands/env.rs create mode 100644 apps/desktop/src-tauri/src/commands/mod.rs create mode 100644 apps/desktop/src-tauri/src/lib.rs create mode 100644 apps/desktop/src-tauri/src/main.rs create mode 100644 apps/desktop/src-tauri/tauri.conf.json create mode 100644 apps/desktop/src/App.tsx create mode 100644 apps/desktop/src/components/CliMonogram.tsx create mode 100644 apps/desktop/src/components/Header.tsx create mode 100644 apps/desktop/src/components/KpiCard.tsx create mode 100644 apps/desktop/src/components/MonoChip.tsx create mode 100644 apps/desktop/src/components/Sidebar.tsx create mode 100644 apps/desktop/src/components/StatusBadge.tsx create mode 100644 apps/desktop/src/hooks/useCatalog.ts create mode 100644 apps/desktop/src/hooks/useEnv.ts create mode 100644 apps/desktop/src/ipc/index.ts create mode 100644 apps/desktop/src/ipc/types.ts create mode 100644 apps/desktop/src/main.tsx create mode 100644 apps/desktop/src/pages/Backup.tsx create mode 100644 apps/desktop/src/pages/Catalog.tsx create mode 100644 apps/desktop/src/pages/ConfigCenter.tsx create mode 100644 apps/desktop/src/pages/MyCli.tsx create mode 100644 apps/desktop/src/pages/Overview.tsx create mode 100644 apps/desktop/src/pages/Settings.tsx create mode 100644 apps/desktop/src/styles/global.css create mode 100644 apps/desktop/src/tokens/color.css create mode 100644 apps/desktop/src/tokens/effects.css create mode 100644 apps/desktop/src/tokens/motion.css create mode 100644 apps/desktop/src/tokens/space.css create mode 100644 apps/desktop/src/tokens/tiers.css create mode 100644 apps/desktop/src/tokens/typography.css create mode 100644 apps/desktop/tsconfig.json create mode 100644 apps/desktop/vite.config.ts create mode 100644 crates/agentdock-adapter/Cargo.toml create mode 100644 crates/agentdock-adapter/src/catalog.rs create mode 100644 crates/agentdock-adapter/src/error.rs create mode 100644 crates/agentdock-adapter/src/lib.rs create mode 100644 crates/agentdock-config/Cargo.toml create mode 100644 crates/agentdock-config/src/lib.rs create mode 100644 crates/agentdock-core/Cargo.toml create mode 100644 crates/agentdock-core/src/lib.rs create mode 100644 crates/agentdock-diag/Cargo.toml create mode 100644 crates/agentdock-diag/src/lib.rs create mode 100644 crates/agentdock-exec/Cargo.toml create mode 100644 crates/agentdock-exec/src/lib.rs create mode 100644 crates/agentdock-platform/Cargo.toml create mode 100644 crates/agentdock-platform/src/detect.rs create mode 100644 crates/agentdock-platform/src/lib.rs create mode 100644 crates/agentdock-platform/src/model.rs create mode 100644 crates/agentdock-secrets/Cargo.toml create mode 100644 crates/agentdock-secrets/src/lib.rs create mode 100644 crates/agentdock-store/Cargo.toml create mode 100644 crates/agentdock-store/src/error.rs create mode 100644 crates/agentdock-store/src/lib.rs create mode 100644 crates/agentdock-store/src/migrations.rs create mode 100644 crates/agentdock-store/src/schema.rs create mode 100644 crates/agentdock-store/src/store.rs create mode 100644 docs/architecture.md create mode 100644 docs/visual-spec-v1.2.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..df98f69 --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +# 构建产物 +node_modules/ +dist/ +target/ +*.log + +# Rust +Cargo.lock + +# 系统与编辑器 +.DS_Store +Thumbs.db +.idea/ +.vscode/ +*.swp + +# Tauri 本地运行文件 +apps/desktop/src-tauri/gen/ + +# 临时文件 +*.tmp +*.bak diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..b9282a3 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,26 @@ +[workspace] +resolver = "2" +members = [ + "crates/agentdock-core", + "crates/agentdock-adapter", + "crates/agentdock-platform", + "crates/agentdock-config", + "crates/agentdock-secrets", + "crates/agentdock-exec", + "crates/agentdock-diag", + "crates/agentdock-store", + "apps/desktop/src-tauri", +] + +[workspace.package] +version = "0.1.0" +edition = "2021" +license = "Apache-2.0" + +# 统一输出,避免各 crate 各自配置重复 +[profile.dev] +debug = false + +[profile.release] +lto = "thin" +strip = true diff --git a/README.md b/README.md new file mode 100644 index 0000000..696cbfa --- /dev/null +++ b/README.md @@ -0,0 +1,51 @@ +# AgentDock + +跨平台、中文化、可扩展的 Agent CLI 软件管理器。帮助用户发现、安装、更新、配置、授权和排查 Agent CLI。 + +**本仓库当前为 Wave 0 状态**:桌面应用空壳可运行(Tauri 2 + React 19 + TypeScript + Vite),含设计 Token、 +八层 Rust crate 骨架、适配器目录骨架、Windows 本机环境检测与 SQLite 空库。 + +## 仓库结构 + +```text +agentdock/ +├── apps/desktop/ # Tauri 2 应用入口(React UI + src-tauri) +│ └── src/tokens/ # 设计 Token(对接视觉规范 v1.2,唯一品味依据) +├── crates/ # 本机能力层(八层) +│ ├── agentdock-core/ # 编排(发现/安装/配置/授权/诊断流水线) +│ ├── agentdock-adapter/ # 适配器 schema 加载、版本校验、执行器接口 +│ ├── agentdock-platform/# Win/Linux 环境检测、PATH、发行版识别 +│ ├── agentdock-config/ # 配置读写(原子写入、备份、多格式编解码) +│ ├── agentdock-secrets/ # 系统密钥库封装 + 脱敏 +│ ├── agentdock-exec/ # 参数白名单、禁止 shell 拼接的进程执行 +│ ├── agentdock-diag/ # 诊断规则引擎 +│ └── agentdock-store/ # SQLite 空库与 schema 迁移骨架 +├── adapters/ # 版本化适配器 YAML(14 + 目录索引) +├── docs/ # 架构文档副本 +└── tests/ # 测试夹具与 e2e 脚本 +``` + +## 本地开发 + +```bash +# 前端依赖 + 构建 +cd apps/desktop +npm install +npm run build + +# Rust 工作区测试(八 crate + 桌面壳) +cargo test + +# 启动桌面应用(开发模式) +cd apps/desktop +npm run tauri dev +``` + +## Wave 0 范围 + +- 应用外壳:左侧竖导航六项 + 顶栏 + 六个占位页(视觉规范 v1.2 §3.0 + PRD §7) +- IPC 心跳:`detect_env` 命令(Windows 本机环境检测,架构 §5) +- `agentdock-store`:SQLite 空库 + schema 迁移骨架 +- 假目录:CLI 目录页以 `adapters/catalog.yaml` 渲染 14 张卡片 + +后续波次见 `docs/architecture.md` §12。 diff --git a/adapters/catalog.yaml b/adapters/catalog.yaml new file mode 100644 index 0000000..6c46ebb --- /dev/null +++ b/adapters/catalog.yaml @@ -0,0 +1,33 @@ +# AgentDock 适配器目录索引(v1) +# 第一批 14 个(数据取自调研底稿 agent-cli-survey-2026-08-24.md,不编造) +# 第二批 4 个(grok / amp / deepseek-dsh / plandex)暂缓,本目录不含,后续按需加入。 +catalog_version: 1 +tools: + - id: codex + file: tools/codex.yaml + - id: claude-code + file: tools/claude-code.yaml + - id: gemini + file: tools/gemini.yaml + - id: copilot + file: tools/copilot.yaml + - id: kimi + file: tools/kimi.yaml + - id: qwen + file: tools/qwen.yaml + - id: codebuddy + file: tools/codebuddy.yaml + - id: opencode + file: tools/opencode.yaml + - id: crush + file: tools/crush.yaml + - id: goose + file: tools/goose.yaml + - id: aider + file: tools/aider.yaml + - id: cursor + file: tools/cursor.yaml + - id: cline + file: tools/cline.yaml + - id: warp + file: tools/warp.yaml diff --git a/adapters/schema/adapter.schema.json b/adapters/schema/adapter.schema.json new file mode 100644 index 0000000..3168452 --- /dev/null +++ b/adapters/schema/adapter.schema.json @@ -0,0 +1,33 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://agentdock.local/schemas/adapter.schema.json", + "title": "AgentDock Adapter", + "description": "Agent CLI 适配器定义(v1)。Wave 0 仅含占位字段;完整 schema 见架构 §3.1,随 Wave 1 落地。", + "type": "object", + "additionalProperties": false, + "required": ["id", "name", "name_zh", "vendor", "status"], + "properties": { + "id": { + "type": "string", + "description": "稳定 ID,如 codex", + "pattern": "^[a-z0-9][a-z0-9-]*$" + }, + "name": { + "type": "string", + "description": "展示名" + }, + "name_zh": { + "type": "string", + "description": "中文展示名" + }, + "vendor": { + "type": "string", + "description": "厂商" + }, + "status": { + "type": "string", + "enum": ["available", "watch"], + "description": "目录状态:available=可安装列表;watch=观察中(第二批)" + } + } +} diff --git a/adapters/tools/aider.yaml b/adapters/tools/aider.yaml new file mode 100644 index 0000000..19c1ff9 --- /dev/null +++ b/adapters/tools/aider.yaml @@ -0,0 +1,6 @@ +# aider 适配器占位(Wave 0) +id: aider +name: Aider +name_zh: Aider +vendor: aider.chat +status: available diff --git a/adapters/tools/claude-code.yaml b/adapters/tools/claude-code.yaml new file mode 100644 index 0000000..294f326 --- /dev/null +++ b/adapters/tools/claude-code.yaml @@ -0,0 +1,6 @@ +# claude-code 适配器占位(Wave 0) +id: claude-code +name: Claude Code +name_zh: Claude Code +vendor: Anthropic +status: available diff --git a/adapters/tools/cline.yaml b/adapters/tools/cline.yaml new file mode 100644 index 0000000..0b6e194 --- /dev/null +++ b/adapters/tools/cline.yaml @@ -0,0 +1,6 @@ +# cline 适配器占位(Wave 0) +id: cline +name: Cline +name_zh: Cline +vendor: Cline +status: available diff --git a/adapters/tools/codebuddy.yaml b/adapters/tools/codebuddy.yaml new file mode 100644 index 0000000..6e248ba --- /dev/null +++ b/adapters/tools/codebuddy.yaml @@ -0,0 +1,6 @@ +# codebuddy 适配器占位(Wave 0) +id: codebuddy +name: CodeBuddy Code +name_zh: CodeBuddy Code +vendor: 腾讯 +status: available diff --git a/adapters/tools/codex.yaml b/adapters/tools/codex.yaml new file mode 100644 index 0000000..4fddbe6 --- /dev/null +++ b/adapters/tools/codex.yaml @@ -0,0 +1,6 @@ +# codex 适配器占位(Wave 0) +id: codex +name: Codex CLI +name_zh: Codex CLI +vendor: OpenAI +status: available diff --git a/adapters/tools/copilot.yaml b/adapters/tools/copilot.yaml new file mode 100644 index 0000000..d25617d --- /dev/null +++ b/adapters/tools/copilot.yaml @@ -0,0 +1,6 @@ +# copilot 适配器占位(Wave 0) +id: copilot +name: Copilot CLI +name_zh: Copilot CLI +vendor: GitHub +status: available diff --git a/adapters/tools/crush.yaml b/adapters/tools/crush.yaml new file mode 100644 index 0000000..d3b7ed1 --- /dev/null +++ b/adapters/tools/crush.yaml @@ -0,0 +1,6 @@ +# crush 适配器占位(Wave 0) +id: crush +name: Crush +name_zh: Crush +vendor: Charm +status: available diff --git a/adapters/tools/cursor.yaml b/adapters/tools/cursor.yaml new file mode 100644 index 0000000..33fa755 --- /dev/null +++ b/adapters/tools/cursor.yaml @@ -0,0 +1,6 @@ +# cursor 适配器占位(Wave 0) +id: cursor +name: Cursor CLI +name_zh: Cursor CLI +vendor: Cursor +status: available diff --git a/adapters/tools/gemini.yaml b/adapters/tools/gemini.yaml new file mode 100644 index 0000000..5d8de6f --- /dev/null +++ b/adapters/tools/gemini.yaml @@ -0,0 +1,6 @@ +# gemini 适配器占位(Wave 0) +id: gemini +name: Gemini CLI +name_zh: Gemini CLI +vendor: Google +status: available diff --git a/adapters/tools/goose.yaml b/adapters/tools/goose.yaml new file mode 100644 index 0000000..7f7dd38 --- /dev/null +++ b/adapters/tools/goose.yaml @@ -0,0 +1,6 @@ +# goose 适配器占位(Wave 0) +id: goose +name: Goose +name_zh: Goose +vendor: Linux 基金会(AAIF) +status: available diff --git a/adapters/tools/kimi.yaml b/adapters/tools/kimi.yaml new file mode 100644 index 0000000..2afaed9 --- /dev/null +++ b/adapters/tools/kimi.yaml @@ -0,0 +1,6 @@ +# kimi 适配器占位(Wave 0) +id: kimi +name: Kimi CLI +name_zh: Kimi CLI +vendor: 月之暗面 +status: available diff --git a/adapters/tools/opencode.yaml b/adapters/tools/opencode.yaml new file mode 100644 index 0000000..120d647 --- /dev/null +++ b/adapters/tools/opencode.yaml @@ -0,0 +1,6 @@ +# opencode 适配器占位(Wave 0) +id: opencode +name: OpenCode +name_zh: OpenCode +vendor: opencode.ai +status: available diff --git a/adapters/tools/qwen.yaml b/adapters/tools/qwen.yaml new file mode 100644 index 0000000..87c73f6 --- /dev/null +++ b/adapters/tools/qwen.yaml @@ -0,0 +1,6 @@ +# qwen 适配器占位(Wave 0) +id: qwen +name: Qwen Code +name_zh: Qwen Code +vendor: 阿里巴巴 +status: available diff --git a/adapters/tools/warp.yaml b/adapters/tools/warp.yaml new file mode 100644 index 0000000..81d551b --- /dev/null +++ b/adapters/tools/warp.yaml @@ -0,0 +1,6 @@ +# warp 适配器占位(Wave 0) +id: warp +name: Warp Agent CLI +name_zh: Warp Agent CLI +vendor: Warp +status: available diff --git a/apps/desktop/index.html b/apps/desktop/index.html new file mode 100644 index 0000000..744cbb6 --- /dev/null +++ b/apps/desktop/index.html @@ -0,0 +1,12 @@ + + + + + + AgentDock + + +
+ + + diff --git a/apps/desktop/package-lock.json b/apps/desktop/package-lock.json new file mode 100644 index 0000000..64a0632 --- /dev/null +++ b/apps/desktop/package-lock.json @@ -0,0 +1,2137 @@ +{ + "name": "agentdock-desktop", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "agentdock-desktop", + "version": "0.1.0", + "dependencies": { + "@tauri-apps/api": "^2", + "lucide-react": "^0.525.0", + "react": "^19.1.0", + "react-dom": "^19.1.0" + }, + "devDependencies": { + "@tauri-apps/cli": "^2", + "@types/react": "^19.1.0", + "@types/react-dom": "^19.1.0", + "@vitejs/plugin-react": "^4.5.0", + "typescript": "^5.6.3", + "vite": "^6.3.5" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz", + "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.8", + "@babel/types": "^7.29.8", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz", + "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.8" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.29.7.tgz", + "integrity": "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.29.7.tgz", + "integrity": "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.8.tgz", + "integrity": "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.8", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.8", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.8", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@napi-rs/lzma-linux-x64-gnu": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@napi-rs/lzma-linux-x64-gnu/-/lzma-linux-x64-gnu-1.5.1.tgz", + "integrity": "sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^22.20 || ^24.12 || >=25" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.27", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", + "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.62.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.5.tgz", + "integrity": "sha512-jfkGfTwhQpsiSckPF8r9bU3pn3vyd72NlWaO+TgEO6WPSDnUhXzrNYCHBMOYj0ACaUgjm6eERLF+XV9a6RstoA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.62.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.5.tgz", + "integrity": "sha512-oGVqyQlxnrz9/ty89oHpU857VUHEl5/Xu4R2lS+aivCTrNnSsbiENzTnNaBsjxH0CNWGPhzHArOLFwo+oKXveA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.62.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.5.tgz", + "integrity": "sha512-bW7B8xMEq8n99Q3ieEcPRGuphurdZAaFzQc9Efyyw3FL6DZO6pMy9xhdN+kBoD7Sy05xNXSr4OyPPnpkYriS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.62.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.5.tgz", + "integrity": "sha512-YSwBS86QeHOGlrxJ1PSOIZSkzRL/JmKeunhc+lV6M1a6En8QuVCD/T/qIA0J4Gd2Y86RIOBYrLcOUtqGh9+/1w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.62.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.5.tgz", + "integrity": "sha512-2fST8lILgl7cKbme/1KDdPCmbXbG+gqoV3bHp19L0ypX/3akYMBVdOunPleRCwonoLnXOZ/0F+Mt/v8POFmfcQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.62.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.5.tgz", + "integrity": "sha512-cpIxQCP9J+EVad0a6LO1kY3ZGODlk80VlI+2I96B8xMcdHZ4pLVhfQ49JFpYqjPF91FFkQWftf57YlDcTiw9yQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.62.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.5.tgz", + "integrity": "sha512-r9fGh3eFs3e/udWh5ZjXQtxiYK/xoFxQaYR/cELxac/Udkl5Th+IsFm0CX3Kl9hmUH/we7EoMpjJgeQNnE0+IA==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.62.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.5.tgz", + "integrity": "sha512-xdvFdp7OM6KLJviJT2g/YuRSUjnZgGHk4RNgwIbN7X6cPugOucV60DdHXWzsBVCUdrGb6qSXnJQrrAKMmQuj3Q==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.62.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.5.tgz", + "integrity": "sha512-rRqILAndyzHzP7T9NFQrq+4HFWNhqkqkKur7eiBpfLmz01PO0JKx5Vchu3YllE4YXI/Ftgq/szrDWg5GJ0mI8g==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.62.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.5.tgz", + "integrity": "sha512-Gf4X3qVMucayUvux6aXXPgXovocSFUC0rrffDuPI/S2nHhNMhjcZxsrAFYCOF350PRreW1XwzFj3CT/3bKsWCw==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.62.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.5.tgz", + "integrity": "sha512-+s5qA0TNM0qm8PK/a5gt/1Hpx+NV08uSuCncvhziIlQzT6AEV2fnUQo7eBtFTFO0nA9scauvoR2HusfXmQnO4w==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.62.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.5.tgz", + "integrity": "sha512-ybb6QvWwWJCbBWqERpc8K3pYVGIrXlG8MEQ8IIuJY6Y9KdHQxoFoNyfkAOtKn1VHu3KuLidXvwrvGR1mEjeWCw==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.62.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.5.tgz", + "integrity": "sha512-nZb1DtnOyhCmYvsC8A2CwOkopVg+IS1+fPUa7rMOAXtNw5+lLCLLPqd6XAiNrGtoQKsbvIBOwsHnBH/3wnb4HQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.62.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.5.tgz", + "integrity": "sha512-yMbj63Sp89ryrXLWyz+sy+fYD2HpOnMCLGbe4Oa1smclFSUukdtD/BgdiHaAetJNb74URD8U4hM+qG5KVzMEkg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.62.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.5.tgz", + "integrity": "sha512-mhoan3OJw2kYV/e1jtIdmvUZgyBFeA6zGWsOswmR0Tg19TQbowZuR+JMLID6spbbBN7Zee2ejrgmy3+FxGrIdA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.62.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.5.tgz", + "integrity": "sha512-5ZTLmjWbb1VZdjuyhe83K/8QO0/h11midQCBP+X5OYn32ra7eOBoM0ZqtaY4nkgNsYgmdVhMYPoyVPTjUpHf3w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.62.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.5.tgz", + "integrity": "sha512-m53kG+br6PGxOTmgBEM2DHSDs9RVjsyEbUwjJPJGTFm1grWOG8EKJggDCTb60unD4Tjby8fi7/m9XfkEWasVWg==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.62.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.5.tgz", + "integrity": "sha512-6RHPJR1g/uvdYU8uXBnfq3nlqyZCP82Fr6NHgfGoaIeSh0YEqnX/x6uA9MmJJbnSH7swqX4F+CkGdUF+6doiQA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.62.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.5.tgz", + "integrity": "sha512-xs+OXQtEXgpXT0DmA5+U3qnRZHdCST/5HRQxS8wSPZTUZN/EMWeHuSIod32LQklTBZBV9DyfncKBQ8n5V3eFdw==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.62.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.5.tgz", + "integrity": "sha512-e7hD+sl3s+mcLQDZ8pbudBVsdG6r5yN4w3LqG2TJ8sQHDpblWj5lrJs/3m01Cvlxbt4x13zu5thLjgypgtkYzw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.62.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.5.tgz", + "integrity": "sha512-GiyJaCf+WpMub/17aPcKk27QMl5W6f+KhdPTjlFOn5akH5Wa/DCM9Stdx5cDfmasyKB08MqpVQ1uJE2RkkpbXg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.62.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.5.tgz", + "integrity": "sha512-+OQ8U2DdoEfXl8T4Fb18AjmEwbXMerKDKCL8yCPAYhKCEEKoul7rkbeGCBFCbAlaGaa7pmtRTpkAJM2LE/i5FA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.62.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.5.tgz", + "integrity": "sha512-KanvAZrPKbDBFwrgiU9yEVpQoox9QPV1WZOXX7HudJQY+eSlu82CtWxDU8WtuRRvtN5EGkLczkd6Y6DTcvm9wA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.62.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.5.tgz", + "integrity": "sha512-1aC3UEWTtRl3RK3VpDJ/Tqk1XI4SLTmXIthAq6wRWo8XiSXJNd+VprJM4/1P4+i6HIaFEFlVi9sTTziniD2tOQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.62.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.5.tgz", + "integrity": "sha512-/gDJaRs4gl0NPIwqCz+6PkpmhhjRAD2j6P4rSNHBzUkO3naEx2mIU0pRle1vUNRQ7mE/+8OOeXLTv/J56FKiQg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@tauri-apps/api": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.11.1.tgz", + "integrity": "sha512-M2FPuYND2m+wh5hfW9ZpSdxMPdEJovPBWwoHJmwUpysTYNHaOkVFN419m/K0LIgjb/7KU2vBgsUepJWugQCvAA==", + "license": "Apache-2.0 OR MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/tauri" + } + }, + "node_modules/@tauri-apps/cli": { + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.11.4.tgz", + "integrity": "sha512-R8xGtMpwyetawSqm9kYOuMmEqkhUbvcUy8n0aNXIxollKBLESUu5f4Fx+64hgASYm1H+jSWq6jCW6zqTnH6hqQ==", + "dev": true, + "license": "Apache-2.0 OR MIT", + "bin": { + "tauri": "tauri.js" + }, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/tauri" + }, + "optionalDependencies": { + "@tauri-apps/cli-darwin-arm64": "2.11.4", + "@tauri-apps/cli-darwin-x64": "2.11.4", + "@tauri-apps/cli-linux-arm-gnueabihf": "2.11.4", + "@tauri-apps/cli-linux-arm64-gnu": "2.11.4", + "@tauri-apps/cli-linux-arm64-musl": "2.11.4", + "@tauri-apps/cli-linux-riscv64-gnu": "2.11.4", + "@tauri-apps/cli-linux-x64-gnu": "2.11.4", + "@tauri-apps/cli-linux-x64-musl": "2.11.4", + "@tauri-apps/cli-win32-arm64-msvc": "2.11.4", + "@tauri-apps/cli-win32-ia32-msvc": "2.11.4", + "@tauri-apps/cli-win32-x64-msvc": "2.11.4" + } + }, + "node_modules/@tauri-apps/cli-darwin-arm64": { + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.11.4.tgz", + "integrity": "sha512-1ryOF3ZhpZ/nemHV5zVwBQBz9jDGKmKPvWPADOhc83ig0P4bMc2iER4NbC6r9sjeIZ6RVQ4g3RZIYvezhcl4TQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-darwin-x64": { + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.11.4.tgz", + "integrity": "sha512-uFsGQAAfuyz1k/yGLmkWfkBlgKAqZfxqlHmLWx81QU27RJWfmbNHCIq8T8w1e+VClleIuZUjpHWfoE4E3DLo3A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": { + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.11.4.tgz", + "integrity": "sha512-IaHZn5CdBL21oUmjiVOS1ctw6Ip1O0pjp70FwOWmYz1myWe0SY96ZIj2FYf7pT0m8bI2h/hrs5ZbEXXh44/MkQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-linux-arm64-gnu": { + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.11.4.tgz", + "integrity": "sha512-N41/ukTRVe6XSuUTESuFdGeOW2i7k62tK+6gHK5Kd5/q5RPvvi19GaWAVPPb9u95HSGmTChSolBfzynUsssFaA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-linux-arm64-musl": { + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.11.4.tgz", + "integrity": "sha512-v277UnT/fB64xAfSroL5N3Km3tLmvATWqJJw/wRI+g6o+HkeD0slyE7gOhNs1MbjE41R7bQOTxMVoL3aomUJmw==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-linux-riscv64-gnu": { + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-riscv64-gnu/-/cli-linux-riscv64-gnu-2.11.4.tgz", + "integrity": "sha512-qqgNkQ2u1yZHxjhxsZaxUtRDW8dIqIYm33rx/mzwQv0SfY9x1B+iraj8vWeFiXjjSVVhEMepXSOts1TqPzvXNQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-linux-x64-gnu": { + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.11.4.tgz", + "integrity": "sha512-2VRNWl84FOH0m2giiDkO2h0QXlcMJeX+zJDpI5kDIQAx6s+geF3v48F4DXfJez4GS/FdoDGnPnw1C2iYGbQ7bQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-linux-x64-musl": { + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.11.4.tgz", + "integrity": "sha512-o9GyhYor/nc7xarmwDE3ka2szuW3uuZzXjHWh64Q8YX5AtSgxdQkFWzrY4O8KiGtVNvFBI14H3Q49Qj5TOIP/A==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-win32-arm64-msvc": { + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.11.4.tgz", + "integrity": "sha512-ld5Ehb598m0VkYyylRPNeCFsBe/km0jxis6KgMpl3IGY6I/i1RwQXO05I1AsXUXO2WC6AvB/Lw4qTf/asiuEiQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-win32-ia32-msvc": { + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.11.4.tgz", + "integrity": "sha512-12Hxi0XX/H5VFxO/bGgHkFWhml9VMgEOu9CidjeCeTNQ1l6fpUlbiGgSP7CLI3PFtW9/FfbeHieZ+kyWK5H7CA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-win32-x64-msvc": { + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.11.4.tgz", + "integrity": "sha512-+vDiqBIU5dMISg/wNvX3sF+ZHfgJGJ5T0AcO+EHNXV9GGAG+P5fzodlDXD3QdKCRgZxMoCm5PPvj3BqLNjBthw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "19.2.18", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.18.tgz", + "integrity": "sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.5", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.5.tgz", + "integrity": "sha512-fMPwH9v7r/pp43yUd2/Mbiex5KouJwwR3dzHkhLREUC6764VyDsqxhAxv6OFEYR1RhjOyD1naqba8ECDBe7ZQg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", + "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.28.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.27", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.11.19", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.19.tgz", + "integrity": "sha512-Grytf1xOxOEMTGRwx6rLGKkTabd4vMg3VrKdj/7joCmV0qgh4QwMMO6xh34YEXQqirAuUdgQGa5orJQQ+69RBw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/browserslist": { + "version": "4.28.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.8.tgz", + "integrity": "sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.11.12", + "caniuse-lite": "^1.0.30001809", + "electron-to-chromium": "^1.5.402", + "node-releases": "^2.0.53", + "update-browserslist-db": "^1.3.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001809", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001809.tgz", + "integrity": "sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.413", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.413.tgz", + "integrity": "sha512-F1XPKvt7HVfly5WND90ec16nFsdr4g5x/cVUP3EqjeyXynupabGDqpMa84wwvuYGDnldXLBz6DLXyZXWO9TPvw==", + "dev": true, + "license": "ISC" + }, + "node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lucide-react": { + "version": "0.525.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.525.0.tgz", + "integrity": "sha512-Tm1txJ2OkymCGkvwoHt33Y2JpN5xucVq1slHcgE6Lk0WjDfjgKWor5CdVER8U6DvcfMwh4M8XxmpTiyzfmfDYQ==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.53", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.53.tgz", + "integrity": "sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.17", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/react": { + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.8.tgz", + "integrity": "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.8.tgz", + "integrity": "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.8" + } + }, + "node_modules/react-refresh": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "4.62.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.5.tgz", + "integrity": "sha512-/tqMfgP7GPA3PHhCmuiS4vIjrSVhHLgY++i+dhbG462euyAj7FpM4D9uq1X3BgjlqRdpcOrYhcQtfiQLNc8tqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@napi-rs/lzma-linux-x64-gnu": "1.5.1", + "@rollup/rollup-android-arm-eabi": "4.62.5", + "@rollup/rollup-android-arm64": "4.62.5", + "@rollup/rollup-darwin-arm64": "4.62.5", + "@rollup/rollup-darwin-x64": "4.62.5", + "@rollup/rollup-freebsd-arm64": "4.62.5", + "@rollup/rollup-freebsd-x64": "4.62.5", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.5", + "@rollup/rollup-linux-arm-musleabihf": "4.62.5", + "@rollup/rollup-linux-arm64-gnu": "4.62.5", + "@rollup/rollup-linux-arm64-musl": "4.62.5", + "@rollup/rollup-linux-loong64-gnu": "4.62.5", + "@rollup/rollup-linux-loong64-musl": "4.62.5", + "@rollup/rollup-linux-ppc64-gnu": "4.62.5", + "@rollup/rollup-linux-ppc64-musl": "4.62.5", + "@rollup/rollup-linux-riscv64-gnu": "4.62.5", + "@rollup/rollup-linux-riscv64-musl": "4.62.5", + "@rollup/rollup-linux-s390x-gnu": "4.62.5", + "@rollup/rollup-linux-x64-gnu": "4.62.5", + "@rollup/rollup-linux-x64-musl": "4.62.5", + "@rollup/rollup-openbsd-x64": "4.62.5", + "@rollup/rollup-openharmony-arm64": "4.62.5", + "@rollup/rollup-win32-arm64-msvc": "4.62.5", + "@rollup/rollup-win32-ia32-msvc": "4.62.5", + "@rollup/rollup-win32-x64-gnu": "4.62.5", + "@rollup/rollup-win32-x64-msvc": "4.62.5", + "fsevents": "~2.3.2" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.1.tgz", + "integrity": "sha512-ZZ61DsRsOnakl74HAmp3oSN4aXUmEWXf+i/yv0h7tIBfICc3VdrFErQKUUKPgu3AMsTUMbcongALEN4l6GSUrQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/vite": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.3.tgz", + "integrity": "sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + } + } +} diff --git a/apps/desktop/package.json b/apps/desktop/package.json new file mode 100644 index 0000000..3f2c16b --- /dev/null +++ b/apps/desktop/package.json @@ -0,0 +1,26 @@ +{ + "name": "agentdock-desktop", + "private": true, + "version": "0.1.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "preview": "vite preview", + "tauri": "tauri" + }, + "dependencies": { + "@tauri-apps/api": "^2", + "lucide-react": "^0.525.0", + "react": "^19.1.0", + "react-dom": "^19.1.0" + }, + "devDependencies": { + "@tauri-apps/cli": "^2", + "@types/react": "^19.1.0", + "@types/react-dom": "^19.1.0", + "@vitejs/plugin-react": "^4.5.0", + "typescript": "^5.6.3", + "vite": "^6.3.5" + } +} diff --git a/apps/desktop/src-tauri/Cargo.toml b/apps/desktop/src-tauri/Cargo.toml new file mode 100644 index 0000000..d48e290 --- /dev/null +++ b/apps/desktop/src-tauri/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "agentdock-desktop" +version.workspace = true +edition.workspace = true +license.workspace = true +description = "AgentDock 桌面壳(Tauri 2)" + +[lib] +name = "agentdock_desktop_lib" +crate-type = ["staticlib", "cdylib", "rlib"] + +[build-dependencies] +tauri-build = { version = "2", features = [] } + +[dependencies] +tauri = { version = "2", features = [] } +serde = { version = "1", features = ["derive"] } +serde_json = "1" +agentdock-platform = { path = "../../../crates/agentdock-platform" } +agentdock-adapter = { path = "../../../crates/agentdock-adapter" } +agentdock-store = { path = "../../../crates/agentdock-store" } diff --git a/apps/desktop/src-tauri/build.rs b/apps/desktop/src-tauri/build.rs new file mode 100644 index 0000000..d860e1e --- /dev/null +++ b/apps/desktop/src-tauri/build.rs @@ -0,0 +1,3 @@ +fn main() { + tauri_build::build() +} diff --git a/apps/desktop/src-tauri/capabilities/default.json b/apps/desktop/src-tauri/capabilities/default.json new file mode 100644 index 0000000..b1f62ef --- /dev/null +++ b/apps/desktop/src-tauri/capabilities/default.json @@ -0,0 +1,7 @@ +{ + "$schema": "../gen/schemas/desktop-schema.json", + "identifier": "default", + "description": "默认能力:主窗口(Wave 0 仅调用自有 invoke 命令)", + "windows": ["main"], + "permissions": ["core:default"] +} diff --git a/apps/desktop/src-tauri/icon-source.png b/apps/desktop/src-tauri/icon-source.png new file mode 100644 index 0000000000000000000000000000000000000000..c0354994f19a77a2e3752ecc8327afb05602cf22 GIT binary patch literal 8452 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 O)X!cpYu`-63;zSQFA_}v literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/128x128.png b/apps/desktop/src-tauri/icons/128x128.png new file mode 100644 index 0000000000000000000000000000000000000000..4b8387589b149e1f02921da9d151df70fc3f779a GIT binary patch literal 4126 zcmbW))kD({z%}sif|M8`4H9A?F%Xb$WR%qCngazDkp^i-gGz&lbT>$ffV7mfATb%C zbW9}2#`Alx-s|VNIOklPzu*&V_(+SEnu8hu09tK?hVg$J`u{>n{$KYhJstr7`rq0b zsz|?uJzJ_oWIsFU%W{_IdGjJoag1e=IArg=k_j zy8CG)fEaRh6>^1d)1Q#Y>z~oh1LbK#RN~1)S!e+f4!}whXmkdgCxMBA|JC7WN7*Gz zZ9HfSy@kGig);xP`-rxVGf* z_1>mklZ2;(X*MEOPKV$T8mX{kCYAx&QZB!He3t-DN<1&u1HD&+ZP;rVd!a~H+c7l- zAjHa+E&G~M^9yg~4u_8Naf$Zzb8D3w0TDhnUNx#2rLA|zLfz%VSU+dEk)(eI?sXHb zTYQ!__z`5SuZ+5gF^-3t8=N*bF0-gZ zb$K!I>$@1&>v0Gtz;v4&ML2Psj7=F)16iojtWmpLezYumU56L(u1N_zo_bC9EV~p> z#k(IC8^AjQ%L4|g=4i8)-QdmMUm=((53XdQ-`7bVIgh_ykIwE#kn70m$~nfek#t&H zk&^i(LoY|vkTxa_uSTYYZpxsBFl_T?q(mbp+xS_duo{V;%xsO^XBf`iAVDEvO4iVj z%o(_oMqEOR)wWW|HxP)13!rSd>gP;1R1yrkJ%PO@^pZZYhuPF7O1ziyQ35k91loOz zoenMjCj^M$#J0~fy56YnRNJy;(W7CL;g_Y|U{N=Ki&*_@vKWaz2u`Gh!44+r^1bzNR9f`v@bLb4@5fDQ*V~$Ltf3$=XaiV2HXrx#6GO_Mau-zGmO7x9 z_>6A$;h&MgUe&L1$;uE75Iat^$?Vtln3#3ZDUK!hgn5z2hL@j9%9x#th8K>dzB2PwaWE9c-4WZiUzfxm$bD*ZazJ$7at^2s{=_f6VIGiU76l?ma(UZsLT! zfEK2bG}Uk^nJU7s*=`2t*S4>O*;FU3vZ@mxx~OCaz2ca+ybLhL}j87`&%aQLKKThBfJbXeyWpVEO9V)VUW zh}K#02H&TrO&(cfWI+1w1mjSf8)Jd2V1L`!D&__poP6&6HqOC^qIKUA$OC%Vob4{J zm4)n%qjJ3%6BjtHGa{7JrTPvEW=@YRB?Af@6q&tF6*x@O?GtjdCa2b%d4I6n99M*F zODj;s&U>2r)g{wC*mOX^)&e%&5$&3HBN>;I&9|{3>wZ#GgmJ&reVe9YT?|nr z%S#lrBR4=wWiW&yxLcCz#Wwazb9*N&EhF6fuMCwCV}kszt}pwEA%Nl5Bc+MdxYPQg z1U9gh6|YS_L*5`?P%}1(3U>&fnV*neQ!86M<8Rc@qAMyfljK<+=b84Wc57-@8!>nl z-L_#L)pmT{@T)(>!eO9bE;imOiUJF~x^d@-H-jUrlEopZXRQQHbP^JZI_C1zNNP8v z1j{RRS>%SU%Q`_K@ZXry!Qnd$aLL0@suTY6f?aXZDyWeF%8yTRNiooHH8t}Z8zNn| zl$BT;^urCSP+oOK^h1Ij_{N`mUBam*yhwNw`aXcTk%omQ9^-C z4e70jUqABA)mf)Vd2q>xFhy5|p8{H-XZkXMye2m%68HdPEXS60n#&;yuDk&1_k5~$ zX2ex4mN(4VdNWLwo+fO)J|dfvCsyre}j+YoRx%Wn8e3-|iQHt@_2 zu@HfItt}ogR~@!$nW38ZH%Jo}`PZ_|3%_V+k7sPmPS`@fY`S>xQ0JXN8($GSJ!oko zttE=InYH=a`}r!aJHlr*q3V6 zs0SGTc042qIL-uXAi6&0Mhd`!9c7uncW}MQ#umq$s}e6ZcwaAUAz&}yY7FPYQKtv% z6fyLmu7v;)yN%q+Sbtw8g07eNrSXav9qBO6@ONw?Zn8$`Nc_8#&RVqc+C z6N#Nl!wuWzK{(LTY=!y$ceA+PPoBV*{;{Om_=BKxoluw@I#lBj40<#ZuroR@6UUHt z44EK6pXSk_94o6A?EBO8SYKY+P@nkI{j7Hp7oL*#=9nQK(>iAbuz!%z^x-3874Vqsbd zO-WJ{EA{@l;QJdc8QfYpEW6-14px!%{R{>OPmjw|Rlagfzf!+Um*)*$14M-mWOL%Qq(8h}4*d#i*t zDd<7jPD)#E>rS7$jA$oU@_kV?a{5n4b3@ya7+tsm@;2`$H}ME*g|~uhcMeyLE#cc< zBG|1oCVenL4}8JA-pcQ>Srhp;g*BMMYTugL#Zi_~@piUulRv(533~MXC5-q3iwbPl z9b*_Y#7W2c(VJY(Fv92f@*XtdQf-Y0D*x(`_i~tEaj!b|pQnBLQNrgRdG?u>*JJsB zxBYqKKaQ#2zUNS*;dXSJD#L0&GUimYOPyYYARR8e(2V$3rJa)hWJvw}ueV!>gHf+7 zEKiJR-#^zy7F=<$kc)-cDU}zc&~Tp^;v!=FZd$G=pNG+WEc|Rr{)eN12}eQn7I!yj60=kD%`c?%QjQ5y zgeKK$O=~uD$d{ zY|;9abSs1BtYv;x_n?rmKt4QL@@K8U_(D(UUiJ`KSXSWQQvNzDR>>OQ z?cR8x=61X$;kgz*LI??`%o!>f2dW@2*Xa`-j+JjYFOYa!sU0#^6Ys$NLfMX!Ea#(K3SKwh!eLAd8*qqC z&!@Qj267|lhPz$8{qeNxTG@BWAV{cAO_cY~(lNSv|BMOOiqOFq=wKbl=MMw?Uu4%} zJAETAh5Nds7#I8Z^`v-~UG&T(9Y?iVA;aaHD{RgNi8b7Jo8xP#;htXl-$OWqK3TWI zPHDJE%?AOs+Z}S;S^hyfcY6h9u;0U*el1oyHY?oB zK768cF5&30oWo^hp|mZf^Y+?dXFsx}+(B9MWZXv@d3BI#*C>AEB4n|@?6};;wp^V$ zPT}#eEBkwj#{N|=v%%I}p@U|wXPjjSyg3)%8U>@a#0rQIE?OqesP<{(zT*Fb#=D)C zpy0qjJxrcd=UT5y(a#(Om$Qf29Gb5Z63lrMYig^D z_p?=sC`bARBE6L$oNU}LOj(x-|di>hr6Ta`chMW`Lceye>fhahzcKA_?cqC%9ck z^_!XW!aWDr-I6)=1u+S4+++v5fo1Xb3N|a!7y$K^eVdImaN00l$QscYajOwq9uN0C z=pF0#*HVJNd?1j=?KENfXS3L+O(}y0Mx}`~DIzt9@TWs)(yItc5d^6r5CjB7s#NI+(t9tVihwi$ z=@>w&v_v7)1YXX$-|m-tzr7#k?Cv>xc4u~GcAoQ0G+a-ehKijE000_I4OK$`09{W( z00r6gVC7Zf1OQw;nyQbD{TKGLsr{`?8V6>TwnlWgb@_EwBG@4o$?rXf8ympE>;aU) zHpb!Lh<|W+kd5g3!9HzJXhD?NP5QDXmIOnp?;GuTOJEah5uA!N|3@$%uf@wEcT9$( z)0pf<75XH@@l(9gW}@Tf$W`%^j~Ru!V_C#y*XpYUS9u6fV#a9&2B6m(QCtfc08rNh z^jiKmme=p2e0??jwLq@r|Fy)1ck>NWMr#8g!Fo`qGJJQ61%E zXjNd9?uvawv{-%!ZgZi6H7`Xf+dUNub(NW&l-VpZ*?D(#^5%(t_5?;;+-yyAx!)(G znA%0QuIk}S12LLcn2tct_}Q+;>32|N;2Q_`Q6&pqpv=Y4x3I0BmM;-<=3c4LTG(=I zB<1bQv!? z8RGLrz2$|49f$);gBmRU^meJkI@zN0`NROOBZP6ektdOtmNoSSOVAZnXPIH#r-V~) zB4^bpx3sb~jF#ND)8I@KsaZ6Bb#i{15la}d_203*#idofRQKH7Az2v_MFj=atYU16 zpAhb0i8!f0=UaaxovDWd#b8I>sX@;^F^DQ67o#U;XO?DKau8fpg9hV+D-sr3T*=T9 zy6LG-Eb-&UDue!H!I+FGtl8VR#=DRV3Is%)8-3wIDlEID{fiVZfBMycB!}l5=2WwL zk9yWyf%NS_XXkNmoymI9XOcgatIex%?(XA+z*A<46O1;01Nve4&IZd79(Sg3}49 zU|-AXHaf|1b-GjMS*xW=@4sGt65gn+MnO<2lEEEPH#b(=6m&VvR8Uk}?>d+RpgCfN zzQXR5kl)USdEL@N@ABv7Tjkr?x0$Fm)W?K#?PHkJ5R&*AE|ryMz3kb=d$XFuRX)1wM9|mmHq~HJ9kYt z(cQ7Nv0B8vO5DC2n6fg0`bgD0kBQfg$jqqg?R%p=Y%o1kV$~abWR?B%@cE}|IE1w% ziv*0e@-|jp2{_R16xj0dRk*O&REz|Sf!nA@XVb{D_586!btjW z>FY6S1#X>iFc_|Be>E(Y+2bLr9pFSShj3#=LXQlp%WmV4!_nMET+1G|ETQVL@-;Rp zfRO#>R!`SBs6Kwh=kl2o?!v|n8~WY+oa*_$g|DNYNl;g1*f0HxQdPga-dBNo=WYSt zOekTPhWh^^iEM-&tUu{&I=^#C?S>y+3FmQB zTFI1nWi2D_YB})9C&gIU`0+#2@=NQF46WgPowpu0@r3c(4zXLYU_)&84`M*-Z#h>6~5n591uxdTgj=dg-{r5d$?Q#(6!dEn~*)C zxbVb=Wv7x@-L*Sg&#C$BKKfnDjLM8z{9<=Gk^HK% zTZk1PwC2Rkb+s?eQAco1rpoOMCsR8u-M-FO1s9bt^31P6!l3Vu z2p&qF#~&3gc!oQxV;p#D29P9QuFU)__~~~3_?ODF2{3A-{_U=A$)KH&|8`W#&+Kgt ztdJuf-1{dA&k<+md~d^k9By~&4X{|dEc~^fpgXnzb57euwVF-GLVo2#ynyF?Zo9;L z7d*1Du=59z-cR{FPJuJwSY(NO zIAA<+!1IazjbJ#Ogh7w2Y;kL9K9LWSSJ)Tg9mSjWCfhNvUt1~!5`bm>Sp^-^PdDin zS_iapR&;+iE~+2dOMqQN5<=_~GGOZ?ZKd^@Z*jKDfEI#?Ef13m*yiCjlbz8RmQlbB z{>eWl^%Q@p8`t0Qq&_X39+l)6`qcUUzW!EpR|d6QVf2cp*jgg?Nd&;s9Lpg2f3~c@ zysv>7nY2cS(E}(Iz1zlDwUE&V+9UTE!SJ$?9T~omx5opMJU7J{N<7MleW$w-8c1V8bf%EK0>Cb=K7rZPJ_CMU*2(w?{yjjQB{SRvQ*(rK51kOvEuvz7@ z%~$px1kUYmPW=dYZy+{25Pzcm6O=6FEs0+gJ+OdV74npp`rQWjDyPaKm`*?m1!{hN zRL39^xM#6=0hz4S9AlHBRDL<6B69)Ly?e#-5+g+c2!1ng;Kov}FsW6h?rAW|q7022 zG`_C|)4tMNf7v?SL96133v*ODu2sw@WC5jAVb;7L?ckzsYcTK0v}C4wCUcrMK4YqP zdIS=A&pK9DDBc>s7i76>ZuCsGTiA$#Qrj&n68NA=Itw9u?hzIXY#SnWuS&hydAW|p z(i6+juSrZ4JKkoQ+VGppM+^2w{_q!kDjbuksYRh2&_sIcDm+nxuk@;nR7&cKv%n%) zl!9}rvi`*j%)D_U0aQkupwl?QCso8B?uv_u6Yo-*UCuqU>_`3#nP-+d!YZ6vKh4wQ zULtk|l*FIK=f{lY9Tc4y1#WgF&DB2hAG$8~d2ZE(7Ke1{H6fQl1kr3*`~pfyWgGIIR0Q=e;mvXLhE#ZjyJ%xA88=D1zx37kZ6bvLm8tBlx} z9JQDs`4weG>ukCAKL%L9*XV$kIy|-G* znpSnoY}(Sxf}7tKmbnfJy928)YA6%_m<4Gy^6hJ%qGoqily0u^0TS$Ycd;RB*=w=u z+%i*UA*~0Rh9rX7d5bfyGs7W8U3#?`2-eS4}tOdFdB8bN)#y}g#&yp43CCVc-;j)Fx1OFm@DE7Ls~9GE9J%Ie56MiG6QvD ztNP^wior%CAJw4e#l@O(uf5{sdI^X3WMpz-OnN8YQn&+tt(-u)@hZZ}Y$+(5bF zJ1^J3=c@en%y*kPrQ|So-EtDv|BfGRKc~CmM7p^KABoq=U1}z7&C-_|Zo$<+NtxQ_ zWvy=85NL-eDm_o9whU7B-eBL475*!N^-!)evSi|c>zNgKL=&~5;uNjTG2f1LLwE;C zigin$<7x!k;&T5pP+9rs+q4&@VuL0hSS0YRfjPFOw#A(`NZZr8E3d-w8@DN=zV06s z0F9jK3K<3ZikdXuFtv%uD~+35j~!x`T(3kBUq#)rb$`(*^~%2UCTSO!_N7!YnUhL~ zp49Y>ezJ`qw!e4yc}QqGm&4ux)o@2YUV^#!(nObg#ODTJOfC}1Xm0Ne9Qj2kcV63Y%O zwP=cSRT51){(D75R)O6(=%ZVV;3+=Xh_B)DBe2a!^q|HY{d#b-eUvBw_*h{y0gTW1 zBIKuS-*B5;t>{UX&&;)2B0lf+cD7>+FF9V#SjMDSn{^N&Z&$Lf)1%gNYT=tv{3o8^ z_}|XCn#ZmlIN8m(3~BG|m($An=YjfmnvrTMng1~-kP@2#C*5mTjGozFYkabDTsQ_+vO zXg>JS1eu)xc49z&V7=J{s&012=MSzB8@Xi;>(q{uabx8!WJ>}~PMi$|*v&uWmnIQn zXKSJsb87c|%&_0PJ10u$kFtKTWyiXCA8a3+&IbX0JerF*sk8R~R7ahAKhFAeK7RLw z@?u1G>s-X0uA*cVH2~^nhn}1o27WnedM&XS;cgtV+UmxNF;HmtoDlQ1XZ@~d)vVQW znbJ` zztBfgst={feOIl@+7RZi_j;eqixT#|4%Gbnxj!Wq&`14X;rszvj0m=4oeAFZDr?`4 z>2IVCX?^3|PCu%VNTN)Z_w{K`*@txU;_(UP_0p7^FyiuiSJo>3WU_JD_$WVCEsS-^ zrO2VjFjx|hcw-K*f&r}_(X1o97|XP%PL1_k$fEVxe8k+foyt!VUI&)^$1xFgAWh%y zN7=7`!7HoQK#kxIN}l{KYD}a4c9Xx=?>I5MX@wrB0Daq8J!^XppT05Y(W!~g&DEc7 zUb5kAuZiC8wf&_Q?buO8c66^zS& zwFZL#WA1ip*Xm0anY%==05u}kI^C5Q3U;<hA~qgyls$L{2f^RIOMLrS)A1>F3FR?*SWC;La@Uj9|SIsI0-gA{~v$_Ebx z@>C5nf^5K12clZJo)Y-wp!-8CHY{(>T4f*x3}Jl(13-rMv#}TqwlGpA9E z6~IRmoH2f|))z1x*VSPWRt_$3QNQ9cft}Hu+%dZ@(~O;w24E1>ZB;bG-1bGa%|0dE z{2WxZ;2odax6$EvOtvm}YBE^uglxLezl?Y>nX+6s_#L*R^+b#Ra2(_$1Oh?qR346p z8-RW;WRVvMjcMk1gJ`UfmGd{g%3tW5*viL0btEYIJj99LS}4&MLa|;DrPTS z2J)+*4Q^I`s=!A1w7mvsd-*X9p&O%}?Jq&IbVQPLAyb3iisc;5rtW;Ht~W|6dvz#0 zZFQBq?&hBzB)xl>pQD235wydUqx2T&0f^h$k$j0N4|Y5ak566+&CLo)Emiv?44sgP z?h+e~?!;bYm3ds`j|rSEkwfca=t-`#qXe?2NITVt_FIn>eBF04lqsD(dww}Mh7Qu( z+sJ-ECk*PW-?@r|lx5 zpxG1)T|x@vJ2a3Epdlb-7CSLkLTc0L&s8qWZON8<12pS7xZ4GUh zPo}6CQwg(R%V{}8&vp44u{e$a$WSl+|3?Nj{K6B;JVAaY^ooS=xLwN*OKIhRjCpB&X2k1wL0od`d?6+B(no?d@h0{L7~ zdi$bUED@a_yH8rXd;EJRAlMq2eIAHMwi7G>P~H!2`WH@m52Q4rNo5SKe%mIxy%Imp zVLxrnX(@N|^}*y;?xAxHer=82X-CI$1nWIS92dznb;S!A{&xCY%jb7kch~Ig2kyBY zZ@fZRRi~beK;wP__sF&i0H>&FuUVcXfxhmSPA0@3MxQH8Wlas$%NEz2%y<;EN$PJ1 zU&Z!0gW@dJa-HLN;}sh|6!^iE8*IOFN+oHkmcgdC2pxge$X}jM7*L$u;U1((YwZ!H z^FasplJ^2Iq~}3somtGaJ4)(KUbPy;ykDMkBTE$%$P;^<>{8YGb}!AQaQ%!mF@(ZH z*LUR8av+f==Zw|BtzY7wWHE*P867D71!)3P?eW%!kevp}Ys}SfcffI35K+DP-s8g@ z!UxY}Iv^ICFl5Gzy>F&6q0Y^Z#bxjcydGG&R6=i>f{Q*Ts%l(5283?Bh%IV@1|ETZS2Cq9CmyJ&I`)DE&t$t~qC0%}|Zz~qy=rf8tyrw^?YEH_!d`9OM z5fR+VWx;z3n*6_qR7Kbb^r-jC)Oo4re|RnJs}m7RZj$1@tfYGl2oGr!TffFj8`%Ia z=ncLsjq<@h6<#;x4s%5M=ou$^`~AhW4GUC@(}Dg12<*d8Z+bGWqxW>|DF;B0VpL}y z`#G~yXy!KLfb7KJ?8fH;GZK_)PWZF`-YRR`_^&>WTOUCOtOMViVk^d`%G=K5h%f&U zsH50Nl#sgN_@;Q02-_vrJqSzeu>UjAnp(ozY;^T0A2oO{mM-A!qwRrL+Z2KRS+vW(y9Q4i8l zhznj5wXh~*rqeHfN2+G=F3)r}w+79e)A85;`-g_Ms+ocYS88+i=*RRq35HtB@2KIw ze;Q$-UDk?^*?|mcc=GEzKAH{Np+Itz)?%iN2lu)LB8=_TOA_V$6Xs=uN$eZL%Xd0% z23*HpOsdWnCgkp4UGR1AuZE6H(Lvr}lMkp+uw|e&xyY3HHYF6}jTo zgD8|Wr@ntirtD<=efvB*-Wx-98xXu{OJRQ)+mK&gUMXPq@PZySNjuy0yOUH+R0tve zL7gX3n6gDk18gx~@63_)9i$veWw+3#D8u;Nff8P~`suQI-(&sn@<8;W+$5POBPb6w z%2h`9S#0*XzQnb|4#*d}e5RV(?vZ<}8^E*~A;3*z5j=H-?E^P8);o_>V8pA5~ zZFRQ!4dSV(GyyLf0KI^p;RvDQXXF9HX#)W5iW~ePBbU&t%50U{WTh0v)@#2(>BNWF z&F&$uatUM$B^2N@?){3Sp`gPGinViC1-RS8u)O~Ha4IAO7d6iWt^Lcr&U9&+ML-l` z_jSv|wiGCoZ;6nE^RZ-DK<7fCTLE89n`3W!y{5mE-_AA({=GT7FG-Xgu5S##h(3B`+$vub=!ZcyX%Z`=+lv#Ox83kpDPE$ek&49@HqU%K; zp_Ri^VAXm&^iBm)g!%sa`=cv#CwuzLNz7Y4O81j=I?m%?xQEpUUp(tz^fYI7D*@Ov zSv1pJzj1cTOz5m_e@3MRDo{tmD`hwUuRTyjXBnwpGE=rTXO)!c7-CxPAH2U#fBnQ;iprD~$4 zKDtpd*fXA*%eC5bRetI2Zc8&mWM*c5YWK2&G4!cGidpkR!zp@ahDYyoGHNJjv0*IX z9ld`3ILkmBY#{9FCVR^Lw?OzOT0FmHsp{<7#Lj7F*3B%YWU6OJrr}iEA7FIB*j9`C zua~;JmF3u|nbVlcjz%BcN!bpTGGtzMp}e@6Lj8NOPpwrv;?d%`N8QFFg;Uu*4;Y^- z&U8KXH3y6Md}+^tG$&=l-{M@Bw$Lb@avM)Ju~n_((v#$mU8z_EY-bsBIbHDpUQ4_q z93J+KYo!fal!J5r`w8bEq;SKDT8fcUf3Uhz5wqeQd=+=>0XgY3`Gb9+Vm-Rhz!>_q zDb9zum`S^NCx6jICOz>5@YKH5>CD7I#%R^K-7C=6`PK?x%jo)!P%j2uCIQ(Rzt);4O{FYK_`eLHu(8s51-PeX;D>>BNT|YjYz-2ab8$2k& z9yLJs0>{;s4C_coulZ$glLYhE^1jWap7kR1FUTB=r1?*XLoTDQt?fh1Lkh9R*$(D%u_iN-7suaIgVQ}WPl*7}w&RRs{p5~EZ}{(H z($A3_OJxeVK@mJLinp=U3;xf^I^!F!k7`lr{wdAnPqFOl#xW^yI-U_EsmEfTc8%}q z?~e;c33`s6DBvn5$lIa}w%XG(Y`A9mav7B>w|Do&_}rTf@F~&enN5kv`K#FSkp3DtQk(d2W7MKbQ>oF$m9LgH3cu-o&u59LV5ySs zws_Ng2=f?a`nh)fqwn(jBrR-~{i>>J%K4@0#3;={kBaV$OO=%mK0Os&O6adPXE2{- zQ@S>{qDrKR)9Aoi;eh`h1@yY%sG_W|a82p`@3b8MuX{n=eE(r S@aeVwfTo(BYL$xJ+y4PwK3f<7 literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/32x32.png b/apps/desktop/src-tauri/icons/32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..33942d67140b557fbcc2354a81e16de35ca9c487 GIT binary patch literal 1041 zcmV+s1n&EZP)S1JXIAay`+CA6go-E>o2 ziHky^2%_LvEY>bW#O-J)7COl^>HNIr=iPHW@4lBdlTI>kQbCm7;gUNy_n!Nm@BGHc zzdZa$0RAfg2sms|UZPB=7akMfE7p}{5WLkWE69atIQ_Q1yA=SVlZ*SFDR>x}C2&c% z^p4eSujgoIk3~S$R@+=zx$$GIBV!lUyUQKtySaB zt@t1JNo-4l9IYRPnD1Ovev+Bd`{rfdON^ZT8i3G$T zXCDB-It^hX@Wcd0E?q?K?q zM7Iq9sRpTy8x4$qasv66-vB?k2la0+p>br+G2tB3^WCFJsoyZ|5UJQ&hUX>PI3clS zyLQ39av3`h&S3qcd90tDM|eo}iL0+jlnI zp4l?h4#;Pm*plMRreRpEpfxj#`uA7SeDxKKz5g-B-+fzws2J+9eTR|M55U9tfVHUy zOS0av1L6FqSi5*0=Eim8559zv^O_`cxgqNxx(U#(Y+9(0Syl&#R#q#g=}Pc z{np~rW|zEv%ru)TVQ#E=hm1L-LgILglGKQFcCUM<`_4DYoHBTPt+M!C$~I^02i!r^ z3~Sedu|h?uEgPbo)_9X?YFz5Wq3U{kwYqpZ)trZJ$tEYCn35nUs|iZZsDs-~bqcOZ z;9u@X`!<_WM_u#~U3c`5UGcqhYOZp|;|rZG^`B_VAN?}=p9A)**KM00000 LNkvXXu0mjf_mu$N literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/64x64.png b/apps/desktop/src-tauri/icons/64x64.png new file mode 100644 index 0000000000000000000000000000000000000000..d823e959cac32fd50ea0f00b61188325254b7463 GIT binary patch literal 2063 zcmV+q2=MobP)FjiSB!+p; zv2_yIB!H7V(1Edy=UeSynCBfc^HQgFEIKpIHU{!Zy(txu;uw%^y!R))5K?cBSbDFs z?p1xrM?nhdNNrf;xx2p5PSU|<>H(m_ z`xv%o{BgkGN6Ka6G$tACFl#FR`$2ziDnK}CGtRTI4_q*`fqii^%T6|#A}r59g0=54 zISvi18ydF%xy=a=fZ;z$%SK|W)D~YQyk!GG?}2o5;2*EDdwfTPmkN(oh(ldW#1^Qb zpyr{QBm<-rzo#&HK!1ehA^u!s_c%x))&h2NMYK{{EzFl+Yhz{_VyXzrc7f7q!1KbT zLu(Cv^&Axv2UI4fj88s|#Kgjj>1n97Yf;+%9jFg|7~`4;>X(q~N^$AN1Vt zb!0~l0ZG<4TfZ6{K;gHCQM`Sx4WyF=rr?D2-((Wh#~e1nuTm+{d2B6iv765xf`-$^oiwy(WHXiX+x+e?Jm0{S&>{U4!&}4*}h54a{-g$JQhN=o2X2d<#Tr z3Zl$};mGDZv$$j^up!7Lr69f!x1d7igITDqF7tEt&fCy^!**tR4vRWqapgR9+YaO( zcnIE_HHHW)r5QDR7J`6k))E;2s?PMzU9i|BNN0vjY^l-b(fj2sNIm*A`#R?g<1=u- zuo08L`i%{dO$79_UC`nC?ID(XC70c}*YSg8pnCNOj5 z=aK*YQOsO_HAe=1H<&`=x#Q^m-c7!x%+WsZzi9#FZ<4Au+d_jJ=0xEv*8>?$-7$jc zZ+*jrM4cqT5ytQRTD>6A&#r3{pS@5`m*YRdAZWAI<36Dml!#8$X4q zeRsjzupW4iwY<`SbK-SmcmD{9fBfBW17>II3MQ%(rwtc~7Jxcao##|6e5u4PsZjpz z4wQE6v?qm=Fkx`Ty$>RD@E08VN}yE(EVyf2#E_s1n*s~#HZ9j^m6}HfKz$&pa{=k+ z^=sB*YGgm$&6}*&vkv6xab$1*36e+u0P5*AwSi87HDH3%UXgnb=;t}cxs)#C{laPS zE)b~&=qM-!`O2Xh%kvAt0u}GR58lwnfgEeG&q4C3XOP{uo5S9Jp;q-90L?+5%z&v34a(#^*@iua*c~?Ap`O7DU*JaV z<)pYZCYJ504R?j4!+Uu7?D!j(L=^=pb=@vT{xAHEF9etv6mfGDR7;n|PSm>HUfAt% z(yi#3;)#E!vOPuaQEwsRhx$M;st&Pf$?5*M!`-=`7RLW|e-Po9a7oJa;pNO!?!{!b zr^LzZ76Eh2>-iZ;SPpOI=3bzq*R#T(+Fi**qrM_jxy7Zr2R`yy-q%5Hm=3iWh6A0# zXrJdyeCOFSr;oHQOQX9brg_8!`|g2t9E0d8c8H63;y&i*bVsfRktnltdCtII;q(7z zi)Y?^E~w9kbWP4|M1`pOR%?14xNp~)a8x-8v3GTA*m5Z@J! t0f+&J0f+&J0f+&J0f+&J0r>xT-Uo)M91|iA{%!yO002ovPDHLkV1j1J?xg?# literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/Square107x107Logo.png b/apps/desktop/src-tauri/icons/Square107x107Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..6b0571f7364831d03c69562146e6bc6c1ac7ba44 GIT binary patch literal 3462 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 literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/Square150x150Logo.png b/apps/desktop/src-tauri/icons/Square150x150Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..ff970f783c43db267ff3e0ffffa9bca64f8d424d GIT binary patch literal 4745 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 Ns3~bHR=}*o{tKI!6@&l) literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/Square284x284Logo.png b/apps/desktop/src-tauri/icons/Square284x284Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..405d4ec9b6bf08d4d0d2a70f689a4dd71a7d5041 GIT binary patch literal 9026 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 Qb7)49lU9_fkTml950)Si5&!@I literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/Square30x30Logo.png b/apps/desktop/src-tauri/icons/Square30x30Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..cb733ccc04b4da48d4952e7ddb8b22d126656573 GIT binary patch literal 887 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 b{{{RPu&SR#%_=Wc00000NkvXXu0mjfE{m<8 literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/Square71x71Logo.png b/apps/desktop/src-tauri/icons/Square71x71Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..be20a2276f7eb99d549f4b2a4a89d7aaf159f8c6 GIT binary patch literal 2353 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 literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/android/mipmap-anydpi-v26/ic_launcher.xml b/apps/desktop/src-tauri/icons/android/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..2ffbf24 --- /dev/null +++ b/apps/desktop/src-tauri/icons/android/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/apps/desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png b/apps/desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..fa35b24ec68eded7e47845e3d0b9f6690292b3d4 GIT binary patch literal 1494 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 Qr5}#^3vI|JC9BB)1NZ2oZU6uP literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png b/apps/desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..5b0345468608c7344a9ee8213e716e5d30ff7819 GIT binary patch literal 1658 zcmV-=28H>FP)BcNGbe7ly z#=D}>3#3+oaSG&F4A5YRLSN0-Az|%}%c~p+Ml3{0+_ps4+tDBy zyN3eQ1qK+_3-rQja?0Zr@H!QImf zvA7kP_g=;5&fO-g1};$O<;ZK}6YW;P81bPpL+10NS|CK8K?;KOsXRinh;$Pvdmarh zzli$HTfq89$SV(FghT}a@Pl7 zqoWvm_kD=FZ$DhR?{$PwoL?S7Gn+Ffb`Rk z!})PP^}0m;0a0!7+bM=#Oq8D!cDZ@YbP>x7A?w5UC~0X~u(})BEw4k|(+2kU0FpaD zLERUhnOs^(1vr(Y!bnAr^Q&2IijZZpnjo~DVof|Xf-;dp?u8zBn>Uh@l)K*?Mq>MR z*hhYcoHySnMO14Y{fmImXO{*b9anpAsznH^nkQsDuT2<1*N7}}{}Oo5Z=^&XL*2Gr z+WM-PiG^(hGB7kuw3>RUhYB2dV|b8&C-pN4T;mO)y~N8(aC`b|CzA=qFbIiSlS%N? zCy?6I12!}S=U^{nLmHB5gX*F3)t;nKf}ig<1+qS^8LYIyl&q}0#)7j4AvB*7sdy6% z73uy7;~w0v_vv-MnA2*Mrk<+U#TFXI`UZ0^@ULSoi$2MCSMz#B*l7tf)A{`}UN00~ zD&CrxBHy~G@z3EBd;M>@f^lInVP zOFY%a`rvkNTy7;d3RK4%HO{$xKewGngopwnOa~P@$OpdKEf8V&)99tX2MY2kOtDM{ zx8T@7=K77g^A0H^S$>mHqS6j@~W|Urmd4|ZC^lZy}g#@u9CVsC~;Ad z#Z244N^mtVzQ>Bo8Rm=7`!y7N{rKfmXUg%yOt&$M0_t1Zx{20lQ7=?Ut}`sArc9J@ zka{*=07D6o^(6RNazk%sxc~df^H+B-cEX%dg*Ug$@BT2mtvmI(W2%$dNDwo$h4!9` z|KP^%ikHaE=}jw9P9eL&AZq_9s)4A1sDY?~xCuf02U&ZdZtf2q2LJ#707*qoM6N<$ Ef`yS5N&o-= literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png b/apps/desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..c0452b5e8ecd7204640fe0445c37286a631a64de GIT binary patch literal 1492 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 O7XYrI2gR!)!~O@6h^`I* literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png b/apps/desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..6409f599012ef93356725645d8154fb976fe543b GIT binary patch literal 1699 zcmV;U23+}xP)Ffe9f(L0Cium0%ze{)i}Psfd2`C8#MT z_$Md}Qlk7*ih*QAqDh)j>6*B0itgv^?99FAyuIh%JF`3Mt~;~N7{c7;%-K78&pq$Q z^FHtUo^^1GUrtSdngTTiY6{d8_Rpm>>2H?qB&^vYyXiTU$gT)xb* z&?JR0O0+I;kj?^LZc^_MliPR+d+vmvziYmu&B=NLQk3{Qt8UEo=t{>Q-tf0~^E;3G zH$j1w68P3kpS@(B$$1-8qP|VJ@u`}$W1&=%0uZEx(SEM6$7C-ZBk67H={)&+0a?{k zATRt~FREC>7AaMX#Q+(N5@nC%6Tu{;hE#DFgPivJUb)io%ZKGEp~{2J584Xv#G5`M zKc`6hEV+rKq7ui5XGsugZ8(r!<)&68rcCS4^mZKu+IX){Q#lWaqyi0U3mfSsPqW}L z8-cu97Fl(&7g;Nib!aZ@{d-UE-+!JG;sr&tTTir9mZs&Lz*AZeZD5?o*m&A*SRfy% zLZcc}x+996!ta7lL@~$2H->?JNL45gFvrtr6Kb1iBV&n!#4wh5&hd9{EcApPBOdHC zLQLc+X|%_$NiGd<&uSqg?``OYJRm}DG|e*?Im(SqH5{;H;Tsr_;X7nGoY}9hhoP)t zT$h8|M9)z8JA24Dt_8{P-^{2HXlLMS(UfX#O(F`C8-`F`{VWYi!&F&_L#tdm1Mj}& z=>2#Xh8}qoqQ4h%pdU!Yqs8nv7FuKmp}H;xv%SYyMvdSkgi)^aRH*^#l+L#S1cDC= z?krq9=$2XVRxg9U{9gErTanzg3+kT>&@)p<(S)a1ZOesT$~F}0(j;fu>=REiO}2w>PeL6!iMsbbfP3%&XnHfKv5^yAI`m;K3lU`EJRywJ?TD%< zAPSbtmpY=q57}p*!{GL}fU6$j@9sf-=k_3xnU>qa0Oy?Qe0LD>_9mXc;oOk|aRLme zRE#YB#c-jmOLv1)j`(@1p!~jUebIRV&R0he+xsOawNF9uIP}aGh-@}|Jf46&_ZRBk z+069X0II8FI`zW1DQcyo9KflVJS{4&fEF$}1RZQ-f_92af&|>dhk1O@88^#RI)#Ik zlT{`YTGtMn@L1@8X01npYIRh1mX9%O8E!RQ<(o{!6bLy_4P5H*QZwfDDCq>jh6n-_ zk3rbBvaT_FJ~tF{!-&iZ-w#KTv1wGf7*?KIqIckGXFBQ@O$AuUg1$9)j&$Z2q{#DN zsD!<l|7;Y1xhe9wV!PtxO)DJ z2-<#yPbIqSM#9VV9d+ZWekq+5e5h!P8xi3*noAid%t9*3@A0(GwWqI~e>;k5Q_YjP zAPAC;v+smsHcBVHl-=G0Nh)l3O5PkGF$t*J5P*|hpK$ESnT4u)U2d* z`J^^X5n`f(-1gbVhspF`Opo`@YAax!Zv)vvP?vigIBI_t1T2w%6AyQbkJqCnx%}o% tfJ&jt>MBtC4^2&hngTTiY6{%S*MHWq2DRb?wPOGP002ovPDHLkV1g$%G&BGJ literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png b/apps/desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..dc1f966eb36a6acc3363ff5e98aa90f1ea6373d5 GIT binary patch literal 3174 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 literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png b/apps/desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..ce012755eae15237763caa643196b33d20192f48 GIT binary patch literal 6832 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 literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png b/apps/desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..ba46dd2c3e0fd69b48ceaf32ddc5b1767c29397a GIT binary patch literal 3533 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 Hu0mjfn^mr0 literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png b/apps/desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..a28de0eddf9b6fdd608d93244b3f7000b8e72fbf GIT binary patch literal 4819 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 V%-C15zhD)Py0W%XnSxdDe*r4L8O8tr literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png b/apps/desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..9357412bfdd1d6e042b2a664e41b1096a4601142 GIT binary patch literal 10311 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 literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png b/apps/desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..1372019313f8bc0ea4bb68762232151dbe942dfc GIT binary patch literal 5338 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 literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png b/apps/desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..c8ec08ba28e3c5878143e27babe301fbe520ecdb GIT binary patch literal 6524 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 Ju8}i~_#fFB9i9LH literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png b/apps/desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..bf65767ec0f05a6b1494a11a3ee2eac9dee99c13 GIT binary patch literal 13987 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 literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png b/apps/desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..2091c9f8f9965230b9b2062901d1472a3becdbe4 GIT binary patch literal 7343 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 dUg4f643u%{c; literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/android/values/ic_launcher_background.xml b/apps/desktop/src-tauri/icons/android/values/ic_launcher_background.xml new file mode 100644 index 0000000..ea9c223 --- /dev/null +++ b/apps/desktop/src-tauri/icons/android/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #fff + \ No newline at end of file diff --git a/apps/desktop/src-tauri/icons/icon.icns b/apps/desktop/src-tauri/icons/icon.icns new file mode 100644 index 0000000000000000000000000000000000000000..35bb0b461743be6b4fbfbcf7e01a101d30a489bb GIT binary patch literal 62551 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 literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/icon.ico b/apps/desktop/src-tauri/icons/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..e8ce7a17355da8e71eeca1e22667a6fae2ebfd06 GIT binary patch literal 14386 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 literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/icon.png b/apps/desktop/src-tauri/icons/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..2329e7eab4b5579169045d7a199dc3b09913f3f1 GIT binary patch literal 14421 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 literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/ios/AppIcon-20x20@1x.png b/apps/desktop/src-tauri/icons/ios/AppIcon-20x20@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..134688a9843db5f710189328113deebf130e2d08 GIT binary patch literal 622 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%0DPwD}iz>Qjy@@9%z$rU(cn zB04(|d2}ZFj!@>^uoiI9eV+sF-TNti8%aHRla5K?%ukH!nfWtr)hHU1_lUuO%A`T2 z>$>*=56veD8SS4Ac(*jbd8$=WS0$quIBT&d6M3QlHKP<^lsceL+X;y7P8ic4f`7|) zgy%j3(DKO3Ov#Bhc(*k{>-djiccLnjDEVikco7z2R7hLeIE!SIVpJM_(btR6%daBv zA!XGmKIKJ0`$td97PyXnqo^t?CJ^|bD#3uMOWI#Lo#x-t!Wt<>M(Rk*E*Zrd$0Y40 zg6kXL-?JNXf=_u-zxX?RRKar{J_ut%g-PoO?QTkRh>lw*`QZe_m0mbcx5mImZHR`v zdNihQWm=4~fh6jO7QF(L(ck?B+`D$c{rMiXN9ARPwj4)?Lqzg>i6fb4DdVmbi&3>;3Srr>s) z)U_n&}XE)Zyj$=H&!?I=0(BP}CtND}SCH{NpenTsnV8)Y&FvBaS} z@(0x8anr8eLj~(@Q@W*sWjgVWpQNAiPBda;gJ7@p>7^>Z*W<~3GU5$4SKPRcI%9g3 znSYW2nSRRu`t(iN= zcDd7b0lTlSAG02>Mt4tdOm!Bf>M3HXnZie2zI0AJFlBOnJjxw%QL4P$hmTt}#q@0a z08Hk!ndePHsi~IcMg@{>v2!$OOE7SZGF@J+U4V`CYgGAGoo7-e<}(;O#Vsq1`{cfP z3@TltZuLs6T(&fkFYd;Y~KGQC*UB4-~xXdTs*<5@oP)a(us)`PR=T>6{0c5)Jm^{Im zoTlgWXx~p&`~aP{g=veH-O;{I>!h2Okg}W|?Tc)`#v1>!2G4XRC(%~=zUyDsxUar` ulP|+i{N`8@Xc1@;Xc1@;Xc6c=bNvrf4-_W*BU+;X0000rQTt%QophciXphciXp!Yh^Tx$;@#JvNQ!9}A{GD?HPq2&~4G-^=) z2KDR68nnnp0!AVc=(;}4us|?K_oEpb#^&g{10J_)Sl{Vm70jdYfrG(896f#-ZSB9{ z>b0BFA7G#nK}e-tsM16#*n_2B4`xiChMMP}#_P2&qTE-eCNfjjWaQEKfNeir!1~6W z=Dt`;3#Jwz|ci88++Q_0MRmitO^>D+NltgJ}bWaZMV z$7NK#9yxZ3K;DLf`X{m*-o?dR#Yp<=So>c(LH z5a2WI=hfJDl9FzfwjBJN1g`#dgT^uh&9O*Nu9634Dlw%fJLdX|Mx|h?Ucd3T@cRQO zE%jQaudQ{I#lV2yPxxY#O3N6+KLCV604?^?TgsMM%QQAJH9zVP1P~k?R6ui1-FViG zgd-#4l0niWgr1#){@r^Jery)B&Q6s=5h(oJJOGe%=O!r_Q5HfZ+OHswwv8wXDm z(piFmP0bj3s|LLXzJ`BI9f9{l3*LT6Kq0}CWGVz{xy5rvUVtWcDAIg2 z-*U8)l|w^twVnWoy>My>YnnK+dedP|bXrs6k6!RTG>6QZ2(R#^^@)d~lsShKkn~qU7waL`%9` z=7E3bHj3T7^u7$D_cq;kn4p-l0eZ_5pfaZw+GeJuwTwWH)rgL=vJ%>@e^I__IlRpu zQ5H6ocSDOPcE4*ysQLwHU7d;r;N?h5?H3jkQURzdhy9E)=aDec*a?HY=lNnE%9k#N zMApMMb8S`4mw z7r}Sd5M2!n)~!JF;YT1i0cn*ZnKGUM>KP;78}IaZx%0DPwD}iz>Qjy@@9%z$rU(cn zB04(|d2}ZFj!@>^uoiI9eV+sF-TNti8%aHRla5K?%ukH!nfWtr)hHU1_lUuO%A`T2 z>$>*=56veD8SS4Ac(*jbd8$=WS0$quIBT&d6M3QlHKP<^lsceL+X;y7P8ic4f`7|) zgy%j3(DKO3Ov#Bhc(*k{>-djiccLnjDEVikco7z2R7hLeIE!SIVpJM_(btR6%daBv zA!XGmKIKJ0`$td97PyXnqo^t?CJ^|bD#3uMOWI#Lo#x-t!Wt<>M(Rk*E*Zrd$0Y40 zg6kXL-?JNXf=_u-zxX?RRKar{J_ut%g-PoO?QTkRh>lw*`QZe_m0mbcx5mImZHR`v zdNihQWm=4~fh6jO7QF(L(ck?B+`D$c{rMiXN9ARPwj4)?Lqzg>i6fb4DdVmbi&3>;3Srr>s) z)U_n&}XE)Zyj$=H&!?I=0(BP}CtND}SCH{NpenTsnV8)Y&FvBaS} z@(0x8anr8eLj~(@Q@W*sWjgVWpQNAiPBda;gJ7@p>7^>Z*W<~3GU5$4SKPRcI%9g3 znSYW2nSRRu`t(iN= zcDd7b0lTlSAG02>Mt4tdOm!Bf>M3HXnZie2zI0AJFlBOnJjxw%QL4P$hmTt}#q@0a z08Hk!ndePHsi~IcMg@{>v2!$OOE7SZGF@J+U4V`CYgGAGoo7-e<}(;O#Vsq1`{cfP z3@TltZuLs6T(&fkFYd;Y~KGQC*UB4-~xXdTs*<5@oP)a(us)`PR=T>6{0c5)Jm^{Im zoTlgWXx~p&`~aP{g=veH-O;{I>!h2Okg}W|?Tc)`#v1>!2G4XRC(%~=zUyDsxUar` ulP|+i{N`8@Xc1@;Xc1@;Xc6c=bNvrf4-_W*BU+;X0000Z6JUL2Ma| zPL-nagH9bRP{Ao!OK31W6j~@Yg0z6rf}n;%LK2euzW3~|wa-0yK*;mt=A?6WI3)Mp z$=UmS=i6(2Ywfj9bV&_v>y@Uv5V+vF;JVEP*9F%F*KIDiF1RkZZgatP!F9oPn+vWB zt_yBDT3=*2g%JP0;3ks>foee0GFHnecCws7)ilwHIoxF|7DqS| zRiDu?)P>vG_`HT8;m`2F=kvC@q1=BmnS`$E{S#b1Enl3)lJ_c)Vn@Zh@*jtfiBCSQ zLNpdbC=@Y!?~NI&u1bom%uHkuz$Hc3V9coDm^OI=CR}%I6PwK&q4ghdnXMM6J9qEL zvoEZZ?;klXcuGpX>Qt8!y>EMk^*_xV{$kVgwXY154=tQ6?zrW~E5_?+aIJyH6A3JO zbOp9-D^D?r%mZDZgz8bG%duJJh`Xkr1i<8 zEny1H{&AQ<8uIkn&rn{mua%kWQ*c=~a@+CtUK*j6in#h;6DgW*FW=MZy81M?V0qTc z_y4I_OM_x6^gDzNnt^N|4u5b=z4mxKeG4v6CkB_lpZTOpeWx!WJ8S41R0C*5HdW`& z%f`l_2vA_rQ@d+RND`wwK{OgAV2xC`Dcc8?5AxE`y_Sx12EcSs&O=0^aRdSmkz$

2d1g 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 literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/ios/AppIcon-512@2x.png b/apps/desktop/src-tauri/icons/ios/AppIcon-512@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..29025c7ae745c07c487f6156a9fa0d2beadb766a GIT binary patch literal 8220 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 Sspz^yGp9e5{^2zH=KlpyF?weJ literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/ios/AppIcon-60x60@2x.png b/apps/desktop/src-tauri/icons/ios/AppIcon-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4045cf2aee192600e563b353a289bdd8e43ebe4d GIT binary patch literal 3926 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 literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/ios/AppIcon-60x60@3x.png b/apps/desktop/src-tauri/icons/ios/AppIcon-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..d14405ad2d857b79a5fc7af237f8eda9095c705a GIT binary patch literal 5752 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 literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/ios/AppIcon-76x76@1x.png b/apps/desktop/src-tauri/icons/ios/AppIcon-76x76@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..e65e7d790fbbfcba114ee75e8420a06e146646b3 GIT binary patch literal 2495 zcmV;w2|)IVP)&R2<$^018v>Pm{39MTG6ycV=LN#@wF;rOBF#&(`9O_ z7D6|{fT>WGZ7t2xX6pDDi~-WLKiCjuT}Q`6w{@kkHc8Wb*s+t?@9vy?{Sqg$)5Ly` zjr6W{^`4z)zw>_goZmV3+;iiW)Znx!H@5?U1DFGt1DFGt1DMksz#PCFz#PCFz?|j) zR%(Fp++O#>-bV=TLiLX%V2MP6gg4-F83lic^p;GTG&m;R*Hw`F3cJ%gEHHy)wMcXj zr$0D@fk+h5XsjR_90>Rj3Io4!1anlYQ|Hr>m&tgIom@JrS zjy{4g6b*3u_{Fu@(b9+|*DQusDLLGcUl>&G3d*caUwEil$0wl|WgcaN)q7R$TkVtMdlU7L#0h<2Q)2{-w;Y*qW8e zM43J3lL!6t>jxEBQs&O5Mn0y#rU-_`H%#f@!wI&`NbvCK)=kb-ZZt+sp#SD$U##p* zaDA2zX-j~ZCtxz|n1M7BBQUG0F?jcPfj}7&i|f$)%L5p^XFWtL3K6I5h1)e5@zEg( zG0>;9RB5M*pK>8GEvG0hU|NWb9)~|OC@0n52lv}=0U;)kVQ};@xaoW7+r1abd9@Hd z=OF1itvwljgFcToZA5Qd2Zp}<6=Lo|y57jmQOWwFr?1TVRF= z`H_Uyn@so2(o;i=d?B+byC$>q8_(N@VhA>UAHnsFq-Eq;XO%;o8-nzE5qV@Q26jCP z84S|j&g<)~X$!?pvZ|W2iq3l|Ixj0D(+<$*3HxL$hDmB!vd&GESCmziC_mhRiu&a! zd-;!$v&%X7Cg6rKTz>=lesvhbORuB%T^cCXFb15mA4*F0tm=I-J8w?bWl4}e#=x44 zYdJ`yxu>kEf~)f^!gqcP{s*_~OlhTuOf(L&_G1`$>Su_O+41KFnIk4<6+~`WjVV_N z047t+FeQlzG_$-MCYhh_sV7mfb|qX#jziA%lG%~wM3ac$vkraF9>T~KS89haA*&$A z-F50+mWD}=sryu4Y;N4m>KeG-{X4?9)Wf@LHxML~^Hc8}MzZb`=s(bg*lpj@p@)%a zh~%_hTFm^-(y#-sNlh|aXA|}N$?VGDe`p)RtJc6caf(QtJm~=O7AxGAZ5UbnIXX#` zG}rm0O&aF5&qK;QQI|PfKb?Du(%`Uh)1&F&>vHSJo#L;-4I9yas2%1d3rL$NxDC-b zl63}}??>62Z_o*pN6lNtQt*;GK*f~jbkY!t$T@sSTzVP$_Z>w1K3WfmkPQw}pY4I` z*n0@ASq<-=Cm_APabQ_IB&Ru-ly-#q`I=<9cg*gE(oBKFgcxNwNULJE-;LOY2S|Ge zyfbmguvckS`A_%4w`-@;JhQSUL+U8qFUx5dBo9>nzS3V1 zT$n=1#^IIq7~K3L$csX1J}G?^?bmqVX?p>_t(#$VbwSqD=xClhn-WL(CiMIC6wh?i zH8!pPxeGd%WFZqo;y%9$5r)5hlbRQbZZg3dFCAm>Jjnk| zukb^sfliKSN0HMah6F^>I82UXl+mCt19b_SOGa8BLt^cmkJi+EgV2;f!tKm5$nWg*pFQdG54`nN^hWGIwlNt9aaHpH*=86S7!ZG_y5*ZgS zDIF6=;xmhZetKU)CKw02TXw>``*AhF=7`_YDmfvnlX|rRzHQB;TBX5CV*2W0kC(Ku zcq&77pv+As)eY}syC}XIf$Pn`BDi)1ypOi(DBtTHop74Q=Y#j@C*b)_2j#nZA%>X0W{r~i)W#u^TBgh6VQnfR$_uc78gZF@ zQPhe$$c#j9kBaUkhYN{BZYd-i@^-;sz*=^jIl!!&g+l?gTy?=mVb0;8Ri@61&`haU zl0(7Z%yXCp*!~jlqkhaTQ(~~XDje{%CK<3{Jbn^)g*3O%&z{|BD#mINH=;qZctupr&r;paHc2)b(UH3v2{mFil%fvpp;(1(A6J1 zw>K-W^o9#joWPZLTd)9MT5=7xY-&uEeIvzZ#jkDU8aDPd4fozASA2Du8sMT91&_My zR7rR1Po6}})`!)|x>;CKIbCRn8LggX&PpV8ZGOYOcgU8_O~QK2d~5Y>0nA#CXV6}K z?GI>Z+=%y2|97+4q=vmZcj6 zuK)MmnRn)W=YBZn%skIL=gXP%0lhDIWuZH(DxM9b+H1RJ1gzsdI7`P>1t3j7mBpu(+0j~`fEPoo{ zj%h~UN$syXeo1jd>>x@oS|p4jl|dyG)|1`$oalunoTZO$iflwZ{vKImdtoF^*1aZ& zHXGa8X9;FOdcK^iu=(E{#)F(xD^iPsdFKoTfSm`h`)C!;H)d;Yg z%Fu|fd5E5zdePd#TI`t(k%jYRzSTD4?H22k>vierO;%IC5RsNLkPu-0#HT^lfC5_0 zy0`|?1GpIFj62-6vjqNwlZ~1J*7)=|6!9<-*6h7acXw|gtD7x}SyWyCm3F?yr5nRk zuE7KG@sRdqI1qmS9?(yHQaK}&BP63%tdulJF~>XS zDlK*S$W+`tE}2Y2usV74gu6w*8u9)Za-is@nZs-luAit_wMac>Xz1aC%&Fi0J%pnk z_j2p_c$qqY8`eMb+j-i=Z#0+=+5pE*U@y}js$L`Sq7ih#XpN|Wp~iDf6EpmNPFpwf zVY{&LCFFWVWki=1&65AToKwt-J=Pr`g)X9 zXk-O;{Mp{$)sg%(iwebhLR%Lmz+xC2$!BpbMaRn}jK#8vqJ!zbFQcWR;xo_BN?i`F z>>2Oclq};r5Xv{lOHHSNxI@{+x*nuZlY>ybSR?lf?;ameFa=9m^BF$*ALZh@7#dgq zQ<>({><9Ep$3hok z{`+iNQzT^te? zD?HnWg;*k)ajF9jO<%&=z&nJ(lF7SJkvrM;JiMH}snk z5Qmm_h>3XQX+jA|&pctdyjo$d9oO<{4q*JU;G$*PG7%@Fp%@jPPTG|^G|8kGat=KwK;GXPR zP^e|?Y^fBd;1z?ecft5LEXP8=?PVrj(7gGd2bE_vx0ednzmeec`lxIlW25n)E;0@u zitK(ICt2UKnt)JVYQtd`>(N7ihVRPWdV|B~6s8&%+@weD$!^6$TzvDovt@N)Zv+vi zSuIVn6-&0`c6Rb?fJss3+Mn#@Xz{$?$0a&S>oW1+l*Ya2b6$aN1oK8SNuK$n+(Si$;2CeI9<2=J3kw;O)yHq@o*nvB zn{$S^KYxZK@-5)JLuKx9upmX@0HE5L{37s2H`LS75p*)sC z3uv+AoPG2v)(%`6_Bx+BJ+=&ZnN{Gu;dXG)P|8d*>X@!Y9KMftms0rR`)^{Y02HW@$QZ@Cn-IvMN+6<&7Wg0dD9x!6l%bi@DO(_t0~;FUGUDn!@2M&gg>gqO z0f)&F*eXei+bVoh3xNCj+&l5z3HyWaK$&SIKc?;nL0}~>hKALO5W)MMq#2!W&U^t5 zGx=p@nw8}A5_<}WCAReB-gQGGR zB>Ck3bPz!!4U|$+@wSIo*u55)mbPuGaSxTY-E1A`BvBP2g;S}}$0k%;uG=4ToU99tiUQDn)! zwP>7KjjmWK3_WF`a<_i{r&SQA-QxEnxG7U*LfAQsD7idFmrDO$f3+=1#z}gb@!d4wx{@(wnRNYoS{zJhUlLw1 z+l}0pH2+jYe`nI5QVq@yuBMwopItzlh8RSsw|M6Bw%3EK>AwyLde{`Z?2Hl3$^eA; zKXSI6GC>kN|ic2Ha%qJayv$$^6y~_^}8yX^73Cdkwoj&ueJ)A4x?JIwtV7i%RBt??HfHqPMxJ)co z%+vBYdp#qQvD%@Sro!Epr@iRTWL5QQ1i&CnrPtq;M?5S2%dx?;9xt=;QN)fn@KN~u z{Ucx(XC!F%HFDbK+}T;ngJqQ)(WiYkdCzWmIjx?ts+>(M+HyUYC>zl_M4l~s!;(B- zNcD+_L-nSDYL`Shd{&f)%lW*(S-$Ez(>bi~a2@pGkW9m`DG9lO{fe0Rdvoow#%DHaNEF+ty=1umibJ%%O@U5?XIExI6uU`c!Y^tNa>UI;x6IIyou}SJbI0 z6DSOpa%=V8VoRPk@h}{8m_qKlwx6kNGsj=N_F4rak$#q!$tGeE;(;e&JG&QHW>sU2rZ)xXVqdNv=<&72d3?SB<=cQ47&^j6W_ zr2(bacd6{WZ{2UA_LUQCZLX)!bh2L$)=I>wXp0`yQ*f#tcVB(?i&p#Ys>e_K+1{{v z^391laV?B1;cgQC)5OGP7&Hj`q;-uv9gMi$I!zOvkt>~rkviyWwjtJjtC6+tZr2oiou)RFM zx}BYIOf=$22!`BRtqT>&C|xM|HahW(SnQ$ce}znhvy+wFF9_W<&t8jw#On3N$B?3d zzmkzdZjhZTVC9z|8gm_LSK&7L;q*cGfQ;h#3oO-K8FH>S4?VSvbwY_Yaz076vr_gk zKRvC+5S!>y+>5N3!NYK^N#Y*WurIoDG6XK<8I4rDRs^=Le(@8DSm5S1ypUf zQ;rLptTt}S#_;Wp<#iWh5o$6|S8~voSy2IS*^`0;74csF9i`&kG}YU&(^>QSX*wJC zVVPvSUnLyRIlG>=QIaTNjt6YgBYa3rQL(Xro5MzB!R2<(U%Bjcz}p_>w7}f`?hkGz zkYP=haWfc*1v;8Eiw{6VYHV(rJS@^8Vp0*j^v)JCgd-AGB4sP>Py&2YEsfpKBf__crZwp&D49x22%pigzOAMLk}RI+ulfVtT4+}Tbb_J#k*EHtf5q>0D}_9Yol)J zp^89Tb||hk3mdWwvK#BljP|`61QW_36;X(CDmh*S%!i4?_82Rr36b5YG(d$D1<&9_ zZ-?Jq%9=@o-E*eU(l7xADbTG9hc=zV;1=}EO9mzyZyk4fzc2LX@TXiMx!XNqO`j?yN#)XMb@cWIhea8lPhuEeIVIQ2{eE=@)g>`M3 z>-vtwQ(*!;Qf?=v{Zde5uk}Ohyi8DM9}Fb0BU)Wi;vLMBd6wx?Pj(kbDbHqy%bht( zeogbcPfeZ3YBa>O;4mFpPou@|d|G>4p+BoO89pasC-h2vq~=|3mcQ>EZQ$NO?r)u; zWCjCHuwAf}A*;sA$U9f0R6{(NTTRQp%{C0+YdM0ZG6T7TOcJofi= xHvIp~W&Rts`3r0Q!)5*(w)sD(NA=YoxjlD8Xp+$p=r5_lPy=ZxS1DS;{srhXMJ50M literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png b/apps/desktop/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..35b41809047b7f7b32db3694e6d7994b4167e0a3 GIT binary patch literal 5208 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 literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/src/commands/catalog.rs b/apps/desktop/src-tauri/src/commands/catalog.rs new file mode 100644 index 0000000..c4785b0 --- /dev/null +++ b/apps/desktop/src-tauri/src/commands/catalog.rs @@ -0,0 +1,11 @@ +//! IPC 命令:假目录(架构 §2 adapters/,IPC 契约 listCatalog) + +use agentdock_adapter::catalog::{self, CatalogEntry}; + +use crate::adapters_dir; + +/// 读取 adapters/catalog.yaml 与 tools/*.yaml,返回 14 个目录条目 +#[tauri::command(rename = "listCatalog")] +pub fn list_catalog() -> Result, String> { + catalog::load_catalog(adapters_dir()).map_err(|e| e.to_string()) +} diff --git a/apps/desktop/src-tauri/src/commands/env.rs b/apps/desktop/src-tauri/src/commands/env.rs new file mode 100644 index 0000000..b95f17c --- /dev/null +++ b/apps/desktop/src-tauri/src/commands/env.rs @@ -0,0 +1,10 @@ +//! IPC 命令:本机环境检测(架构 §5,IPC 契约 detectEnv) + +use agentdock_platform::detect; +use agentdock_platform::model::PlatformEnv; + +/// 返回本机真实环境快照(Windows/Linux 双平台) +#[tauri::command(rename = "detectEnv")] +pub fn detect_env() -> PlatformEnv { + detect::detect_env() +} diff --git a/apps/desktop/src-tauri/src/commands/mod.rs b/apps/desktop/src-tauri/src/commands/mod.rs new file mode 100644 index 0000000..beeb2cd --- /dev/null +++ b/apps/desktop/src-tauri/src/commands/mod.rs @@ -0,0 +1,2 @@ +pub mod catalog; +pub mod env; diff --git a/apps/desktop/src-tauri/src/lib.rs b/apps/desktop/src-tauri/src/lib.rs new file mode 100644 index 0000000..83e1c38 --- /dev/null +++ b/apps/desktop/src-tauri/src/lib.rs @@ -0,0 +1,42 @@ +mod commands; + +use std::path::PathBuf; + +/// 解析适配器目录。 +/// 优先级:环境变量 AGENTDOCK_ADAPTERS_DIR > CWD 相对路径(tauri dev 时 CWD=apps/desktop) +/// > CARGO_MANIFEST_DIR 相对路径(仓库根)。 +fn adapters_dir() -> PathBuf { + if let Ok(dir) = std::env::var("AGENTDOCK_ADAPTERS_DIR") { + return PathBuf::from(dir); + } + let cwd = std::env::current_dir().unwrap_or_default(); + let cargo_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let candidates = [ + cwd.join("../../adapters"), + cargo_dir.join("../../../adapters"), + ]; + for c in candidates { + if c.join("catalog.yaml").exists() { + return c; + } + } + cargo_dir.join("../../../adapters") +} + +#[cfg_attr(mobile, tauri::mobile_entry_point)] +pub fn run() { + tauri::Builder::default() + .setup(|_app| { + // 自测标记:`tauri dev` 启动后日志出现该行即代表壳已就绪 + println!("[agentdock] window-ready"); + // Wave 0:初始化 SQLite 空库(架构 §2 状态存储层) + let _ = agentdock_store::Store::open_default(); + Ok(()) + }) + .invoke_handler(tauri::generate_handler![ + commands::env::detect_env, + commands::catalog::list_catalog, + ]) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} diff --git a/apps/desktop/src-tauri/src/main.rs b/apps/desktop/src-tauri/src/main.rs new file mode 100644 index 0000000..2a1c0bb --- /dev/null +++ b/apps/desktop/src-tauri/src/main.rs @@ -0,0 +1,6 @@ +// Prevents additional console window on Windows in release, DO NOT REMOVE!! +#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] + +fn main() { + agentdock_desktop_lib::run() +} diff --git a/apps/desktop/src-tauri/tauri.conf.json b/apps/desktop/src-tauri/tauri.conf.json new file mode 100644 index 0000000..94002ca --- /dev/null +++ b/apps/desktop/src-tauri/tauri.conf.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://schema.tauri.app/config/2", + "productName": "AgentDock", + "version": "0.1.0", + "identifier": "cn.agentdock.desktop", + "build": { + "beforeDevCommand": "npm run dev", + "devUrl": "http://localhost:1420", + "beforeBuildCommand": "npm run build", + "frontendDist": "../dist" + }, + "app": { + "windows": [ + { + "title": "AgentDock", + "width": 1280, + "height": 800, + "minWidth": 960, + "minHeight": 600, + "center": true + } + ], + "security": { + "csp": null + } + }, + "bundle": { + "active": true, + "targets": ["nsis"], + "icon": [ + "icons/32x32.png", + "icons/128x128.png", + "icons/128x128@2x.png", + "icons/icon.ico" + ] + } +} diff --git a/apps/desktop/src/App.tsx b/apps/desktop/src/App.tsx new file mode 100644 index 0000000..7bff421 --- /dev/null +++ b/apps/desktop/src/App.tsx @@ -0,0 +1,65 @@ +import { useMemo, useState } from "react"; +import { Sidebar, type PageKey, PAGE_META } from "./components/Sidebar"; +import { Header } from "./components/Header"; +import { OverviewPage } from "./pages/Overview"; +import { CatalogPage } from "./pages/Catalog"; +import { MyCliPage } from "./pages/MyCli"; +import { ConfigCenterPage } from "./pages/ConfigCenter"; +import { BackupPage } from "./pages/Backup"; +import { SettingsPage } from "./pages/Settings"; +import { useEnv } from "./hooks/useEnv"; +import type { PlatformEnv, RuntimeInfo } from "./ipc/types"; + +/** 平台相关运行时集合(Windows 不看 apt,Linux 不看 winget) */ +const WIN_RUNTIMES = ["node", "npm", "python", "uv", "git", "winget"] as const; +const LINUX_RUNTIMES = ["node", "npm", "python", "uv", "git", "apt"] as const; + +function envWarningCount(env: PlatformEnv | null): number { + if (!env) return 0; + const keys = env.os === "windows" ? WIN_RUNTIMES : LINUX_RUNTIMES; + let n = 0; + for (const k of keys) { + const info = env.runtimes[k] as RuntimeInfo | null | undefined; + if (info && info.status !== "installed") n++; + } + return n; +} + +export default function App() { + const [page, setPage] = useState("overview"); + const { env } = useEnv(); + const warningCount = envWarningCount(env); + + const content = useMemo(() => { + switch (page) { + case "overview": + return ; + case "catalog": + return ; + case "my-cli": + return ; + case "config": + return ; + case "backup": + return ; + case "settings": + return ; + } + }, [page]); + + return ( +

+ + ); +} diff --git a/apps/desktop/src/components/CliMonogram.tsx b/apps/desktop/src/components/CliMonogram.tsx new file mode 100644 index 0000000..b72d908 --- /dev/null +++ b/apps/desktop/src/components/CliMonogram.tsx @@ -0,0 +1,19 @@ +/** CLI 单色字母头像(视觉规范 §7:双字母单色,--ad-bg-2 底 + 1px --ad-border) */ +export function CliMonogram({ + name, + size = 32, +}: { + name: string; + size?: number; +}) { + const chars = name.replace(/\s+/g, "").slice(0, 2).toUpperCase(); + return ( + + ); +} diff --git a/apps/desktop/src/components/Header.tsx b/apps/desktop/src/components/Header.tsx new file mode 100644 index 0000000..c92f63d --- /dev/null +++ b/apps/desktop/src/components/Header.tsx @@ -0,0 +1,34 @@ +import { ChevronDown, Search } from "lucide-react"; + +interface HeaderProps { + title: string; + /** 环境警告条数(0 时整颗 chip 不渲染,规范 §3.0) */ + warningCount?: number; +} + +/** 顶栏(视觉规范 §3.0):页面标题 + 搜索框 + 环境警告 chip */ +export function Header({ title, warningCount = 0 }: HeaderProps) { + return ( +
+

{title}

+
+
+
+ {warningCount > 0 && ( + + )} +
+
+ ); +} diff --git a/apps/desktop/src/components/KpiCard.tsx b/apps/desktop/src/components/KpiCard.tsx new file mode 100644 index 0000000..acdfaf3 --- /dev/null +++ b/apps/desktop/src/components/KpiCard.tsx @@ -0,0 +1,39 @@ +export type KpiTone = "primary" | "attention" | "accent" | "warning"; + +const TONE_COLOR: Record = { + primary: "var(--ad-primary)", + attention: "var(--ad-attention)", + accent: "var(--ad-accent)", + warning: "var(--ad-warning)", +}; + +interface KpiCardProps { + label: string; + value: number; + tone: KpiTone; + /** 副标题:对象点名句式(视觉规范 §3.1.1) */ + subtitle: string; +} + +/** + * KPI 卡(视觉规范 §3.1.1): + * - 径向渐变玻璃板 + 上缘高光 + --ad-shadow-panel + * - 顶部色条贯通整宽;数值为 0 时色条降灰、数字回 --ad-text-1 + * - 数字随状态色贯穿 + */ +export function KpiCard({ label, value, tone, subtitle }: KpiCardProps) { + const color = value > 0 ? TONE_COLOR[tone] : "var(--ad-border)"; + const valueColor = value > 0 ? TONE_COLOR[tone] : "var(--ad-text-1)"; + return ( +
+ + ); +} diff --git a/apps/desktop/src/components/MonoChip.tsx b/apps/desktop/src/components/MonoChip.tsx new file mode 100644 index 0000000..342c84e --- /dev/null +++ b/apps/desktop/src/components/MonoChip.tsx @@ -0,0 +1,6 @@ +import type { ReactNode } from "react"; + +/** 内联等宽 chip(视觉规范 §2.2:文件名/版本号/命令专用) */ +export function MonoChip({ children }: { children: ReactNode }) { + return {children}; +} diff --git a/apps/desktop/src/components/Sidebar.tsx b/apps/desktop/src/components/Sidebar.tsx new file mode 100644 index 0000000..6e4a846 --- /dev/null +++ b/apps/desktop/src/components/Sidebar.tsx @@ -0,0 +1,79 @@ +import { + Archive, + Gauge, + Library, + Settings, + SlidersHorizontal, + SquareTerminal, +} from "lucide-react"; +import type { LucideIcon } from "lucide-react"; + +export type PageKey = + | "overview" + | "catalog" + | "my-cli" + | "config" + | "backup" + | "settings"; + +export interface PageMeta { + title: string; +} + +export const PAGE_META: Record = { + overview: { title: "总览" }, + catalog: { title: "CLI 目录" }, + "my-cli": { title: "我的 CLI" }, + config: { title: "配置中心" }, + backup: { title: "备份与迁移" }, + settings: { title: "设置" }, +}; + +interface NavItem { + key: PageKey; + label: string; + icon: LucideIcon; +} + +const NAV_ITEMS: NavItem[] = [ + { key: "overview", label: "总览", icon: Gauge }, + { key: "catalog", label: "CLI 目录", icon: Library }, + { key: "my-cli", label: "我的 CLI", icon: SquareTerminal }, + { key: "config", label: "配置中心", icon: SlidersHorizontal }, + { key: "backup", label: "备份与迁移", icon: Archive }, + { key: "settings", label: "设置", icon: Settings }, +]; + +const ENGINE_VERSION = "v0.1.0"; + +interface SidebarProps { + current: PageKey; + onNavigate: (page: PageKey) => void; +} + +/** 左侧竖导航 + 底部引擎状态区(视觉规范 §3.0) */ +export function Sidebar({ current, onNavigate }: SidebarProps) { + return ( + + ); +} diff --git a/apps/desktop/src/components/StatusBadge.tsx b/apps/desktop/src/components/StatusBadge.tsx new file mode 100644 index 0000000..7e13f54 --- /dev/null +++ b/apps/desktop/src/components/StatusBadge.tsx @@ -0,0 +1,18 @@ +export type BadgeKind = "installed" | "update" | "auth" | "uninstalled"; + +const KIND_CLASS: Record = { + installed: "badge badge-installed", + update: "badge badge-update", + auth: "badge badge-auth", + uninstalled: "badge badge-uninstalled", +}; + +interface StatusBadgeProps { + kind: BadgeKind; + label: string; +} + +/** 状态角标(视觉规范 §3.1.4 / §3.2:已安装=青、可更新=品红+弱辉光、待授权=紫、未安装=灰) */ +export function StatusBadge({ kind, label }: StatusBadgeProps) { + return {label}; +} diff --git a/apps/desktop/src/hooks/useCatalog.ts b/apps/desktop/src/hooks/useCatalog.ts new file mode 100644 index 0000000..02f5dc9 --- /dev/null +++ b/apps/desktop/src/hooks/useCatalog.ts @@ -0,0 +1,38 @@ +import { useEffect, useState } from "react"; +import { listCatalog } from "../ipc"; +import type { CatalogEntry } from "../ipc/types"; + +export interface UseCatalogResult { + entries: CatalogEntry[]; + loading: boolean; + error: string | null; +} + +/** 加载适配器目录(listCatalog) */ +export function useCatalog(): UseCatalogResult { + const [entries, setEntries] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + let cancelled = false; + listCatalog() + .then((list) => { + if (!cancelled) { + setEntries(list); + setLoading(false); + } + }) + .catch((err: unknown) => { + if (!cancelled) { + setError(String(err)); + setLoading(false); + } + }); + return () => { + cancelled = true; + }; + }, []); + + return { entries, loading, error }; +} diff --git a/apps/desktop/src/hooks/useEnv.ts b/apps/desktop/src/hooks/useEnv.ts new file mode 100644 index 0000000..f713687 --- /dev/null +++ b/apps/desktop/src/hooks/useEnv.ts @@ -0,0 +1,38 @@ +import { useEffect, useState } from "react"; +import { detectEnv } from "../ipc"; +import type { PlatformEnv } from "../ipc/types"; + +export interface UseEnvResult { + env: PlatformEnv | null; + loading: boolean; + error: string | null; +} + +/** 加载本机环境检测结果(一次性的只读快照) */ +export function useEnv(): UseEnvResult { + const [env, setEnv] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + let cancelled = false; + detectEnv() + .then((e) => { + if (!cancelled) { + setEnv(e); + setLoading(false); + } + }) + .catch((err: unknown) => { + if (!cancelled) { + setError(String(err)); + setLoading(false); + } + }); + return () => { + cancelled = true; + }; + }, []); + + return { env, loading, error }; +} diff --git a/apps/desktop/src/ipc/index.ts b/apps/desktop/src/ipc/index.ts new file mode 100644 index 0000000..1b12d66 --- /dev/null +++ b/apps/desktop/src/ipc/index.ts @@ -0,0 +1,58 @@ +// 类型化 invoke 封装(唯一前端 → Rust 入口,架构 §2「界面层禁直接拼命令」) +import { invoke } from "@tauri-apps/api/core"; +import type { CatalogEntry, PlatformEnv } from "./types"; + +/** 是否运行在 Tauri 环境(否则走 mock,便于纯浏览器联调 UI) */ +function isTauri(): boolean { + return typeof window !== "undefined" && "__TAURI_INTERNALS__" in window; +} + +export async function detectEnv(): Promise { + if (!isTauri()) { + return mockPlatformEnv(); + } + return invoke("detectEnv"); +} + +export async function listCatalog(): Promise { + if (!isTauri()) { + return mockCatalog(); + } + return invoke("listCatalog"); +} + +// ---- 浏览器联调用 mock(仅当不在 Tauri 内时生效,不影响真实数据) ---- +const mockCatalog = (): CatalogEntry[] => [ + { id: "codex", name: "Codex CLI", name_zh: "Codex CLI", vendor: "OpenAI", status: "available" }, + { id: "claude-code", name: "Claude Code", name_zh: "Claude Code", vendor: "Anthropic", status: "available" }, + { id: "gemini", name: "Gemini CLI", name_zh: "Gemini CLI", vendor: "Google", status: "available" }, + { id: "copilot", name: "Copilot CLI", name_zh: "Copilot CLI", vendor: "GitHub", status: "available" }, + { id: "kimi", name: "Kimi CLI", name_zh: "Kimi CLI", vendor: "月之暗面", status: "available" }, + { id: "qwen", name: "Qwen Code", name_zh: "Qwen Code", vendor: "阿里巴巴", status: "available" }, + { id: "codebuddy", name: "CodeBuddy Code", name_zh: "CodeBuddy Code", vendor: "腾讯", status: "available" }, + { id: "opencode", name: "OpenCode", name_zh: "OpenCode", vendor: "opencode.ai", status: "available" }, + { id: "crush", name: "Crush", name_zh: "Crush", vendor: "Charm", status: "available" }, + { id: "goose", name: "Goose", name_zh: "Goose", vendor: "Linux 基金会(AAIF)", status: "available" }, + { id: "aider", name: "Aider", name_zh: "Aider", vendor: "aider.chat", status: "available" }, + { id: "cursor", name: "Cursor CLI", name_zh: "Cursor CLI", vendor: "Cursor", status: "available" }, + { id: "cline", name: "Cline", name_zh: "Cline", vendor: "Cline", status: "available" }, + { id: "warp", name: "Warp Agent CLI", name_zh: "Warp Agent CLI", vendor: "Warp", status: "available" }, +]; + +const mockPlatformEnv = (): PlatformEnv => ({ + os: "windows", + os_version: "Windows 11 24H2 (Build 26100)", + arch: "x86_64", + shells: { powershell_version: "5.1.26100.1", pwsh_version: null, bash_available: true }, + runtimes: { + node: { status: "installed", version: "24.18.0", path: "C:\\Program Files\\nodejs\\node.exe" }, + npm: { status: "installed", version: "11.16.0", path: "C:\\Program Files\\nodejs\\npm.cmd" }, + python: { status: "installed", version: "3.14.6", path: "C:\\Python314\\python.exe" }, + uv: { status: "not_in_path", version: null, path: null }, + git: { status: "installed", version: "2.47.1", path: "C:\\Program Files\\Git\\cmd\\git.exe" }, + winget: { status: "installed", version: "1.8.1911", path: "C:\\Users\\MoBai\\AppData\\Local\\Microsoft\\WindowsApps\\winget.exe" }, + apt: { status: "not_in_path", version: null, path: null }, + }, + path_entries: ["C:\\Windows\\system32", "C:\\Windows", "C:\\Program Files\\nodejs"], + capabilities: { keyring: "ok", can_elevate: false }, +}); diff --git a/apps/desktop/src/ipc/types.ts b/apps/desktop/src/ipc/types.ts new file mode 100644 index 0000000..e1ced7a --- /dev/null +++ b/apps/desktop/src/ipc/types.ts @@ -0,0 +1,54 @@ +// IPC 契约类型(对齐架构 §5 PlatformEnv / listCatalog) +// 字段命名与 Rust 侧 serde 输出一致(snake_case)。 + +export interface PlatformEnv { + os: string; + os_version: string; + arch: string; + shells: Shells; + runtimes: Runtimes; + path_entries: string[]; + capabilities: Capabilities; +} + +export interface Shells { + powershell_version: string | null; + pwsh_version: string | null; + bash_available: boolean; +} + +export interface Runtimes { + node: RuntimeInfo | null; + npm: RuntimeInfo | null; + python: RuntimeInfo | null; + uv: RuntimeInfo | null; + git: RuntimeInfo | null; + winget: RuntimeInfo | null; + apt: RuntimeInfo | null; +} + +export type RuntimeStatus = + | "installed" + | "not_installed" + | "not_in_path" + | "exec_failed" + | "version_unparseable"; + +export interface RuntimeInfo { + status: RuntimeStatus; + version: string | null; + path: string | null; +} + +export interface Capabilities { + keyring: string; + can_elevate: boolean; +} + +export interface CatalogEntry { + id: string; + name: string; + name_zh: string; + vendor: string; + status: string; +} diff --git a/apps/desktop/src/main.tsx b/apps/desktop/src/main.tsx new file mode 100644 index 0000000..673ca6d --- /dev/null +++ b/apps/desktop/src/main.tsx @@ -0,0 +1,30 @@ +import React from "react"; +import ReactDOM from "react-dom/client"; +import App from "./App"; + +// 设计 Token(视觉规范 v1.2,唯一品味依据) +import "./tokens/color.css"; +import "./tokens/typography.css"; +import "./tokens/space.css"; +import "./tokens/motion.css"; +import "./tokens/effects.css"; +import "./tokens/tiers.css"; +import "./styles/global.css"; + +/** 性能档位自动判定(架构 §8.3 / 视觉规范 §5) */ +function applyFxTier(): void { + const html = document.documentElement; + const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches; + const cores = navigator.hardwareConcurrency ?? 8; + if (reduce || cores <= 4) { + html.dataset.fxTier = "low"; + } +} + +applyFxTier(); + +ReactDOM.createRoot(document.getElementById("root")!).render( + + + , +); diff --git a/apps/desktop/src/pages/Backup.tsx b/apps/desktop/src/pages/Backup.tsx new file mode 100644 index 0000000..0f799c9 --- /dev/null +++ b/apps/desktop/src/pages/Backup.tsx @@ -0,0 +1,19 @@ +import { Archive } from "lucide-react"; + +/** 备份与迁移(PRD §7):创建备份、查看内容、恢复。Wave 0 占位。 */ +export function BackupPage() { + return ( +
+
+
+

备份与迁移

+

+ 备份功能在 Wave 4 落地。备份将明确标注是否包含敏感信息,密钥永不进备份。 +

+ +
+ ); +} diff --git a/apps/desktop/src/pages/Catalog.tsx b/apps/desktop/src/pages/Catalog.tsx new file mode 100644 index 0000000..dafab11 --- /dev/null +++ b/apps/desktop/src/pages/Catalog.tsx @@ -0,0 +1,113 @@ +import { useMemo, useState } from "react"; +import { Search } from "lucide-react"; +import { useCatalog } from "../hooks/useCatalog"; +import { StatusBadge } from "../components/StatusBadge"; +import { MonoChip } from "../components/MonoChip"; +import { CliMonogram } from "../components/CliMonogram"; + +type StatusFilter = "all" | "installed" | "uninstalled" | "update"; +type PlatformFilter = "all" | "windows" | "linux"; + +const STATUS_FILTERS: { key: StatusFilter; label: string }[] = [ + { key: "all", label: "全部" }, + { key: "installed", label: "已安装" }, + { key: "uninstalled", label: "未安装" }, + { key: "update", label: "可更新" }, +]; + +const PLATFORM_FILTERS: { key: PlatformFilter; label: string }[] = [ + { key: "all", label: "全部平台" }, + { key: "windows", label: "Windows" }, + { key: "linux", label: "Linux" }, +]; + +/** CLI 目录页(视觉规范 §3.2 + PRD §7):搜索 + 筛选 + 14 张卡片(数据来自 catalog.yaml) */ +export function CatalogPage() { + const { entries, loading, error } = useCatalog(); + const [query, setQuery] = useState(""); + const [status, setStatus] = useState("all"); + const [platform, setPlatform] = useState("all"); + + const filtered = useMemo(() => { + const q = query.trim().toLowerCase(); + return entries.filter((e) => { + if (q) { + const haystack = `${e.name_zh} ${e.name} ${e.vendor} ${e.id}`.toLowerCase(); + if (!haystack.includes(q)) return false; + } + // Wave 0:14 个均为未安装;已安装/可更新筛选结果为空(诚实占位) + if (status === "installed") return false; + if (status === "update") return false; + // 平台:全部 14 个均支持 Windows + Ubuntu(调研底稿结论),筛选不改变集合 + if (platform === "windows" || platform === "linux") return true; + return true; + }); + }, [entries, query, status, platform]); + + return ( +
+
+
+
+
+ {STATUS_FILTERS.map((f) => ( + + ))} +
+
+ {PLATFORM_FILTERS.map((f) => ( + + ))} +
+
+ + {error &&

目录加载失败:{error}

} + {loading && !error &&

目录加载中…

} + +
+ {filtered.map((entry) => ( +
+
+ +
+
{entry.name_zh}
+
{entry.vendor}
+
+
+

官方渠道安装 · 适配器随 Wave 1 落地

+
+ + Windows · Linux + v1 +
+
+ ))} + {!loading && filtered.length === 0 && ( +

没有符合条件的 CLI

+ )} +
+
+ ); +} diff --git a/apps/desktop/src/pages/ConfigCenter.tsx b/apps/desktop/src/pages/ConfigCenter.tsx new file mode 100644 index 0000000..778aeb7 --- /dev/null +++ b/apps/desktop/src/pages/ConfigCenter.tsx @@ -0,0 +1,19 @@ +import { SlidersHorizontal } from "lucide-react"; + +/** 配置中心(PRD §7):按 CLI 展示中文配置表单。Wave 0 占位。 */ +export function ConfigCenterPage() { + return ( +
+
+
+

配置中心

+

+ 中文配置表单在 Wave 2 落地。敏感字段将使用密码输入与系统密钥库。 +

+ +
+ ); +} diff --git a/apps/desktop/src/pages/MyCli.tsx b/apps/desktop/src/pages/MyCli.tsx new file mode 100644 index 0000000..b423456 --- /dev/null +++ b/apps/desktop/src/pages/MyCli.tsx @@ -0,0 +1,19 @@ +import { SquareTerminal } from "lucide-react"; + +/** 我的 CLI(PRD §7):版本 / 路径 / 授权状态。Wave 0 尚无已安装 CLI,展示空态。 */ +export function MyCliPage() { + return ( +
+
+
+

暂无已安装 CLI

+

+ 安装功能在 Wave 1 开放。届时这里会展示每个 CLI 的版本、路径与授权状态。 +

+ +
+ ); +} diff --git a/apps/desktop/src/pages/Overview.tsx b/apps/desktop/src/pages/Overview.tsx new file mode 100644 index 0000000..0aca283 --- /dev/null +++ b/apps/desktop/src/pages/Overview.tsx @@ -0,0 +1,254 @@ +import { useState } from "react"; +import { Activity, Archive, ChevronRight, Lock, Plus } from "lucide-react"; +import { useEnv } from "../hooks/useEnv"; +import { useCatalog } from "../hooks/useCatalog"; +import { KpiCard } from "../components/KpiCard"; +import { MonoChip } from "../components/MonoChip"; +import { StatusBadge } from "../components/StatusBadge"; +import { CliMonogram } from "../components/CliMonogram"; +import type { PlatformEnv, RuntimeInfo } from "../ipc/types"; + +/** 平台相关运行时集合(Windows 不看 apt,Linux 不看 winget) */ +const WINDOWS_RUNTIMES = ["node", "npm", "python", "uv", "git", "winget"] as const; +const LINUX_RUNTIMES = ["node", "npm", "python", "uv", "git", "apt"] as const; + +function runtimeProblems(env: PlatformEnv): { name: string; info: RuntimeInfo }[] { + const keys = env.os === "windows" ? WINDOWS_RUNTIMES : LINUX_RUNTIMES; + const problems: { name: string; info: RuntimeInfo }[] = []; + for (const key of keys) { + const info = env.runtimes[key]; + if (info && info.status !== "installed") { + problems.push({ name: key, info }); + } + } + return problems; +} + +function runtimeStatusText(status: string): string { + switch (status) { + case "not_in_path": + return "不在 PATH"; + case "not_installed": + return "未安装"; + case "exec_failed": + return "执行失败"; + case "version_unparseable": + return "版本未知"; + default: + return "未知"; + } +} + +function RuntimeItem({ name, info }: { name: string; info: RuntimeInfo }) { + const dotClass = + info.status === "installed" + ? "status-dot ok" + : info.status === "exec_failed" + ? "status-dot error" + : "status-dot warn"; + return ( +
+
+ ); +} + +function EnvPanel() { + const { env, loading, error } = useEnv(); + const [showAllPath, setShowAllPath] = useState(false); + + if (error) { + return ( +
+
+

本机环境

+
+

环境检测失败:{error}

+
+ ); + } + + const pathPreview = env ? env.path_entries.slice(0, 8) : []; + + return ( +
+
+

本机环境

+ {loading && 检测中…} +
+ {env && ( + <> +
+
+
+ 系统 + {env.os_version} +
+
+ 架构 + {env.arch} +
+
+ Shell + + {env.shells.powershell_version ? ( + <>PowerShell {env.shells.powershell_version} + ) : null} + {env.shells.pwsh_version ? ( + <> · pwsh {env.shells.pwsh_version} + ) : null} + {env.shells.bash_available ? " · Bash ✓" : ""} + +
+
+ 密钥库 + + {env.capabilities.keyring === "ok" ? "Credential Manager ✓" : "密钥库缺失"} + +
+
+ 提权 + {env.capabilities.can_elevate ? "可用" : "不可用"} +
+
+
+ {(["node", "npm", "python", "uv", "git", "winget", "apt"] as const).map( + (key) => { + const info = env.runtimes[key]; + if (!info) return null; + return ; + }, + )} +
+
+
+
+ + PATH({env.path_entries.length} 条) + {env.path_entries.length} + + {env.path_entries.length > pathPreview.length && ( + + )} +
+ {(showAllPath ? env.path_entries : pathPreview).map((entry, idx) => ( +
+ {entry} +
+ ))} +
+ + )} +
+ ); +} + +/** 总览页(视觉规范 §3.1 + PRD §7):KPI + 最近诊断/快速操作 + CLI 状态网格 + 本机环境 */ +export function OverviewPage() { + const { env } = useEnv(); + const { entries } = useCatalog(); + + const warningCount = env ? runtimeProblems(env).length : 0; + const warningNames = env ? runtimeProblems(env).map((p) => p.name) : []; + + return ( +
+ {/* ① KPI 一排 4 张 */} +
+ + + + 0 ? warningNames.join(" · ") : "环境正常"} + /> +
+ + {/* ② 中段:左 2/3 最近诊断 + 右 1/3 快速操作 */} +
+
+
+

最近诊断

+ +
+
    +
  • +
  • +
+
+
+

快速操作

+ + + +
+
最近安装
+

暂无记录

+
+

+

+
+
+ + {/* ③ 下段:CLI 状态网格通栏 */} +
+
+

CLI 状态

+ +
+
+ {entries.map((entry) => ( +
+
+ + {entry.name_zh} + +
+
+ +
+
+
+
+ ))} +
+
+ + {/* ④ 本机环境(真实检测结果,架构 §5) */} + +
+ ); +} diff --git a/apps/desktop/src/pages/Settings.tsx b/apps/desktop/src/pages/Settings.tsx new file mode 100644 index 0000000..6cc303e --- /dev/null +++ b/apps/desktop/src/pages/Settings.tsx @@ -0,0 +1,44 @@ +import { Settings } from "lucide-react"; + +/** 设置(PRD §7):下载源策略 / 自动检查更新 / 语言 / 日志与隐私。Wave 0 静态占位。 */ +export function SettingsPage() { + return ( +
+

常规

+
+
+
+
下载源策略
+
选择 CLI 安装时的首选下载渠道(Wave 1 生效)
+
+ 官方渠道 +
+
+
+
自动检查更新
+
启动时检查 AgentDock 自身与 CLI 的更新(Wave 4 生效)
+
+ +
+
+
+
语言
+
第一版仅提供简体中文
+
+ 简体中文 +
+
+
+
日志与隐私
+
日志本地保存,敏感值自动脱敏(Wave 1 生效)
+
+ 默认 +
+
+
+
+
+ ); +} diff --git a/apps/desktop/src/styles/global.css b/apps/desktop/src/styles/global.css new file mode 100644 index 0000000..f99911c --- /dev/null +++ b/apps/desktop/src/styles/global.css @@ -0,0 +1,1009 @@ +/* ============================================================ + * AgentDock 全局样式(Wave 0) + * 全部颜色/辉光/动效时长来自 tokens/(视觉规范 v1.2), + * 本文件不出现任何魔法色值;布局尺寸来自规范 §3.0/§6。 + * ============================================================ */ + +/* ---------- 重置与基础 ---------- */ +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +html, +body, +#root { + height: 100%; +} + +body { + font-family: var(--ad-font-ui); + font-size: var(--ad-text-m-size); + line-height: var(--ad-text-m-height); + color: var(--ad-text-1); + background: var(--ad-bg-0); + overflow: hidden; + -webkit-font-smoothing: antialiased; +} + +button { + font-family: inherit; +} + +/* ---------- 背景网格(§3.0:5% + 边缘羽化,低档静态) ---------- */ +.bg-grid { + position: fixed; + inset: 0; + z-index: 0; + pointer-events: none; + background-image: + linear-gradient(var(--ad-grid-color) 1px, transparent 1px), + linear-gradient(90deg, var(--ad-grid-color) 1px, transparent 1px); + background-size: var(--ad-grid-size) var(--ad-grid-size); + -webkit-mask-image: var(--ad-grid-mask); + mask-image: var(--ad-grid-mask); +} + +/* ---------- 应用外壳 ---------- */ +.app-shell { + position: relative; + display: flex; + height: 100%; + z-index: 1; +} + +.app-main { + flex: 1; + min-width: 0; + display: flex; + flex-direction: column; +} + +.app-content { + flex: 1; + overflow-y: auto; + width: 100%; + max-width: 1440px; /* §6 宽阔断点锁宽居中 */ + margin: 0 auto; + padding: var(--ad-space-6) var(--ad-space-8); +} + +/* ---------- 侧边栏(§3.0) ---------- */ +.sidebar { + width: 232px; + flex-shrink: 0; + display: flex; + flex-direction: column; + background: var(--ad-bg-1); + border-right: 1px solid var(--ad-border); + padding: var(--ad-space-3) 0 0; +} + +.sidebar-nav { + flex: 1; + display: flex; + flex-direction: column; + gap: 2px; + padding: 0 var(--ad-space-2); +} + +/* 导航项:圆角背景块,选中态为「左缘生长光晕 + 内描边」,无独立指示条(v1.2) */ +.nav-item { + display: flex; + align-items: center; + gap: var(--ad-space-3); + width: 100%; + height: 40px; + padding: 0 var(--ad-space-3); + border: none; + border-radius: var(--ad-radius-m); + background: transparent; + color: var(--ad-text-2); + font-size: var(--ad-text-m-size); + cursor: pointer; + user-select: none; + transition: background var(--ad-dur-fast) var(--ad-ease-out), + color var(--ad-dur-fast) var(--ad-ease-out); +} + +.nav-item:hover { + background: var(--ad-bg-3); + color: var(--ad-text-1); +} + +.nav-item.active { + background: var(--ad-nav-selected-bg); + box-shadow: var(--ad-nav-selected-border); + color: var(--ad-primary); +} + +.nav-icon { + flex-shrink: 0; +} + +/* 底部引擎状态区(§3.0:48px + 顶部分隔线) */ +.sidebar-engine { + height: 48px; + flex-shrink: 0; + display: flex; + align-items: center; + gap: var(--ad-space-2); + padding: 0 var(--ad-space-4); + border-top: 1px solid var(--ad-border); + color: var(--ad-text-2); + font-size: var(--ad-text-s-size); + white-space: nowrap; + overflow: hidden; +} + +.engine-version { + margin-left: auto; +} + +/* ---------- 顶栏(§3.0) ---------- */ +.header { + height: 56px; + flex-shrink: 0; + display: flex; + align-items: center; + justify-content: space-between; + gap: var(--ad-space-4); + padding: 0 var(--ad-space-8); + background: var(--ad-bg-0); + border-bottom: 1px solid var(--ad-border); +} + +.header-title { + font-size: var(--ad-text-xl-size); + font-weight: var(--ad-text-xl-weight); + white-space: nowrap; +} + +.header-actions { + display: flex; + align-items: center; + gap: var(--ad-space-3); +} + +/* 搜索框(§3.0:限宽 320px,聚焦青边框 + 主辉光) */ +.search-box { + position: relative; + width: 320px; +} + +.search-box input { + width: 100%; + height: 36px; + padding: 0 var(--ad-space-3) 0 36px; + border: 1px solid var(--ad-border); + border-radius: var(--ad-radius-m); + background: var(--ad-bg-1); + color: var(--ad-text-1); + font-size: var(--ad-text-m-size); + outline: none; + transition: border-color var(--ad-dur-micro) var(--ad-ease-out), + box-shadow var(--ad-dur-micro) var(--ad-ease-out); +} + +.search-box input::placeholder { + color: var(--ad-text-3); +} + +.search-box input:focus { + border-color: var(--ad-primary); + box-shadow: var(--ad-glow-primary); +} + +.search-icon { + position: absolute; + left: var(--ad-space-3); + top: 50%; + transform: translateY(-50%); + color: var(--ad-text-3); + pointer-events: none; +} + +/* 环境警告 chip(§3.0:黄描边 + 黄点 + chevron,悬浮带辉光) */ +.env-chip { + display: inline-flex; + align-items: center; + gap: var(--ad-space-2); + height: 28px; + padding: 0 var(--ad-space-3); + border: 1px solid var(--ad-warning-chip-border); + border-radius: var(--ad-radius-s); + background: var(--ad-warning-dim); + color: var(--ad-warning); + font-size: var(--ad-text-s-size); + cursor: pointer; + transition: border-color var(--ad-dur-fast) var(--ad-ease-out), + box-shadow var(--ad-dur-fast) var(--ad-ease-out); +} + +.env-chip:hover { + border-color: var(--ad-warning); + box-shadow: var(--ad-glow-warning); +} + +/* ---------- 按钮 ---------- */ +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: var(--ad-space-2); + height: 36px; + padding: 0 var(--ad-space-4); + border: 1px solid transparent; + border-radius: var(--ad-radius-s); + font-size: var(--ad-text-m-size); + font-weight: 500; + cursor: pointer; + transition: filter var(--ad-dur-fast) var(--ad-ease-out), + box-shadow var(--ad-dur-fast) var(--ad-ease-out), + border-color var(--ad-dur-fast) var(--ad-ease-out); +} + +.btn:disabled { + opacity: 0.55; + cursor: not-allowed; +} + +/* 主按钮(§2.6 v1.2:内渐变 + 内高光 + 常驻弱辉光,hover 双层扩散辉光) */ +.btn-primary { + background: var(--ad-btn-primary-bg); + box-shadow: var(--ad-btn-primary-inner), var(--ad-btn-primary-glow); + color: var(--ad-btn-primary-text); +} + +.btn-primary:hover:not(:disabled) { + filter: brightness(1.08); + box-shadow: var(--ad-btn-primary-inner), var(--ad-btn-primary-glow-hover); +} + +.btn-primary:active:not(:disabled) { + filter: brightness(0.94); + box-shadow: var(--ad-btn-primary-inner); +} + +/* 次按钮(§3.6) */ +.btn-secondary { + background: transparent; + border-color: var(--ad-border-bright); + color: var(--ad-text-1); +} + +.btn-secondary:hover:not(:disabled) { + border-color: var(--ad-primary); +} + +/* 链接式按钮 */ +.link-btn { + display: inline-flex; + align-items: center; + gap: var(--ad-space-1); + border: none; + background: none; + color: var(--ad-primary); + font-size: var(--ad-text-s-size); + cursor: pointer; + transition: color var(--ad-dur-fast) var(--ad-ease-out); +} + +.link-btn:hover { + color: var(--ad-primary-hover); +} + +.link-btn svg { + transition: transform var(--ad-dur-fast) var(--ad-ease-out); +} + +.link-btn:hover svg { + transform: translateX(2px); +} + +/* ---------- 通用小组件 ---------- */ +/* Mono chip(§2.2) */ +.mono-chip { + display: inline-block; + font-family: var(--ad-mono-chip-font); + font-size: var(--ad-mono-chip-size); + line-height: 1.5; + background: var(--ad-mono-chip-bg); + border: var(--ad-mono-chip-border); + border-radius: var(--ad-mono-chip-radius); + padding: var(--ad-mono-chip-padding); + color: var(--ad-mono-chip-color); + white-space: nowrap; +} + +/* CLI 单色字母头像(§3.1.4 / §7) */ +.monogram { + display: inline-flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + border: 1px solid var(--ad-border); + border-radius: var(--ad-radius-m); + background: var(--ad-bg-2); + color: var(--ad-text-2); + font-weight: 600; + letter-spacing: 0.02em; +} + +/* 状态角标(§3.1.4 / §3.2) */ +.badge { + display: inline-flex; + align-items: center; + height: 22px; + padding: 0 var(--ad-space-2); + border: 1px solid transparent; + border-radius: var(--ad-radius-s); + font-size: var(--ad-text-xs-size); + white-space: nowrap; +} + +.badge-installed { + color: var(--ad-primary); + border-color: var(--ad-primary-border); + background: var(--ad-primary-dim); +} + +.badge-update { + color: var(--ad-accent); + border-color: var(--ad-accent-border); + background: var(--ad-accent-dim); + box-shadow: var(--ad-glow-accent); +} + +.badge-auth { + color: var(--ad-attention); + border-color: var(--ad-attention-border); + background: var(--ad-attention-dim); +} + +.badge-uninstalled { + color: var(--ad-text-3); + border-color: var(--ad-border); + background: var(--ad-bg-1); +} + +/* 状态点(§4.5:绿静态;警告/错误可呼吸;紫/灰静态) */ +.status-dot { + width: 8px; + height: 8px; + border-radius: 50%; + flex-shrink: 0; +} + +.status-dot.ok { + background: var(--ad-success); +} + +.status-dot.warn { + background: var(--ad-warning); +} + +.status-dot.error { + background: var(--ad-danger); +} + +.status-dot.unknown { + background: var(--ad-text-3); +} + +.status-dot.breathe { + animation: ad-breathe var(--ad-breathe-duration) var(--ad-ease-inout) infinite; +} + +/* ---------- 面板 ---------- */ +.panel { + background: var(--ad-bg-1); + border: 1px solid var(--ad-border); + border-radius: var(--ad-radius-l); + padding: var(--ad-space-5); +} + +.panel-head { + display: flex; + align-items: center; + justify-content: space-between; + gap: var(--ad-space-4); + margin-bottom: var(--ad-space-4); +} + +.panel-title { + font-size: var(--ad-text-l-size); + font-weight: var(--ad-text-l-weight); +} + +.panel-hint { + color: var(--ad-text-2); + font-size: var(--ad-text-xs-size); +} + +.panel-empty { + padding: var(--ad-space-5); + color: var(--ad-text-2); + font-size: var(--ad-text-s-size); +} + +/* ---------- 总览:KPI 卡(§3.1.1) ---------- */ +.kpi-grid { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: var(--ad-space-4); + margin-bottom: var(--ad-space-6); +} + +.kpi-card { + position: relative; + overflow: hidden; + padding: var(--ad-space-4) var(--ad-space-5) var(--ad-space-5); + border-radius: var(--ad-radius-l); + background: var(--ad-surface-card); + box-shadow: var(--ad-card-highlight), var(--ad-shadow-panel); + transition: transform var(--ad-dur-fast) var(--ad-ease-out); +} + +.kpi-card:hover { + transform: translateY(-2px); +} + +.kpi-bar { + position: absolute; + top: 0; + left: 0; + right: 0; + height: 2px; +} + +.kpi-value { + font-size: var(--ad-text-num-size); + line-height: var(--ad-text-num-height); + font-weight: var(--ad-text-num-weight); +} + +.kpi-label { + margin-top: 2px; + color: var(--ad-text-2); + font-size: var(--ad-text-s-size); +} + +.kpi-subtitle { + margin-top: var(--ad-space-2); + color: var(--ad-text-2); + font-size: var(--ad-text-xs-size); +} + +/* ---------- 总览:中段(诊断 + 快速操作) ---------- */ +.overview-mid { + display: grid; + grid-template-columns: 2fr 1fr; + gap: var(--ad-space-4); + margin-bottom: var(--ad-space-6); +} + +.diag-row { + display: flex; + align-items: center; + gap: var(--ad-space-3); + min-height: 48px; + padding: 0 var(--ad-space-2); + border-bottom: 1px solid var(--ad-border); +} + +.diag-row:last-child { + border-bottom: none; +} + +.diag-cli { + color: var(--ad-text-1); + font-size: var(--ad-text-m-size); + white-space: nowrap; +} + +.diag-text { + color: var(--ad-text-2); + font-size: var(--ad-text-s-size); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.diag-time { + margin-left: auto; + color: var(--ad-text-2); + font-size: var(--ad-text-xs-size); + white-space: nowrap; +} + +.quick-card { + display: flex; + flex-direction: column; + gap: var(--ad-space-3); +} + +.quick-card .btn { + width: 100%; +} + +.recent-installs { + margin-top: var(--ad-space-2); +} + +.group-label { + color: var(--ad-text-3); + font-size: var(--ad-text-xs-size); +} + +.group-empty { + padding: var(--ad-space-2) 0; + color: var(--ad-text-2); + font-size: var(--ad-text-s-size); +} + +.safety-note { + display: flex; + align-items: center; + gap: var(--ad-space-2); + margin-top: auto; + padding-top: var(--ad-space-3); + border-top: 1px solid var(--ad-border); + color: var(--ad-text-2); + font-size: var(--ad-text-xs-size); +} + +/* ---------- 总览:CLI 状态网格(§3.1.4) ---------- */ +.cli-status-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); + gap: var(--ad-space-4); +} + +.cli-block { + display: flex; + flex-direction: column; + gap: var(--ad-space-2); + padding: var(--ad-space-4); + background: var(--ad-bg-1); + border: 1px solid var(--ad-border); + border-radius: var(--ad-radius-m); + transition: border-color var(--ad-dur-fast) var(--ad-ease-out); +} + +.cli-block:hover { + border-color: var(--ad-border-bright); +} + +.cli-block-top { + display: flex; + align-items: center; + gap: var(--ad-space-3); +} + +.cli-block-name { + flex: 1; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-size: var(--ad-text-m-size); + color: var(--ad-text-1); +} + +.cli-block-version .mono-chip { + color: var(--ad-text-3); +} + +.cli-block-auth { + display: flex; + align-items: center; + gap: var(--ad-space-2); + color: var(--ad-text-2); + font-size: var(--ad-text-xs-size); +} + +/* ---------- 总览:本机环境 ---------- */ +.env-panel { + margin-top: var(--ad-space-6); +} + +.env-grid { + display: grid; + grid-template-columns: 1.1fr 1fr; + gap: var(--ad-space-6); +} + +.env-basic { + display: flex; + flex-direction: column; + gap: var(--ad-space-3); +} + +.env-row { + display: flex; + align-items: baseline; + gap: var(--ad-space-3); +} + +.env-key { + flex-shrink: 0; + width: 64px; + color: var(--ad-text-2); + font-size: var(--ad-text-s-size); +} + +.env-val { + color: var(--ad-text-1); + font-size: var(--ad-text-m-size); + word-break: break-all; +} + +.runtime-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + gap: var(--ad-space-3); + align-content: start; +} + +.runtime-item { + display: flex; + align-items: center; + gap: var(--ad-space-2); +} + +.runtime-name { + flex: 1; + color: var(--ad-text-2); + font-size: var(--ad-text-s-size); +} + +.runtime-missing { + color: var(--ad-warning); + font-size: var(--ad-text-xs-size); +} + +.path-block { + margin-top: var(--ad-space-5); + padding-top: var(--ad-space-4); + border-top: 1px solid var(--ad-border); +} + +.path-head { + display: flex; + align-items: center; + gap: var(--ad-space-3); + margin-bottom: var(--ad-space-2); +} + +.path-title { + display: flex; + align-items: center; + gap: var(--ad-space-2); + color: var(--ad-text-2); + font-size: var(--ad-text-s-size); +} + +.path-entry { + padding: var(--ad-space-1) 0; + color: var(--ad-text-2); + font-size: var(--ad-text-xs-size); + font-family: var(--ad-font-mono); + word-break: break-all; +} + +/* ---------- CLI 目录(§3.2) ---------- */ +.catalog-toolbar { + display: flex; + align-items: center; + gap: var(--ad-space-4); + flex-wrap: wrap; + margin-bottom: var(--ad-space-5); +} + +.filter-group { + display: flex; + align-items: center; + gap: var(--ad-space-2); +} + +.pill { + height: 32px; + padding: 0 var(--ad-space-3); + border: 1px solid var(--ad-border); + border-radius: 16px; + background: transparent; + color: var(--ad-text-2); + font-size: var(--ad-text-s-size); + cursor: pointer; + transition: border-color var(--ad-dur-fast) var(--ad-ease-out), + color var(--ad-dur-fast) var(--ad-ease-out); +} + +.pill:hover { + border-color: var(--ad-border-bright); + color: var(--ad-text-1); +} + +.pill.active { + border-color: var(--ad-primary); + color: var(--ad-primary); + background: var(--ad-primary-dim); +} + +.catalog-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); + gap: var(--ad-space-4); +} + +.catalog-card { + display: flex; + flex-direction: column; + gap: var(--ad-space-3); + padding: var(--ad-space-5); + background: var(--ad-bg-1); + border: 1px solid var(--ad-border); + border-radius: var(--ad-radius-m); + transition: border-color var(--ad-dur-fast) var(--ad-ease-out), + box-shadow var(--ad-dur-fast) var(--ad-ease-out); +} + +.catalog-card:hover { + border-color: var(--ad-primary); + box-shadow: var(--ad-glow-primary); +} + +.catalog-card-top { + display: flex; + align-items: center; + gap: var(--ad-space-3); +} + +.catalog-card-head { + min-width: 0; +} + +.catalog-card-name { + font-size: var(--ad-text-l-size); + font-weight: var(--ad-text-l-weight); + color: var(--ad-text-1); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.catalog-card-vendor { + color: var(--ad-text-2); + font-size: var(--ad-text-s-size); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.catalog-card-desc { + color: var(--ad-text-2); + font-size: var(--ad-text-s-size); + line-height: 1.5; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.catalog-card-bottom { + display: flex; + align-items: center; + gap: var(--ad-space-3); + margin-top: auto; +} + +.catalog-platforms { + margin-left: auto; + color: var(--ad-text-3); + font-size: var(--ad-text-xs-size); + white-space: nowrap; +} + +.catalog-empty { + grid-column: 1 / -1; +} + +/* ---------- 占位页(Wave 0 页面) ---------- */ +.placeholder-page { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: var(--ad-space-4); + min-height: 60vh; + text-align: center; +} + +.placeholder-icon { + color: var(--ad-text-3); +} + +.placeholder-title { + font-size: var(--ad-text-xl-size); + font-weight: var(--ad-text-xl-weight); +} + +.placeholder-desc { + max-width: 480px; + color: var(--ad-text-2); + font-size: var(--ad-text-m-size); +} + +/* ---------- 设置页 ---------- */ +.settings-page { + max-width: 720px; +} + +.settings-group { + margin-top: var(--ad-space-4); + background: var(--ad-bg-1); + border: 1px solid var(--ad-border); + border-radius: var(--ad-radius-l); +} + +.setting-row { + display: flex; + align-items: center; + justify-content: space-between; + gap: var(--ad-space-4); + padding: var(--ad-space-4) var(--ad-space-5); + border-bottom: 1px solid var(--ad-border); +} + +.setting-row:last-child { + border-bottom: none; +} + +.setting-label { + color: var(--ad-text-1); + font-size: var(--ad-text-m-size); +} + +.setting-hint { + margin-top: 2px; + color: var(--ad-text-2); + font-size: var(--ad-text-xs-size); +} + +.setting-value { + flex-shrink: 0; + color: var(--ad-text-2); + font-size: var(--ad-text-s-size); +} + +.settings-page-foot { + display: flex; + align-items: center; + gap: var(--ad-space-2); + margin-top: var(--ad-space-5); + color: var(--ad-text-2); + font-size: var(--ad-text-xs-size); +} + +/* ---------- 页面切换动效(§4.2) ---------- */ +.page-enter { + animation: page-in var(--ad-dur-med) var(--ad-ease-out); +} + +@keyframes page-in { + from { + opacity: 0; + transform: translateY(8px); + } + to { + opacity: 1; + transform: none; + } +} + +/* ---------- 响应式(§6 三断点) ---------- */ +/* 紧凑 960–1199px:导航收起 64px,KPI 2×2,中段上下堆叠,状态网格 2 列 */ +@media (max-width: 1199px) { + .sidebar { + width: 64px; + padding: var(--ad-space-3) 0 0; + } + + .sidebar-nav { + padding: 0 var(--ad-space-2); + } + + .nav-item { + justify-content: center; + padding: 0; + } + + .nav-label { + display: none; + } + + .sidebar-engine { + justify-content: center; + padding: 0; + } + + .engine-text, + .engine-version { + display: none; + } + + .kpi-grid { + grid-template-columns: repeat(2, 1fr); + } + + .overview-mid { + grid-template-columns: 1fr; + } + + .cli-status-grid { + grid-template-columns: repeat(2, 1fr); + } + + .env-grid { + grid-template-columns: 1fr; + } +} + +/* 紧凑断点搜索框收缩为 36px 图标按钮 */ +@media (max-width: 1199px) { + .search-box { + width: 36px; + } + + .search-box input { + padding: 0; + border-color: transparent; + background: transparent; + cursor: pointer; + } + + .search-box input::placeholder { + color: transparent; + } + + .search-box:focus-within { + width: 240px; + } + + .search-box:focus-within input { + padding: 0 var(--ad-space-3) 0 36px; + border-color: var(--ad-border); + background: var(--ad-bg-1); + } + + .search-icon { + left: 10px; + } +} + +/* 标准 1200–1599px:默认样式(完整导航、KPI 一排 4、诊断+快速 2:1、状态网格 3 列) */ +/* 宽阔 ≥1600px:内容锁 1440 居中,状态网格 4 列 */ +@media (min-width: 1600px) { + .cli-status-grid { + grid-template-columns: repeat(4, 1fr); + } +} + +/* 窗口高度 < 700px:顶栏 44px,KPI 大数字缩小 */ +@media (max-height: 699px) { + .header { + height: 44px; + } + + .kpi-value { + font-size: 22px; + line-height: 28px; + } +} + +/* 低档/减弱动效下呼吸灯停用(tiers.css 已兜底 animation,此处补充过渡抑制) */ +[data-fx-tier="low"] .kpi-card:hover { + transform: none; +} diff --git a/apps/desktop/src/tokens/color.css b/apps/desktop/src/tokens/color.css new file mode 100644 index 0000000..411a201 --- /dev/null +++ b/apps/desktop/src/tokens/color.css @@ -0,0 +1,57 @@ +/* ============================================================ + * 设计 Token · 配色(color) + * 来源:视觉规范 v1.2 §2.1(施工唯一品味依据) + * 禁止在此文件之外出现任何魔法色值;改动需先征得总管同意。 + * ============================================================ */ +:root { + /* ---- 底色(深空阶梯,由深到浅)---- */ + --ad-bg-0: #070B14; /* 应用窗口底色 */ + --ad-bg-1: #0D1420; /* 面板、卡片底色 */ + --ad-bg-2: #131C2E; /* 浮层、弹窗、下拉、mono chip 底 */ + --ad-bg-3: #1A2438; /* 悬浮态、按下态的填充 */ + --ad-border: #22304A; /* 常规 1px 分隔线 */ + --ad-border-bright: #35507A; /* 悬浮/选中的边框 */ + + /* ---- 霓虹强调色(全系统只有这两个霓虹色)---- */ + --ad-primary: #00E5FF; /* 主操作、链接、聚焦、选中态(青) */ + --ad-primary-hover: #4DEFFF; /* 主操作悬浮 */ + --ad-primary-pressed: #00B4CC; /* 主操作按下 */ + --ad-primary-dim: rgba(0, 229, 255, 0.12); /* 选中项底、标签底 */ + --ad-accent: #FF4DDB; /* 可更新标记、重要提醒(品红,克制使用) */ + --ad-accent-dim: rgba(255, 77, 219, 0.12); /* 品红标签底 */ + + /* ---- 状态色(诊断四级 + 通用语义,六色语义表 v1.2 定稿)---- */ + --ad-success: #2EE6A8; /* 正常 / 已安装 / 已授权 / 已自动修复 */ + --ad-attention: #A78BFA; /* 需要留意:提示级 + 待授权 / 未授权(紫) */ + --ad-warning: #FFB020; /* 警告 / 需要你注意的异常 */ + --ad-danger: #FF4D5E; /* 错误 / 需要你处理 / 高危操作 */ + --ad-success-dim: rgba(46, 230, 168, 0.12); /* 状态色 12% 透明底色 */ + --ad-attention-dim: rgba(167, 139, 250, 0.12); /* 状态色 12% 透明底色 */ + --ad-warning-dim: rgba(255, 176, 32, 0.12); /* 状态色 12% 透明底色 */ + --ad-danger-dim: rgba(255, 77, 94, 0.12); /* 状态色 12% 透明底色 */ + + /* ---- 文字 ---- */ + --ad-text-1: #E8EEF7; /* 主文案 */ + --ad-text-2: #9AA8BD; /* 次要说明(承载信息的最低允许色,对比度 ≥ 4.5:1) */ + --ad-text-3: #5E6E87; /* 仅占位、禁用、纯装饰(禁止承载信息) */ + + /* ---- 侧边栏选中态(v1.2 §3.0:左缘生长光晕,无独立指示条)---- */ + --ad-nav-selected-bg: linear-gradient( + 90deg, + rgba(0, 229, 255, 0.30), + rgba(0, 229, 255, 0.12) 45%, + rgba(0, 229, 255, 0.05) + ); + --ad-nav-selected-border: inset 0 0 0 1px rgba(0, 229, 255, 0.38); + + /* ---- 组件表面(§3.0 / §3.1 明示值)---- */ + --ad-surface-card: radial-gradient(120% 100% at 50% 0%, #16233A 0%, #0D1420 60%); /* KPI 卡悬浮玻璃板 */ + --ad-card-highlight: inset 0 1px 0 rgba(255, 255, 255, 0.06); /* 卡片上缘高光 */ + --ad-warning-chip-border: rgba(255, 176, 32, 0.5); /* 环境警告 chip 描边 */ + + /* ---- 状态角标描边(§3.1.4 / §3.2 明示值)---- */ + --ad-primary-border: rgba(0, 229, 255, 0.4); + --ad-accent-border: rgba(255, 77, 219, 0.5); + --ad-attention-border: rgba(167, 139, 250, 0.5); + --ad-success-border: rgba(46, 230, 168, 0.4); +} diff --git a/apps/desktop/src/tokens/effects.css b/apps/desktop/src/tokens/effects.css new file mode 100644 index 0000000..e1195d0 --- /dev/null +++ b/apps/desktop/src/tokens/effects.css @@ -0,0 +1,39 @@ +/* ============================================================ + * 设计 Token · 阴影与辉光(effects) + * 来源:视觉规范 v1.2 §2.4 / §2.6 / §3.0 + * 辉光只给:主按钮、选中导航项、聚焦输入框、需处理状态指示灯、 + * 可更新角标、环境警告 chip。列表每行都发光 = 全部不发光,禁止。 + * ============================================================ */ +:root { + /* ---- 阴影 ---- */ + --ad-shadow-panel: 0 8px 24px rgba(0, 0, 0, 0.45); + --ad-shadow-pop: 0 12px 40px rgba(0, 0, 0, 0.6); + + /* ---- 辉光 ---- */ + --ad-glow-primary: 0 0 12px rgba(0, 229, 255, 0.35), 0 0 32px rgba(0, 229, 255, 0.12); + --ad-glow-accent: 0 0 12px rgba(255, 77, 219, 0.35); + --ad-glow-warning: 0 0 10px rgba(255, 176, 32, 0.28); /* 仅警告 chip / 警告状态灯 */ + --ad-glow-danger: 0 0 12px rgba(255, 77, 94, 0.35); + + /* ---- 主按钮(§2.6,v1.2 hover 双层扩散辉光)---- */ + --ad-btn-primary-bg: linear-gradient(180deg, #33D9EE 0%, #06BCD9 55%, #049EBB 100%); + --ad-btn-primary-text: #03252E; + --ad-btn-primary-inner: inset 0 1px 0 rgba(255, 255, 255, 0.30), + inset 0 -1px 0 rgba(2, 20, 26, 0.35); + --ad-btn-primary-glow: 0 0 10px rgba(0, 229, 255, 0.22); + --ad-btn-primary-glow-hover: 0 0 14px rgba(0, 229, 255, 0.30), + 0 0 36px rgba(0, 229, 255, 0.12); + + /* 品红更新按钮(全应用唯一允许品红做按钮的场景) */ + --ad-btn-accent-bg: linear-gradient(180deg, #F26AD9 0%, #D633B8 55%, #B5209C 100%); + --ad-btn-accent-glow-hover: 0 0 14px rgba(255, 77, 219, 0.30), + 0 0 36px rgba(255, 77, 219, 0.12); + + /* ---- 背景网格(§3.0:要么可见要么不做)---- */ + --ad-grid-color: rgba(0, 229, 255, 0.05); /* 透明度固定 5%,施工员不许再调 */ + --ad-grid-size: 40px; + --ad-grid-mask: radial-gradient(120% 90% at 50% 40%, #000 30%, transparent 75%); + + /* ---- 弹窗遮罩(§3.6)---- */ + --ad-modal-mask: rgba(4, 7, 13, 0.7); +} diff --git a/apps/desktop/src/tokens/motion.css b/apps/desktop/src/tokens/motion.css new file mode 100644 index 0000000..57559eb --- /dev/null +++ b/apps/desktop/src/tokens/motion.css @@ -0,0 +1,21 @@ +/* ============================================================ + * 设计 Token · 动效(motion) + * 来源:视觉规范 v1.2 §2.5 / §4 + * 通则:只动 transform 与 opacity;辉光可用 box-shadow 过渡但仅限单个聚焦元素。 + * ============================================================ */ +:root { + /* ---- 缓动曲线 ---- */ + --ad-ease-out: cubic-bezier(0.16, 1, 0.3, 1); /* 进场、浮现,主力曲线 */ + --ad-ease-inout: cubic-bezier(0.65, 0, 0.35, 1); /* 展开收起、位移、呼吸 */ + --ad-ease-linear: linear; /* 仅环境循环动画 */ + + /* ---- 时长 ---- */ + --ad-dur-micro: 120ms; /* 按下、勾选 */ + --ad-dur-fast: 200ms; /* 悬浮、淡入淡出 */ + --ad-dur-med: 320ms; /* 面板展开、页面切换 */ + --ad-dur-slow: 600ms; /* 仅入场编排,一次性 */ + + /* ---- 状态点呼吸(§4.5)---- */ + --ad-breathe-duration: 2400ms; + --ad-breathe-min-opacity: 0.4; /* 透明度下限 40%,再低像灭了 */ +} diff --git a/apps/desktop/src/tokens/space.css b/apps/desktop/src/tokens/space.css new file mode 100644 index 0000000..3db43da --- /dev/null +++ b/apps/desktop/src/tokens/space.css @@ -0,0 +1,24 @@ +/* ============================================================ + * 设计 Token · 间距 / 圆角(space) + * 来源:视觉规范 v1.2 §2.3 + * 赛博感靠小圆角 + 发光描边,不做大圆角。 + * ============================================================ */ +:root { + /* ---- 间距(4px 基数)---- */ + --ad-space-1: 4px; + --ad-space-2: 8px; + --ad-space-3: 12px; + --ad-space-4: 16px; + --ad-space-5: 20px; + --ad-space-6: 24px; + --ad-space-8: 32px; + --ad-space-10: 40px; + + /* ---- 圆角 ---- */ + --ad-radius-s: 4px; /* 标签、小按钮、chip */ + --ad-radius-m: 8px; /* 卡片、输入框、弹窗 */ + --ad-radius-l: 12px; /* 主面板 */ + + /* ---- 描边 ---- */ + --ad-border-width: 1px; /* 描边统一 1px;发光描边 = 1px 实色 + 外辉光,不加粗 */ +} diff --git a/apps/desktop/src/tokens/tiers.css b/apps/desktop/src/tokens/tiers.css new file mode 100644 index 0000000..5c23ce5 --- /dev/null +++ b/apps/desktop/src/tokens/tiers.css @@ -0,0 +1,59 @@ +/* ============================================================ + * 设计 Token · 性能档位(tiers) + * 来源:视觉规范 v1.2 §5(性能降级策略)/ 架构 §8.3 + * + * 三档:高 / 中 / 低,默认 balanced(自动降档由 JS 判定后设置 + * data-fx-tier 属性,见 src/main.tsx)。 + * - prefers-reduced-motion 强制 low + * - low:仅 L0 + 必要过渡,无循环动画、无辉光、无切角 + * ============================================================ */ +:root { + --ad-fx-tier: balanced; +} + +@media (prefers-reduced-motion: reduce) { + :root { + --ad-fx-tier: low; + } +} + +/* ---- 低档:移除辉光、循环动画、过渡、切角 ---- */ +[data-fx-tier="low"] *, +[data-fx-tier="low"] *::before, +[data-fx-tier="low"] *::after { + animation: none !important; + transition: none !important; + box-shadow: none !important; +} +[data-fx-tier="low"] .clip-notch { + clip-path: none !important; +} + +/* ---- 中档:只保留单层辉光(半径减半),循环动画停用 ---- */ +[data-fx-tier="balanced"] .fx-multilayer-glow { + box-shadow: 0 0 6px rgba(0, 229, 255, 0.3); +} + +/* 背景网格漂移(§4.8,60s 一周,仅高档/中档) */ +[data-fx-tier="low"] .grid-drift { + animation: none; +} +.grid-drift { + animation: grid-drift 60s linear infinite; +} +@keyframes grid-drift { + from { background-position: 0 0; } + to { background-position: 40px 40px; } +} + +/* 状态点呼吸(§4.5:仅警告/错误/授权可能过期呼吸;低档停用) */ +[data-fx-tier="low"] .status-dot-breathe { + animation: none; +} +.status-dot-breathe { + animation: ad-breathe var(--ad-dur-slow) var(--ad-ease-inout) infinite; +} +@keyframes ad-breathe { + 0%, 100% { opacity: 1; } + 50% { opacity: var(--ad-breathe-min-opacity); } +} diff --git a/apps/desktop/src/tokens/typography.css b/apps/desktop/src/tokens/typography.css new file mode 100644 index 0000000..b322769 --- /dev/null +++ b/apps/desktop/src/tokens/typography.css @@ -0,0 +1,31 @@ +/* ============================================================ + * 设计 Token · 字体(typography) + * 来源:视觉规范 v1.2 §2.2 + * 不加任何外联 Web 字体(离线可用、安装包不膨胀)。 + * ============================================================ */ +:root { + /* ---- 字体栈 ---- */ + --ad-font-ui: "PingFang SC", "Microsoft YaHei UI", "Microsoft YaHei", + "Noto Sans CJK SC", "Source Han Sans SC", system-ui, sans-serif; + --ad-font-mono: "Cascadia Code", "JetBrains Mono", Consolas, + "Noto Sans Mono CJK SC", monospace; + + /* ---- 字阶(字号 / 行高 / 字重)---- */ + --ad-text-xs-size: 12px; --ad-text-xs-height: 18px; --ad-text-xs-weight: 400; + --ad-text-s-size: 13px; --ad-text-s-height: 20px; --ad-text-s-weight: 400; + --ad-text-m-size: 14px; --ad-text-m-height: 22px; --ad-text-m-weight: 400; + --ad-text-l-size: 16px; --ad-text-l-height: 24px; --ad-text-l-weight: 500; + --ad-text-xl-size: 20px; --ad-text-xl-height: 28px; --ad-text-xl-weight: 600; + --ad-text-num-size: 28px; --ad-text-num-height: 36px; --ad-text-num-weight: 600; + + /* ---- Mono chip(§2.2 对比度三件套之二)---- + * 正文/列表中内联出现的文件名、版本号、命令一律套此样式: + * 12px 等宽、--ad-bg-2 底、1px --ad-border、--ad-radius-s、内边距 1px 6px、文字 --ad-text-1 */ + --ad-mono-chip-font: var(--ad-font-mono); + --ad-mono-chip-size: 12px; + --ad-mono-chip-bg: var(--ad-bg-2); + --ad-mono-chip-border: 1px solid var(--ad-border); + --ad-mono-chip-radius: var(--ad-radius-s); + --ad-mono-chip-padding: 1px 6px; + --ad-mono-chip-color: var(--ad-text-1); +} diff --git a/apps/desktop/tsconfig.json b/apps/desktop/tsconfig.json new file mode 100644 index 0000000..ead86d8 --- /dev/null +++ b/apps/desktop/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ES2021", + "useDefineForClassFields": true, + "lib": ["ES2021", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"] +} diff --git a/apps/desktop/vite.config.ts b/apps/desktop/vite.config.ts new file mode 100644 index 0000000..73d4e47 --- /dev/null +++ b/apps/desktop/vite.config.ts @@ -0,0 +1,28 @@ +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; + +const host = process.env.TAURI_DEV_HOST; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], + + // Tauri 开发约定:固定端口 1420,避免占用冲突 + clearScreen: false, + server: { + port: 1420, + strictPort: true, + host: host || false, + hmr: host + ? { + protocol: "ws", + host, + port: 1421, + } + : undefined, + watch: { + // 不监听 src-tauri,避免 Rust 改动触发前端重载 + ignored: ["**/src-tauri/**"], + }, + }, +}); diff --git a/crates/agentdock-adapter/Cargo.toml b/crates/agentdock-adapter/Cargo.toml new file mode 100644 index 0000000..200e4d3 --- /dev/null +++ b/crates/agentdock-adapter/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "agentdock-adapter" +version.workspace = true +edition.workspace = true +license.workspace = true +description = "适配器 schema 加载、版本校验、dry-run、执行器接口(架构 §3)" + +[dependencies] +serde = { version = "1", features = ["derive"] } +serde_yaml = "0.9" diff --git a/crates/agentdock-adapter/src/catalog.rs b/crates/agentdock-adapter/src/catalog.rs new file mode 100644 index 0000000..5b28db3 --- /dev/null +++ b/crates/agentdock-adapter/src/catalog.rs @@ -0,0 +1,110 @@ +//! 目录索引与占位条目加载(Wave 0) +//! +//! 从 `adapters/catalog.yaml` 读取索引,再逐个读取 `tools/*.yaml`, +//! 返回目录条目。仅消费 `id / name / name_zh / vendor / status` 五个字段。 + +use std::fs; +use std::path::Path; + +use serde::{Deserialize, Serialize}; + +use crate::error::AdapterError; + +/// 目录索引(adapters/catalog.yaml) +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)] +pub struct Catalog { + #[serde(rename = "catalog_version")] + pub version: u32, + pub tools: Vec, +} + +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)] +pub struct CatalogRef { + pub id: String, + pub file: String, +} + +/// 目录条目(占位 schema,Wave 0 仅五字段;完整字段见架构 §3.1) +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)] +pub struct CatalogEntry { + pub id: String, + pub name: String, + #[serde(rename = "name_zh")] + pub name_zh: String, + pub vendor: String, + /// available | watch + pub status: String, +} + +/// 加载目录索引与全部工具占位 YAML +pub fn load_catalog>(adapters_dir: P) -> Result, AdapterError> { + let dir = adapters_dir.as_ref(); + let catalog_text = fs::read_to_string(dir.join("catalog.yaml")) + .map_err(|e| AdapterError::Io(format!("读取 catalog.yaml 失败: {e}")))?; + let catalog: Catalog = serde_yaml::from_str(&catalog_text) + .map_err(|e| AdapterError::Parse(format!("解析 catalog.yaml 失败: {e}")))?; + + let mut entries = Vec::with_capacity(catalog.tools.len()); + for r in &catalog.tools { + let text = fs::read_to_string(dir.join(&r.file)) + .map_err(|e| AdapterError::Io(format!("读取 {} 失败: {e}", r.file)))?; + let entry: CatalogEntry = serde_yaml::from_str(&text) + .map_err(|e| AdapterError::Parse(format!("解析 {} 失败: {e}", r.file)))?; + if entry.id != r.id { + return Err(AdapterError::Parse(format!( + "索引 id 与文件内 id 不一致: 索引={} 文件={}", + r.id, entry.id + ))); + } + if entry.status != "available" && entry.status != "watch" { + return Err(AdapterError::Parse(format!( + "{} 的 status 非法: {}(应为 available | watch)", + entry.id, entry.status + ))); + } + entries.push(entry); + } + Ok(entries) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn parses_minimal_tool_yaml() { + let yaml = "id: codex\nname: Codex CLI\nname_zh: Codex CLI\nvendor: OpenAI\nstatus: available\n"; + let entry: CatalogEntry = serde_yaml::from_str(yaml).expect("应能解析"); + assert_eq!(entry.id, "codex"); + assert_eq!(entry.name_zh, "Codex CLI"); + assert_eq!(entry.vendor, "OpenAI"); + assert_eq!(entry.status, "available"); + } + + #[test] + fn rejects_invalid_status() { + let yaml = "id: x\nname: X\nname_zh: X\nvendor: V\nstatus: unknown\n"; + let entry: Result = serde_yaml::from_str(yaml); + // 解析本身成功,非法 status 由 load_catalog 校验;此处确认 schema 字段可读 + assert!(entry.is_ok()); + } + + #[test] + fn loads_real_catalog_from_repo() { + // 以真实 adapters/ 目录做集成测试(相对本 crate 位于 ../../adapters) + let dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("../../adapters"); + let entries = load_catalog(&dir).expect("真实目录应可加载"); + assert_eq!(entries.len(), 14, "第一批应为 14 个工具"); + for e in &entries { + assert!(!e.id.is_empty()); + assert!(!e.name.is_empty()); + assert!(!e.name_zh.is_empty()); + assert!(!e.vendor.is_empty()); + } + let ids: Vec<&str> = entries.iter().map(|e| e.id.as_str()).collect(); + for want in ["codex", "claude-code", "gemini", "copilot", "kimi", "qwen", "codebuddy", + "opencode", "crush", "goose", "aider", "cursor", "cline", "warp"] { + assert!(ids.contains(&want), "目录应包含 {want}"); + } + } +} diff --git a/crates/agentdock-adapter/src/error.rs b/crates/agentdock-adapter/src/error.rs new file mode 100644 index 0000000..1e6c70d --- /dev/null +++ b/crates/agentdock-adapter/src/error.rs @@ -0,0 +1,20 @@ +//! 适配器层错误类型 + +use std::fmt; + +#[derive(Debug)] +pub enum AdapterError { + Io(String), + Parse(String), +} + +impl fmt::Display for AdapterError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + AdapterError::Io(m) => write!(f, "IO: {m}"), + AdapterError::Parse(m) => write!(f, "Parse: {m}"), + } + } +} + +impl std::error::Error for AdapterError {} diff --git a/crates/agentdock-adapter/src/lib.rs b/crates/agentdock-adapter/src/lib.rs new file mode 100644 index 0000000..133a4d7 --- /dev/null +++ b/crates/agentdock-adapter/src/lib.rs @@ -0,0 +1,11 @@ +//! agentdock-adapter —— 适配器层 +//! +//! 负责适配器 schema 加载、版本校验、dry-run 与执行器接口(架构 §3)。 +//! Wave 0:仅落地目录索引与占位条目加载(`catalog` 模块); +//! 完整 schema 校验、执行器接口随 Wave 1 实现。 + +pub mod catalog; +pub mod error; + +pub use catalog::{Catalog, CatalogEntry, CatalogRef, load_catalog}; +pub use error::AdapterError; diff --git a/crates/agentdock-config/Cargo.toml b/crates/agentdock-config/Cargo.toml new file mode 100644 index 0000000..38e5db8 --- /dev/null +++ b/crates/agentdock-config/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "agentdock-config" +version.workspace = true +edition.workspace = true +license.workspace = true + +[dependencies] diff --git a/crates/agentdock-config/src/lib.rs b/crates/agentdock-config/src/lib.rs new file mode 100644 index 0000000..748d003 --- /dev/null +++ b/crates/agentdock-config/src/lib.rs @@ -0,0 +1,18 @@ +//! agentdock-config —— 配置读写层(架构 §6) +//! +//! 职责:原子写入 + 自动备份、多格式统一编解码(ConfigCodec trait: +//! toml / json / jsonc / yaml / env / crushrc)。 +//! Wave 0:空骨架,随 Wave 1/2 落地。 + +/// 配置层能力标记(占位) +pub const LAYER: &str = "agentdock-config"; + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn layer_identity() { + assert_eq!(LAYER, "agentdock-config"); + } +} diff --git a/crates/agentdock-core/Cargo.toml b/crates/agentdock-core/Cargo.toml new file mode 100644 index 0000000..01e638a --- /dev/null +++ b/crates/agentdock-core/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "agentdock-core" +version.workspace = true +edition.workspace = true +license.workspace = true + +[dependencies] diff --git a/crates/agentdock-core/src/lib.rs b/crates/agentdock-core/src/lib.rs new file mode 100644 index 0000000..c587834 --- /dev/null +++ b/crates/agentdock-core/src/lib.rs @@ -0,0 +1,17 @@ +//! agentdock-core —— 编排层(架构 §2 模块关系:UI --invoke--> commands --→ core orchestrator) +//! +//! 职责:发现 / 安装 / 配置 / 授权 / 诊断 流水线编排。 +//! Wave 0:空骨架,流水线自 Wave 1 起逐波落地。 + +/// 编排层能力标记(占位) +pub const LAYER: &str = "agentdock-core"; + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn layer_identity() { + assert_eq!(LAYER, "agentdock-core"); + } +} diff --git a/crates/agentdock-diag/Cargo.toml b/crates/agentdock-diag/Cargo.toml new file mode 100644 index 0000000..4268a84 --- /dev/null +++ b/crates/agentdock-diag/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "agentdock-diag" +version.workspace = true +edition.workspace = true +license.workspace = true + +[dependencies] diff --git a/crates/agentdock-diag/src/lib.rs b/crates/agentdock-diag/src/lib.rs new file mode 100644 index 0000000..ab29470 --- /dev/null +++ b/crates/agentdock-diag/src/lib.rs @@ -0,0 +1,17 @@ +//! agentdock-diag —— 诊断规则引擎(架构 §10) +//! +//! 职责:PATH / 依赖缺失 / 版本冲突 / 配置损坏 四类检查的规则引擎。 +//! Wave 0:空骨架,随 Wave 2 落地。 + +/// 诊断层能力标记(占位) +pub const LAYER: &str = "agentdock-diag"; + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn layer_identity() { + assert_eq!(LAYER, "agentdock-diag"); + } +} diff --git a/crates/agentdock-exec/Cargo.toml b/crates/agentdock-exec/Cargo.toml new file mode 100644 index 0000000..9d76486 --- /dev/null +++ b/crates/agentdock-exec/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "agentdock-exec" +version.workspace = true +edition.workspace = true +license.workspace = true + +[dependencies] diff --git a/crates/agentdock-exec/src/lib.rs b/crates/agentdock-exec/src/lib.rs new file mode 100644 index 0000000..cc3b925 --- /dev/null +++ b/crates/agentdock-exec/src/lib.rs @@ -0,0 +1,17 @@ +//! agentdock-exec —— 安全进程执行层(架构 §3.2 / §4.2) +//! +//! 职责:仅执行适配器声明的 argv,禁止 shell 拼接、管道、重定向; +//! 参数白名单校验。Wave 0:空骨架,随 Wave 1 落地。 + +/// 执行层能力标记(占位) +pub const LAYER: &str = "agentdock-exec"; + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn layer_identity() { + assert_eq!(LAYER, "agentdock-exec"); + } +} diff --git a/crates/agentdock-platform/Cargo.toml b/crates/agentdock-platform/Cargo.toml new file mode 100644 index 0000000..5bf1d50 --- /dev/null +++ b/crates/agentdock-platform/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "agentdock-platform" +version.workspace = true +edition.workspace = true +license.workspace = true +description = "Win/Linux 环境检测、PATH、发行版识别(架构 §5)" + +[dependencies] +serde = { version = "1", features = ["derive"] } + +[target.'cfg(windows)'.dependencies] +winreg = "0.52" diff --git a/crates/agentdock-platform/src/detect.rs b/crates/agentdock-platform/src/detect.rs new file mode 100644 index 0000000..43b922f --- /dev/null +++ b/crates/agentdock-platform/src/detect.rs @@ -0,0 +1,315 @@ +//! 环境检测实现(架构 §5) +//! +//! 只做「探测」不执行用户命令:调用系统 `--version` 类只读命令并解析输出; +//! 进程执行统一走 `std::process::Command`,不做 shell 拼接。 + +use std::path::{Path, PathBuf}; +use std::process::Command; + +use crate::model::{Capabilities, PlatformEnv, RuntimeInfo, Runtimes, Shells}; + +/// 全量环境检测(Windows / Linux 双平台) +pub fn detect_env() -> PlatformEnv { + #[cfg(windows)] + let (os, os_version) = (String::from("windows"), windows_os_version()); + #[cfg(not(windows))] + let (os, os_version) = (String::from("linux"), linux_os_version()); + + PlatformEnv { + os, + os_version, + arch: std::env::consts::ARCH.to_string(), + shells: detect_shells(), + runtimes: detect_runtimes(), + path_entries: path_entries(), + capabilities: detect_capabilities(), + } +} + +/// 从命令输出中提取首个版本号(如 "v24.18.0" -> "24.18.0")。 +/// 规则:取第一段以数字开头、由数字与点组成的子串,尾部点剔除。 +pub fn extract_version(output: &str) -> Option { + let bytes = output.as_bytes(); + let n = bytes.len(); + let mut i = 0; + while i < n { + if bytes[i].is_ascii_digit() { + let mut j = i; + while j < n && (bytes[j].is_ascii_digit() || bytes[j] == b'.') { + j += 1; + } + let s = output[i..j].trim_end_matches('.'); + if !s.is_empty() { + return Some(s.to_string()); + } + i = j; + } else { + i += 1; + } + } + None +} + +/// 按平台分隔符拆分 PATH +fn path_entries() -> Vec { + std::env::var("PATH") + .unwrap_or_default() + .split(path_list_sep()) + .filter(|s| !s.is_empty()) + .map(|s| s.to_string()) + .collect() +} + +#[cfg(windows)] +fn path_list_sep() -> char { + ';' +} + +#[cfg(not(windows))] +fn path_list_sep() -> char { + ':' +} + +/// 在 PATH 中解析可执行文件。 +/// Windows 优先 .exe/.cmd/.bat(CreateProcess 无法直接执行无扩展名文件, +/// 例如 nodejs 目录下的 npm bash 脚本),最后才回退无扩展名。 +fn resolve_program(program: &str) -> Option { + let direct = Path::new(program); + if direct.is_absolute() && direct.is_file() { + return Some(direct.to_path_buf()); + } + let exts: &[&str] = if cfg!(windows) { + &[".exe", ".cmd", ".bat", ""] + } else { + &[""] + }; + for dir in path_entries() { + for ext in exts { + let cand = Path::new(&dir).join(format!("{program}{ext}")); + if cand.is_file() { + return Some(cand); + } + } + } + None +} + +/// 探测一个可执行文件:返回状态 / 版本 / 路径。 +/// 结果分类:installed / not_in_path / exec_failed / version_unparseable。 +fn probe(program: &str, args: &[&str]) -> Option { + let path = resolve_program(program); + let path_str = path.as_ref().map(|p| p.to_string_lossy().to_string()); + + let Some(exe) = path else { + return Some(RuntimeInfo { + status: "not_in_path".into(), + version: None, + path: None, + }); + }; + + let mut cmd = Command::new(&exe); + cmd.args(args); + #[cfg(windows)] + { + use std::os::windows::process::CommandExt; + // CREATE_NO_WINDOW:探测命令不闪黑框 + cmd.creation_flags(0x0800_0000); + } + + let output = match cmd.output() { + Ok(o) => o, + Err(_) => { + return Some(RuntimeInfo { + status: "exec_failed".into(), + version: None, + path: path_str, + }); + } + }; + + if !output.status.success() { + return Some(RuntimeInfo { + status: "exec_failed".into(), + version: None, + path: path_str, + }); + } + + let stdout = String::from_utf8_lossy(&output.stdout); + let text = if stdout.trim().is_empty() { + String::from_utf8_lossy(&output.stderr).to_string() + } else { + stdout.to_string() + }; + + match extract_version(&text) { + Some(version) => Some(RuntimeInfo { + status: "installed".into(), + version: Some(version), + path: path_str, + }), + None => Some(RuntimeInfo { + status: "version_unparseable".into(), + version: None, + path: path_str, + }), + } +} + +fn detect_runtimes() -> Runtimes { + Runtimes { + node: probe("node", &["--version"]), + npm: probe("npm", &["--version"]), + python: probe_python(), + uv: probe("uv", &["--version"]), + git: probe("git", &["--version"]), + winget: probe("winget", &["--version"]), + apt: probe("apt", &["--version"]), + } +} + +/// Python:优先 `python --version`,失败退回 `py --version`(Windows 启动器) +fn probe_python() -> Option { + let direct = probe("python", &["--version"]); + if matches!(direct, Some(ref i) if i.status == "installed") { + return direct; + } + probe("py", &["--version"]) +} + +fn detect_shells() -> Shells { + Shells { + powershell_version: probe_powershell(), + pwsh_version: probe("pwsh", &["-NoProfile", "-Command", "$PSVersionTable.PSVersion.ToString()"]) + .and_then(|i| i.version), + bash_available: resolve_program("bash").is_some(), + } +} + +#[cfg(windows)] +fn probe_powershell() -> Option { + probe( + "powershell", + &["-NoProfile", "-Command", "$PSVersionTable.PSVersion.ToString()"], + ) + .and_then(|i| i.version) +} + +#[cfg(not(windows))] +fn probe_powershell() -> Option { + None +} + +fn detect_capabilities() -> Capabilities { + #[cfg(windows)] + { + Capabilities { + // Windows Credential Manager 常驻可用(架构 §4.1) + keyring: "ok".into(), + // `net session` 仅在管理员上下文返回成功(提权探测,仅检测不执行用户命令) + can_elevate: run_success("net", &["session"]), + } + } + #[cfg(not(windows))] + { + Capabilities { + keyring: if resolve_program("secret-tool").is_some() { + "ok".into() + } else { + "missing".into() + }, + can_elevate: std::env::var("USER").map(|u| u == "root").unwrap_or(false), + } + } +} + +fn run_success(program: &str, args: &[&str]) -> bool { + let mut cmd = Command::new(program); + cmd.args(args); + #[cfg(windows)] + { + use std::os::windows::process::CommandExt; + cmd.creation_flags(0x0800_0000); + } + cmd.output().map(|o| o.status.success()).unwrap_or(false) +} + +#[cfg(windows)] +fn windows_os_version() -> String { + use winreg::enums::HKEY_LOCAL_MACHINE; + use winreg::RegKey; + + let hklm = RegKey::predef(HKEY_LOCAL_MACHINE); + match hklm.open_subkey(r"SOFTWARE\Microsoft\Windows NT\CurrentVersion") { + Ok(key) => { + let product: String = key.get_value("ProductName").unwrap_or_else(|_| "Windows".into()); + let display: String = key.get_value("DisplayVersion").unwrap_or_default(); + let build: String = key.get_value("CurrentBuildNumber").unwrap_or_default(); + let major: u32 = key.get_value("CurrentMajorVersionNumber").unwrap_or(0); + let minor: u32 = key.get_value("CurrentMinorVersionNumber").unwrap_or(0); + let ver = if !display.is_empty() { + display + } else { + format!("{major}.{minor}") + }; + format!("{product} {ver} (Build {build})") + } + Err(_) => "Windows (unknown version)".into(), + } +} + +#[cfg(not(windows))] +fn linux_os_version() -> String { + let content = std::fs::read_to_string("/etc/os-release").unwrap_or_default(); + for line in content.lines() { + if let Some(v) = line.strip_prefix("PRETTY_NAME=") { + return v.trim().trim_matches('"').to_string(); + } + } + "Linux (unknown distro)".into() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn extracts_version_from_common_outputs() { + assert_eq!(extract_version("v24.18.0"), Some("24.18.0".into())); + assert_eq!(extract_version("11.16.0\n"), Some("11.16.0".into())); + assert_eq!(extract_version("Python 3.14.6"), Some("3.14.6".into())); + assert_eq!(extract_version("git version 2.47.1.windows.1"), Some("2.47.1".into())); + assert_eq!(extract_version("GNU bash, version 5.2.26(1)-release"), Some("5.2.26".into())); + assert_eq!(extract_version("v1.8.1911"), Some("1.8.1911".into())); + assert_eq!(extract_version("5.1.26100.1"), Some("5.1.26100.1".into())); + } + + #[test] + fn extracts_none_when_no_digits() { + assert_eq!(extract_version("command not found"), None); + assert_eq!(extract_version(""), None); + } + + #[test] + fn trims_trailing_dots() { + assert_eq!(extract_version("v1.2.3."), Some("1.2.3".into())); + } + + #[test] + fn env_has_path_on_windows() { + // PATH 变量在任何真实 Windows/Linux 上都存在 + assert!(!path_entries().is_empty(), "PATH 不应为空"); + } + + /// 实机自测:打印本机环境检测快照(cargo test -p agentdock-platform -- --ignored --nocapture) + #[test] + #[ignore] + fn print_detect_env_snapshot() { + let env = detect_env(); + println!("{:#?}", env); + assert_eq!(env.os, "windows"); + assert!(!env.os_version.is_empty()); + assert!(!env.arch.is_empty()); + } +} diff --git a/crates/agentdock-platform/src/lib.rs b/crates/agentdock-platform/src/lib.rs new file mode 100644 index 0000000..1f7fb38 --- /dev/null +++ b/crates/agentdock-platform/src/lib.rs @@ -0,0 +1,10 @@ +//! agentdock-platform —— 平台检测层 +//! +//! 负责 Windows / Linux 的本机环境检测(架构 §5): +//! OS 版本、架构、PATH、shell、运行时(Node/npm/Python/uv/Git/winget/apt)、 +//! 能力(密钥库、提权探测)。 + +pub mod detect; +pub mod model; + +pub use model::{Capabilities, PlatformEnv, RuntimeInfo, Runtimes, Shells}; diff --git a/crates/agentdock-platform/src/model.rs b/crates/agentdock-platform/src/model.rs new file mode 100644 index 0000000..315a416 --- /dev/null +++ b/crates/agentdock-platform/src/model.rs @@ -0,0 +1,56 @@ +//! 平台环境数据结构(对齐架构 §5 `PlatformEnv`) + +use serde::{Deserialize, Serialize}; + +/// 平台环境快照 +#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)] +pub struct PlatformEnv { + /// os: windows | linux + pub os: String, + /// 人类可读的系统版本(如 "Windows 11 24H2 (Build 26100)" / "Ubuntu 24.04 LTS") + pub os_version: String, + /// 架构(std::env::consts::ARCH,如 x86_64) + pub arch: String, + pub shells: Shells, + pub runtimes: Runtimes, + /// PATH 条目(Windows 用 ';' 分割,Linux 用 ':') + pub path_entries: Vec, + pub capabilities: Capabilities, +} + +#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)] +pub struct Shells { + /// Windows PowerShell(5.x)版本 + pub powershell_version: Option, + /// PowerShell 7+(pwsh)版本 + pub pwsh_version: Option, + pub bash_available: bool, +} + +#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)] +pub struct Runtimes { + pub node: Option, + pub npm: Option, + pub python: Option, + pub uv: Option, + pub git: Option, + pub winget: Option, + pub apt: Option, +} + +/// 单个运行时探测结果 +#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)] +pub struct RuntimeInfo { + /// installed | not_installed | not_in_path | exec_failed | version_unparseable + pub status: String, + pub version: Option, + /// 解析到的可执行文件绝对路径(PATH 搜索) + pub path: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)] +pub struct Capabilities { + /// ok | missing(Linux 依赖 secret-tool / DBus Secret Service) + pub keyring: String, + pub can_elevate: bool, +} diff --git a/crates/agentdock-secrets/Cargo.toml b/crates/agentdock-secrets/Cargo.toml new file mode 100644 index 0000000..2058188 --- /dev/null +++ b/crates/agentdock-secrets/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "agentdock-secrets" +version.workspace = true +edition.workspace = true +license.workspace = true + +[dependencies] diff --git a/crates/agentdock-secrets/src/lib.rs b/crates/agentdock-secrets/src/lib.rs new file mode 100644 index 0000000..adf88fa --- /dev/null +++ b/crates/agentdock-secrets/src/lib.rs @@ -0,0 +1,17 @@ +//! agentdock-secrets —— 系统密钥库封装与日志脱敏(架构 §4.1 / §4.3) +//! +//! 职责:keyring 封装(Windows Credential Manager / Linux Secret Service)、 +//! 敏感值脱敏。Wave 0:空骨架,随 Wave 1 落地。 + +/// 密钥层能力标记(占位) +pub const LAYER: &str = "agentdock-secrets"; + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn layer_identity() { + assert_eq!(LAYER, "agentdock-secrets"); + } +} diff --git a/crates/agentdock-store/Cargo.toml b/crates/agentdock-store/Cargo.toml new file mode 100644 index 0000000..5a1c461 --- /dev/null +++ b/crates/agentdock-store/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "agentdock-store" +version.workspace = true +edition.workspace = true +license.workspace = true +description = "SQLite 本地状态存储:schema 迁移与仓库(架构 §2 状态存储层)" + +[dependencies] +rusqlite = { version = "0.32", features = ["bundled"] } +serde = { version = "1", features = ["derive"] } +serde_json = "1" diff --git a/crates/agentdock-store/src/error.rs b/crates/agentdock-store/src/error.rs new file mode 100644 index 0000000..61b5fe8 --- /dev/null +++ b/crates/agentdock-store/src/error.rs @@ -0,0 +1,32 @@ +//! 存储层错误类型 + +use std::fmt; + +#[derive(Debug)] +pub enum StoreError { + Io(std::io::Error), + Sqlite(rusqlite::Error), +} + +impl fmt::Display for StoreError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + StoreError::Io(e) => write!(f, "IO: {e}"), + StoreError::Sqlite(e) => write!(f, "SQLite: {e}"), + } + } +} + +impl std::error::Error for StoreError {} + +impl From for StoreError { + fn from(e: std::io::Error) -> Self { + StoreError::Io(e) + } +} + +impl From for StoreError { + fn from(e: rusqlite::Error) -> Self { + StoreError::Sqlite(e) + } +} diff --git a/crates/agentdock-store/src/lib.rs b/crates/agentdock-store/src/lib.rs new file mode 100644 index 0000000..fb4a85d --- /dev/null +++ b/crates/agentdock-store/src/lib.rs @@ -0,0 +1,11 @@ +//! agentdock-store —— 本地状态存储(SQLite) +//! +//! Wave 0:SQLite 空库 + schema 迁移骨架。仓库查询接口随后续波次实现。 + +pub mod error; +pub mod migrations; +pub mod schema; +pub mod store; + +pub use error::StoreError; +pub use store::{Store, default_data_dir}; diff --git a/crates/agentdock-store/src/migrations.rs b/crates/agentdock-store/src/migrations.rs new file mode 100644 index 0000000..9b32459 --- /dev/null +++ b/crates/agentdock-store/src/migrations.rs @@ -0,0 +1,26 @@ +//! 迁移执行器(Wave 0 骨架) + +use rusqlite::Connection; + +use crate::schema::{MIGRATIONS, SCHEMA_VERSION}; + +/// 应用全部迁移。所有语句均为幂等(IF NOT EXISTS),可安全重复执行。 +pub fn migrate(conn: &Connection) -> rusqlite::Result<()> { + let tx = conn.unchecked_transaction()?; + for sql in MIGRATIONS { + tx.execute_batch(sql)?; + } + tx.execute( + "INSERT OR REPLACE INTO schema_version (version) VALUES (?1)", + [SCHEMA_VERSION], + )?; + tx.commit() +} + +/// 读取当前 schema 版本(未初始化返回 0) +pub fn current_version(conn: &Connection) -> rusqlite::Result { + conn.query_row("SELECT version FROM schema_version ORDER BY version DESC LIMIT 1", [], |r| { + r.get(0) + }) + .or(Ok(0)) +} diff --git a/crates/agentdock-store/src/schema.rs b/crates/agentdock-store/src/schema.rs new file mode 100644 index 0000000..c6fd5d6 --- /dev/null +++ b/crates/agentdock-store/src/schema.rs @@ -0,0 +1,33 @@ +//! schema 定义与迁移骨架(Wave 0) +//! +//! 迁移采用顺序数组:每个元素是一段幂等 SQL(CREATE TABLE IF NOT EXISTS)。 +//! 后续波次新增表时在 `MIGRATIONS` 尾部追加并提升 `SCHEMA_VERSION`。 + +/// 当前 schema 版本 +pub const SCHEMA_VERSION: i64 = 1; + +/// 迁移列表(按顺序执行,均需幂等) +pub const MIGRATIONS: [&str; 3] = [ + // 迁移 1:schema 版本表 + "CREATE TABLE IF NOT EXISTS schema_version ( + version INTEGER NOT NULL, + applied_at TEXT NOT NULL DEFAULT (datetime('now')) + );", + // 迁移 2:已安装 CLI 记录 + "CREATE TABLE IF NOT EXISTS installed_clis ( + cli_id TEXT PRIMARY KEY, + name_zh TEXT NOT NULL, + version TEXT, + install_channel TEXT, + detected_at TEXT + );", + // 迁移 3:诊断历史 + "CREATE TABLE IF NOT EXISTS diagnostic_history ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + cli_id TEXT NOT NULL, + rule_id TEXT NOT NULL, + severity TEXT NOT NULL, + message_zh TEXT NOT NULL, + created_at TEXT NOT NULL DEFAULT (datetime('now')) + );", +]; diff --git a/crates/agentdock-store/src/store.rs b/crates/agentdock-store/src/store.rs new file mode 100644 index 0000000..1d32c17 --- /dev/null +++ b/crates/agentdock-store/src/store.rs @@ -0,0 +1,105 @@ +//! Store:打开/创建 SQLite 空库并应用迁移(Wave 0) + +use std::path::{Path, PathBuf}; + +use rusqlite::Connection; + +use crate::error::StoreError; +use crate::migrations; + +/// 本地状态存储句柄 +pub struct Store { + conn: Connection, + path: PathBuf, +} + +impl Store { + /// 打开(不存在则创建)指定路径的 SQLite 库并应用迁移 + pub fn open>(path: P) -> Result { + let path = path.as_ref().to_path_buf(); + if let Some(parent) = path.parent() { + if !parent.as_os_str().is_empty() { + std::fs::create_dir_all(parent)?; + } + } + let conn = Connection::open(&path)?; + conn.pragma_update(None, "foreign_keys", true)?; + migrations::migrate(&conn)?; + Ok(Self { conn, path }) + } + + /// 打开默认数据目录下的 agentdock.db(Windows: %APPDATA%\agentdock) + pub fn open_default() -> Result { + Self::open(default_data_dir().join("agentdock.db")) + } + + pub fn path(&self) -> &Path { + &self.path + } + + pub fn connection(&self) -> &Connection { + &self.conn + } +} + +/// 默认数据目录 +pub fn default_data_dir() -> PathBuf { + #[cfg(windows)] + { + if let Some(appdata) = std::env::var_os("APPDATA") { + return PathBuf::from(appdata).join("agentdock"); + } + PathBuf::from(".").join("agentdock") + } + #[cfg(not(windows))] + { + if let Some(xdg) = std::env::var_os("XDG_DATA_HOME") { + return PathBuf::from(xdg).join("agentdock"); + } + if let Some(home) = std::env::var_os("HOME") { + return PathBuf::from(home).join(".local/share").join("agentdock"); + } + PathBuf::from(".").join("agentdock") + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::migrations::current_version; + use crate::schema::SCHEMA_VERSION; + + #[test] + fn in_memory_migration_applies_and_is_idempotent() { + let conn = Connection::open_in_memory().expect("内存库应可打开"); + migrations::migrate(&conn).expect("首次迁移应成功"); + assert_eq!(current_version(&conn).unwrap(), SCHEMA_VERSION); + + // 幂等:重复迁移不报错、版本不变 + migrations::migrate(&conn).expect("重复迁移应成功"); + assert_eq!(current_version(&conn).unwrap(), SCHEMA_VERSION); + + // 关键表存在 + let tables: Vec = conn + .prepare("SELECT name FROM sqlite_master WHERE type='table' AND name IN ('schema_version','installed_clis','diagnostic_history')") + .unwrap() + .query_map([], |r| r.get(0)) + .unwrap() + .collect::>() + .unwrap(); + assert_eq!(tables.len(), 3); + } + + #[test] + fn open_creates_empty_db_file() { + let dir = std::env::temp_dir().join(format!("agentdock-test-{}", std::process::id())); + let db = dir.join("agentdock.db"); + let _ = std::fs::remove_dir_all(&dir); + + let store = Store::open(&db).expect("应能创建库文件"); + assert!(db.exists(), "SQLite 空库文件应已创建"); + assert_eq!(current_version(store.connection()).unwrap(), SCHEMA_VERSION); + + let _ = std::fs::remove_dir_all(&dir); + } +} diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..61fb579 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,559 @@ +# AgentDock 技术架构方案 + +版本:1.0 · 日期:2026-08-24 · 角色:总工 · 状态:方案期交付 +依据:`PRODUCT-REQUIREMENTS.md` v0.1 + `agent-cli-survey-2026-08-24.md` +范围:首批 14 适配器设计;第二批 4 个仅预留扩展点,不实现 + +--- + +## 0. 一句话定位与竞品差异 + +**AgentDock** = 本机桌面「Agent CLI 生命周期管家」:发现 → 环境检查 → 安装/识别 → 中文配置 → 授权 → 更新/卸载 → 诊断。 + +| 维度 | AgentDock | 智谱 ZCode(竞品) | +|---|---|---| +| 形态 | 纯本地桌面管理器 | GUI 开发环境 + 管理 | +| 模型绑定 | **渠道中立**,不绑任何厂商套餐 | 捆绑 GLM Coding Plan | +| 管理对象 | 官方渠道安装的第三方 CLI | 自家 Harness + 切换多工具 | +| 数据与密钥 | 全本地;密钥进系统钥匙串 | 订阅与账号体系偏云端 | +| 核心卖点 | 中文化、离线可用、可扩展适配器 | 可视化切换 + 自家模型 | + +差异化口号(给总管翻译老板用):**「不卖模型、不绑套餐——只管帮你把各家官方 CLI 装好、配好、查清楚。」** + +--- + +## 1. 技术栈清单(以 PRD 4.2 为基线) + +| 层 | 选型 | 理由 | 以后怎么扩展 | +|---|---|---|---| +| 桌面壳 | **Tauri 2** | 体积小、Rust 本机能力天然契合;比 Electron 更适合「管本机命令/文件」 | 二期加 macOS / ARM 时复用同一壳 | +| UI | **React 19 + TypeScript + Vite** | 生态熟、施工员上手快;与赛博风组件库兼容 | 可加路由/状态库,不换栈 | +| 样式 | **CSS Variables 设计 Token + 少量 Tailwind(或纯 CSS Modules)** | Token 对接美术师规范;避免硬编码颜色 | 主题切换 = 换 Token 集 | +| 动效 | **Framer Motion(布局/页面)+ CSS `@property`/滤镜光效;重粒子用 Canvas 可选** | 可控帧率、易降级 | 高特效档可再加 WebGL | +| 本机能力 | **Rust(Tauri commands + 独立 crate)** | 进程、PATH、文件原子写、密钥库、平台差异 | 能力以 IPC 契约暴露,UI 不直调 OS | +| 适配器定义 | **版本化 YAML(主)+ JSON Schema 校验** | 人可读、可热更新目录;PRD 已示意 YAML | 远程目录更新可不发版 | +| 本地状态 | **SQLite(`rusqlite` / `sqlx`)** | 安装记录、诊断历史、备份索引;比散落 JSON 好查 | 导出仍可用 JSON | +| 敏感信息 | **keyring crate** → Win Credential Manager / Linux Secret Service | 满足 PRD 4.2/8;禁止明文落盘 | 迁移仅钥匙串或用户重授权 | +| 配置解析 | **toml / serde_json / serde_yaml**;Crush 用专用 `crushrc` 解析器 | 覆盖 14 家格式差异 | 新格式 = 新 `ConfigCodec` | +| 包构建 | **tauri-cli + NSIS(Win)+ deb + AppImage(Ubuntu)** | 覆盖目标平台 | 二期可加 flatpak | +| 自动更新 | **Tauri updater(签名校验)**;更新源仅官方 CDN | 离线核心功能不依赖更新 | 可关自动检查 | +| 测试 | **Rust:cargo test;前端:Vitest;适配器:fixture 驱动** | 双平台 CI 矩阵 | 真机 smoke 人工/脚本 | + +### 相对 PRD 的明确修正(仅 2 处) + +1. **本地状态优先 SQLite,不用「纯原子 JSON」作主库**——诊断历史、备份索引、操作审计需要查询;配置文件本身仍原子写。 +2. **适配器主格式定 YAML**——与 PRD 示例一致;运行时编译/校验为内部 JSON 表示,避免双源真相。 + +--- + +## 2. 目录结构与模块边界 + +```text +agentdock/ +├── apps/ +│ └── desktop/ # Tauri 2 应用入口 +│ ├── src/ # React UI +│ │ ├── pages/ # 总览 / 目录 / 我的CLI / 配置 / 备份 / 设置 +│ │ ├── components/ +│ │ ├── tokens/ # 对接美术师:颜色/字体/动效/光效变量 +│ │ ├── hooks/ +│ │ └── ipc/ # 类型化 invoke 封装(唯一前端→Rust 入口) +│ ├── src-tauri/ +│ │ ├── src/ +│ │ │ ├── main.rs +│ │ │ ├── commands/ # Tauri IPC 命令(薄层) +│ │ │ └── lib.rs +│ │ └── tauri.conf.json +│ └── package.json +├── crates/ +│ ├── agentdock-core/ # 编排:发现/安装/配置/授权/诊断流水线 +│ ├── agentdock-adapter/ # schema 加载、版本校验、dry-run、执行器接口 +│ ├── agentdock-platform/ # Win/Linux:PATH、权限提升探测、发行版识别 +│ ├── agentdock-config/ # 原子写入、备份、多格式编解码 +│ ├── agentdock-secrets/ # 系统密钥库封装 + 脱敏 +│ ├── agentdock-exec/ # 参数白名单、禁止 shell 拼接的进程执行 +│ ├── agentdock-diag/ # 规则引擎 +│ └── agentdock-store/ # SQLite schema 与仓库 +├── adapters/ # 版本化适配器 YAML(14 + 目录元数据) +│ ├── catalog.yaml # 目录索引 +│ ├── schema/ +│ │ └── adapter.schema.json # JSON Schema(校验 YAML) +│ └── tools/ +│ ├── codex.yaml +│ ├── claude-code.yaml +│ ├── gemini.yaml +│ ├── copilot.yaml +│ ├── kimi.yaml +│ ├── qwen.yaml +│ ├── codebuddy.yaml +│ ├── opencode.yaml +│ ├── crush.yaml +│ ├── goose.yaml +│ ├── aider.yaml +│ ├── cursor.yaml +│ ├── cline.yaml +│ └── warp.yaml +├── docs/ +│ └── architecture.md # 本方案落仓后副本 +└── tests/ + ├── fixtures/ # 假 PATH、假配置文件、假 --version 输出 + └── e2e/ # 可选:双平台 smoke 脚本 +``` + +### 四层边界(施工员铁律) + +| 层 | 职责 | 禁止 | +|---|---|---| +| **界面层** | 渲染适配器数据、表单、确认对话框、赛博视觉 | 直接拼命令、读写密钥、解析配置格式 | +| **本机能力层(Rust)** | IPC、编排、平台检测、执行、密钥、SQLite | 硬编码某 CLI 的特殊路径逻辑(应进适配器) | +| **适配器层** | 声明安装/检测/配置/授权/诊断;提供 dry-run | 在 YAML 里写任意 shell 字符串 | +| **状态存储** | SQLite 元数据 + 用户配置文件原子写 + 钥匙串 | 把 API Key 写入 SQLite/日志/备份默认项 | + +### 模块关系(简图) + +```text +UI --invoke--> commands --→ core orchestrator + ├→ adapter registry (YAML) + ├→ platform (env detect) + ├→ exec (safe spawn) + ├→ config codecs + atomic IO + ├→ secrets (keyring) + ├→ diag engine + └→ store (sqlite) +``` + +### 关键 IPC 契约(示意,施工员按此生成 TS 类型) + +```typescript +// 均返回 Result;错误带 code + message_zh + raw(原始错误永不吞) +detectEnv(): PlatformEnv +listCatalog(): CatalogEntry[] +detectCli(id: string): DetectResult +previewAction(id, action, opts): DryRunPlan // 安装/更新/卸载/写配置/授权/修复 +runAction(id, action, opts): ActionStream // 事件流:step/stdout/stderr/done +readConfig(id): ConfigFormState +writeConfig(id, patch): WriteResult +authStatus(id): AuthStatus +authorize(id, mode): AuthFlowHandle +diagnose(id): DiagnosticReport +listBackups() / createBackup() / restoreBackup(id, preview) +``` + +--- + +## 3. 适配器 Schema(完整定义 + 14 工具渠道矩阵) + +### 3.1 Schema 核心(在 PRD §6 上扩展) + +```yaml +# adapter.schema 关键字段(v1) +id: string # 稳定 ID,如 codex +name: string # 展示名 +name_zh: string +vendor: string +adapter_version: semver +license: string # 展示用;专有许可注明「仅官方渠道安装、不重打包」 +platforms: + windows: + architectures: [x64] + notes: string? # 如 Gemini 要求 Win11 24H2+ + linux: + distributions: [ubuntu] + architectures: [x64] + min_ubuntu: "22.04"? +official: + homepage: url + docs: url + allowed_hosts: [string] # 网络白名单(诊断/下载仅可访问) +runtime_deps: # 依赖探测 + - id: node | python | git | powershell | ... + semver_range: ">=20" + required_for: [install|run] +install: + preferred: channel_id # 默认渠道 + channels: + - id: npm | official_script | winget | choco | scoop | brew | apt | pypi_uv | github_release + platforms: [windows|linux] + # 命令必须是 argv 数组,禁止字符串拼接 + command: [string, ...] + # 脚本类:下载 URL 必须在 allowed_hosts;执行走专用 runner,不经 /bin/sh -c + script: + url: url? + kind: powershell_irm | bash_pipe | ps1_file + integrity: { sha256: hex }? # 有则强制校验 + package: string? # npm/pypi 包名 + elevate: never | if_needed | required + elevate_reason_zh: string? + post_checks: [detect] # 安装后自动检测 +detect: + executable: string # PATH 上的命令名;Cursor 为 agent + version_args: [string] + version_regex: string + version_unconfirmed: bool? # 调研标注「文档未能确认」时 true,UI 显示「实测兜底」 + path_hints: [string]? # 非 PATH 常见位置 +update: + method: npm_update | self_update_cmd | channel_reinstall | winget_upgrade | ... + command: [string, ...]? +uninstall: + method: npm_uninstall | package_manager | manual_delete + command: [string, ...]? + keep_config_default: true +authorization: + modes: # 可多选 + - mode: browser_oauth | device_code | api_key | local_tui + command: [string, ...]? + env_keys: [string]? # 写入钥匙串后注入的环境变量名 + status_command: [string, ...]? # 如 codex login status + notes_zh: string +configuration: + files: + - path: string # 支持 ~ 与平台变量 + format: toml | json | jsonc | yaml | env | crushrc + scope: user | project | system + environment: + - key: string + sensitive: bool + maps_to_field: string + fields: # 中文配置表单 + - id: string + label_zh: string + help_zh: string + required: bool + sensitive: bool + type: string | url | enum | bool + storage: file | env | keyring # keyring 永不进普通备份 + platforms: [windows|linux]? + docs_url: url? +diagnostics: + - rule_id: string # 引用规则库或内联 +documentation: + quickstart_zh: string + commands: [{ cmd, desc_zh }] + updated_at: date + risks_zh: [string] +``` + +### 3.2 统一执行器接口(Rust trait) + +```text +AdapterExecutor: + detect() -> DetectResult + install(plan) / update / uninstall + read_config() / write_config(patch) + authorization_status() / authorize(mode) + diagnose() -> Vec + dry_run(action) -> DryRunPlan # 必须:命令 argv、权限、影响文件、回滚说明 +``` + +所有 `command` 经 `agentdock-exec`:`Command::new(prog).args(args)`,**禁止** `cmd /C`、`sh -c`、管道字符串。官方「curl | bash」类安装:下载到临时文件 → SHA256(若有)→ 用明确解释器执行文件(PowerShell `-File` / `bash script.sh`),并在 UI 展示完整脚本来源。 + +### 3.3 首批 14 CLI 安装渠道与设计依据(均来自调研底稿) + +| ID | 命令 | 首选安装(Win / Ubuntu) | 备选 | 配置格式 | 授权模式 | 备注(底稿依据) | +|---|---|---|---|---|---|---| +| `codex` | `codex` | Win: 官方 PS 脚本或 npm `@openai/codex`;Ubuntu: 官方脚本或 npm | brew、GitHub Releases | TOML `~/.codex/config.toml` | browser + device_code + api_key | `--version` 文档未列,`version_unconfirmed` | +| `claude-code` | `claude` | Win: winget `Anthropic.ClaudeCode` 或 PS 脚本;Ubuntu: 官方脚本或 apt | npm(Node 22+) | JSON `~/.claude/settings.json` | browser + api_key | 专有许可:只引导官方安装 | +| `gemini` | `gemini` | 双端 npm `@google/gemini-cli`(Node 20+) | brew | JSON `~/.gemini/settings.json` | browser + api_key + vertex | Win 官方要求 11 24H2+,适配器 notes 声明 | +| `copilot` | `copilot` | Win: winget `GitHub.Copilot`(需 PS v6+)或 npm;Ubuntu: 脚本/npm/brew | — | JSON + env(`COPILOT_*`) | local_tui(`/login`) + PAT env | `--version` 未确认;需 Copilot 订阅 | +| `kimi` | `kimi` | 官方 `code.kimi.com` 脚本(内装 uv + **PyPI `kimi-cli`**) | `uv tool install kimi-cli` | TOML `~/.kimi/config.toml` | browser + api_key | **禁止** npm 仿名包 `kimi-code` | +| `qwen` | `qwen` | npm `@qwen-code/qwen-code`(Node 22+)或阿里 OSS 独立脚本 | brew | JSON `~/.qwen/settings.json` | **仅 api_key**(OAuth 已停) | `--version` 未确认 | +| `codebuddy` | `codebuddy` | npm `@tencent-ai/codebuddy-code` | `codebuddy install stable` 原生线 | 经 `codebuddy config`(路径待实测) | browser(微信登录);api_key 未确认 | 双升级路径要分 channel | +| `opencode` | `opencode` | Win: choco/scoop;Ubuntu: 官方脚本/npm | brew、Releases | JSON/jsonc `~/.config/opencode/opencode.json` | api_key + browser + device_code | 授权面最全之一 | +| `crush` | `crush` | Win: winget `charmbracelet.crush`;Ubuntu: 官方 apt(GPG) | npm、scoop、Releases | **crushrc**(Bash 语法) | api_key(环境变量) | `--version` 未确认;FSL 许可展示说明 | +| `goose` | `goose` | Win: 官方 `download_cli.ps1`;Ubuntu: 官方脚本 | brew、deb | YAML;Win 注意 `%APPDATA%\Block\goose\...` | api_key + 订阅 ACP | 密钥默认进系统钥匙串 | +| `aider` | `aider` | 官方 `aider-install` / PS 脚本 / PyPI `aider-chat` | uv/pipx;**不推荐 brew** | YAML `.aider.conf.yml` | **仅 api_key** | 独立 Python 3.12 环境 | +| `cursor` | `agent` | **仅官方脚本**(Win PS / Linux curl);**无 npm** | — | Cursor 账户体系 | browser(`agent login`) | 命令名是 `agent` 不是 cursor-agent | +| `cline` | `cline` | npm `cline`(Node 22+) | nightly 通道 | JSON `~/.cline/data/settings/providers.json` | browser + api_key + 本地模型 | 密钥已用系统 keychain | +| `warp` | `warp` | Win: 官方 agent-cli.ps1;Ubuntu: curl 脚本 | brew cask(Linux) | Warp 账户 / `WARP_API_KEY` | device_code + browser + api_key | 管 Agent CLI,不管 Warp 终端本体 | + +### 3.4 第二批(暂缓,仅 catalog 占位 `status: watch`) + +`grok`、`amp`、`deepseek-dsh`、`plandex` —— schema 允许加载但不出现在默认「可安装」列表,或灰显「观察中」。 + +--- + +## 4. 安全设计 + +### 4.1 密钥库封装 + +| 平台 | 后端 | API | +|---|---|---| +| Windows | Credential Manager(via `keyring`) | `secrets::set(service, account, secret)` | +| Linux | Secret Service / libsecret | 同上;无 daemon 时降级:**拒绝写入明文**,UI 提示安装 `gnome-keyring` | + +- `service` 固定前缀 `agentdock.`;`account` 为字段 id(如 `api_key`)。 +- 读配置时:表单敏感字段只显示「已保存 / 未保存」,回显用遮罩;真实值仅在写回目标 CLI 时短暂注入。 +- **禁止**:SQLite、普通备份、日志、崩溃报告、剪贴板默认复制密钥。 + +### 4.2 命令执行边界 + +1. 仅执行适配器声明的 argv;用户输入只作为**已校验参数槽位**(枚举/路径/版本号),不做字符串拼接。 +2. 默认禁止:管道、重定向、`$()`、反引号、`&&` 链、隐式脚本。 +3. 工作目录限制在用户主目录或用户确认的项目根。 +4. 下载:HTTPS + `allowed_hosts`;可选 SHA256;展示来源 URL。 +5. 权限提升:`elevate: if_needed|required` 时弹窗说明 `elevate_reason_zh`;**应用本身不以管理员启动**。 +6. 禁止远程网页驱动本机执行;禁止任意 URL 代理(防 SSRF)。 + +### 4.3 日志脱敏规则 + +| 模式 | 处理 | +|---|---| +| `sk-` / `xai-` / `ghp_` / `gho_` / JWT 形态 | 替换为 `***REDACTED***` | +| 适配器标记 `sensitive: true` 的 env/字段值 | 一律脱敏 | +| 家目录绝对路径 | 可选折叠为 `~`(诊断导出前提示) | +| 原始错误 | 保留结构,但过脱敏器后再落盘 | + +--- + +## 5. 环境检测方案(Win 10/11 x64 · Ubuntu 22.04/24.04 x64) + +`PlatformEnv` 结构: + +```text +os: windows | linux +os_version: ... +arch: x64 | other(reject) +distro?: ubuntu + version +shells: powershell_version?, bash_available? +runtimes: { node?, npm?, python?, uv?, git?, winget?, apt? } +path_entries: [...] +capabilities: { keyring: ok|missing, can_elevate: bool } +``` + +| 检测项 | Windows | Ubuntu | +|---|---|---| +| OS/版本 | `RtlGetVersion` / 注册表 | `/etc/os-release` | +| PATH | 用户+系统 PATH 合并,注意商店别名 | `$PATH` + `~/.local/bin` 是否在内(Goose/Cursor 常见坑) | +| Node/npm | `where node` + `node -v` | `command -v` + 版本 | +| Python/uv | `py -0p` / `uv --version` | 同上 | +| 包管理器 | winget / choco / scoop 可用性 | apt;可选 brew-on-linux | +| PowerShell | 区分 Windows PowerShell 5 vs pwsh 6+(Copilot winget 依赖) | N/A | +| 密钥库 | Credential Manager 可用性 | `secret-tool` / DBus Secret Service | + +检测失败分类(对齐 FR-02):`not_installed` | `not_in_path` | `permission_denied` | `exec_failed` | `version_unparseable`。 + +--- + +## 6. 配置读写设计 + +### 6.1 原子写入 + 自动备份 + +对任意目标文件 `F`: + +1. 若 `F` 存在 → 复制到 `F.bak.`(及 SQLite 备份索引)。 +2. 写入临时文件 `F.tmp.`。 +3. `fsync` 后 `rename` 覆盖(Windows 用 `MoveFileEx` 替换语义)。 +4. 失败则保留原文件与临时文件,UI 展示原始错误。 + +### 6.2 多格式统一策略:`ConfigCodec` trait + +| format | 实现要点 | 代表 CLI | +|---|---|---| +| `toml` | `toml_edit` 保注释 | Codex、Kimi | +| `json` / `jsonc` | jsonc 用 `jsonc-parser` 或 strip comments | Claude、Gemini、Qwen、OpenCode、Cline、Copilot | +| `yaml` | serde_yaml | Goose、Aider | +| `env` | KEY=VALUE 行;敏感键走钥匙串引用 | 多 CLI 辅助 | +| `crushrc` | **专用解析器**:识别 Crush 内建赋值语句,不做任意 bash 执行;未知行保留原样 | Crush | + +表单字段 `storage`: + +- `file` → Codec 读写 +- `env` → 用户级环境变量(Win:用户环境;Linux:`~/.config/agentdock/env.d/*.sh` 并提示加入 shell,或仅会话注入说明) +- `keyring` → 只写钥匙串;可选写入 CLI 期望的「env 变量名指针」到配置(如 Codex `env_key`) + +Goose:尊重其「密钥默认进系统钥匙串」——AgentDock 与之对齐,不把 Key 写入 `config.yaml`。 + +--- + +## 7. 授权状态统一模型 + +```text +AuthStatus = authorized | unauthorized | unknown | possibly_expired +AuthMode = browser_oauth | device_code | api_key | local_tui +``` + +| 模式 | AgentDock 行为 | +|---|---| +| `browser_oauth` | 启动适配器 login 命令;监听进程结束;可选检测本机打开浏览器;结果只存状态枚举 | +| `device_code` | 弹出「设备码」面板展示 stdout 中的 user_code + verification_url(解析规则在适配器);不截获 token 明文到日志 | +| `api_key` | 表单写入钥匙串;按 CLI 要求设置 env 或 `login --with-api-key`(stdin 传,不进 argv) | +| `local_tui` | 打开一次性伪终端面板(如 Copilot `/login`、部分 onboarding);结束后关闭,只留脱敏状态 | + +状态探测优先级: + +1. 适配器 `status_command`(如 `codex login status`、`opencode auth list`) +2. 钥匙串是否有对应 key +3. 配置文件非敏感标记 +4. 否则 `unknown` + +Qwen:UI 文案明确「免费 OAuth 已停用,请配置 API Key」。 +Kimi:安装源校验拦截非官方 npm。 + +--- + +## 8. 赛博风 UI 技术支撑与性能底线 + +### 8.1 与美术师对接点(施工员只消费 Token) + +```text +src/tokens/ + color.css /* --ad-bg, --ad-neon-cyan, --ad-danger, ... */ + typography.css + space.css + motion.css /* --ad-duration-fast/mid, --ad-ease-cyber */ + effects.css /* --ad-glow-strength, --ad-scanline-opacity */ + tiers.css /* data-fx-tier="high|balanced|low" */ +``` + +页面结构按 PRD §7:总览 / CLI 目录 / 我的 CLI / 配置中心 / 备份 / 设置。视觉细节以美术师 HEL-101 规范为准;架构只保证:**所有颜色/光晕/动效时长走 Token,组件不写死魔法数。** + +### 8.2 实现分层 + +| 层级 | 技术 | 用途 | +|---|---|---| +| L0 静态 | CSS 渐变、网格背景、边框霓虹(`box-shadow` Token) | 常驻,成本低 | +| L1 过渡 | Framer Motion / CSS transition | 路由、列表、按钮 | +| L2 光效 | SVG/CSS 扫光、有限 blur | 卡片 hover、焦点 | +| L3 粒子/噪点 | 可选 Canvas,**默认关** | 总览背景 | + +### 8.3 性能底线与降级 + +- 目标:集成显卡笔记本上总览页 **≥45 FPS**;交互延迟 <100ms。 +- 默认档 `balanced`:关 L3、降低 blur、减少同时动画数量(`max-concurrent-motions ≤ 3`)。 +- `low`:仅 L0+必要过渡;`prefers-reduced-motion` 强制 `low`。 +- 长列表虚拟滚动;日志终端用虚拟化,避免万行 DOM。 +- WebView 合成层:大面积滤镜仅用于静态背景层,不叠在滚动内容上。 + +--- + +## 9. 安装包分发与自动更新 + +| 产物 | 工具链 | 校验 | +|---|---|---| +| Windows x64 安装包 | Tauri + NSIS(或 MSI 二选一,首期 NSIS) | Authenticode 签名(有证书则必须;无证书时 UI 提示校验 SHA256) | +| Ubuntu | `.deb` + **AppImage**(覆盖无 root 场景) | deb 可用 GPG;AppImage 附 SHA256SUMS | +| 更新 | Tauri Updater | ed25519/minisign 签名;更新端点在 `allowed_hosts` | +| 回滚 | 保留上一版安装包;失败则提示卸载重装 + Git tag 对应版本 | 方案期约定:发版打 tag,坏版本从更新通道撤下 | + +应用自动更新与「CLI 更新」分离:设置页两项独立开关。核心管理功能 **离线可用**(目录 YAML 内置;在线仅用于检查更新与声明过的诊断 URL)。 + +--- + +## 10. 诊断规则引擎 + +### 10.1 规则模型 + +```yaml +rule_id: path.missing_executable +severity: path | dependency | version_conflict | config_corrupt | network | auth +severity: info | warn | error +when: { adapter_expr } # 可选:仅某些 CLI +check: # 声明式检查器 + type: which | semver | file_parse | http_head | keyring_has + ... +message_zh: "..." +evidence: capture # 原始 which 输出等 +fix: + - id: add_to_path + dry_run: true + reversible: true + impact_zh: "..." +``` + +### 10.2 四类必检(可扩展) + +| 类 | 示例规则 | +|---|---| +| PATH | 可执行文件不在 PATH;Windows Store alias 劫持;`~/.local/bin` 未入 PATH | +| 依赖缺失 | Node 版本不满足(Gemini≥20、Claude/Qwen/Cline/Copilot npm≥22);无 Git;无 uv(Kimi) | +| 版本冲突 | 多路径同名命令;npm global 与独立脚本双装(CodeBuddy 双通道) | +| 配置损坏 | JSON/TOML/YAML 解析失败;crushrc 无法识别关键赋值;权限不可读 | + +网络类:仅 `HEAD/GET` 适配器 `allowed_hosts`。 +输出:级别 + 证据 + 中文解释 + 推荐修复(修复前 dry-run + 备份)。 + +--- + +## 11. 测试策略 + +| 层级 | 内容 | +|---|---| +| 适配器单元测试 | 每个 YAML:schema 校验;dry-run 快照;version_regex 对 fixture stdout;危险命令(含 shell 元字符)必须拒载 | +| Codec 测试 | 各格式往返;保留未知键;原子写失败注入 | +| Exec 测试 | 拒绝管道字符串;参数白名单 | +| Secrets 测试 | mock keyring;断言日志无明文 | +| 平台检测测试 | Win/Ubuntu CI 或容器:`PlatformEnv` 字段;对「未安装」场景断言错误码 | +| UI 冒烟 | 目录渲染 14 条;安装确认框展示 argv;降级档无运行时错误 | +| 手工验收(对齐 PRD §10) | 双平台干净机:装应用→检测→至少 1 个 CLI GUI 安装成功→配置往返→Key 不进日志 | + +Wave A 五个适配器必须先有绿灯测试,再扩 Wave B。 + +--- + +## 12. 分波次交付节奏(14 = 5 + 9,每步可运行) + +对齐 PRD §11,并按老板升级的 14 适配器拆波: + +### Wave 0 — 空壳可运行(约 1 迭代) + +Tauri2 + React 壳、Token 占位、IPC 心跳、SQLite 空库、平台检测页、假目录。 + +### Wave 1 — 适配器框架 + 环境检测 + +Schema、加载器、dry-run、exec 沙箱、密钥库封装、日志脱敏。 + +### Wave 2 — Wave A 五件套打通全链路(安装→检测→配置→授权状态→诊断) + +优先选「文档全、双平台稳、配置清晰」: + +1. **Codex**(三授权 + TOML) +2. **Claude Code**(winget/脚本 + JSON) +3. **Gemini**(npm + JSON Schema) +4. **Kimi**(脚本/PyPI,验证非 npm 路径) +5. **OpenCode**(多渠道 + 多授权) + +验收:五者均可 detect;至少两者 GUI 安装成功;API Key 配置往返;三类诊断可命中。 + +### Wave 3 — Wave B 补齐 9 个 + +**B1(npm/脚本同类)**:Qwen、CodeBuddy、Cline、Copilot +**B2(包管理器/特殊)**:Crush(winget/apt + crushrc)、Goose(PS 脚本 + YAML 路径差异)、Aider(Python 安装器) +**B3(闭源脚本)**:Cursor(`agent`)、Warp(`warp`) + +每合入一个:单元测试 + 双平台 detect 记录。 + +### Wave 4 — 备份迁移 + 安装包 + 更新通道 + +备份不含密钥;Win NSIS + Ubuntu deb/AppImage;签名/SHA256;赛博视觉按美术规范挂满并做降级开关。 + +### Wave 5 — 打磨 + +批量更新、文档页中文、诊断规则扩容、第二批 watch 列表 UI。 + +--- + +## 13. 施工员开工检查清单(拿到本方案应无需再问架构) + +- [ ] 按目录建 monorepo;适配器只加 YAML,不改 core 流程 +- [ ] 一切安装命令来自上表与调研底稿,禁止凭记忆改包名 +- [ ] Kimi 绝不走 npm;Cursor 绝不走 npm;命令名 `agent` +- [ ] 用户确认前只 `dry_run`;确认后流式展示 stdout/stderr +- [ ] 密钥只进 keyring;日志过脱敏 +- [ ] 颜色/动效只引用 `tokens/`,等美术师规范合并 +- [ ] 不实现第二批 4 个,不建远程业务后端 +- [ ] 每 Wave 结束保持 `cargo test` + 前端 build 通过 + +--- + +## 14. 风险与需总管转告老板的点(非阻塞,已在方案内消化) + +1. 若干 CLI 的 `--version` 官方未文档化 → 适配器 `version_unconfirmed` + 实测表。 +2. CodeBuddy 配置路径、Copilot 登录是浏览器还是设备码 → Wave B 实测补字段。 +3. Gemini 官方写 Win11 24H2+ → 低版本 Win10 显示「官方未支持」而非强装。 +4. 无代码签名证书时 Win 智能筛选会报警 → 提供 SHA256 核对说明。 +5. Crush FSL 许可 → 关于页展示,不做竞品再分发其源码。 + +--- + +**本方案只交付设计,不含实现代码、不建仓库、不部署。** +施工员以本文 + PRD + 调研底稿三件套开工;视觉以美术师规范为准。 diff --git a/docs/visual-spec-v1.2.md b/docs/visual-spec-v1.2.md new file mode 100644 index 0000000..c2890a5 --- /dev/null +++ b/docs/visual-spec-v1.2.md @@ -0,0 +1,448 @@ +# AgentDock 视觉规范 v1.2(赛博风 · 终版,施工唯一依据) + +适用范围:AgentDock 第一版全部界面(Tauri 2 + React,Windows / Ubuntu,简体中文)。 +本规范是施工员写样式、总工验收的唯一品味依据。未覆盖到的新场景,按「视觉方向」一节的原则推演,不要自创风格。 + +**v1.2 修订说明**:老板已对 v3 样图拍板「通过」,本版把 v3 上按老板意见做的 4 处改动合入规范,为**施工开工的最终依据**。与 v1.1 的差异在 §0 总览逐条映射,并在对应节开头用【v1.2】标注;未标注的条文沿用 v1.1(含其【v1.1】标注)不变。施工对照基准 = 本规范 + v3 样图(HEL-107 附件 `overview3.png`)。 + +## 0. v1.2 变更总览(老板拍板 → 条文映射) + +| v3 已通过的改动 | 覆盖 v1.1 条文 | v1.2 条文 | +|---|---|---| +| ① 侧边栏选中态:废止嵌入 3px 指示条,改为左缘生长的青色渐变 + 1px 青色内描边,一种形态语言 | §3.0 侧边栏选中态 | §3.0【v1.2 重写】 | +| ② 「提示」级由中性冷灰空心点改为紫色实心点,语义升级为「紫 = 需要留意(提示 / 待授权)」 | §2.1 `--ad-note`、§3.5 提示级 | §2.1、§3.5【v1.2 修订】 | +| ③ 待授权 KPI 卡数字与顶部色条改紫色;色彩语义表定稿为六色;CLI 状态网格「待授权」角标与「未授权」空心点同步改紫 | §3.1.1 KPI 卡、§3.1.4 状态网格、§3.2、§3.3 | §2.1、§3.1.1、§3.1.4、§3.2、§3.3【v1.2 修订】 | +| ④ 主按钮 hover 微光扩散:`brightness(1.08)` + 双层扩散辉光,按下收回 | §2.6 悬浮/按下参数 | §2.6【v1.2 修订】 | +| ⑤ 验收对照同步更新(选中态形态语言、紫色语义红线) | §9 | §9【v1.2 修订】 | + +--- + +## 1. 视觉方向(一句话) + +**「深夜运维舱」:像一台运行良好的未来机器——深空蓝黑打底,霓虹青做交互指引,品红只点在关键状态上;光效和动效全部服务于「状态可读」,信息区永远干净克制。** + +三条不可违反的原则: + +1. **炫在框架,不在内容**。辉光、网格、扫描线只出现在背景、边框、导航、状态指示上;正文、表单、诊断文本区域保持高对比、零装饰。 +2. **光即语义**。霓虹色不是装饰色:青 = 可交互/主操作,品红 = 可更新/重要提醒,绿 = 正常,黄 = 警告,红 = 错误,【v1.2】紫 = 需要留意(提示 / 待授权)。用户看到颜色就能猜到含义,不许混用。 +3. **普通人友好**。所有动效可降级、可关闭;任何承载信息的文字对比度不低于 WCAG AA(正文 4.5:1,大字 3:1)。 + +【v1.1 新增第四条,v1.2 不变】 + +4. **密度优先**。总览页是信息密度最高的页面,首屏任何区域不允许出现超 15% 的无效空白;「留白高级」在本产品不成立,空 = 内容没做完。 + +--- + +## 2. 设计 Token 全套 + +统一用 CSS 变量命名,前缀 `--ad-`。以下值直接可用,施工员不得自行调参。 + +### 2.1 配色 + +【v1.2 修订:废止 `--ad-note` 中性冷灰,「提示 / 待授权」统一升级为紫色 `--ad-attention`;色彩语义表定稿为六色。其余沿用 v1.1】 + +**底色(深空阶梯,由深到浅):** + +| Token | 色值 | 用途 | +|---|---|---| +| `--ad-bg-0` | `#070B14` | 应用窗口底色 | +| `--ad-bg-1` | `#0D1420` | 面板、卡片底色(实际卡片表面用 §3.1 的径向渐变面) | +| `--ad-bg-2` | `#131C2E` | 浮层、弹窗、下拉、mono chip 底 | +| `--ad-bg-3` | `#1A2438` | 悬浮态、按下态的填充 | +| `--ad-border` | `#22304A` | 常规 1px 分隔线 | +| `--ad-border-bright` | `#35507A` | 悬浮/选中的边框 | + +**霓虹强调色(全系统只有这两个霓虹色):** + +| Token | 色值 | 用途 | +|---|---|---| +| `--ad-primary` | `#00E5FF` | 主操作、链接、聚焦、选中态(青) | +| `--ad-primary-hover` | `#4DEFFF` | 主操作悬浮 | +| `--ad-primary-pressed` | `#00B4CC` | 主操作按下 | +| `--ad-primary-dim` | `rgba(0,229,255,0.12)` | 选中项底、标签底 | +| `--ad-accent` | `#FF4DDB` | 可更新标记、重要提醒(品红,克制使用) | +| `--ad-accent-dim` | `rgba(255,77,219,0.12)` | 品红标签底 | + +**状态色(诊断四级 + 通用语义,必须分明,不许互相借用):** + +| Token | 色值 | 语义 | +|---|---|---| +| `--ad-success` | `#2EE6A8` | 正常 / 已安装 / 已授权 / 已自动修复 | +| `--ad-attention` | `#A78BFA` | **需要留意:「提示」级 + 「待授权 / 未授权」**(v1.2 新增,紫;实心点、不发光、不呼吸) | +| `--ad-warning` | `#FFB020` | 警告 / 需要你注意的异常 | +| `--ad-danger` | `#FF4D5E` | 错误 / 需要你处理 / 高危操作(卸载并删除配置等) | + +每个状态色配对应的 12% 透明度底色:`--ad-success-dim` / `--ad-attention-dim`(`rgba(167,139,250,0.12)`)/ `--ad-warning-dim` / `--ad-danger-dim`,用于状态标签、诊断条目背景。 + +**完整色彩语义表(v1.2 定稿,六色,全系统唯一标准):** + +| 语义 | 颜色 | 形态 | +|---|---|---| +| 可交互 / 主操作 / 选中 / 已安装 | 青 `--ad-primary` | 实心渐变按钮、描边、链接、聚焦辉光、状态点、角标 | +| 需要留意(提示 / 待授权 / 未授权) | 紫 `--ad-attention` | **实心圆点**、ⓘ 图标、待授权角标、未授权空心圈(仅圈形描边用紫,见 §3.1.4),**不发光、不呼吸** | +| 可更新 / 重要提醒 | 品红 `--ad-accent` | 角标、数字、更新按钮(唯一允许品红做按钮的场景) | +| 警告 / 需要你注意 | 黄 `--ad-warning` | 状态点、⚠ 图标、警告 chip,允许呼吸 | +| 错误 / 需要你处理 | 红 `--ad-danger` | 状态点、✕ 图标、危险描边,允许呼吸 | +| 正常 / 已授权 / 已修复 | 绿 `--ad-success` | 状态点、✓ 图标、chips | + +**状态色贯穿规则(强制)**:状态色不许只停在装饰条/色点上——凡是表达该状态的**数字、关键文字、图标**必须同色。例:环境异常卡的数字 `1` 必须是 `--ad-warning` 黄,待授权卡的数字必须是 `--ad-attention` 紫,不是白色数字配彩色装饰条。 + +**红色使用红线(强制)**:红只留给「需要你处理」的未解决项。已自愈/已自动修复的条目一律用绿 + 灰化文字 + 「已自动修复」标签(见 §3.1),禁止挂红点。 + +**紫色使用规则(v1.2 新增)**:紫介于「正常」与「警告」之间,表达「现在不用处理,但需要你留意」——诊断「提示」级、待授权/未授权状态专用。紫色任何形态**不发光、不呼吸**(避免与警告/错误的动态信号混淆);诊断列表中「提示」级用紫色**实心**点(v1.1 的中性空心点废止)。 + +**已删除**:`--ad-info` `#4DA3FF` 及 `--ad-info-dim`(蓝色退出系统,界面任何位置出现蓝色 = 不合格);`--ad-note` `#8E9BB0` 及 `--ad-note-dim`(v1.2 起由 `--ad-attention` 取代)。 + +**文字:** + +| Token | 色值 | 用途 | +|---|---|---| +| `--ad-text-1` | `#E8EEF7` | 主文案 | +| `--ad-text-2` | `#9AA8BD` | 次要说明(对 `--ad-bg-1` 对比度约 6.9:1,是承载信息的最低允许色) | +| `--ad-text-3` | `#5E6E87` | 仅占位、禁用、纯装饰(对比度约 3.3:1,**禁止承载信息**) | + +**对比度三件套之一**:任何承载信息的文字(含次要说明、时间戳、安全承诺文案)对比度 ≥ 4.5:1,即最低用 `--ad-text-2`;`--ad-text-3` 只允许出现在禁用态与占位符。安全承诺、授权提示这类建立信任的文字尤其不许压暗。 + +### 2.2 字体 + +【v1.2 不变】 + +```css +--ad-font-ui: "PingFang SC", "Microsoft YaHei UI", "Microsoft YaHei", + "Noto Sans CJK SC", "Source Han Sans SC", system-ui, sans-serif; +--ad-font-mono: "Cascadia Code", "JetBrains Mono", Consolas, + "Noto Sans Mono CJK SC", monospace; +``` + +- 等宽字体只用于:命令、路径、版本号、日志/终端输出、API Key 掩码、文件名。路径里的中文允许回落到 UI 字体,不用强求等宽。 +- **Mono chip**(对比度三件套之二):正文/列表中内联出现的文件名、版本号、命令,一律套 mono chip:`--ad-font-mono` 12px、`--ad-bg-2` 底、1px `--ad-border` 描边、`--ad-radius-s`、内边距 `1px 6px`,文字色 `--ad-text-1`。例:`settings.json`、`v0.22.0`、`20.x`。 +- 字阶(字号 / 行高 / 字重): + +| Token | 规格 | 用途 | +|---|---|---| +| `--ad-text-xs` | 12px / 18px / 400 | 标签、辅助说明、时间戳 | +| `--ad-text-s` | 13px / 20px / 400 | 表格次级信息、卡片描述 | +| `--ad-text-m` | 14px / 22px / 400 | 正文、表单、按钮(基准字号) | +| `--ad-text-l` | 16px / 24px / 500 | 卡片标题、分组标题 | +| `--ad-text-xl` | 20px / 28px / 600 | 页面标题 | +| `--ad-text-num` | 28px / 36px / 600 | 仪表盘大数字(UI 字体,不用等宽) | + +不加任何外联 Web 字体(离线可用、安装包不膨胀)。 + +### 2.3 间距、圆角、描边 + +【v1.2 不变】 + +- 间距 4px 基数:`--ad-space-1: 4px` `-2: 8px` `-3: 12px` `-4: 16px` `-5: 20px` `-6: 24px` `-8: 32px` `-10: 40px` +- 圆角:`--ad-radius-s: 4px`(标签、小按钮、chip)`--ad-radius-m: 8px`(卡片、输入框、弹窗)`--ad-radius-l: 12px`(主面板)。**赛博感靠小圆角 + 发光描边,不做大圆角。** +- 可选切角:仅仪表盘 KPI 卡、CLI 详情页头卡允许用 `clip-path` 切一个 8px 的右上斜角,制造硬核感;低性能档一律退回直角,见第 5 节。 +- 描边统一 1px;选中/聚焦的「发光描边」= 1px 实色 + 外辉光,不允许加粗到 2px(会跳动)。 + +### 2.4 阴影与辉光 + +【v1.2 微调:不发光对象表述对齐紫色新语义;主按钮 hover 辉光参数见 §2.6】 + +```css +--ad-shadow-panel: 0 8px 24px rgba(0, 0, 0, 0.45); +--ad-shadow-pop: 0 12px 40px rgba(0, 0, 0, 0.6); +--ad-glow-primary: 0 0 12px rgba(0, 229, 255, 0.35), 0 0 32px rgba(0, 229, 255, 0.12); +--ad-glow-accent: 0 0 12px rgba(255, 77, 219, 0.35); +--ad-glow-warning: 0 0 10px rgba(255, 176, 32, 0.28); /* 仅警告 chip / 警告状态灯 */ +--ad-glow-danger: 0 0 12px rgba(255, 77, 94, 0.35); +``` + +辉光只给:主按钮、选中导航项、聚焦输入框、需处理状态指示灯、可更新角标、环境警告 chip。**列表里每一行都发光 = 全部不发光,禁止。**「需要留意」级(`--ad-attention` 紫)任何形态不发光。 + +### 2.5 动效曲线与时长 + +【v1.2 不变】 + +```css +--ad-ease-out: cubic-bezier(0.16, 1, 0.3, 1); /* 进场、浮现,主力曲线 */ +--ad-ease-inout: cubic-bezier(0.65, 0, 0.35, 1); /* 展开收起、位移、呼吸 */ +--ad-ease-linear: linear; /* 仅环境循环动画 */ +--ad-dur-micro: 120ms; /* 按下、勾选 */ +--ad-dur-fast: 200ms; /* 悬浮、淡入淡出 */ +--ad-dur-med: 320ms; /* 面板展开、页面切换 */ +--ad-dur-slow: 600ms; /* 仅入场编排,一次性 */ +``` + +### 2.6 主按钮规格 + +【v1.2 修订:老板裁定大面积青保留为风格选择,但 hover 必须用扩散光消化高饱和——悬浮辉光由单层升级为双层扩散,按下收回;其余沿用 v1.1】 + +```css +/* 主按钮(添加 CLI、安装 等主操作) */ +--ad-btn-primary-bg: linear-gradient(180deg, #33D9EE 0%, #06BCD9 55%, #049EBB 100%); +--ad-btn-primary-text: #03252E; +--ad-btn-primary-inner: inset 0 1px 0 rgba(255, 255, 255, 0.30), + inset 0 -1px 0 rgba(2, 20, 26, 0.35); +--ad-btn-primary-glow: 0 0 10px rgba(0, 229, 255, 0.22); +/* v1.2 新增:hover 双层扩散辉光 */ +--ad-btn-primary-glow-hover: 0 0 14px rgba(0, 229, 255, 0.30), + 0 0 36px rgba(0, 229, 255, 0.12); +``` + +- 结构:高 36px,`--ad-radius-s`,`--ad-btn-primary-bg` 内渐变 + `--ad-btn-primary-inner` 内高光/内阴影 + 常驻 `--ad-btn-primary-glow` 弱辉光,字 14px / 500 / `--ad-btn-primary-text`。 +- 悬浮(v1.2 定稿):`filter: brightness(1.08)` + 辉光扩为双层 `--ad-btn-primary-glow-hover`(内层 14px 聚焦、外层 36px 弥散),200ms `--ad-ease-out`。原理:用向外扩散的柔光消化大面积高饱和青在悬浮时的刺眼感,而不是再提亮本体。 +- 按下:`filter: brightness(0.94)`,辉光收回(消失),120ms。 +- 荧光感控制:`#00E5FF` 只用于描边、图标、文字、辉光这类「线」与「点」,实心填充一律用上面的降明度内渐变。 +- 品红更新按钮同理:`linear-gradient(180deg, #F26AD9 0%, #D633B8 55%, #B5209C 100%)`,内高光/内阴影同构,常驻辉光用 `--ad-glow-accent` 半强度;悬浮辉光同样按「半径放大、透明度分层」扩散(`0 0 14px rgba(255,77,219,0.30), 0 0 36px rgba(255,77,219,0.12)`)。 + +--- + +## 3. 关键页面布局与组件样式 + +### 3.0 整体框架 + +【v1.2 修订:侧边栏选中态重写(废止嵌入指示条,改左缘生长渐变 + 内描边一体形态);背景网格、导航图标、引擎状态区、Header 分组沿用 v1.1】 + +整体框架:**左侧竖导航 + 顶栏 + 内容区**。 + +**背景网格(要么可见要么不做,禁止两头不占):** + +- 规格:1px 线、40px 间距、颜色 `rgba(0,229,255,0.05)`(透明度固定 5%,允许区间 3–6%,施工员取 5% 不许再调); +- **边缘羽化**:整体罩一层径向遮罩 `mask-image: radial-gradient(120% 90% at 50% 40%, #000 30%, transparent 75%)`,中心可见、向四边淡出至 0; +- 中高档附 60s 缓慢漂移(见 §4.8),低档静态; +- 若实现后静态截图下网格仍不可见,宁可删掉网格也不许留在「若隐若现」区间。 + +**侧边栏:** + +- 宽 232px,收起后 64px(只留图标)。 +- **选中态(v1.2 定稿,废止 v1.1「圆角背景块 + 嵌入 3px 指示条」方案——老板两轮审图判定指示条与圆角背景是两张皮)**:选中项 = 一个圆角背景块,**无独立指示条**,整个选中态只有一种形态语言: + - 背景:`linear-gradient(90deg, rgba(0,229,255,0.30), rgba(0,229,255,0.12) 45%, rgba(0,229,255,0.05))`——一层从块左缘「生长」的青色渐变,左浓右淡,到右缘几乎消隐; + - 内描边:`inset 0 0 0 1px rgba(0,229,255,0.38)`,与背景块同圆角; + - 块规格:`--ad-radius-m`、左右内边距 12px、块左右各留 8px 外边距(不贴窗口边缘); + - 图标与文字变 `--ad-primary`; + - 不额外加辉光(渐变 + 内描边已足够表达选中,再叠光则脏)。 + - 收起态(64px 图标栏):同一套渐变 + 内描边作用于 40px 见方图标块,形态语言不变。 + - 定义 token:`--ad-nav-selected-bg`(上述渐变)、`--ad-nav-selected-border`(上述内描边)。 +- 导航图标:5 个一级导航统一 20px 显示尺寸、**1.5px 描边**、圆角端点线性风格(§7),粗细不一致的图标混用前必须调 stroke 到 1.5px 观感。 +- 底部引擎状态区:独立区块高 48px,顶部 1px `--ad-border` 分隔线,内边距 `0 16px`;内容 = 8px 状态灯(运行中=绿静态、异常=黄呼吸,规则见 §4.5)+ 「本地引擎 · 运行中」`--ad-text-s` / `--ad-text-2` + 版本号 mono chip(如 `v1.0.0`)。收起态只留状态灯居中。 + +**顶栏(Header):** + +- 高 56px,左起:当前页标题(`--ad-text-xl`)。 +- 右侧状态区分组:搜索框与环境警告 chip 为一组,间距 `--ad-space-3`(12px),组内基线对齐,与页面标题拉开间距。 +- 搜索框限宽:标准断点固定宽 320px,紧凑断点收缩为 36px 图标按钮、点击展开。聚焦 = 边框变青 + `--ad-glow-primary`。 +- **环境警告 chip**:高 28px、`--ad-radius-s`、1px `rgba(255,176,32,0.5)` 描边、`--ad-warning-dim` 底;内容 = 6px 黄点(异常存在时按 §4.5 呼吸)+ 「N 项环境警告」`--ad-text-s` / `--ad-warning` + 12px chevron-down。悬浮:描边转实色 `--ad-warning` + `--ad-glow-warning` + 手型指针,200ms;点击展开警告明细下拉。无警告时整颗 chip 不渲染,不留占位。 + +**内容区:** 最大宽 1440px 居中,左右留白 `--ad-space-8`。 + +### 3.1 总览(仪表盘) + +【v1.2 修订:KPI 卡「待授权」数字与色条改紫;CLI 状态网格「待授权」角标与「未授权」点改紫;其余布局与规则沿用 v1.1】 + +**布局(自上而下三段,首屏必须填满):** + +1. KPI 卡一排 4 张:已安装 / 待授权 / 可更新 / 环境异常。 +2. 中段:左 2/3「最近诊断结果」列表,右 1/3「快速操作」卡。 +3. **下段(必选模块):「CLI 状态」网格通栏**,已收录 CLI 以状态块平铺(见 §3.1.4)。后续迭代可在其下再接「资源占用」「活动流」模块,规则同本页组件语言;首屏任何纵向区间无效空白 ≤ 15%。 + +**3.1.1 KPI 卡:** + +- 卡片表面(悬浮玻璃板):底为径向渐变面 `radial-gradient(120% 100% at 50% 0%, #16233A 0%, #0D1420 60%)` + 上缘 1px 高光 `inset 0 1px 0 rgba(255,255,255,0.06)` + `--ad-shadow-panel`;与页面背景明度差必须拉开,验收时卡片边界在静态截图下清晰可辨。 +- `--ad-radius-l`、右上 8px 切角(可选,低档退回直角)。 +- **顶部色条贯通整宽**(废止半拉子短条;也不许做左侧短装饰条):2px 高、与卡片同宽,颜色按卡语义【v1.2 定稿】:已安装=青、**待授权=紫 `--ad-attention`**(v1.1 的中性 `--ad-border-bright` 废止)、可更新=品红、异常=黄;**数值为 0 时色条降为 `--ad-border` 灰**。 +- 大数字 `--ad-text-num`,**数字随状态色贯穿**【v1.2 定稿】:已安装=青、**待授权=紫 `--ad-attention`**(v1.1 的中性白废止——待授权是「需要留意」的待办,按六色语义表归紫色,不再是「不色」)、可更新=品红、环境异常=黄;数值为 0 时数字回 `--ad-text-1`。 +- 副标题统一「对象点名」句式(强制):不解释、不形容,直接点出对象名,超过 3 个用「A · B · C 等 N 个」。例:待授权 → `Kimi CLI · Warp Agent`;环境异常 → `Node.js 20.x`(版本号套 mono chip);已安装 → `最新安装 · Qwen Code`;可更新 → `Qwen Code · Goose · Aider`。 +- 悬浮:整体抬升 2px + 顶部色条辉光,200ms `--ad-ease-out`,不打断数据。 + +**3.1.2 最近诊断列表(五条硬规则):** + +1. **时间格式(三件套之三,全应用统一)**:<1 分钟显示「刚刚」;<1 小时显示「N 分钟前」;<24 小时显示「N 小时前」;≥24 小时一律绝对时间「M月D日 HH:mm」(跨年开始带年「YYYY年M月D日」);悬浮显示完整绝对时间 tooltip。禁止相对/绝对混排无规则出现。 +2. **mono chip**:条目内的文件名、版本号、命令一律按 §2.2 套 mono chip。 +3. **对比度**:结论文字最低 `--ad-text-2`,时间戳最低 `--ad-text-2`,任何承载信息的文字不低于 4.5:1。 +4. **红色只留「需要你处理」**:已自动修复的条目 = 绿点 + 文字灰化(`--ad-text-2`)+ 右侧「已自动修复」标签(绿字、1px `rgba(46,230,168,0.4)` 描边、`--ad-success-dim` 底、高 20px);未解决错误才用红点 + `--ad-text-1` 文字。【v1.2】「提示」级用 `--ad-attention` **紫色实心圆点**(v1.1 的中性空心点废止),不发光、不呼吸。 +5. **「查看全部」**:`--ad-text-s` 青字 + 14px chevron-right 图标,悬浮文字变 `--ad-primary-hover`、chevron 右移 2px,200ms。 + +行结构不变:级别点 + CLI 名 + 一句话结论 + 右侧时间,行高 48px,整行可点击进诊断详情。 + +**3.1.3 快速操作卡:** + +- 结构自上而下:主按钮「添加 CLI」(§2.6 规格,+ 图标)→ 次按钮「立即诊断」→ 次按钮「创建备份」→「最近安装」迷你列表 → 安全承诺行。密度必须与左侧诊断列表视觉平衡,不允许一侧拥挤一侧空荡。 +- 图标语义(定死):「立即诊断」用 pulse/scan 类图标(心电脉冲或扫描线),不许用公文包等无关图标;「添加 CLI」用标准加号图标,全应用加号统一同一枚;「创建备份」用下载/存档类图标。 +- 按钮内图标 16px,与文字间距统一 `--ad-space-2`(8px),三个按钮对齐方式一致(统一居中)。 +- 「最近安装」列表:分组标题 `--ad-text-xs` / `--ad-text-3`(此为唯一允许的 `--ad-text-3` 分组标签用法,下同不例)+ 最多 3 条,每条 = 16px CLI 图标 + 名称 `--ad-text-s` + 右侧相对时间 `--ad-text-xs` / `--ad-text-2`。 +- 安全承诺行:12px 锁图标 + 「所有操作在本地完成,密钥只存系统保险柜,不上传。」,`--ad-text-xs` 但文字色**最低 `--ad-text-2`**(建立信任的文案不许压暗)。 + +**3.1.4 CLI 状态网格:** + +- 容器:通栏面板,标题「CLI 状态」+ 右侧「管理全部 N 个」青字 + chevron-right。 +- 网格:`repeat(auto-fill, minmax(280px, 1fr))`,间距 `--ad-space-4`;各断点列数见 §6。 +- 状态块结构(自上而下): + - 第一行:左 32px CLI 图标(单色剪影,无品牌彩色,无厂商图标时用双字母单色头像,`--ad-bg-2` 底 + 1px `--ad-border`)+ 名称 `--ad-text-m` / `--ad-text-1`;右侧**状态角标**(高 22px、`--ad-radius-s`、`--ad-text-xs`)。 + - 第二行:版本号 mono chip(未安装显示 `—` 不套 chip)。 + - 第三行(授权行):8px 授权状态点 + 授权状态文案 `--ad-text-xs` + `·` + 最近检测时间。 +- 状态角标规则【v1.2 修订】:已安装 = 青字 + 1px `rgba(0,229,255,0.4)` 描边 + `--ad-primary-dim` 底;可更新 = 品红字 + 1px `rgba(255,77,219,0.5)` 描边 + `--ad-accent-dim` 底 + 弱 `--ad-glow-accent`;**待授权 = 紫字 `--ad-attention` + 1px `rgba(167,139,250,0.5)` 描边 + `--ad-attention-dim` 底**(v1.1 的中性方案废止,紫色不发光);未安装 = `--ad-text-3` 字 + `--ad-border` 描边。 +- 授权状态点规则【v1.2 修订】:已授权 = 绿实心点(静态,不呼吸);**未授权 = 紫色空心圈(1.5px `--ad-attention` 描边)**+ 文案「未授权 · 点击去授权」,悬浮整行变青可点击(v1.1 的中性空心圈废止);授权可能过期 = 黄点 + 按 §4.5 呼吸;未检测/未知 = `--ad-text-3` 灰实心点 + 文案给出下一步(如「未检测 · 可一键安装」)。 +- 块体样式:`--ad-bg-1` 底、1px `--ad-border`、`--ad-radius-m`、内边距 `--ad-space-4`;悬浮边框变 `--ad-border-bright`,200ms;不发光、不放大。 +- 排序:需要你处理的排最前(可更新 > 待授权 > 未安装 > 已安装),同级按最近检测时间倒序。 + +### 3.2 CLI 目录(卡片列表) + +【v1.2 微调:状态角标颜色对齐六色语义表】 + +- 顶部工具条:搜索框(320px 限宽、青聚焦辉光)+ 平台筛选(Windows / Linux 胶囊按钮)+ 状态筛选(全部/已安装/未安装/可更新)。 +- 卡片网格:`repeat(auto-fill, minmax(280px, 1fr))`,间距 `--ad-space-4`。 +- 卡片结构:左上图标 40px + 中文名(`--ad-text-l`)+ 厂商小字;中间两行简介(超出省略);底部状态角标 + 平台图标 + 适配器版本 mono chip。 +- 状态角标样式:与 §3.1.4 状态角标规则完全一致(已安装=青、可更新=品红 + 弱辉光、**待授权=紫**、未安装=灰)。 +- 悬浮:卡片边框从 `--ad-border` 过渡到 `--ad-primary` 并带弱辉光,200ms;不做放大(网格会抖)。 + +### 3.3 CLI 详情页 + +【v1.2 微调:授权状态灯「未授权」改紫】 + +- 头卡:左 56px 图标 + 名称 + 厂商 + 版本/路径(等宽、`--ad-text-2`);右侧主操作按钮区。主操作按状态变化:未安装=「安装」(§2.6 主按钮)、已安装=「打开配置」(青描边)、可更新=「更新到 x.y.z」(§2.6 品红按钮,全应用唯一允许品红做按钮的地方)。卸载永远是文字按钮 + 悬停变红,藏进「更多」。 +- 授权状态灯:头卡内一颗 10px 圆点 + 中文状态(已授权/未授权/授权可能过期/未知):已授权=绿(静态)、**未授权=紫 `--ad-attention`(静态)**、可能过期=黄(呼吸)、未知=`--ad-text-3` 灰。 +- 下方标签页:概览 / 配置 / 中文文档 / 诊断。标签选中 = 底部 2px 青条 + 青色文字,切换 200ms。 +- 中文文档区按普通阅读排版:正文 `--ad-text-m`,最大行宽 720px,禁止在正文区加任何光效。 + +### 3.4 配置表单(含敏感字段) + +【v1.2 不变】 + +- 单列布局,最大宽 640px;标签在上(`--ad-text-s`,`--ad-text-2`)、控件在下,字段间距 `--ad-space-5`。必填项标签后加青色 `*`;每项下方一行中文用途说明(`--ad-text-xs` / `--ad-text-2`)。 +- 输入框:`--ad-bg-0` 底、1px `--ad-border`、`--ad-radius-m`、高 36px、内边距 `0 12px`。聚焦 = 边框变 `--ad-primary` + `--ad-glow-primary`,120ms。 +- **敏感字段(API Key 等)**:密码框 + 右侧「眼睛」显隐切换;已存入系统密钥库时输入框左侧显示 12px 锁形图标 + 说明「已加密保存于系统密钥库」(`--ad-text-2`)。显示掩码时一律用 `●` 不用 `*`。 +- 校验:错误时边框变 `--ad-danger` + 下方一行中文错误说明,不弹 toast;保存按钮常驻底部吸底条,保存成功给一次性青色对勾动画(见 §4.6)。 +- 「保存来源 / 最近修改 / 备份状态」放表单页脚,`--ad-text-xs` / `--ad-text-2`。 + +### 3.5 诊断结果页 + +【v1.2 修订:「提示」级由中性冷灰改紫 `--ad-attention`,形态仍为空心 ⓘ 图标(靠形态而非颜色区分色弱用户),色条同紫、不发光】 + +顶部一颗大状态灯 + 汇总句(如「发现 1 个错误、2 个提示」),下方按级别分组列出检查项。 + +- 每个检查项 = 左侧 3px 级别色条 + 级别图标(正常 ✓ 实心 / 提示 ⓘ 空心 / 警告 ⚠ / 错误 ✕)+ 标题 + 中文解释 + 「推荐修复」按钮(警告/错误才显示)。 +- 级别色严格用 §2.1 状态色:**正常=绿、提示=紫 `--ad-attention`、警告=黄、错误=红**,配合不同图标与实心/空心形态,色弱用户也能分辨。「提示」级色条与图标不发光。 +- 原始证据(命令输出、路径、错误码):等宽字体、`--ad-bg-0` 底、默认折叠,点击展开 320ms `--ad-ease-inout`。允许 1px 青色行号槽,但不发光。 +- 高危修复按钮(覆盖配置等):`--ad-danger` 描边,点击后二次确认弹窗,弹窗标题栏左侧红色辉光点。 + +### 3.6 通用组件速查 + +【v1.2 微调:新增侧边栏选中态条目,指向 §3.0】 + +| 组件 | 规格 | +|---|---| +| 主按钮 | 见 §2.6:降明度内渐变 + 内高光 + 常驻弱辉光;hover 双层扩散辉光 | +| 次按钮 | 透明底 + 1px `--ad-border-bright` + `--ad-text-1`;悬浮边框变青 | +| 危险按钮 | `--ad-danger` 描边 + 红字;确认后才实心 | +| 侧边栏选中态 | 见 §3.0:左缘生长青渐变 + 1px 青色内描边,无独立指示条 | +| 环境警告 chip | 见 §3.0:黄描边 + 黄点 + chevron,悬浮带 `--ad-glow-warning`,可点击 | +| Mono chip | 见 §2.2:文件名/版本号/命令的内联等宽 chip | +| 弹窗 | `--ad-bg-2` 底、`--ad-radius-l`、`--ad-shadow-pop`、遮罩 `rgba(4,7,13,0.7)` | +| Toast | 右下角滑入,底 `--ad-bg-2` + 左侧 3px 状态色条,4s 自动消失,错误 Toast 常驻需手关 | +| 空状态 | 线性插画(见 §7)+ 一句中文引导 + 主按钮;**总览页不允许出现空状态式大留白,用 §3.1 模块填满** | + +--- + +## 4. 动效规范 + +【v1.2 不变(紫色不呼吸的规则已在 §2.1 / §4.5 内体现)】 + +通则:**所有动效只动 `transform` 和 `opacity`**(辉光强弱可用 `box-shadow` 过渡,但仅限单个聚焦元素);任何循环动画在低配档必须可停。`prefers-reduced-motion: reduce` 时全局只保留透明度渐变,时长压到 100ms。 + +**§4.0 动效启用前提**:排版三件套(时间格式、mono chip、对比度)与密度、色彩未达标前,任何动效装饰不进入验收——基础不修,动效越炫越显糙。验收顺序固定为:① 密度 → ② 色彩 → ③ 排版三件套 → ④ 形态语言(渐变条/选中态)→ ⑤ 动效。 + +| # | 动效 | 触发条件 | 时长 | 缓动 | 可否打断 | +|---|---|---|---|---|---| +| 4.1 | 按钮/卡片悬浮辉光渐入 | hover | 200ms | `--ad-ease-out` | 可(鼠标移出即反向) | +| 4.2 | 页面切换 | 路由变化 | 320ms,新页 `translateY(8px)+淡入`,旧页只淡出 | `--ad-ease-out` | 可,立即跳到目标页 | +| 4.3 | 面板/折叠区展开(诊断证据、高级选项) | 点击 | 320ms | `--ad-ease-inout` | 可 | +| 4.4 | 仪表盘 KPI 数字滚动 | 数据首次加载 | 600ms,一次性,不循环 | `--ad-ease-out` | 不可(太短,直接播完) | +| 4.5 | **状态点呼吸** | **仅「需要处理」的项呼吸:警告(黄)、错误(红)、授权可能过期(黄)。绿/正常/提示(紫)/待授权(紫)一律静态** | 2400ms | `--ad-ease-inout`,**透明度 1 ↔ 0.4(下限 40%,再低像灭了,禁止)** | 状态恢复即停 | +| 4.6 | 保存成功对勾 | 配置保存成功 | 400ms 描边绘制 + 200ms 青辉光脉冲一次 | `--ad-ease-out` | 不可 | +| 4.7 | 安装/诊断进行中 | 任务运行 | 进度条用确定值;不确定时用 1.6s 青色流光扫过(linear infinite) | `--ad-ease-linear` | 任务结束即停 | +| 4.8 | 背景网格漂移 | 常驻氛围 | 60s 一周 | linear | 降档即停 | +| 4.9 | Toast 滑入滑出 | 出现/消失 | 200ms / 200ms | `--ad-ease-out` | 鼠标悬停暂停计时 | + +**§4.5 补充规则**: + +1. 全应用所有呼吸点**同频同相位**——用同一个全局动画时钟(同一个 CSS animation 名 + 同步起始),禁止各组件各自起动画导致此起彼伏。 +2. 呼吸只动透明度(1 ↔ 0.4),不动尺寸、不动辉光半径。 +3. 同屏呼吸点超过 3 个时,只保留级别最高的 3 个呼吸,其余静态(错误 > 警告)。 +4. 低档:呼吸全部停用,改静态点 + 图标区分(§5)。 + +明确禁止的动效:元素无限弹跳、文字逐字打印、hover 缩放超过 1.02、列表项 stagger 超过 5 个。 + +--- + +## 5. 性能降级策略(高特效项目必备) + +【v1.2 不变】 + +**三档:高 / 中 / 低。默认「自动」:按运行表现动态降档,用户可在设置页手动锁档。** + +| 特效 | 高档 | 中档 | 低档 | +|---|---|---|---| +| 背景氛围 | Canvas 粒子星网(≤60 粒子)+ 网格漂移 | 纯 CSS 渐变 + 可见网格(5% + 羽化) | 静态渐变图,网格可留静态,无动画 | +| 辉光 | 多层 `box-shadow` 全量 | 只保留单层、半径减半 | 全部移除,改 1px 亮色边框 | +| 切角 clip-path | 启用 | 启用 | 禁用(直角) | +| 页面/面板动效 | 全量 | 时长 ×0.7 | 只留 100ms 淡入淡出 | +| 循环动画(呼吸、流光) | 启用(按 §4.5 仅异常呼吸) | 只保留任务进行中的流光 | 全部停用,改静态图标 | +| 数字滚动 | 启用 | 启用 | 直接显示终值 | + +**自动降档规则(施工员照此实现):** + +1. 启动时 `prefers-reduced-motion` 或 `navigator.hardwareConcurrency ≤ 4` → 直接进低档。 +2. 运行中用 `requestAnimationFrame` 采样:连续 3 秒平均帧率 < 45fps → 降一档并记住;低于 30fps → 直接低档。 +3. 降档只降不升(防抖动),重启后重新评估。 +4. 设置页提供「界面特效:自动 / 高 / 中 / 低」四选一,手动选择覆盖自动。 + +--- + +## 6. 窗口尺寸响应 + +【v1.2 不变】 + +桌面窗口,最小 **960 × 600**,不设上限。三个断点: + +| 断点 | 宽度 | 布局变化 | +|---|---|---| +| 紧凑 | 960–1199px | 左导航收起为 64px 图标栏;KPI 卡 2×2;诊断列表与快速操作上下堆叠(诊断在上);CLI 状态网格 2 列;详情页头卡操作按钮折成两行;配置表单仍单列 | +| 标准 | 1200–1599px | 完整 232px 导航;KPI 一排 4 张;诊断 + 快速操作左右 2:1;CLI 状态网格 3 列;目录卡片 3 列左右 | +| 宽阔 | ≥1600px | 内容区锁 1440px 居中,多余空间留黑,不拉伸卡片;CLI 状态网格 4 列;诊断页可「结果列表 + 证据」左右双栏 | + +窗口高度 < 700px 时:顶栏从 56px 压到 44px,KPI 卡大数字从 28px 降到 22px,CLI 状态网格允许纵向滚动但模块不许删除,不允许出现内容被裁切。 + +--- + +## 7. 图标与插画方向 + +【v1.2 微调:「提示」图标颜色改紫】 + +- **图标**:线性风格,统一 24px viewBox、**1.5px 描边**、圆角端点;颜色默认 `--ad-text-2`,选中/激活态变 `--ad-primary`。状态图标(诊断四级、授权灯)用实心填充 + 状态色(「提示」用空心 ⓘ + `--ad-attention` 紫)。CLI 厂商图标一律单色剪影,不上品牌彩色,hover 时叠加青色光晕。 +- **语义图标(定死)**:诊断/扫描类动作用 pulse/scan 图标;「添加」全应用统一同一枚加号图标;「查看全部/展开」统一 chevron 系列,不许混用 `›` 字符与箭头图形。 +- **插画**:只出现在空状态和引导页。等距线框风格(1px 线、`--ad-border-bright` 色)+ 一到两处霓虹青/品红渐变点缀,内容画「终端窗口、线缆、集装箱」这类 Dock 意象,不画人物、不画卡通。 +- 图标库选型由施工员定(任何成熟线性库均可),但描边粗细必须统一为 1.5px 观感,混用前调 stroke。 + +--- + +## 8. 需要总工确认的技术可行性点 + +【v1.2 不变,沿用 v1.0/v1.1 四条(结论已在 HEL-102 由总工给出,若与本规范条文有出入以总工结论为准)】 + +1. **背景氛围层**:计划用 Canvas 2D(≤60 粒子 + 网格)而非 WebGL;若总工想要 WebGL 着色器光效,需评估 Tauri 在 WebView2(Windows)与 WebKitGTK(Ubuntu)下的功耗与兼容性,确认后我再补高档的视觉参数。 +2. **`backdrop-filter` 毛玻璃**:弹窗遮罩想做轻微毛玻璃,WebKitGTK 老版本支持不稳定,需确认目标 WebKitGTK 版本;不支持则退化为纯半透明遮罩(本规范默认值即按退化方案给的)。 +3. **辉光 `box-shadow` 多层过渡**:逐帧过渡多层阴影在低端机可能引起重绘开销,§5 已按「低档移除」兜底;若总工有更省的实现(如预渲染光晕贴图),以技术方案为准,视觉等效即可。 +4. **CJK 字体渲染**:Ubuntu 上 `Noto Sans CJK SC` 依赖系统安装,需确认安装包是否内置兜底字体或声明依赖;不内置则字重 600 可能退化为合成加粗,验收时以实际渲染为准。 + +--- + +## 9. 验收对照(给总工) + +【v1.2 修订:形态语言行更新为「无独立指示条」的选中态标准;色彩行补紫色语义红线】 + +验收顺序固定(老板优先级):**① 密度 → ② 色彩 → ③ 排版三件套 → ④ 形态语言 → ⑤ 动效**。前一项不达标,后一项不看。 + +- **密度**:总览首屏任何纵向区间无效空白 ≤ 15%;下半屏必须有 CLI 状态网格(或同级信息模块)= 合格底线。 +- **色彩**:所有颜色只能来自 §2 Token;界面出现蓝色 = 不合格;状态色未贯穿到数字/关键文字 = 不合格;红色挂在已自愈条目上 = 不合格;【v1.2】「提示 / 待授权 / 未授权」未用 `--ad-attention` 紫、或紫色元素发光/呼吸 = 不合格。 +- **排版三件套**:时间格式违反 §3.1.2 规则、版本号/文件名未套 mono chip、承载信息文字对比度 < 4.5:1,任一 = 不合格。 +- **形态语言**:KPI 色条未贯通整宽、侧边栏选中态出现独立指示条(或任何与圆角背景块两张皮的第二形态)、选中态不是 §3.0 的「左缘生长渐变 + 内描边」、导航图标粗细不一,任一 = 不合格。 +- **动效**:呼吸点不同频同相位、透明度下限低于 40%、正常态绿点或紫色提示/待授权点呼吸,任一 = 不合格;主按钮 hover 未用 §2.6 双层扩散辉光 = 不合格。 +- 其余沿用:正文与表单区零光效;低档模式下无循环动画、无辉光、无粒子且信息完整性不变。 + +--- + +**v1.2 为施工开工的唯一视觉依据。** v3 样图(`overview3.png`)与本规范条文冲突时,以本规范条文为准;规范未覆盖处,参照 v3 样图并按 §1 原则推演。