# visionA Agent — UI 設計規格 | 項目 | 內容 | |------|------| | 專案代號 | visionA Agent(`visiona-agent`) | | 文件版本 | v0.1 | | 最後更新 | 2026-04-22 | | 狀態 | Design Agent 產出(M 級任務,不走三方聯合討論) | | 定位 | visionA 雲端版的 local agent / tunnel bridge | | 技術堆疊 | Wails v2 + React + TypeScript + Tailwind 4 + shadcn/ui(與 visionA-frontend 完全相同)| | Bundle ID | `com.innovedus.visiona-agent`(獨立於 local-tool 的 `com.innovedus.visiona-local`)| > **本規格從 visionA-frontend 的 Design System 延伸**。Design Tokens、元件、字型、Dark Mode 全部沿用,確保同一使用者在雲端 Web 與桌面 Agent 之間切換「能一眼認出是同家人」。 --- ## 1. 設計概述 ### 1.1 產品定位 visionA Agent 是**純橋樑**:它只做一件事 — 讓使用者桌機上的 Kneron 裝置「出現在雲端」。所有裝置管理、模型管理、推論操作都在 visionA 雲端 Web UI。Agent 本身**沒有**裝置面板、沒有攝影機預覽、沒有推論視窗。 它是一個「**開了就忘掉它**」的工具:使用者配對完之後,Agent 只要維持連線、不出問題就好。 ### 1.2 與 visionA-frontend 的對應關係 | 使用者流程 | visionA-frontend(Web)| visionA Agent(桌面) | |-----------|---------------------|--------------------| | 取得 Pairing Token | `/devices/pair` Step 1 | — | | 下載並啟動 Agent | `/devices/pair` Step 2(指引)| **Agent 安裝後首次啟動** | | 輸入 Token 配對 | — | **配對頁** | | 確認連線建立 | `/devices/pair` Step 3 | **狀態頁**(雙端同時顯示)| | 後續使用裝置 | `/devices`、`/workspace/*` | 持續維持連線,無需互動 | **設計職責切分**:Web 負責「拿到 token」+「看到裝置」;Agent 負責「用 token 連上」+「顯示連線狀態」。 ### 1.3 設計原則 1. **極簡優先** — 一個 utility 不是一個 product。不做 onboarding tour、不做裝飾性插圖、不做動畫秀。 2. **誠實呈現狀態** — online / offline / reconnecting / error 必須清楚區分,不只靠顏色(搭配 icon + 文字)。 3. **與雲端視覺一致** — Design Tokens 100% 沿用,使用者看到會立刻聯想「這是 visionA 那家」。 4. **跨平台** — 不做任何倚賴特定 OS 的互動(不做 traffic light 自訂、不做 system tray、不做 Win11 Mica)。 5. **鍵盤友善** — 所有操作 Tab 可達,符合 WCAG 2.1 AA。 6. **Dark Mode 跟隨 OS** — 不提供手動切換,不需要多餘開關。 ### 1.4 範圍內 vs 範圍外 | 範圍內 | 範圍外 | |--------|--------| | 連線狀態頁、配對頁、設定頁 | 裝置管理 / 模型管理 / 推論操作 UI | | 全域 Header + Tab 導航 | System Tray / Menu Bar 圖示 | | 開機自啟、Log 匯出、Relay URL 設定 | Onboarding Tour / Tutorial | | 繁中 + English(跟 OS 語言,無 UI switcher) | i18n 切換 UI、多語言 admin | | Dark Mode 跟隨系統 | 手動 Dark Mode toggle | --- ## 2. Design Tokens(沿用 visionA-frontend) 完整沿用 `.autoflow/03-design/design-tokens.md`。實作時 **直接複製 visionA-frontend 的 `globals.css`**,不動一行。 ### 2.1 Agent 會用到的 token 清單 | 用途 | Token / class | |------|---------------| | 視窗背景 | `--background` → `bg-background` | | 主要文字 | `--foreground` → `text-foreground` | | 次要文字 | `--muted-foreground` → `text-muted-foreground` | | 卡片 / 區塊 | `--card` + `border` + `shadow-sm` + `rounded-xl` | | 主按鈕 | `--primary` + `--primary-foreground` | | 次要按鈕 | `--secondary` / outline variant | | 危險按鈕(重置 / 斷線)| `--destructive` | | Input 邊框 | `--input`,focus `--ring/50` | | Tab bar 背景 | `--sidebar`(沿用) | | Focus ring | `--ring`(`ring-[3px]`)| ### 2.2 連線狀態色(沿用雲端版既有約定) 與 `flow-offline-handling.md` 第 2 節的狀態模型對齊: | 狀態 | 顏色(light / dark)| Icon(Lucide)| |------|---------------------|---------------| | online | `bg-green-500` | `CheckCircle2` | | offline | `bg-gray-400` + `dark:bg-gray-600` | `PowerOff` | | reconnecting | `bg-yellow-400` + `animate-pulse` | `RefreshCw`(旋轉) | | notPaired | `bg-gray-400` | `Unlink` | | error | `bg-red-500` | `AlertTriangle` | **無障礙**:每個狀態**必須同時有**「圓點顏色 + Icon + 文字標籤」,不只靠顏色。 ### 2.3 字型 - UI 文字:`font-sans`(Geist Sans,沿用) - Token 顯示、Log、Relay URL:`font-mono`(Geist Mono) --- ## 3. 全域元件 — Header / Tab 導航 ### 3.1 版型 ``` ┌──────────────────────────────────────────────────────────────────┐ │ [Logo] visionA Agent 狀態 · 配對 · 設定 🟢 在線 │ ← h-14 ├──────────────────────────────────────────────────────────────────┤ │ │ │ [ 當前分頁內容 ] │ │ │ └──────────────────────────────────────────────────────────────────┘ ``` ### 3.2 規格 - **高度**:`h-14`(56px),與 visionA-frontend Header 一致 - **背景**:`bg-sidebar` + `border-b border-sidebar-border` - **左側**:Logo + 產品名「visionA Agent」(`text-sm font-semibold`) - **中央(或左側緊接)**:三個 Tab - 「狀態」(Status)— 預設 - 「配對」(Pair) - 「設定」(Settings) - 使用 shadcn `Tabs` 風格;active tab `bg-primary text-primary-foreground rounded-md`,其餘 `hover:bg-accent` - **右上角**:`ConnectionStatusBadge`(小型 `RemoteDeviceBadge` 的簡化版) - 圓點 + 文字(例:`🟢 在線` / `⚪ 離線` / `🟡 重連中` / `🔗 未配對`) - 點擊可切回「狀態」tab ### 3.3 互動 - Tab 切換:`Ctrl/Cmd+1/2/3` 鍵盤快捷鍵 - Badge 永遠即時反映連線狀態(從 backend event 推送) - **沒有**雲端版的 `PrototypeBanner`、**沒有** Sidebar(視窗太小、功能太少) ### 3.4 視窗規格(Wails 設定) | 項目 | 值 | 說明 | |------|---|------| | 初始大小 | **720 × 560** | 比 800×600 稍收斂,足夠不壅擠 | | 最小大小 | 640 × 480 | 強制最小,避免壞掉 | | 最大大小 | 不限 | 使用者想放大就放大(但內容有 `max-w-2xl` 收斂) | | Title | `visionA Agent` | OS title bar | | Resizable | Yes | 使用者可調整 | | 關閉行為 | **退出 process** | 不隱藏到 tray(已決策) | | Icon | visionA 品牌 logo(3 平台各別規格) | — | --- ## 4. 頁面 1 — 連線狀態頁(首頁 / 預設 Tab) ### 4.1 版型(已配對 + 在線) ``` ┌──────────────────────────────────────────────────────────────────┐ │ │ │ ╭────────────────────╮ │ │ │ ✓ 已連線 │ │ │ │ 🟢 │ │ │ ╰────────────────────╯ │ │ │ │ ┌────────────────────────────────────────────────────────────┐ │ │ │ 帳號 jim@innovedus.com │ │ │ │ Relay wss://relay.visionA.cloud │ │ │ │ 連線開始 2026-04-22 14:30(已連線 2 小時 15 分) │ │ │ │ Session vAs_a1b2c3d4 ··· e7f8 │ │ │ │ │ │ │ │ [ 斷開連線 ] [ 重新配對 ] │ │ │ └────────────────────────────────────────────────────────────┘ │ │ │ │ 最近連線紀錄 [ 查看完整 Log ] │ │ ┌────────────────────────────────────────────────────────────┐ │ │ │ 14:30 ✓ 已連線 │ │ │ │ 14:29 ⟳ 連線中... │ │ │ │ 14:28 ▲ 程式啟動 │ │ │ │ ...(最多 10 筆) │ │ │ └────────────────────────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────────────────────────────┘ ``` ### 4.2 主要元件 #### (A) StatusHero — 大狀態指示器 - **大小**:直徑 80px 的圓,置中 - **內容**: - 頂層:狀態 Icon(Lucide,`h-8 w-8`) - 底層:圓點 + 狀態文字(`text-xl font-semibold`) - **狀態變體**(對應 2.2 狀態色): - online:綠圓 + `CheckCircle2` + 「已連線」 - offline:灰圓 + `PowerOff` + 「離線」 - reconnecting:黃圓 pulse + `RefreshCw` 旋轉 + 「重新連線中...」+ 次行 `text-xs text-muted-foreground`「第 {n}/5 次嘗試」 - notPaired:灰圓 + `Unlink` + 「尚未配對」+ 次行按鈕「立即配對 →」切到配對頁 - error:紅圓 + `AlertTriangle` + 「連線錯誤」+ 次行 `text-xs text-red-600`「{errorMessage}」 #### (B) InfoCard — 連線資訊卡 - shadcn `Card`,`p-6 space-y-3` - **欄位**(每行 `grid grid-cols-[120px_1fr]`,左欄 `text-muted-foreground text-sm`,右欄 `text-sm font-mono`): | 欄位 | 內容 | 未配對 / 離線時 | |------|------|---------------| | 帳號 | `jim@innovedus.com` | `—`(未配對)/ 快取顯示(離線) | | Relay | `wss://relay.visionA.cloud` | 顯示當前設定值 | | 連線開始 | `2026-04-22 14:30(已連線 2 小時 15 分)` | 未配對 `—`;離線顯示上次連線時間 + 「已離線 {duration}」| | Session | `vAs_a1b2c3d4 ··· e7f8`(遮蔽中段)| 未配對 `—`;離線保留顯示(以 `text-muted-foreground` 淡化) | - **Session Token 遮蔽規則**:顯示 `前綴(vAs_) + 前 8 hex + " ··· " + 後 4 hex`(共約 20 字元可見)。完整 token 永遠不顯示、不可複製、不寫進 log。 #### (C) 主要按鈕 於 InfoCard 下方,排成一列: | 狀態 | 主按鈕 | 次按鈕 | |------|--------|--------| | online | `[ 斷開連線 ]`(`variant=outline`)| `[ 重新配對 ]`(ghost 配 `AlertDialog`) | | offline | `[ 立即重試 ]`(`variant=default`)| `[ 重新配對 ]` | | reconnecting | `[ 取消並手動重連 ]`(outline,重連中停用自動策略一次)| `[ 重新配對 ]` | | notPaired | `[ 前往配對 → ]`(default,切 tab)| — | | error | `[ 重試 ]`(default)+ `[ 查看 log ]`(ghost)| `[ 重新配對 ]` | - 「斷開連線」→ `AlertDialog`「確定要斷開嗎?斷開後遠端將無法使用此裝置。Session Token 不會被撤銷,下次可直接重連。」 - 「重新配對」→ `AlertDialog`「確定要重新配對?目前的 Session 會立即失效,需重新取得 Pairing Token。」確認後切配對頁並清除本地 Session Token。 #### (D) RecentLog — 最近連線紀錄 - shadcn `Card`,標題 + 右上角「查看完整 Log」連結(切到設定頁 → Log 區塊) - 每筆紀錄:`時間(HH:mm) · Icon · 事件文字` - `✓ 已連線` / `⟳ 連線中...(嘗試 {n}/5)` / `✗ 連線失敗:{reason}` / `▲ 程式啟動` / `◼ 程式關閉` / `⚙ 設定已更新` - 最多顯示 10 筆,`text-xs font-mono`,超過出現「查看完整 Log」連結 - **只顯示使用者應該看得懂的事件**;debug 級別的細節進 log 檔不上 UI ### 4.3 空狀態(尚未配對) 未配對時,StatusHero 顯示 notPaired 狀態,InfoCard 欄位皆為 `—`,RecentLog 顯示: ``` ┌─────────────────────────────────┐ │ 🔗 │ │ │ │ 尚未配對裝置 │ │ │ │ 去雲端 Web 產生 Pairing Token, │ │ 在「配對」分頁貼上即可開始 │ │ │ │ [ 前往配對 → ] │ └─────────────────────────────────┘ ``` ### 4.4 錯誤狀態 - 連線錯誤:StatusHero 顯示 error,InfoCard 最下方紅色 banner(`bg-red-50 dark:bg-red-950/30 border-red-300`)顯示 `errorMessage`(例:「Pairing Token 已撤銷,請重新配對」「Relay URL 不可達」) - 錯誤分類(對應 `flow-offline-handling.md` 第 1 節的 A/B/C 失效點): - **本機斷網**(A):「你的網路似乎離線了,請檢查 Wi-Fi / 有線連線」 - **雲端不可達**(B):「無法連上 visionA 雲端服務,正在重試...」 - **認證失敗**:「Session Token 已失效,請重新配對」 - **未知錯誤**:「連線錯誤,請[查看 log]{連結}」 ### 4.5 互動行為 | 操作 | 行為 | |------|------| | 進入頁面 | 自動從 backend 取當前狀態(透過 Wails runtime event) | | 狀態變化 | backend 推送事件 → 前端即時更新 StatusHero + Badge + InfoCard | | 點「斷開連線」| AlertDialog 確認 → call backend `Disconnect()` → 狀態變 offline | | 點「重新連線」| call backend `Reconnect()` → 狀態變 reconnecting | | 點「查看完整 Log」| 切到設定頁,自動 scroll 到 Log 區塊 | | 視窗 resize | 內容以 `max-w-2xl mx-auto` 置中,大螢幕不會過寬 | ### 4.6 驗收條件 - [ ] 五種狀態(online / offline / reconnecting / notPaired / error)視覺各異且符合 2.2 色表 - [ ] Session Token 永遠只顯示遮蔽版 - [ ] 離線時「連線開始」欄位顯示「已離線 {duration}」並使用 `text-muted-foreground` - [ ] 「斷開連線」「重新配對」都有 `AlertDialog` 確認 - [ ] 最近 Log 最多 10 筆,時間格式 `HH:mm` - [ ] Dark Mode 下所有顏色對比達 4.5:1 - [ ] 完整鍵盤導航(Tab / Enter / Space / Esc) --- ## 5. 頁面 2 — 配對頁 ### 5.1 版型 ``` ┌──────────────────────────────────────────────────────────────────┐ │ │ │ 配對到 visionA 雲端 │ │ 貼上 Pairing Token,讓你的裝置出現在雲端 Web │ │ │ │ ┌────────────────────────────────────────────────────────────┐ │ │ │ Pairing Token │ │ │ │ ┌────────────────────────────────────────────────────────┐│ │ │ │ │ vAc_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8 ││ │ │ │ └────────────────────────────────────────────────────────┘│ │ │ │ ✓ 格式正確(36 字元) │ │ │ │ │ │ │ │ 還沒有 token?[ 到雲端網頁產生 ↗ ] │ │ │ │ │ │ │ │ [ 取消 ] [ 配對 ] │ │ │ └────────────────────────────────────────────────────────────┘ │ │ │ │ 💡 Token 15 分鐘內有效,一次性使用。Agent 會自動換取長期 Session,│ │ │ 你不需要記住或重複貼上。 │ │ │ │ └──────────────────────────────────────────────────────────────────┘ ``` ### 5.2 元件規格 #### (A) 標題區 - `h1`:「配對到 visionA 雲端」(`text-2xl font-semibold`) - `description`:「貼上 Pairing Token,讓你的裝置出現在雲端 Web」(`text-sm text-muted-foreground`) #### (B) Token 輸入卡 - shadcn `Card`,`p-6 space-y-4`,`max-w-xl mx-auto` - `Label`:「Pairing Token」 - shadcn `Input`: - `font-mono text-sm`(等寬) - `placeholder="貼上 vAc_... 格式的 token"` - 自動 `spellcheck={false}`、`autocapitalize="none"`、`autocomplete="off"` - **貼上時自動清除所有空格與換行**(雲端網頁顯示可能有空格分隔,如 `vAc_a1b2c3d4 e5f6a7b8 ...`) - **焦點**進入自動全選(方便覆蓋貼上) - **即時格式驗證**(在 input 下方顯示 hint line): - 空:`text-muted-foreground`「請貼上 token」 - 格式不對:`text-red-600`「格式不正確 — token 應為 `vAc_` 開頭 + 32 字元 hex」+ `AlertCircle` icon - 格式正確:`text-green-600`「✓ 格式正確(36 字元)」+ `CheckCircle2` icon - 邊框狀態:預設 `border-input` / 錯誤 `border-destructive` + `ring-destructive/20` / 正確 `border-green-500` #### (C) 輔助連結 - 「還沒有 token?[ 到雲端網頁產生 ↗ ]」 - 點擊 → `wails.BrowserOpenURL("https://visionA.cloud/devices/pair")` - **Phase 0 雛形**:URL 寫死 placeholder,正式上線再改為環境變數驅動 #### (D) 按鈕列(右對齊) - 「取消」(`variant=ghost`)→ 切回狀態頁 - 「配對」(`variant=default`):格式不正確時 disabled - 配對中:按鈕變「`⟳ 正在配對...`」(`aria-busy=true`),其餘 input / cancel disabled #### (E) 底部提示 `Alert` 元件(`variant=default`,`bg-blue-50 dark:bg-blue-950/30 border-blue-300`): > 💡 Token 15 分鐘內有效,一次性使用。Agent 會自動換取長期 Session,你不需要記住或重複貼上。 ### 5.3 配對流程狀態 | 階段 | UI | |------|---| | 閒置 | 如 5.1 所示,按鈕依格式驗證 enable / disable | | 驗證中(貼上後)| 即時驗證格式,100ms debounce,無 loading(純 client-side 正規表達式) | | 配對中 | 按鈕變 spinner「正在連線到雲端...」,其餘 disabled。backend 呼叫 WS `/tunnel/connect?token=vAc_...` | | 成功 | Toast `✓ 配對成功` → 0.5s 後自動切回「狀態」tab → StatusHero 顯示 online | | 失敗 | 停留在本頁,Input 下方紅色 `Alert` 顯示錯誤訊息(見 5.4),按鈕恢復為「重試」+「取消」| ### 5.4 錯誤訊息對照 | 後端錯誤代碼 | 顯示訊息 | 建議動作 | |-------------|---------|---------| | `token_expired` | 「此 Token 已過期(15 分鐘有效)」 | 「回雲端網頁重新產生 →」 | | `token_used` | 「此 Token 已被其他裝置使用」 | 「回雲端網頁重新產生 →」 | | `token_invalid` | 「Token 無效或格式錯誤」 | 「請檢查是否複製完整」 | | `token_revoked` | 「此 Token 已被撤銷」 | 「回雲端網頁重新產生 →」 | | `network_error` | 「無法連上雲端服務,請檢查網路」 | 「重試」 | | `relay_unreachable` | 「Relay `{url}` 無法連線,請確認設定」 | 「前往設定 →」| | `unknown` | 「配對失敗,請查看 log」 | 「查看 log」 | ### 5.5 互動行為 | 操作 | 行為 | |------|------| | Focus Input | 全選現有內容 | | 貼上 token | trim + 去空白 + 去換行;立即格式驗證 | | 輸入中 | 100ms debounce 後顯示驗證結果 | | Enter 鍵 | 若格式正確則觸發「配對」;否則無動作 | | Esc 鍵 | 觸發「取消」(切回狀態頁,清空 input) | | 配對成功 | Toast + auto navigate,不留在本頁 | | 配對失敗 | Input 保留原值(方便使用者修改),顯示錯誤,按鈕變「重試」| ### 5.6 i18n key ``` pair.title → 配對到 visionA 雲端 pair.description → 貼上 Pairing Token,讓你的裝置出現在雲端 Web pair.tokenLabel → Pairing Token pair.tokenPlaceholder → 貼上 vAc_... 格式的 token pair.hint.empty → 請貼上 token pair.hint.invalid → 格式不正確 — token 應為 vAc_ 開頭 + 32 字元 hex pair.hint.valid → 格式正確(36 字元) pair.noToken → 還沒有 token? pair.openCloud → 到雲端網頁產生 pair.cancel → 取消 pair.submit → 配對 pair.submitting → 正在配對... pair.bottomHint → Token 15 分鐘內有效,一次性使用。Agent 會自動換取長期 Session,你不需要記住或重複貼上。 pair.toast.success → 配對成功 pair.error.expired → 此 Token 已過期(15 分鐘有效) pair.error.used → 此 Token 已被其他裝置使用 pair.error.invalid → Token 無效或格式錯誤 pair.error.revoked → 此 Token 已被撤銷 pair.error.network → 無法連上雲端服務,請檢查網路 pair.error.relayUnreachable → Relay {url} 無法連線,請確認設定 pair.error.unknown → 配對失敗,請查看 log pair.error.regenerate → 回雲端網頁重新產生 pair.error.goSettings → 前往設定 pair.error.viewLog → 查看 log pair.error.retry → 重試 ``` ### 5.7 驗收條件 - [ ] 貼上含空格 / 換行的 token 自動清乾淨 - [ ] 格式驗證正規表達式:`/^vAc_[a-f0-9]{32}$/i`(大小寫不敏感) - [ ] 格式不正確時按鈕 disabled - [ ] 配對中所有 input + 按鈕 disabled,僅保留「取消」 - [ ] 成功後切回狀態頁,並更新全域狀態 - [ ] 所有錯誤訊息都能明確告訴使用者「下一步該做什麼」 - [ ] 支援完整鍵盤操作(Enter 送出、Esc 取消) --- ## 6. 頁面 3 — 設定頁 ### 6.1 版型 ``` ┌──────────────────────────────────────────────────────────────────┐ │ 設定 │ │ │ │ ── 連線 ───────────────────────────────────────────────────── │ │ Relay URL [ wss://relay.visionA.cloud ] [ 測試連線 ]│ │ 當前設定將於下次連線時生效 │ │ │ │ ── 行為 ───────────────────────────────────────────────────── │ │ ☐ 開機自動啟動 visionA Agent │ │ │ │ 重連策略 ◉ 自動重試(指數退避,最多 5 次) │ │ ○ 手動重連 │ │ │ │ ── Log ───────────────────────────────────────────────────── │ │ Log 等級 [ Info ▼ ](Debug / Info / Warn / Error) │ │ Log 位置 ~/Library/Application Support/visionA Agent/logs/ │ │ [ 開啟資料夾 ] [ 匯出 Log... ] │ │ │ │ ── 關於 ───────────────────────────────────────────────────── │ │ 版本 visionA Agent 0.1.0 │ │ [ 檢查更新 ] [ 開啟文件 ↗ ] [ GitHub ↗ ] │ │ │ │ 危險區域 [ 重置所有設定 ] │ │ │ └──────────────────────────────────────────────────────────────────┘ ``` ### 6.2 區塊規格 容器:`max-w-2xl mx-auto p-6 space-y-8`。每個區塊:`space-y-3`,區塊間用 `Separator`。 #### 6.2.1 連線 - **Relay URL**: - `Label` + `Input`(`font-mono text-sm`)+ `Button "測試連線"`(`variant=outline size=sm`) - 預設值:`wss://relay.visionA.cloud` - 驗證:必須以 `wss://` 或 `ws://` 開頭 - 變更不會立即套用;下方 `text-xs text-muted-foreground` 顯示「當前設定將於下次連線時生效」 - 若與當前連線值不同:顯示橙色 badge `未套用` - **測試連線**按鈕: - 點擊後嘗試 WebSocket handshake(不帶 token,只測 reachability) - Loading:spinner - 成功:`Toast ✓ Relay 可達({latency}ms)` - 失敗:`Toast ✗ 無法連上 {url}:{reason}` #### 6.2.2 行為 - **開機自動啟動**: - shadcn `Checkbox` + `Label` - 預設**關閉**(已決策) - 勾選後立即套用(backend 寫入對應 OS 啟動項;macOS Login Items / Windows Registry Run / Linux `.desktop` autostart) - 變更時 toast:「✓ 已啟用開機自啟動」/ 「已關閉開機自啟動」 - **重連策略**: - shadcn `RadioGroup` - `自動重試` — 預設;指數退避(1s → 2s → 4s → 8s → 16s),最多 5 次失敗後停止並轉為手動 - `手動重連` — 連線中斷後不自動重試,使用者需在狀態頁點「立即重試」 #### 6.2.3 Log - **Log 等級**:shadcn `Select`,選項 `Debug / Info / Warn / Error`,預設 `Info` - 變更立即生效 - **Log 位置**:唯讀顯示 OS 對應路徑(`font-mono text-xs`) - macOS:`~/Library/Application Support/visionA Agent/logs/` - Windows:`%APPDATA%\visionA Agent\logs\` - Linux:`~/.config/visionA-agent/logs/` - 「開啟資料夾」按鈕:call backend 開檔案總管到該路徑 - **匯出 Log**按鈕: - 點擊 → OS save dialog(Wails runtime `SaveFileDialog`) - 預設檔名:`visionA-agent-log-YYYYMMDD-HHmmss.zip` - 內容:壓縮最近 7 天的 log 檔 - 匯出中:按鈕 loading;完成 toast「✓ 已匯出到 {path}」 #### 6.2.4 關於 - **版本**:`visionA Agent {version}`(從 `runtime.Environment` 取) - **檢查更新**按鈕: - Phase 0 stub:call backend `CheckForUpdates()`,雛形直接回 `up-to-date` - Toast:`✓ 已是最新版本` / `有新版本可用:v0.2.0 [ 開啟下載頁 ]` - **開啟文件**:`BrowserOpenURL("https://docs.visionA.cloud/agent")` - **GitHub**:`BrowserOpenURL("https://github.com/innovedus/visionA-agent")` #### 6.2.5 危險區域 - 小標:`危險區域`(`text-sm font-medium text-destructive`) - **重置所有設定**按鈕: - `variant=destructive size=sm` - 點擊 → shadcn `AlertDialog` - 標題:「確定要重置所有設定嗎?」 - 內文:「這將清除:Relay URL、開機自啟、Log 等級、**以及已配對的 Session Token**。你將需要重新配對才能使用。此操作無法復原。」 - 按鈕:`取消` / `確定重置`(destructive) - 確認後:backend 清除 config + session token → toast「已重置所有設定」→ 切到配對頁顯示 notPaired ### 6.3 i18n key ``` settings.title → 設定 settings.connection → 連線 settings.relayUrl → Relay URL settings.relayUrl.hint → 當前設定將於下次連線時生效 settings.relayUrl.unapplied → 未套用 settings.testConnection → 測試連線 settings.testConnection.success → Relay 可達({latency}ms) settings.testConnection.failed → 無法連上 {url}:{reason} settings.behavior → 行為 settings.autoStart → 開機自動啟動 visionA Agent settings.autoStart.enabled → 已啟用開機自啟動 settings.autoStart.disabled → 已關閉開機自啟動 settings.reconnectStrategy → 重連策略 settings.reconnectStrategy.auto → 自動重試(指數退避,最多 5 次) settings.reconnectStrategy.manual → 手動重連 settings.log → Log settings.logLevel → Log 等級 settings.logLocation → Log 位置 settings.openFolder → 開啟資料夾 settings.exportLog → 匯出 Log... settings.exportLog.success → 已匯出到 {path} settings.about → 關於 settings.version → 版本 settings.checkUpdate → 檢查更新 settings.checkUpdate.upToDate → 已是最新版本 settings.checkUpdate.available → 有新版本可用:{version} settings.openDocs → 開啟文件 settings.github → GitHub settings.dangerZone → 危險區域 settings.reset → 重置所有設定 settings.reset.confirm.title → 確定要重置所有設定嗎? settings.reset.confirm.description → 這將清除:Relay URL、開機自啟、Log 等級、以及已配對的 Session Token。你將需要重新配對才能使用。此操作無法復原。 settings.reset.confirm.cancel → 取消 settings.reset.confirm.ok → 確定重置 settings.reset.done → 已重置所有設定 ``` ### 6.4 驗收條件 - [ ] Relay URL 驗證 `ws(s)://` 前綴 - [ ] 變更 Relay URL 不立即套用,顯示「未套用」badge - [ ] 「測試連線」真正發 WS handshake(不是假 loading) - [ ] 開機自啟 checkbox 在三平台都能正確寫入 OS 啟動項 - [ ] Log 位置顯示 OS 對應路徑,可開啟資料夾 - [ ] 匯出 Log 檔名格式正確、可正常解壓 - [ ] 重置設定會清 Session Token 並切回配對頁 --- ## 7. 跨平台適配 ### 7.1 macOS | 項目 | 處理 | |------|------| | 視窗 chrome | **Wails 預設**(標準紅黃綠按鈕),不自訂 traffic light 位置 | | 選單列 | Wails 預設 Menu(App / Edit / Window / Help),不加自訂項 | | 檔案對話框 | `runtime.SaveFileDialog` / `OpenDirectoryDialog` | | 啟動項 | `~/Library/LaunchAgents/com.innovedus.visiona-agent.plist` | | Log 路徑 | `~/Library/Application Support/visionA Agent/logs/` | | 打包 | DMG(參考 local-tool 已有的 `create-dmg` 流程)| ### 7.2 Windows | 項目 | 處理 | |------|------| | 視窗 chrome | 標準 title bar(Windows 11 Mica 可選但**不強制**) | | 檔案對話框 | `runtime.SaveFileDialog`(Wails 內建用 Win32 API) | | 啟動項 | Registry `HKCU\Software\Microsoft\Windows\CurrentVersion\Run` | | Log 路徑 | `%APPDATA%\visionA Agent\logs\` | | 打包 | NSIS installer(`.exe`)| ### 7.3 Linux | 項目 | 處理 | |------|------| | 視窗 chrome | 依 DE(GNOME / KDE / XFCE)走預設 | | 檔案對話框 | GTK / Qt(Wails 依系統偵測) | | 啟動項 | `~/.config/autostart/visiona-agent.desktop` | | Log 路徑 | `~/.config/visionA-agent/logs/`(XDG 規範)| | 打包 | AppImage | ### 7.4 共通原則 - **不用** hover-only 操作(觸控筆電也要能用 — 所有資訊 hover 才顯示的 tooltip,都必須 focus 也顯示) - **不用** OS 特殊動畫 API(避免 Linux 裝了 compositor 死機) - **不用** 特殊字型(全跟 Geist,Wails 會 bundle) - **檔案路徑**顯示時一律 `font-mono text-xs`,避免字型不同導致錯位 --- ## 8. Dark Mode - 跟隨 OS:macOS `appearance` / Windows `apps use dark theme` / Linux `color-scheme` media query - 實作方式:沿用 visionA-frontend 的 `ThemeSync` 元件(react hook + `matchMedia`) - **不提供**手動切換 UI - 所有顏色用 CSS 變數(Design Tokens),自動跟 `.dark` class 切換 - 圖示(Lucide SVG)用 `currentColor`,自動跟文字色 - **logo 圖片**需要 light / dark 兩版(logo-light.svg / logo-dark.svg) --- ## 9. 無障礙基準(WCAG 2.1 AA) - **色彩對比**:一般文字 ≥ 4.5:1;大文字 ≥ 3:1;UI 元件 ≥ 3:1 - **不只靠顏色**:所有狀態搭配 icon + 文字 - **鍵盤導航**: - Tab 依視覺順序移動 - `Ctrl/Cmd+1/2/3` 切 Tab - `Enter` 送出表單 - `Esc` 關閉 Dialog / 取消操作 - Focus ring 永遠可見(`ring-[3px] ring-ring`) - **ARIA**: - Tab 用 `role="tab"` / `role="tabpanel"` / `aria-selected` - StatusHero 用 `role="status" aria-live="polite"` - Toast 用 Sonner 預設 `aria-live="assertive"` - AlertDialog 用 shadcn 內建焦點陷阱 - **螢幕閱讀器**: - Session Token 遮蔽版:`aria-label="Session token, ending in e7f8"`(不念完整字串) - 圖示裝飾:`aria-hidden="true"` - **Reduce motion**:支援 `prefers-reduced-motion`,停用 pulse / spinner 旋轉 --- ## 10. i18n 字典 keys 預估 | 分類 | keys 數 | |------|--------| | 全域(nav / header / common)| ~15 | | 狀態頁(status)| ~25 | | 配對頁(pair)| ~30 | | 設定頁(settings)| ~40 | | 錯誤訊息(errors)| ~15 | | Toast | ~10 | | **總計** | **~135 keys** | 兩語言(繁中 + English)共約 270 條翻譯。文件位置建議: ``` visiona-agent/frontend/src/lib/i18n/ ├── zh-TW.ts └── en.ts ``` 偵測優先序:OS locale → 預設 `en`(若非 `zh-*` 均 fallback en)。 --- ## 11. 需使用者裁決的設計決定 以下三點為設計過程中稍有不確定、建議使用者快速裁決的點(不影響動工,可先照 Design 建議實作): | # | 問題 | Design 建議 | 備選 | |---|------|-----------|------| | 1 | 視窗大小是否允許使用者記住上次大小? | **記住**(Wails 預設行為) | 每次固定 720×560 | | 2 | 配對成功後的轉場 | **0.5 秒後自動切回狀態頁**(有 toast 確認) | 停留原地,顯示大 ✓ 後讓使用者手動點繼續 | | 3 | 「檢查更新」按鈕在 Phase 0 雛形的行為 | **stub:直接回 up-to-date** | 直接隱藏按鈕,Phase 1 再開 | --- ## 12. 交付檔案 | 檔案 | 狀態 | |------|------| | `.autoflow/03-design/visiona-agent-spec.md`(本檔)| ✅ 完成 | **不產出**: - wireframe 子檔(本檔內已含 ASCII wireframe,小規模 utility 無需再拆) - 高保真 prototype(雛形階段無必要) - 獨立 design-tokens(完全沿用 visionA-frontend 既有檔案) --- ## 13. 給 Architect / Frontend Agent 的提醒 ### 13.1 給 Architect - Agent 與 remote-proxy 的通訊契約(WS upgrade、session token 持久化、reconnect 指數退避)請對齊 `04-architecture/security.md` 的 Pairing / Session 兩階段協定 - 前端(Wails runtime 呼叫 Go backend)建議定義清楚的 API:`Connect(token) / Disconnect() / Reconnect() / GetStatus() / TestRelay(url) / ExportLog() / ResetAll()` - 狀態同步:backend 用 Wails `EventsEmit("connection:status", payload)` 推送,前端 `EventsOn` 監聽 ### 13.2 給 Frontend(未來撰寫 Agent 前端的工程師) - **直接複製** `visionA-frontend/src/app/globals.css` 到 Agent 專案,**不動一行** - **直接複製** shadcn 基礎元件(Button / Card / Dialog / Input / Tabs / Checkbox / RadioGroup / Select / AlertDialog / Alert / Sonner) - **不引入** Next.js(Agent 是純 SPA);用 Vite + React Router(或不用 router,三個 tab 用 state 切換) - i18n 沿用 visionA-frontend 的 `src/lib/i18n` 模式(自訂 hook + TS 字典) - 所有 backend 呼叫走 Wails runtime bindings,不碰 HTTP - Dark Mode sync:沿用 `ThemeSync` 元件 --- **本規格結束。共 3 頁面 + 1 全域導航 + 3 平台適配 + 135 i18n keys,符合「極簡 utility」定位。**