jim800121chen c54f16fca0 Initial commit: visionA monorepo with local-tool subproject
local-tool/: visionA-local desktop app
- M1: Wails shell + Go server + Next.js UI + Mock mode (macOS dmg ready)
- M2: i18n (zh-TW/en) + Settings 4-tab refactor
- M3: Embedded Python 3.12 runtime (python-build-standalone) + KneronPLUS wheels
- M4: Windows Inno Setup script (build on Windows runner)
- M5: Linux AppImage script + udev rule (build on Linux runner)
- M6: ffmpeg (GPL, pending legal review) + yt-dlp bundled
- Lifecycle: watchServer health check, fatal native dialog,
            Wails IPC raise endpoint, stale process cleanup

.autoflow/: full PRD / Design Spec / Architecture / Testing docs
            (4 rounds tri-party discussion + cross review)
.github/workflows/: macOS / Windows / Linux build CI

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 22:10:38 +08:00

11 KiB
Raw Permalink Blame History

M1-3 Review — 改寫 main/config/router + 清 import + module rename

  • 審查者Reviewer Agent
  • 日期2026-04-10
  • 審查對象:/Users/jimchen/visionA/local-tool/server/
  • 依據文件:api-endpoints.md §4removed-code.md §3~§6M1-2-review.md

結論: 通過

M1-3 的所有目標達成module 已改名為 visiona-local/server、四個要刪的檔案全數刪除、CLI flag 對齊規格、router/config/main/handlers/test 全部清乾淨,go build ./...go vet ./... 一次通過。可以直接進入 M1-5。


檢查清單

A. 要刪除的檔案removed-code.md §2

檔案 狀態
internal/api/handlers/cluster_handler.go 已刪除
internal/api/ws/flash_ws.go 已刪除
internal/api/ws/cluster_flash_ws.go 已刪除
internal/api/ws/cluster_inference_ws.go 已刪除

剩餘 internal/api/ws/ 下只剩:device_events_ws.gohub.goinference_ws.goserver_logs_ws.go,符合 api-endpoints.md 中保留的 WebSocket 清單。

剩餘 internal/api/handlers/ 下只剩:camera_handler.godevice_handler.gomodel_handler.gomodel_upload_handler.gosystem_handler.go,乾淨。

B. Module 改名

檢查項 結果
go.mod module 行 module visiona-local/server
grep -rn "edge-ai-platform" server/ --include="*.go" ⚠️ 僅命中 driver/kneron/detector.go L32-33 兩處字串 literal~/.edge-ai-platform/venv/...非 import path
全檔 edge-ai-platform/ import 0 處

detector.go 內的路徑字串是掃描使用者家目錄找既有 Python venv 的 fallback 路徑,不是 module import符合 M1-3 要求(僅 import 需更新)。列為 🟢 備註:等 installer / python runtime 重設計時再調整這兩個 legacy 路徑。

C. CLI flag 對齊config.go

Flag 規格 實際 結果
--mock 必須 bool
--dev 必須 bool
--port 必須 intdefault 3721
--data-dir 必須 string
--python-mode 必須 stringauto/bundled/system
--mock-camera 保留 bool 合理
--mock-devices 保留 int 合理
--log-level 保留 string 合理
--model-dir 保留 string 合理
--host 保留(強制覆寫) stringdefault 127.0.0.1 見 D
--relay-url 必砍 不存在
--relay-token 必砍 不存在
--tray 必砍 不存在
--gui 必砍 不存在

PythonMode 定義為 typed string + 三個常數 + 預設 fallback乾淨且符合 api-endpoints.md §5.2 未來要擴充的規劃。

D. Host 強制 127.0.0.1

config.go L48-49

// 強制 localhost-only
cfg.Host = "127.0.0.1"

確實 override。在 flag.Parse() 之後無條件覆寫,即使使用者傳 --host 0.0.0.0 也會被改回 127.0.0.1。防呆正確。

E. Router 乾淨度api-endpoints.md §4

檢查項 結果
簽章移除 clusterMgrflashSvcrelayToken 三參數
/api/clusters/* routes 0 處
/api/devices/:id/flash 已移除
/api/system/update-check 已移除
/auth/token + OPTIONS 已移除
/ws/devices/:id/flash-progress 已移除
/ws/clusters/* 0 處
保留的 REST routes 與 §4 清單逐項比對 完全符合
保留的 WS routesdevices/events, devices/:id/inference, server-logs 三條都在
grep `clusterMgr flashSvc

F. main.go 清理removed-code.md §3, §4

檢查項 結果
imports 內無 cluster/flash/tunnel/hwid
沒有 tunnelClientclusterMgrflashSvcrelayToken 變數
沒有 relayWebURLopenBrowser 函式
NewSystemHandler 呼叫移除 giteaURL L147 只傳 Version, BuildTime, restartFn
NewRouter 呼叫移除 3 個參數 L150 簽章對齊
保留 graceful shutdown + self-restart exec
保留 killExistingProcess 合理(解決 port 被占用)

G. device_handler.go

檢查項 結果
移除 internal/flash import
移除 FlashDevice handler (檔內已無)
建構子 NewDeviceHandler 不再注入 flashSvc 只收 deviceMgr/inferenceSvc/wsHub
保留 Connect/Disconnect/Scan/List/Get/Start/Stop Inference

H. system_handler.go

檢查項 結果
移除 internal/update import
移除 CheckUpdate handler 與 giteaURL 欄位
保留 Health/Info/Metrics/Deps/Restart

備註api-endpoints.md §1.1 有要求 /api/system/info 擴充 actual_portmodepython_mode 三個欄位,以及新增 /api/system/mode/api/system/python-runtime/api/system/port 三個 endpoint。目前 Info() 只回傳 version/platform/uptime/goVersion,新 endpoint 也尚未新增。但這些是後續 milestoneM2 以後)的工作,不屬於 M1-3 的範圍M1-3 的任務是 清理,不是新增功能)。列入待辦追蹤,不影響本次通過。

I. api_e2e_test.go

檢查項 結果
移除 cluster / flash import
移除 cluster / flash / auth 測試案例 檔內無殘留
setupTestServer 呼叫 NewRouter 簽章對齊 L50-53
保留的測試Health、DeviceWorkflow、DeviceScan、ModelList、ConnectNonExistent、MultiDeviceIsolation

Build 驗證

自己實際跑的結果:

cd /Users/jimchen/visionA/local-tool/server
go build ./...  → exit 0無任何輸出
go vet ./...    → exit 0無任何輸出

完全乾淨,無 compile error、無 vet warning。


針對審查重點 6、7、8 的判斷

6. CORS 中的 X-Relay-Token headermiddleware.go L19

c.Header("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Relay-Token")

判斷:🟢 Minor無害但可清

  • relay-url/relay-token flag、RelayToken config、/auth/token endpoint 都已移除,前端也不會再送這個 header。保留在 CORS allow-list 屬於無害殘留(瀏覽器只會放行,不會主動產生請求)。
  • Backend 的判斷「保留但可清」合理。建議 M1-3 收尾或 M1-5 之前順手改成 "Content-Type, Authorization",避免將來審計時引起疑問,但不阻擋進入 M1-5。

7. internal/driver/ 裡的 Flash / FlashProgress

讀了 internal/driver/interface.godriver/kneron/kl720_driver.go:397 附近、driver/mock/mock_driver.go:68,結論:

  • DeviceDriver 介面的 Flash(modelPath, progressCh)把 .nef 模型載入到 Kneron 裝置的方法,對應 Kneron SDK 的 model load APIkl720_driver.go 的註解明確寫「models can be freely reloaded」並搭配 scripts/kneron_bridge.py)。
  • 這跟已刪除的 internal/flash package韌體燒錄服務完全是兩回事 —— 後者是 firmware flashingKL720 firmware binary → device flash memory前者是 model loading把已訓練好的 .nef 模型丟到裝置的 RAM/ flash 區)。
  • 既然 /api/devices/:id/inference/start 仍然需要先把模型載上去,這個 Flash 方法是必要的,不能刪。

Backend 的判斷正確,列為 無問題。唯一 cosmetic 的點:未來可考慮把 Flash / FlashProgress 改名為 LoadModel / LoadProgress 避免語意混淆,但屬於重構,不在 M1-3 範圍。

8. web/out/placeholder.txt 解法

確認:

  • web/embed.go//go:embed all:out 指向 out/ 目錄
  • 因為 frontend 尚未 build原本 out/ 不存在會導致 go build 失敗M1-2 review 已預警)
  • M1-3 在 out/ 下放了一個 placeholder.txt,讓 embed target 存在build 即可通過

判斷:🟢 合理的最小修補all: 前綴會一起 embed 底線或點開頭的檔案,但 placeholder.txt 不影響實際 static serving因為等 frontend build 完就會覆蓋整個 out/)。簡單、正確、不擾動 embed.go。


問題

🔴 Critical

無。

🟡 Major

無。

🟢 Minor / Suggestion

  1. middleware.go L19 的 X-Relay-Token — 無害殘留,建議之後收尾時清掉:
    c.Header("Access-Control-Allow-Headers", "Content-Type, Authorization")
    
  2. driver/kneron/detector.go L32-33 的 .edge-ai-platform 字串 — legacy 路徑字串,不是 import path不影響 M1-3但未來 installer/python runtime 重設計時應跟著改名(例如改為 .visiona-local/venv/...)。
  3. /api/system/info 尚未擴充 actual_port / mode / python_mode,以及 /api/system/mode/api/system/python-runtime/api/system/port 三個新 endpoint 尚未實作 — 屬於 M2 以後的工作api-endpoints.md §1.1, §5不阻擋 M1-3 / M1-5,但要記得追蹤。
  4. Flash / FlashProgress 命名語意模糊 — 未來重構時可考慮改為 LoadModel / LoadProgress,非必要。

優點

  • Module rename 徹底、Go import 0 殘留,找不到任何 edge-ai-platform/ import path。
  • Router 與 api-endpoints.md §4 的規格逐行對齊,連註解順序都維持原作者風格。
  • config.go 的 Host 強制 override 防呆寫得乾淨flag 還是允許傳入便於開發者習慣,但結尾強制覆寫,二者兼顧)。
  • PythonMode 用 typed string + fallback 預設值,為 M2 的 runtime 切換邏輯鋪好路。
  • api_e2e_test.go 精簡得宜,保留了關鍵 workflow 測試build + 編譯都乾淨(雖然本次沒跑 go test,但 vet 通過代表 test file 的 symbol 引用都對)。
  • killExistingProcess 保留是明智的 — 對本地 daemon 很實用,開發時切換 binary 不會被 stale process 擋住。

可以進入 M1-5build Go binary

可以直接進入 M1-5

理由:

  1. go build ./...go vet ./... 在 reviewer 端重現,皆一次通過。
  2. 所有刪除清單、module rename、router 簽章、CLI flag、Host 強制覆寫都對齊規格。
  3. web/out/placeholder.txt 已解決 M1-2 預警的 embed 編譯障礙,go build 不再卡在 embed target 缺失。
  4. 剩餘的 🟢 項目CORS header、detector 路徑字串、system info 擴充)都不影響 binary 能不能 build也不影響 binary 跑起來的核心功能,可延後處理。

建議 M1-5 時:

  • 跑一次 go test ./... 當作額外保險(本次 review 未跑,僅跑 build + vet
  • 驗證 go build -o visiona-local-server . 產出 binary 並直接執行一次,確認 --mock --dev --port 3721 能成功起 server。
  • 順手把 🟢#1CORS header清掉避免審計疑問。