|
|
d0ab479a7f
|
fix(local-agent): 影片上傳後推論卡「等待第一筆結果」— WS join 才開播 + late-join replay
時序競態:UploadVideo 回 200 即刻 pipeline.Start() 廣播推論結果,但瀏覽器
200 後才連結果 WS。WP-4 上傳改 localhost 直連(極快)、結果 WS 仍走慢 tunnel
→ 窗口放大;Hub 對無 client 的 room 廣播靜默丟棄 → 早期結果全丟、第一筆永遠等不到。
修法(A2 主修 + B 保險,結果面維持走 tunnel、不動 ADR-019 混合路徑):
- A2:UploadVideo 存檔即回 200,但 pipeline 建好不 Start;背景 gated-start
等 WS join inference:<serial> room 後才 Start;15s 逾時降級照舊開跑(不永久卡)
- B:inference room 緩存最近 30 筆,client join 時先 replay 再收 live
(順帶修 image 模式晚連 WS 丟結果的同類 bug)
- CameraHandler 加 startMu:gated goroutine 的 check-then-act(二次檢查 startCtx
→ Start)與 stop 的 cancel+Stop 原子化,消滅「stop 後 gated 又 Start 舊 pipeline」race
reviewer 通過(Major-1 修復複審 ✅)。14 test -race 全過(含 3000 輪併發 atomicity
測試)、gosec 改的檔 0 新 finding。serial room key 兩端同形已查證排除。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
2026-08-02 03:16:05 +08:00 |
|
|
|
9031153553
|
feat(adr-019): 影片/圖片/批次上傳走同機 localhost 直連 local-agent
實作 ADR-019 混合路徑:影片/圖片/批次的檔案上傳改由瀏覽器同機直連
local-agent localhost endpoint(繞過雲端 tunnel),控制面 + MJPEG 結果 +
推論 WS 仍走 tunnel。解決大檔頻寬雙倍 + nginx 100M + 300s timeout。
三條 stream(全數過 reviewer + security code-level 複審 APPROVED):
local-agent(Go):
- CORS 雲端 origin 完整精確比對 + Allow-Credentials:false + HostGuard(loopback)
+ PNA header(middleware.go)
- 新 route /api/local/media/upload/*(一律要 token、不看 Origin,關 C1 後門)
- one-time token store(crypto/rand、TTL 120s、綁 deviceId、single-flight consume、
上限 32→429;200 goroutine -race 綠)
- GET /api/local/hello(回 salted SHA-256 serialHashes、最小揭露)
+ POST /api/local/issue-token(Host-based)
- LocalUploadGuard(token+size 驗證放 FormFile 前);video≤500MB / batch 合計 80MB
→ 413;stopActivePipeline + batch 生命週期 temp 檔清理
cloud(visionA-backend):
- POST /api/devices/:serial/local-upload-ticket(OIDC + 裝置歸屬 + 經 tunnel
轉發 issue-token;IDOR-safe、錯誤不洩漏)
frontend(visionA-frontend):
- lib/local-agent.ts(port 探測 3721-3740 並發+快取、Web Crypto serial hash 比對
同機判定、uploadToLocalAgent 通用函式)
- validateBatchFiles 合計大小檢查(MAX_BATCH_TOTAL_BYTES=80MB,消 50×19MB 撞 413 地雷)
回歸:ADR-019 相關 270 測試全綠、既有 tunnel 路徑未被打斷、無 regression。
既有 tunnel(無 Origin)不要求 token(C1 route 分離相容性保證)。
Refs: ADR-019。WP-0(PNA 實機)/WP-4(影片分頁接線)下一批。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
2026-07-30 12:32:26 +08:00 |
|
|
|
fac07c39d0
|
fix(local-agent): 配對前自動 rescan USB,解序號偵測時序問題
問題:配對時 exchange 撈 GET /api/devices(ListDevices=讀快取、不重新
偵測)。若 agent 啟動時 USB 尚未插入/未偵測到,快取為空 → 配對撈不到
序號 → payload 不帶 devices → 雲端裝置「尚未回報序號」,即便之後插上
USB 也不會自動重偵測。
修法(方案 A、最小侵入):
- NewLocalDeviceLister 改打 POST /api/devices/scan(ScanDevices →
Manager.Rescan() 重新偵測 USB),配對前強制重掃一次
- localDeviceListTimeout 2s → localDeviceScanTimeout 8s(真 SDK scan
kp.core.scan_devices 較慢、給餘裕,逾時走 fallback 不卡配對)
- app.go DeviceLister 注入註解同步更新(Reviewer Mi-1)
不變量保留(Reviewer 獨立驗證):
- rescan 失敗/逾時 → lister return nil(不 error)→ payload omit devices
→ 配對照常(序號是加值資訊,不中斷配對)
- Rescan 對序號身分未變的 session 保持連線(serialIdentity 相等 continue)、
只斷被拔除的 → 不誤斷在線 tunnel/inference session
- Pair 由 lifecycleMu 序列化、Rescan write lock 全量重建 → 重試冪等安全
Reviewer 通過(0C/0M/1Mi/2Sug)。兩 module build/vet/test/race 全綠、
8 個新 tunnel 行為測試 PASS(端到端快取空→rescan→序號進 payload +
逾時 fallback)、gitleaks 0。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
2026-07-16 15:02:31 +08:00 |
|
|
|
fc7e1e0bc1
|
fix(local-agent): 修 vendor wheels 多版本累積導致 SDK 沒裝進 bundled runtime
根因:Makefile vendor-wheels 用 pip download --dest 只加不清空,跨多次
vendor-sync 累積出同套件多版本(certifi 三版/numpy 二版等共 17 wheel)→
agent bootstrap 的 ensureBundledPython 把目錄所有 .whl 當獨立參數丟 pip
install → 版本衝突 ResolutionImpossible → pip 失敗 → venv 建了但空 →
無 Kneron PLUS SDK → bridge scan 走 pyusb fallback 回假序號 0x00000000 →
裝置「尚未回報序號」+ 載入模型 device not connected。
修法(3 個 vendor-wheels target):
- 開頭 rm -f vendor/wheels/<plat>/*.whl 清空,確保每次 sync 單版本
- 結尾 dedup 驗證(sort|uniq -d 偵測多版本 → exit 1 fail-fast)
- linux 補「無專屬 KneronPLUS wheel 時退回複製 macos py3-none-any」
- .gitignore 補 local-agent/vendor|payload|dist 對稱規則(保留 ffmpeg
binary + .gitkeep 例外),防 vendor-sync 後 git add -A 撈進 build 產物
決定性 evidence(agent 實際 bundled runtime):清空 runtime → 起剛 build
的 .app → agent 自己 bootstrap 裝 9 個乾淨單版 wheel(修前 17 含重複必失敗)
→ venv 有 kp → GET /api/devices 回真序號 0xB906162C(非 0x00000000)。
Reviewer 通過(0C/0M/4Mi/3Sug)。win/linux 同邏輯已補、未在對應 runner
驗證(已知限制)。follow-up:ensureBundledPython 列舉 wheel 脆弱設計建議
改 find-links 自解析(backend 另案)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
2026-07-16 14:21:08 +08:00 |
|
|
|
26b433eb10
|
fix(local-agent): review follow-up 小批(TLS Mi-3/4 + WP-0 S-3/4)
- Mi-3: insecure Transport 改用 DefaultTransport.Clone() 只覆寫 TLSConfig
(保留 proxy/timeout,消除「開 skip 順便改掉 proxy 行為」副作用)
- Mi-4: exchange 200 分支檢查 Success 欄位(避免 200+success:false 落到
誤導性的 missing session_token;既有回歸測試改用直接斷言防護不減反增)
- S-3: collectLocalDevices 全空 serial 濾掉不送 devices 陣列(payload 對稱)
- S-4: 假序號比對統一用 EqualFold(防未來 bridge 輸出 casing 變化)
Reviewer 通過(0C/0M/1Mi/3Sug)。兩 module build/vet/test + -race 綠、
gitleaks 0、TLS 行為級測試全 PASS。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
2026-07-16 11:40:35 +08:00 |
|
|
|
12b1fe3bad
|
fix(local-agent): Rescan 序號身分比對替換 stale session + 鎖外 Disconnect
- serialIdentity() 三態比對(空/假序號 0x00000000 正規化為無身分、對齊
ADR-018 R2):Rescan 對既存合成 ID 比對身分——同一顆保留 live session、
換位/拔插以新 info 替換 session,serial 索引重建即正確
- stale drivers 改釋放鎖後 Disconnect(不再阻塞 GetDevice 路由)+
Disconnect 錯誤改 WARNING log
- 測試 seam:detectFn/newDriverFn 注入 + newSessionDriverLocked 統一建構
(Start 行為零變動);新 4 支行為級測試(拔除位移/換位 rebind/
同序號保 session/無身分回歸)
- evidence:build/vet/test 全綠 + -race ok;review 通過 0C/0M/0Mi/4Sug
(wp0-serial-routing-review.md「Minor #1 修復審查」章節)
- WP-C 阻擋項解除;觀察項:多裝置實測留意 changed identity log
(偵測順序抖動時解法在 detector 端排序)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-07-10 09:44:47 +08:00 |
|
|
|
b9ee184586
|
feat(device): WP-0 序號串通 + serial 路由(ADR-018 走向 A' 第一階段)
- local-agent/server:detector 保留 kn_number(parseScanDevices 可測化、
合成 ID 語意不動)+ DeviceInfo.SerialNumber + Manager serialToLocalID
反查表 + GetDevice 雙查(sessions 先、serial 後,純加法)
- visiona-agent:pairing exchange 帶本地裝置清單(DeviceLister 失敗不中斷
配對、timeout 2s、omitempty 舊版相容)
- visionA-backend:exchange 收 devices —— R1 取第一顆可用序號、R2 假序號
0x00000000 寫 NULL、R4 同 owner 同序號復用既有 device_id(防 23505)、
pg+mem 兩實作對齊
- 五個 proxy 操作(flash/inference/camera/connect/disconnect)收斂於
GetDevice 單一入口,serial 路由一處涵蓋
- docs:api-spec.md §2 增補 POST /api/pairing/exchange(schema + R1/R2/R4)
- 測試:行為級四環節鏈 + dbtest 130 實跑 6/6 + DBOn 回歸 4/4;
三 module build/vet/test 全綠
- review:通過 0C/0M/6Mi/5Sug(.autoflow/05-implementation/review/
wp0-serial-routing-review.md);Minor #1 Rescan stale session 掛 WP-C 前置
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-07-10 09:31:51 +08:00 |
|
|
|
3d30fdc580
|
feat(local-agent): TLS skip opt-in for self-signed stage + exchange envelope 對齊
- 新增 VISIONA_INSECURE_SKIP_TLS_VERIFY(DEV/TEST ONLY、須明確 opt-in "true"):
pairing exchange HTTP client、tunnel WSS dialer、設定頁 TestConnection 三路徑
共用 TLSConfigForDial(含 ALPN 釘 http/1.1);NewApp 唯一 env 讀取點注入欄位
- exchangeResponse 對齊雲端 /api/pairing/exchange success envelope
(account/relay_url 選填 fallback 保留、舊頂層格式回歸防護)
- .gitignore:.env.stage* + !.env.stage.example + *.pptx(堵 secrets 誤入)
- start-agent.sh(新增):public 模式 export skip env + 預檢 curl https 帶 -k
- 測試:自簽 TLS server 行為級(預設拒絕驗 x509 / 開啟通過)+ opt-in 規則
11+5 案例 + TestConnection 3 測試;go build/vet/test 3 packages 全綠
- review:2 輪通過(.autoflow/05-implementation/review/tls-skip-uncommitted-batch-review.md)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-07-10 09:01:10 +08:00 |
|
|
|
72672972c8
|
chore(local-agent): 從 git 移除誤 commit 的 wails build binary(10MB Mach-O)
3f0175f commit local-agent/ 時連帶把 wails build 出的執行檔
local-agent/visiona-agent/visiona-agent(10MB Mach-O 64-bit x86_64)
一起進 git,違反「build artifact 不進 git」原則:
- 可重新產生:source 已在 git,clone 後 wails build 即可
- 平台特定:x86_64 macOS 執行檔對其他平台無用
- repo 變胖:git history 永遠保留這 10MB
修法:
- git rm --cached(保留磁碟上檔案,下次 wails build 還會用)
- local-agent/.gitignore 補 /visiona-agent/visiona-agent 防再犯
注意:3f0175f 的 history 仍含此 binary,徹底清除需 git filter-repo
(local-only repo、未 push、暫不處理)。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-05-01 18:29:22 +08:00 |
|
|
|
3f0175f1a9
|
feat(local-agent): Phase 0.5 visionA Agent — Wails 桌面 + tunnel client + 配對 UI
從 local-tool 複製出獨立的「visionA Agent」桌面應用(A3 純橋樑:
tunnel client + 配對 UI + 設定,不開 HTTP port、不做本機裝置/推論 UI)。
Bundle ID 與 local-tool 不同(com.innovedus.visiona-agent vs visiona-local),
雙 app 可共存。fork 後不主動 sync,需要時手動 cherry-pick。
Backend / Wails Go(AB1-AB13):
- internal/tunnel:6 狀態機(Idle/Connecting/Connected/Reconnecting/Failed/Stopped)
+ Pair/Unpair/Reconnect/Disconnect binding + ClientHooks event
- internal/auth:encrypted file token store(AES-GCM + scrypt + machineID
fallback salt + 13 tests)
- internal/config:YAML validation + atomic write + 11 tests
- internal/log:ring buffer + ExportLog 升級 zip
- visionA-backend /api/pairing/exchange:SessionTokenStore + 17 new tests
- 三平台 build 驗證(macOS DMG 160 MB / Windows EXE / Linux AppImage)
- end-to-end 5 milestone 全綠(pairing → tunnel → forward → reuse 防護
→ tunnel drop failover)
Frontend / Next.js(AF1-AF7,沿用 visionA-frontend 基礎):
- AppShell + Header + TabNav(StatusView / PairView / SettingsView 三 tab)
- ConnectionStatusBadge 5 種狀態
- TokenInput regex 驗證 + 7 種錯誤 + 0.5s auto-switch 到狀態頁
- 設定頁 4 區塊(含重新配對 AlertDialog)
- agent-api.ts 封裝 Wails bindings(mock/real 雙實作)+ 90 tests
Phase 0.7 review-driven fix(Round 2):
- A1 Session fixation 防護(RotateSessionID)
- A3 mock pairing 預設改 false(必須明確 opt-in)+ startup log
- A4 Pair 失敗後 state 清理矩陣(exchange/Save/Start fail 各自終態)
- A5 Pair/Unpair/Reconnect lifecycleMu + 50 goroutine race test
- F1 重新配對次按鈕 / F2 PairView Esc cancel / F3 Wails BrowserOpenURL
/ F4 Settings draft 持久 + 未儲存 badge
驗證:agent backend go test -race -count=3 ./... 4 packages 全綠 /
agent frontend pnpm test 119 tests 全綠
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-05-01 11:22:01 +08:00 |
|