jim800121chen 8cd5751ce3 feat(local-tool): M8 重構 — Wails 控制台 + 瀏覽器 Web UI(R5 決策)
依 R5 五輪決策把 visionA-local 從「Wails 內嵌 Next.js」重構為「Wails
本機伺服器控制台 + 瀏覽器 Web UI」模式(類比 Docker Desktop / Ollama)。

程式碼變動
  - M8-1 砍 yt-dlp 全套(後端 resolver / URL handler / 前端 URL tab /
    Makefile vendor / installer / bootstrap / CI workflow,-555 行)
  - M8-2 砍 Mock 模式全套(driver/mock、mock_camera、Settings runtimeMode、
    VISIONA_MOCK 環境變數,-528 行)
  - M8-3 ffmpeg 從 GPL 切換到 LGPL 混合方案:Windows/Linux 用 BtbN 現成
    LGPL binary,macOS 自 build minimal decoder-only 進 git
    (vendor/ffmpeg/macos/ffmpeg 5.7MB + ffprobe 5.6MB,比 GPL 版省 85% 空間)
  - M8-4 Wails Server Controller:state machine、log ring buffer 2000 行、
    preferences.json atomic write、boot-id、Gin SkipPaths、shutdown 7+1 秒、
    notify_*.go 三平台 OS 通知、watchServer 改 Error state 不 os.Exit
  - M8-4b 啟動階段管線 R5-E:6 階段進度 event、20s soft / 60s hard timeout、
    stage 5/6 skip 規則、sentinel file、RestartStartupSequence 5 步驟
  - M8-5 Wails 控制台 vanilla HTML/JS/CSS(9 檔 ~2012 行)取代 M7-B splash:
    state 視覺、log panel、startup progress panel、Stage 6 manual CTA
    pulse、shutdown modal、Settings、Dark Mode、i18n 中英雙語
  - M8-6 上傳影片副檔名擴充(mp4/avi/mov/mpeg/mpg)
  - M8-7 Web UI Server Offline Overlay(role=alertdialog + focus trap +
    wsEverConnected 容錯 + Page Visibility)
  - M8-8 CORS middleware(127.0.0.1/localhost only + suffix attack 防護)+
    ws/origin.go 獨立 WebSocket CheckOrigin 避 package cycle
  - MAJ-4 server:shutdown-imminent WebSocket broadcast 機制
    (/ws/system endpoint + notifyShutdownImminent helper)
  - M8-9 Boot-ID + 瀏覽器 tab 自動重連(sessionStorage loop guard)

品質
  - ~105+ 新 unit test + race detector (-count=2) 全綠
  - 10 個 milestone 全部通過 Reviewer 審查
  - 三方 v2 + v2.1 文件(PRD / Design Spec / TDD)+ 交叉互審紀錄
    收錄在 .autoflow/

交付前待處理(M8-10)
  - 重跑 make payload-macos 把舊 GPL 77MB binary 換成新 LGPL
  - 三平台 end-to-end build 驗證

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 17:57:54 +08:00

13 KiB
Raw Permalink Blame History

v2.5 — Settings 頁更新

本章對應 R5-4Settings 新增自動開瀏覽器 toggle+ R5-5a砍 Mock 模式相關設定)+ R5-D2Linux 預設 OFF+ R5-D3每次啟動都自動開+ R5-E階段化啟動進度。 上層索引:../design-spec-v2.md 版本:v2.1 · 更新日期2026-04-14


1. 變更摘要

Settings 維持 v1 的 4 個分頁 結構R4 第四輪決策確認):

Tab v1 內容 v2 變更
一般 語言、深色模式狀態(唯讀) 新增「首次啟動時自動開啟瀏覽器」toggle
硬體 真實 / Mock 切換、裝置掃描策略 刪除 Mock 相關,只保留裝置掃描策略
模型 預置模型清單、上傳、自訂 不變
進階 資料目錄、Python 雙策略、清 log 等 不變

2. 「一般」分頁新增項目

2.1 結構

┌─ Settings > 一般 ───────────────────────────────────────────┐
│                                                               │
│  語言                                                         │
│  ┌───────────────────────────┐                               │
│  │ 繁體中文              ▾   │                               │
│  └───────────────────────────┘                               │
│                                                               │
│  深色模式                                                     │
│  跟隨系統(目前:深色)                                       │
│                                                               │
│  ── 啟動行為 ────────────────────────────────────────        │
│                                                               │
│  首次啟動時自動開啟瀏覽器               [■□] ON              │
│  啟動 visionA-local 時自動在預設瀏覽器開啟 Web UI。           │
│  關閉此選項後,你需要手動點控制台的「在瀏覽器開啟」按鈕。      │
│                                                               │
└──────────────────────────────────────────────────────────────┘

2.2 Toggle 規格

屬性
元件類型 <Switch>shadcn
預設值(依平台) macOS / Windows = ONLinux = OFFR5-D2
i18n key settings.general.autoOpenBrowser.label / settings.general.autoOpenBrowser.description
落地檔案 preferences.json 位於 <dataDir>/(對齊 TDD v2
路徑:
• macOS ~/Library/Application Support/visiona-local/preferences.json
• Windows %APPDATA%\visiona-local\preferences.json
• Linux ~/.local/share/visiona-local/preferences.json
儲存機制 Go server 端負責讀寫visiona-local/preferences.go,非 Wails 內建機制 — Wails v2 沒有 settings store
JSON 格式:{"openBrowserOnStart": true}
原子寫入:write-rename patternos.WriteFile(path+".tmp", ...)os.Rename(path+".tmp", path)POSIX / Windows 均原子
讀取失敗 fallback 呼叫 DefaultPreferences(),依 runtime.GOOS 回傳平台預設:
Preferences{OpenBrowserOnStart: runtime.GOOS != "linux"}
生效時機 立即生效,不需 restart app
影響對象 控制台的「每次啟動自動開瀏覽器」邏輯(見 v2/control-panel.md §7

Linux 首次使用說明R5-D2 落地)

Linux 使用者第一次開 Wails 控制台時Settings > 一般 的「啟動時自動開啟瀏覽器」toggle 預設是關的。原因是 Linux 桌面環境差異大,xdg-open 在無頭環境 / i3 / xmonad / 極簡 WM 下行為可能異常(例如無預設瀏覽器、或開到錯的 DE session。Linux 使用者若確認自己的環境可以正常 xdg-open,可手動打開此 toggle下次啟動就會自動開瀏覽器。

關閉此 toggle 時,啟動進度面板仍然會顯示(見 v2/startup-progress.md),只是第 5 階段「開啟瀏覽器」會被標記為 跳過(依偏好設定)/ Skipped (per preference),第 6 階段「等待 Web UI 連線」改為「等待使用者手動點擊『在瀏覽器開啟』」— 視覺上仍會收尾至 Running state只是由使用者主動觸發第 5 階段(對齊 R5-E 階段化體驗)。

2.3 重要細節R5-D3 已定案)

這個 toggle 同時影響「首次」和「每次」啟動嗎?

R5-D3 決策每次啟動(含每次 StartServer 成功後都會自動開瀏覽器不是只有首次。R5-4 原字面「首次啟動」已於 R5-D3 修正。精確行為:

  • Toggle ONmacOS / Windows 預設):每次雙擊 app 或每次 Start Server 成功後,控制台自動呼叫 OS open browser
  • Toggle OFFLinux 預設):啟動時只開控制台,不開瀏覽器;使用者自行點控制台的「在瀏覽器開啟」按鈕
  • Restart Server 情境:因為 Restart 是同一個 Wails App process 內重啟R5 雙 UI 架構下 Wails 不關),且啟動進度面板只在 Wails 剛啟動時顯示一次Restart 時瀏覽器 tab 應由 Offline Overlay 自動重連,不會再開新 tab避免開一堆重複 tab

Label 定版:「啟動時自動開啟瀏覽器」/ "Auto-open browser on startup"(去掉「首次」二字)

版本 label description
原 R5-4 字面 首次啟動時自動開啟瀏覽器
最終採用R5-D3 定案) 啟動時自動開啟瀏覽器 啟動 visionA-local 時自動在預設瀏覽器開啟 Web UI。關閉此選項後你需要手動點控制台的「在瀏覽器開啟」按鈕。

3. 「硬體」分頁變更

3.1 刪除項目R5-5a

所有 Mock 模式相關設定全砍

v1 項目 說明 v2 處理
模式:真實硬體 / Mock radio 切換整個 app 推論來源 刪除
Mock 模式描述 說明文字 介紹 Mock 用途 刪除
Mock 模式假資料速率 slider 調 Mock 輸出速率 刪除
Mock 模式裝置名稱 input 自訂假裝置名 刪除
切換模式會重啟推論 session 警告 切換時的提醒 刪除

3.2 保留項目

項目 說明
裝置自動掃描頻率 每次啟動時 / 手動 / 關閉
USB 熱插拔偵測 toggle 自動偵測新裝置插入
Kneron KL520 / KL720 韌體版本顯示 唯讀

3.3 新增項目

無。R5-5a 砍 Mock 後這個 tab 變得更簡潔。

3.4 Tab 是否保留?

因為「硬體」tab 被清空後仍有內容(掃描頻率、熱插拔、韌體版本),tab 結構保留,不合併也不刪除。


4. 「模型」與「進階」分頁

完全不動。R5 沒有觸及這兩個 tab 的內容。


5. i18n key 異動

5.1 新增 key

Key zh-TW en
settings.general.sectionStartup 啟動行為 Startup behavior
settings.general.autoOpenBrowser.label 啟動時自動開啟瀏覽器 Auto-open browser on startup
settings.general.autoOpenBrowser.description 啟動 visionA-local 時自動在預設瀏覽器開啟 Web UI。關閉此選項後你需要手動點控制台的「在瀏覽器開啟」按鈕。 Automatically open the Web UI in your default browser when visionA-local starts. When off, you need to manually click "Open in Browser" in the Control Panel.

5.2 刪除 key

執行 grep 找出所有 mock 相關 key

grep -rE "mock|Mock" frontend/src/lib/i18n/

預期刪除(實際清單以 grep 為準):

Key 原值zh-TW
settings.hardware.mode.label 模式
settings.hardware.mode.real 真實硬體
settings.hardware.mode.mock Mock
settings.hardware.mode.description 選擇 visionA-local 的執行模式
settings.hardware.mock.rate.label Mock 速率
settings.hardware.mock.deviceName.label Mock 裝置名稱
settings.hardware.modeSwitchWarning 切換模式會重啟推論 session
firstRun.mode.* 全部(見 v2/first-run-update.md §5.2
devices.mockBadge Mock
dashboard.tryMockHint 或切換到 Mock 模式試用

5.3 type 檔同步

frontend/src/lib/i18n/types.ts 對應 interface 欄位全砍,確保 TypeScript 編譯不留 dangling reference。


6. 清理殘留的 Mock 程式碼

Settings 改完後,前後端其他地方可能仍有 Mock 殘留:

6.1 前端

  • frontend/src/stores/ 任何 mock state / action
  • frontend/src/components/ 任何 Mock badge / pill
  • frontend/src/app/devices/ 頁面右上的「真實 / Mock」切換v1 design-spec.md §第三輪修訂後仍待確認 4. 提到)

6.2 後端

  • Go server 任何 mock handler、假資料 generator
  • Python sidecar 的 mock inference path

這部分非 Design 的 scope,但 Design 提醒 OrchestratorR5-5a 的「完全砍除」不只是 UI 層面,後端也要同步砍。交 Architect Agent 評估實作影響。


7. 遷移策略Migration

使用者情境v1 版本沒有 preferences.jsonMock 模式相關設定(若存在)是記在前端 localStorage 或 v1 舊式 config不在 Go 端的 preferences 檔裡。v2 改用 Go 端 preferences.json 管理「是否啟動時自動開瀏覽器」,是全新的檔案

v2 首次讀取 preferences.json 流程

  1. 檢查 <dataDir>/preferences.json 是否存在
  2. 不存在 → 呼叫 DefaultPreferences()(依 runtime.GOOS 回傳平台預設macOS/Windows OpenBrowserOnStart=trueLinux OpenBrowserOnStart=false
  3. 存在但解析失敗JSON 毀損等)→ 同樣 fallback 到 DefaultPreferences(),並發 log WARN不擋啟動
  4. 存在且解析成功 → 使用使用者設定
  5. 使用者在 Settings 點擊 toggle → write-rename atomic pattern 寫回 preferences.json

v1 → v2 無 migration 成本:因為 v1 沒有對應檔案v2 啟動時若 preferences.json 不存在就建立新檔(或延遲到使用者第一次改 toggle 才寫),行為是靜默的,使用者不需要知道。

Mock 模式殘留v1 localStorage 可能有 mock 相關 keyFrontend 清理見 §6.1;與 preferences.json 無關。


8. 無障礙考量

項目 設計
Toggle 元件 沿用 shadcn <Switch>,已內建 role="switch" / aria-checked
Tab 切換 沿用現有 Tabs 元件,role="tablist" / role="tab" / role="tabpanel"
Keyboard / 切換 tab、Tab 進入 tab panel 內部
分區標題 「啟動行為」區用 <h3> 讓 screen reader 感知結構

9. 與 v1 差異對照

面向 v1 v2
一般 tab 項目數 2語言、深色模式 3(新增 auto-open browser
硬體 tab 項目數 5+(含 Mock 相關) 3只剩真實硬體相關
Mock 模式 UI Settings + Devices pill + First-Run Step 全砍
模型 / 進階 tab 不變

10. v2 → v2.1 Diff2026-04-14

# 位置 v2 v2.1 來源
1 §2.2 落地檔案 settings.json + 「走 Wails 既有 settings store」 preferences.json @ <dataDir>/ + Go server 讀寫 + write-rename atomic Architect Review Major 1
2 §2.2 預設值 三平台一致 ON macOS/Windows = ONLinux = OFF(依 DefaultPreferences()runtime.GOOS R5-D2 / Architect Review Major 2
3 §2.2 新增 Linux 首次使用說明toggle 預設關、關閉時啟動進度面板仍顯示、第 5/6 階段跳過) R5-D2 + R5-E
4 §2.3 標題 「重要細節」待 confirm 「R5-D3 已定案」每次啟動都開瀏覽器label 定版 R5-D3
5 §7 遷移策略 假設 v1 有 settings.json + mock key 遷移 澄清 preferences.json全新檔,無 v1 migration 成本 Architect Review Major 1 衍生

11. 給 Orchestrator 的提醒

  1. R5-4 的 label 字面歧義已於 R5-D3 定案每次啟動都開label 去掉「首次」)
  2. 後端 Mock 清理不在 Design scope需轉給 Architect / Backend Agent
  3. Devices 頁面的 Mock pillv1 design-spec.md 第三輪修訂 §4要一併砍此變更未在本文件細寫但屬 R5-5a 範圍
  4. Linux 預設 OFF 對 E2E 測試的影響testing Agent 在 Linux CI 上跑自動化時要注意,啟動後不會 auto-open需手動模擬點擊「在瀏覽器開啟」或在測試前將 preferences.json 改為 {"openBrowserOnStart": true}

下一步:交 Frontend Agent 更新 Settings 頁面。