依 autoflow-agent workspace v2 設計把 PRD / 設計 / 架構 / 交付類 共享文件從個人層 .autoflow/(ignored)搬到 docs/autoflow/(進 git), 讓團隊可共享產品與架構文件,個人層只留 progress / review / testing 等 per-branch 筆記。 - 02-prd/ 21 個檔(PRD、features、market-analysis 等) - 03-design/ 18 個檔(design-spec、wireframes、flows 等) - 04-architecture/ 31 個檔(TDD、design-doc、ADR×14、API 規格等) - 07-delivery/ 3 個檔(project-summary、phase-0.6-handover、stage-deployment-setup) 合計 73 檔。原檔已從 .autoflow/ 移除(migration 工具執行 git mv, 但因 .autoflow/ 在 .gitignore 中、git 將此操作視為新增、無 rename history)。
37 KiB
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 設計原則
- 極簡優先 — 一個 utility 不是一個 product。不做 onboarding tour、不做裝飾性插圖、不做動畫秀。
- 誠實呈現狀態 — online / offline / reconnecting / error 必須清楚區分,不只靠顏色(搭配 icon + 文字)。
- 與雲端視覺一致 — Design Tokens 100% 沿用,使用者看到會立刻聯想「這是 visionA 那家」。
- 跨平台 — 不做任何倚賴特定 OS 的互動(不做 traffic light 自訂、不做 system tray、不做 Win11 Mica)。
- 鍵盤友善 — 所有操作 Tab 可達,符合 WCAG 2.1 AA。
- 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 tabbg-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)
- 頂層:狀態 Icon(Lucide,
- 狀態變體(對應 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}」
- online:綠圓 +
(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」+AlertCircleicon - 格式正確:
text-green-600「✓ 格式正確(36 字元)」+CheckCircle2icon - 邊框狀態:預設
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
.desktopautostart) - 變更時 toast:「✓ 已啟用開機自啟動」/ 「已關閉開機自啟動」
- shadcn
-
重連策略:
- shadcn
RadioGroup 自動重試— 預設;指數退避(1s → 2s → 4s → 8s → 16s),最多 5 次失敗後停止並轉為手動手動重連— 連線中斷後不自動重試,使用者需在狀態頁點「立即重試」
- shadcn
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 開檔案總管到該路徑
- macOS:
- 匯出 Log按鈕:
- 點擊 → OS save dialog(Wails runtime
SaveFileDialog) - 預設檔名:
visionA-agent-log-YYYYMMDD-HHmmss.zip - 內容:壓縮最近 7 天的 log 檔
- 匯出中:按鈕 loading;完成 toast「✓ 已匯出到 {path}」
- 點擊 → OS save dialog(Wails runtime
6.2.4 關於
- 版本:
visionA Agent {version}(從runtime.Environment取) - 檢查更新按鈕:
- Phase 0 stub:call backend
CheckForUpdates(),雛形直接回up-to-date - Toast:
✓ 已是最新版本/有新版本可用:v0.2.0 [ 開啟下載頁 ]
- Phase 0 stub:call backend
- 開啟文件:
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/ Windowsapps use dark theme/ Linuxcolor-schememedia query - 實作方式:沿用 visionA-frontend 的
ThemeSync元件(react hook +matchMedia) - 不提供手動切換 UI
- 所有顏色用 CSS 變數(Design Tokens),自動跟
.darkclass 切換 - 圖示(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切 TabEnter送出表單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 內建焦點陷阱
- Tab 用
- 螢幕閱讀器:
- Session Token 遮蔽版:
aria-label="Session token, ending in e7f8"(不念完整字串) - 圖示裝飾:
aria-hidden="true"
- Session Token 遮蔽版:
- 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」定位。