- 統一目錄名為 local-tool(連字號),修正所有文件中殘留的底線版本 - 新增 scripts/bootstrap-linux.sh 與 scripts/bootstrap-windows.ps1 一鍵安裝依賴(Go/Node/pnpm/Wails/MSYS2)並執行 payload + installer build Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
11 KiB
11 KiB
Code Reuse Plan — visionA-local
從
/Users/jimchen/Innovedus/edge-ai-platform/edge-ai-platform/取用程式碼的完整對照表。 三種策略:直接複製、改寫、新寫。
1. 總體比例(預估)
- 直接複製:~60% LOC
- 改寫:~20%
- 新寫:~20%
- 刪除:獨立計算,見
removed-code.md
2. 目錄層級策略
| From(edge-ai-platform) | To(local-tool) | 策略 | 備註 |
|---|---|---|---|
server/main.go |
server/main.go |
改寫 | 移除 cluster / tunnel / relay / hwid / gitea 邏輯 |
server/go.mod |
server/go.mod |
改寫 | 移除不再需要的 imports;module name 可改為 visiona-local |
server/go.sum |
server/go.sum |
改寫 | 跟著 go.mod 重新生成 |
server/internal/api/router.go |
server/internal/api/router.go |
改寫 | 見 api-endpoints.md §4 |
server/internal/api/middleware.go |
同路徑 | 直接複製 | |
server/internal/api/handlers/ |
同路徑 | 部分複製 / 改寫 | 見下方 §3.1 |
server/internal/api/ws/ |
同路徑 | 部分複製 / 改寫 | 見下方 §3.2 |
server/internal/api/api_e2e_test.go |
同路徑 | 改寫 | 刪除 cluster / flash / auth test case |
server/internal/camera/ |
同路徑 | 直接複製 | 除了 ffmpeg 路徑查找改為「優先 bundled」,見 §3.4 |
server/internal/config/config.go |
同路徑 | 改寫 | 見 §3.3 |
server/internal/deps/ |
同路徑 | 改寫 | 移除 update / relay 相關檢查 |
server/internal/device/ |
同路徑 | 直接複製 | 核心裝置管理 |
server/internal/driver/ |
同路徑 | 直接複製 | |
server/internal/inference/ |
同路徑 | 直接複製 | |
server/internal/model/ |
同路徑 | 直接複製 | |
server/internal/flash/ |
❌ 刪除 | 使用者決策 Q9 | |
server/internal/cluster/ |
❌ 刪除 | 使用者決策 | |
server/internal/tunnel/ |
❌ 刪除 | 使用者決策 | |
server/internal/update/ |
❌ 刪除 | 使用者決策 Q6 | |
server/pkg/logger/ |
同路徑 | 直接複製 | |
server/pkg/hwid/ |
❌ 刪除 | 只給 relay 用的 | |
server/cmd/relay-server/ |
❌ 刪除 | 不需要 relay | |
server/tray/ |
❌ 刪除 | 使用者決策 Q-A=A3:砍掉 tray,省跨平台圖資產與 Wails tray 踩坑 | |
server/scripts/kneron_bridge.py |
server/scripts/kneron_bridge.py |
直接複製 | |
server/scripts/requirements.txt |
同路徑 | 直接複製 | |
server/scripts/update_kl720_firmware.py |
❌ 刪除 | flash 已砍 | |
server/scripts/firmware/ |
❌ 刪除 | 同上 | |
server/data/models.json |
同路徑 | 直接複製 | |
server/data/nef/kl520/ |
同路徑 | 直接複製 | 全部預置模型 |
server/data/nef/kl720/ |
同路徑 | 直接複製 | |
server/web/ |
同路徑(空目錄) | 直接複製 | go:embed 掛載點 |
frontend/ |
frontend/ |
改寫 | M1 就要清乾淨:刪除 cluster / relay / tunnel 相關頁面、元件、store、API client,讓 pnpm build 通過且 UI 乾淨(使用者決策 Q-C=C2) |
installer/ |
visiona-local/ |
改寫(改名 + 精簡) | 見 §3.5 |
installer/wheels/ |
vendor/wheels/ 或 visiona-local/payload/scripts/wheels/ |
直接複製 | KneronPLUS wheel |
installer/drivers/ |
vendor/drivers/ 或 visiona-local/payload/drivers/ |
直接複製 | Windows WinUSB |
installer/payload/ |
visiona-local/payload/ |
結構沿用,內容重建 | 由 Makefile payload target 重新 stage |
Makefile |
Makefile |
改寫 | 見 build-pipeline.md |
docker/ |
❌ 刪除 | ||
scripts/deploy-*.sh |
❌ 刪除 | ||
scripts/kneron_detect.py |
server/scripts/kneron_detect.py |
直接複製 | installer 裝置偵測用 |
tools/ |
視檔案決定 | 多數刪除 | 只保留開發相關的 script |
docs/ |
❌ 刪除(之後重寫) |
3. 需要改寫的檔案細節
3.1 server/internal/api/handlers/
| 檔案 | 策略 | 動作 |
|---|---|---|
system_handler.go |
改寫 | 移除 CheckUpdate、giteaURL 參數;刪除 update-check handler |
model_handler.go |
直接複製 | |
model_upload_handler.go |
直接複製 | |
device_handler.go |
改寫 | 移除 FlashDevice handler 與 flashSvc 注入 |
camera_handler.go |
直接複製 | 但 StartFromURL 內部的 yt-dlp 路徑查找改為 bundled(見 §3.4) |
cluster_handler.go |
❌ 刪除 |
3.2 server/internal/api/ws/
| 檔案 | 策略 |
|---|---|
hub.go |
直接複製 |
device_events.go |
直接複製 |
server_logs.go |
直接複製 |
inference.go |
直接複製 |
flash_progress.go |
❌ 刪除 |
cluster_*.go |
❌ 刪除 |
3.3 server/internal/config/config.go 改寫版
package config
import (
"flag"
"fmt"
"os"
"path/filepath"
)
type Config struct {
Port int
Host string
MockMode bool
MockCamera bool
MockDeviceCount int
LogLevel string
DevMode bool
PythonBin string // 新增:由 Wails app 傳入
ScriptsDir string // 新增
DataDir string // 新增
// ❌ 以下全部移除:
// RelayURL, RelayToken, GUIMode, GiteaURL
}
func Load() *Config {
cfg := &Config{}
flag.IntVar(&cfg.Port, "port", 3721, "Server port")
flag.StringVar(&cfg.Host, "host", "127.0.0.1", "Server host (always localhost)")
flag.BoolVar(&cfg.MockMode, "mock", false, "Enable mock device driver")
flag.BoolVar(&cfg.MockCamera, "mock-camera", false, "Enable mock camera")
flag.IntVar(&cfg.MockDeviceCount, "mock-devices", 1, "Number of mock devices")
flag.StringVar(&cfg.LogLevel, "log-level", "info", "Log level")
flag.BoolVar(&cfg.DevMode, "dev", false, "Dev mode")
flag.StringVar(&cfg.PythonBin, "python", "", "Path to python3 interpreter")
flag.StringVar(&cfg.ScriptsDir, "scripts-dir", "", "Path to scripts directory")
flag.StringVar(&cfg.DataDir, "data-dir", "", "Path to data directory")
flag.Parse()
// 合理 default(dev 模式)
if cfg.ScriptsDir == "" {
cfg.ScriptsDir = filepath.Join(".", "scripts")
}
if cfg.DataDir == "" {
cfg.DataDir = filepath.Join(".", "data")
}
return cfg
}
func (c *Config) Addr() string {
return fmt.Sprintf("%s:%d", c.Host, c.Port)
}
3.4 ffmpeg / yt-dlp 路徑查找
新增 server/internal/camera/binaries.go:
package camera
import (
"os"
"path/filepath"
"runtime"
)
// FfmpegBinary returns the ffmpeg binary to use, preferring bundled over PATH.
func FfmpegBinary() string {
if p := os.Getenv("VISIONA_FFMPEG"); p != "" {
return p
}
if p := bundled("ffmpeg"); p != "" {
return p
}
return "ffmpeg" // PATH fallback
}
func YtDlpBinary() string {
if p := os.Getenv("VISIONA_YTDLP"); p != "" {
return p
}
if p := bundled("yt-dlp"); p != "" {
return p
}
return "yt-dlp"
}
func bundled(name string) string {
exe, err := os.Executable()
if err != nil {
return ""
}
dir := filepath.Dir(exe)
candidate := filepath.Join(dir, name)
if runtime.GOOS == "windows" {
candidate += ".exe"
}
if _, err := os.Stat(candidate); err == nil {
return candidate
}
return ""
}
3.5 installer/app.go → visiona-local/app.go 改寫
原 894 行,改寫要點:
移除的欄位 / 函式:
relayURL,relayToken,dashboardURLGetDashboardURL,GenerateToken,OpenBrowser中任何跟 relay 有關的邏輯stepInstallUSBDriver需要保留,但只給 Windows 用(flash driver 已砍但 WinUSB 還需要)stepInstallFfmpeg改寫:不去系統 PATH 找,而是從 payload/bin 解壓 bundled ffmpeg
新增的欄位 / 函式:
pythonMode(bundled/system/auto)stepSetupPythonStandalone(解壓內嵌 python-build-standalone)stepSetupPythonSystem(fallback 到系統 python,沿用舊的setupPythonVenv邏輯)stepInstallWheelsOffline(用pip install --no-index --find-links)i18ntranslator 注入launchServer/stopServer/watchServer(見tray-and-lifecycle.md§4)single-instance lock
保留(幾乎不動):
GetSystemInfo,BrowseDirectory,ValidatePathstepCreateDir,stepExtractBinary,stepExtractData,stepExtractScriptsDetectHardware,parseDetectOutputextractFile,extractDir- Platform-specific 檔案(
platform_darwin.go/platform_linux.go/platform_windows.go)
4. 新寫的程式碼
完全新寫的檔案:
4.1 Wails app 側
visiona-local/
├── python_runtime.go ← python-build-standalone 解壓 + 版本偵測
├── server_launcher.go ← spawn / stop / watch Go server
├── lifecycle.go ← single-instance lock、port picking、cleanup
├── ipc.go ← /ipc/raise 小型 HTTP listener
├── i18n.go ← Translator + locales embed
└── locales/
├── en.json
└── zh-TW.json
4.2 Build / CI
scripts/
├── vendor-sync.sh ← 下載 python-build-standalone、ffmpeg、yt-dlp 到 vendor/
├── build-appimage.sh ← Linux AppImage 打包腳本
├── check-i18n.sh ← 檢查 i18n key 一致性
└── smoke-test.sh ← 安裝後 smoke test
visiona-local-installer.iss ← Inno Setup 腳本
dmg-config.py ← macOS dmgbuild 設定
.github/workflows/release.yml ← CI(選配)
5. 搬家步驟(建議執行順序)
- 建立骨架:
mkdir -p local-tool/{server,frontend,visiona-local,vendor,scripts,dist} - 複製 server core:
cp -r edge-ai-platform/server/{internal/{api,camera,config,deps,device,driver,inference,model},pkg/logger,scripts,data,web} local-tool/server/ - 跳過要刪的 package:不要複製
cluster、tunnel、flash、update、pkg/hwid、cmd/relay-server、tray(使用者決策 Q-A:砍 tray) - 改寫
main.go+config.go+router.go(見上方 §3) - 改寫 go.mod:
go mod init visiona-local/server→go mod tidy(會自動清掉 unused imports) - 驗證
go build ./...通過 - 複製 frontend:
cp -r edge-ai-platform/frontend local-tool/frontend - 清理前端 cluster / relay / tunnel UI(使用者決策 Q-C=C2:M1 就要清乾淨,不留到 M2):刪除
src/app/clusters/、src/app/workspace/cluster/、src/components/cluster/、src/components/relay-token-sync.tsx、src/lib/api/clusters.ts、src/lib/api/tunnel.ts(若有)、src/lib/api/update.ts(若有),修改sidebar.tsx移除 Clusters 導航項、page.tsx移除 cluster stat、settings/page.tsx移除 relay / cluster 區塊。最後驗證pnpm build通過且 UI 乾淨。 - 複製 installer:
cp -r edge-ai-platform/installer local-tool/visiona-local,改main.go的 app 名稱與 bundle ID - 先跑 M1-12:全新機器上 installer 能裝起來並跑通 Mock 模式