From 8cd5751ce381a04e7eff719acdd375973f149d99 Mon Sep 17 00:00:00 2001 From: jim800121chen Date: Wed, 15 Apr 2026 17:57:54 +0800 Subject: [PATCH] =?UTF-8?q?feat(local-tool):=20M8=20=E9=87=8D=E6=A7=8B=20?= =?UTF-8?q?=E2=80=94=20Wails=20=E6=8E=A7=E5=88=B6=E5=8F=B0=20+=20=E7=80=8F?= =?UTF-8?q?=E8=A6=BD=E5=99=A8=20Web=20UI=EF=BC=88R5=20=E6=B1=BA=E7=AD=96?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 依 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) --- .gitignore | 9 +- .../pm-analysis-round2-refactor.md | 419 ++++++ local-tool/.autoflow/02-prd/PRD-v2.md | 500 ++++++++ .../02-prd/reviews/design-review-of-prd-v2.md | 347 +++++ .../design-analysis-round2-refactor.md | 537 ++++++++ .../.autoflow/03-design/design-spec-v2.md | 127 ++ .../architect-review-of-design-spec-v2.md | 551 ++++++++ .../.autoflow/03-design/v2/control-panel.md | 465 +++++++ .../03-design/v2/first-run-update.md | 340 +++++ .../03-design/v2/server-offline-overlay.md | 275 ++++ .../.autoflow/03-design/v2/settings-update.md | 239 ++++ .../03-design/v2/source-selector-update.md | 204 +++ .../03-design/v2/startup-progress.md | 417 ++++++ .../.autoflow/04-architecture/TDD-v2.md | 162 +++ .../architect-analysis-round2-refactor.md | 798 ++++++++++++ .../04-architecture/ffmpeg-lgpl-research.md | 312 +++++ .../reviews/pm-review-of-tdd-v2.md | 515 ++++++++ .../04-architecture/v2/code-reuse-v2.md | 219 ++++ .../04-architecture/v2/control-panel.md | 849 +++++++++++++ .../04-architecture/v2/cors-security.md | 358 ++++++ .../.autoflow/04-architecture/v2/deletions.md | 634 ++++++++++ .../04-architecture/v2/ffmpeg-lgpl.md | 461 +++++++ .../04-architecture/v2/milestone-plan.md | 513 ++++++++ .../04-architecture/v2/server-lifecycle.md | 1006 +++++++++++++++ .../04-architecture/v2/startup-pipeline.md | 719 +++++++++++ .../v2/web-ui-offline-overlay.md | 679 ++++++++++ .../reviews/M8-1+M8-2-review.md | 326 +++++ .../05-implementation/reviews/M8-3-review.md | 271 ++++ .../05-implementation/reviews/M8-4-review.md | 360 ++++++ .../reviews/M8-4b-patch-review.md | 229 ++++ .../05-implementation/reviews/M8-4b-review.md | 273 ++++ .../reviews/M8-5-patch-review.md | 214 ++++ .../05-implementation/reviews/M8-5-review.md | 281 +++++ .../05-implementation/reviews/M8-7-review.md | 188 +++ .../05-implementation/reviews/M8-8-review.md | 202 +++ .../05-implementation/reviews/M8-9-review.md | 154 +++ .../05-implementation/reviews/MAJ-4-review.md | 168 +++ local-tool/.autoflow/progress.md | 299 ++++- local-tool/.github/workflows/build.yml | 9 +- local-tool/.gitignore | 7 + local-tool/Makefile | 254 ++-- local-tool/README.md | 15 +- local-tool/frontend/src/app/layout.tsx | 4 + local-tool/frontend/src/app/settings/page.tsx | 19 - .../src/components/camera/camera-controls.tsx | 8 +- .../src/components/camera/source-selector.tsx | 94 +- .../system/server-offline-overlay.tsx | 162 +++ .../system/shutdown-watcher-mount.tsx | 16 + .../src/hooks/use-shutdown-watcher.ts | 358 ++++++ local-tool/frontend/src/lib/i18n/en.ts | 24 +- local-tool/frontend/src/lib/i18n/types.ts | 20 +- local-tool/frontend/src/lib/i18n/zh-TW.ts | 24 +- .../frontend/src/stores/camera-store.ts | 32 - .../frontend/src/stores/system-store.ts | 104 ++ .../tests/hooks/use-shutdown-watcher.test.ts | 125 ++ .../src/tests/stores/system-store.test.ts | 53 + local-tool/installer/linux/build-appimage.sh | 11 +- .../installer/windows/visiona-local.iss | 7 +- local-tool/scripts/bootstrap-linux.sh | 5 +- local-tool/scripts/bootstrap-windows.ps1 | 9 +- .../server/internal/api/api_e2e_test.go | 247 ---- .../internal/api/handlers/camera_handler.go | 176 +-- .../internal/api/handlers/system_handler.go | 88 +- .../api/handlers/system_handler_test.go | 231 ++++ local-tool/server/internal/api/middleware.go | 99 +- .../server/internal/api/middleware_test.go | 201 +++ local-tool/server/internal/api/router.go | 28 +- .../internal/api/ws/device_events_ws.go | 7 +- local-tool/server/internal/api/ws/hub.go | 60 + .../internal/api/ws/hub_broadcast_test.go | 132 ++ .../internal/api/ws/hub_sentinel_test.go | 85 ++ local-tool/server/internal/api/ws/origin.go | 40 + .../server/internal/api/ws/origin_test.go | 38 + .../server/internal/api/ws/system_ws.go | 58 + .../api/ws/system_ws_integration_test.go | 83 ++ local-tool/server/internal/camera/manager.go | 28 +- .../server/internal/camera/mock_camera.go | 95 -- .../server/internal/camera/video_source.go | 83 +- local-tool/server/internal/config/config.go | 22 +- local-tool/server/internal/deps/checker.go | 10 +- local-tool/server/internal/device/manager.go | 23 +- .../server/internal/device/manager_test.go | 45 +- .../internal/driver/mock/mock_driver.go | 183 --- local-tool/server/main.go | 21 +- local-tool/vendor/.gitkeep | 0 local-tool/vendor/ffmpeg/macos/BUILD.md | 294 +++++ local-tool/vendor/ffmpeg/macos/COPYING.LGPLv3 | 165 +++ local-tool/vendor/ffmpeg/macos/ffmpeg | Bin 0 -> 6007520 bytes local-tool/vendor/ffmpeg/macos/ffprobe | Bin 0 -> 5865568 bytes local-tool/visiona-local/app.go | 173 ++- local-tool/visiona-local/frontend/app.js | 399 +++++- .../visiona-local/frontend/control-panel.js | 126 ++ local-tool/visiona-local/frontend/i18n.js | 222 ++++ local-tool/visiona-local/frontend/index.html | 188 ++- .../visiona-local/frontend/log-panel.js | 175 +++ .../visiona-local/frontend/settings-panel.js | 111 ++ .../visiona-local/frontend/startup-panel.js | 281 +++++ local-tool/visiona-local/frontend/style.css | 739 +++++++++-- .../frontend/wailsjs/go/main/App.js | 65 +- local-tool/visiona-local/log_buffer.go | 205 +++ local-tool/visiona-local/log_buffer_test.go | 151 +++ local-tool/visiona-local/main.go | 17 +- local-tool/visiona-local/notify_darwin.go | 43 + local-tool/visiona-local/notify_linux.go | 29 + local-tool/visiona-local/notify_windows.go | 43 + local-tool/visiona-local/preferences.go | 96 ++ local-tool/visiona-local/preferences_test.go | 112 ++ local-tool/visiona-local/server_control.go | 1121 +++++++++++++++++ .../visiona-local/server_control_test.go | 355 ++++++ local-tool/visiona-local/shutdown_notify.go | 58 + .../visiona-local/shutdown_notify_test.go | 176 +++ local-tool/visiona-local/startup_pipeline.go | 433 +++++++ .../visiona-local/startup_pipeline_test.go | 677 ++++++++++ 113 files changed, 23145 insertions(+), 1372 deletions(-) create mode 100644 local-tool/.autoflow/01-requirements/pm-analysis-round2-refactor.md create mode 100644 local-tool/.autoflow/02-prd/PRD-v2.md create mode 100644 local-tool/.autoflow/02-prd/reviews/design-review-of-prd-v2.md create mode 100644 local-tool/.autoflow/03-design/design-analysis-round2-refactor.md create mode 100644 local-tool/.autoflow/03-design/design-spec-v2.md create mode 100644 local-tool/.autoflow/03-design/reviews/architect-review-of-design-spec-v2.md create mode 100644 local-tool/.autoflow/03-design/v2/control-panel.md create mode 100644 local-tool/.autoflow/03-design/v2/first-run-update.md create mode 100644 local-tool/.autoflow/03-design/v2/server-offline-overlay.md create mode 100644 local-tool/.autoflow/03-design/v2/settings-update.md create mode 100644 local-tool/.autoflow/03-design/v2/source-selector-update.md create mode 100644 local-tool/.autoflow/03-design/v2/startup-progress.md create mode 100644 local-tool/.autoflow/04-architecture/TDD-v2.md create mode 100644 local-tool/.autoflow/04-architecture/architect-analysis-round2-refactor.md create mode 100644 local-tool/.autoflow/04-architecture/ffmpeg-lgpl-research.md create mode 100644 local-tool/.autoflow/04-architecture/reviews/pm-review-of-tdd-v2.md create mode 100644 local-tool/.autoflow/04-architecture/v2/code-reuse-v2.md create mode 100644 local-tool/.autoflow/04-architecture/v2/control-panel.md create mode 100644 local-tool/.autoflow/04-architecture/v2/cors-security.md create mode 100644 local-tool/.autoflow/04-architecture/v2/deletions.md create mode 100644 local-tool/.autoflow/04-architecture/v2/ffmpeg-lgpl.md create mode 100644 local-tool/.autoflow/04-architecture/v2/milestone-plan.md create mode 100644 local-tool/.autoflow/04-architecture/v2/server-lifecycle.md create mode 100644 local-tool/.autoflow/04-architecture/v2/startup-pipeline.md create mode 100644 local-tool/.autoflow/04-architecture/v2/web-ui-offline-overlay.md create mode 100644 local-tool/.autoflow/05-implementation/reviews/M8-1+M8-2-review.md create mode 100644 local-tool/.autoflow/05-implementation/reviews/M8-3-review.md create mode 100644 local-tool/.autoflow/05-implementation/reviews/M8-4-review.md create mode 100644 local-tool/.autoflow/05-implementation/reviews/M8-4b-patch-review.md create mode 100644 local-tool/.autoflow/05-implementation/reviews/M8-4b-review.md create mode 100644 local-tool/.autoflow/05-implementation/reviews/M8-5-patch-review.md create mode 100644 local-tool/.autoflow/05-implementation/reviews/M8-5-review.md create mode 100644 local-tool/.autoflow/05-implementation/reviews/M8-7-review.md create mode 100644 local-tool/.autoflow/05-implementation/reviews/M8-8-review.md create mode 100644 local-tool/.autoflow/05-implementation/reviews/M8-9-review.md create mode 100644 local-tool/.autoflow/05-implementation/reviews/MAJ-4-review.md create mode 100644 local-tool/frontend/src/components/system/server-offline-overlay.tsx create mode 100644 local-tool/frontend/src/components/system/shutdown-watcher-mount.tsx create mode 100644 local-tool/frontend/src/hooks/use-shutdown-watcher.ts create mode 100644 local-tool/frontend/src/stores/system-store.ts create mode 100644 local-tool/frontend/src/tests/hooks/use-shutdown-watcher.test.ts create mode 100644 local-tool/frontend/src/tests/stores/system-store.test.ts delete mode 100644 local-tool/server/internal/api/api_e2e_test.go create mode 100644 local-tool/server/internal/api/handlers/system_handler_test.go create mode 100644 local-tool/server/internal/api/middleware_test.go create mode 100644 local-tool/server/internal/api/ws/hub_broadcast_test.go create mode 100644 local-tool/server/internal/api/ws/hub_sentinel_test.go create mode 100644 local-tool/server/internal/api/ws/origin.go create mode 100644 local-tool/server/internal/api/ws/origin_test.go create mode 100644 local-tool/server/internal/api/ws/system_ws.go create mode 100644 local-tool/server/internal/api/ws/system_ws_integration_test.go delete mode 100644 local-tool/server/internal/camera/mock_camera.go delete mode 100644 local-tool/server/internal/driver/mock/mock_driver.go create mode 100644 local-tool/vendor/.gitkeep create mode 100644 local-tool/vendor/ffmpeg/macos/BUILD.md create mode 100644 local-tool/vendor/ffmpeg/macos/COPYING.LGPLv3 create mode 100755 local-tool/vendor/ffmpeg/macos/ffmpeg create mode 100755 local-tool/vendor/ffmpeg/macos/ffprobe create mode 100644 local-tool/visiona-local/frontend/control-panel.js create mode 100644 local-tool/visiona-local/frontend/i18n.js create mode 100644 local-tool/visiona-local/frontend/log-panel.js create mode 100644 local-tool/visiona-local/frontend/settings-panel.js create mode 100644 local-tool/visiona-local/frontend/startup-panel.js create mode 100644 local-tool/visiona-local/log_buffer.go create mode 100644 local-tool/visiona-local/log_buffer_test.go create mode 100644 local-tool/visiona-local/notify_darwin.go create mode 100644 local-tool/visiona-local/notify_linux.go create mode 100644 local-tool/visiona-local/notify_windows.go create mode 100644 local-tool/visiona-local/preferences.go create mode 100644 local-tool/visiona-local/preferences_test.go create mode 100644 local-tool/visiona-local/server_control.go create mode 100644 local-tool/visiona-local/server_control_test.go create mode 100644 local-tool/visiona-local/shutdown_notify.go create mode 100644 local-tool/visiona-local/shutdown_notify_test.go create mode 100644 local-tool/visiona-local/startup_pipeline.go create mode 100644 local-tool/visiona-local/startup_pipeline_test.go diff --git a/.gitignore b/.gitignore index 9fba9f7..aff6b44 100644 --- a/.gitignore +++ b/.gitignore @@ -15,9 +15,16 @@ Thumbs.db # ───────────────────────────────────── # 不進 git 的依賴與產物(決策 R4-D2) -local-tool/vendor/ +# 注意:使用 /** 而非 /,否則後面的 ! 例外無法 re-include(git 規則: +# 父目錄被排除時無法 re-include 檔案)— R5-6b 需要 macOS ffmpeg binary 進 git +local-tool/vendor/** local-tool/dist/ local-tool/payload/ +# R5-6b:macOS LGPL ffmpeg binary 進 git(沒有現成 LGPL binary 來源,自 build 成本高, +# commit 後開發者 clone 即可用,不必每次重 build ~15 分鐘) +!local-tool/vendor/ffmpeg/ +!local-tool/vendor/ffmpeg/macos/ +!local-tool/vendor/ffmpeg/macos/** # Go server 的 embed 與 build 產物 local-tool/server/web/out/ diff --git a/local-tool/.autoflow/01-requirements/pm-analysis-round2-refactor.md b/local-tool/.autoflow/01-requirements/pm-analysis-round2-refactor.md new file mode 100644 index 0000000..9a7c50d --- /dev/null +++ b/local-tool/.autoflow/01-requirements/pm-analysis-round2-refactor.md @@ -0,0 +1,419 @@ +# PM 第一輪分析 — visionA-local 方向變更(2026-04-14) + +> 作者:PM Agent +> 性質:**第一輪分析筆記,非正式 PRD 修訂** +> 觸發事件:使用者在 M7 收尾階段提出三項重大方向變更 +> 對應使用者訊息:「推論只需包含 camera / image / video upload」「模型只預設 + 只能上傳」「介面希望是網頁不是包在應用程式中」「Wails 負責顯示 server log / 啟停重啟 / 打開 localhost 網頁」 + +--- + +## 摘要(3 行) + +1. **這是一個 L 級變更,不是 S 級**:三項變更疊加起來等於把 visionA-local 從「Wails 內嵌式桌面 app」重新定位為「Ollama / LM Studio / Stable Diffusion WebUI 式的 server 管理器 + 獨立 web UI」,PRD 第 1 章(定位)、第 2 章(使用情境)、第 4 章(功能清單)、第 6 章(非功能需求)、第 8 章(風險)全部要改,競品類比也要換。 +2. **最大的哲學衝突**:原 PRD 的 北極星指標是「內部 FAE 在客戶現場 5 分鐘內跑出第一次推論 ≥ 95%」,現在多一步「要使用者先在桌面 app 按 Start Server → 再點 Open Browser → 瀏覽器才看到 UI」,這對「零摩擦 3 分鐘 demo」體驗是**退步而非進步**,PM 必須先釐清使用者動機,否則會做出一個「技術上更乾淨、但使用體驗更差」的產品。 +3. **目前開發階段是最糟的時機點**:M1-M6 已經做完,dmg 220MB 可跑,M7 Windows build 在收尾。此時做這種方向轉彎代價很高——前端 Sidebar / 4 主導航 / Workspace / Settings 全部要重新思考「誰住在 Wails 裡、誰住在瀏覽器裡」。但如果使用者的動機夠強(見 C1),延後改比現在改更貴。**必須先釐清動機再做決定,不要為了「使用者說了就做」而跳過第一輪分析**。 + +--- + +## A. 變更解讀 + +### A1. 影片來源變更(砍 URL / yt-dlp) + +**新要求**:推論只包含 `camera / image / upload 影片(avi, mpeg, mp4 瀏覽器能吃的格式)`。 + +**PM 解讀**: +- 使用者明確砍掉 `/api/media/url`(YouTube / yt-dlp 相關)。 +- 「瀏覽器能吃的格式」是一個**關鍵措辭**——暗示使用者的 mental model 從「我用桌面 app 解影片」轉向「我用瀏覽器播影片」。這跟 A3 介面變更是同一件事的兩面。 +- 但這裡有個**語意陷阱**:瀏覽器能播的 `