/** * 硬體相容性檢查 — visionA Cloud(flash 前的 UX 早警示) * * 移植自 POC edge-ai-platform/frontend/src/lib/hardware-compat.ts(唯讀參考、非搬 code)。 * * ⚠️ 與 POC 的關鍵契約差異(見 flash-model-load-mapping.md §2.3-C): * - POC model 用 `supportedHardware: string[]`(多值陣列),比對「device 晶片 ∈ 陣列」。 * - visionA model 只有 `targetChip: TargetChip`(單值,見 model-store.ts:33),故改為單值比對。 * * 定位(重要):**這只是前端 UX 早警示**,避免使用者選了不相容 model 才 POST 被拒。 * 真正的權威把關在 local agent(`flash/service.go isCompatible`)——即使前端誤放行, * agent 仍會擋。因此前端邏輯**寧鬆勿嚴**(無法判定時預設相容),避免誤擋合法組合。 * * device.type 來源多樣(local agent 回報值 / 後端正規化值),可能是: * - `kneron_kl520` / `kneron_kl720` …(driver type 前綴) * - `KL520` / `kl520`(大小寫混用) * 這裡統一正規化到小寫晶片代號(`kl520`…),與 `TargetChip` 對齊後比對。 */ import type { TargetChip } from "@/stores/model-store"; /** * 把 device.type 正規化成小寫晶片代號(如 `kl520`)。 * 無法辨識時回傳原字串的小寫,交由呼叫端寬鬆處理(寧鬆勿嚴)。 */ export function getChipFromDeviceType(deviceType: string): string { if (!deviceType) return ""; const lower = deviceType.toLowerCase(); // 抓出 kl 後接 3 碼數字的晶片代號(涵蓋 `kneron_kl520` / `KL520` / `kl-520` 等變體)。 const match = lower.match(/kl\s*[-_]?\s*(\d{3})/); if (match) return `kl${match[1]}`; return lower; } /** * 判斷 model(單一 targetChip)是否與 device 相容。 * * 寧鬆勿嚴規則(前端只做早警示、權威在 agent): * - model.targetChip 為 `unknown` → 視為相容(無法判定,不擋)。 * - device.type 無法辨識出晶片代號 → 視為相容(無法判定,不擋)。 * - 兩者都可辨識 → 嚴格比對晶片代號是否相同。 */ export function isModelCompatible( targetChip: TargetChip, deviceType: string, ): boolean { if (targetChip === "unknown") return true; const deviceChip = getChipFromDeviceType(deviceType); // device 端無法辨識晶片 → 不擋(交給 agent 權威把關)。 if (!deviceChip.startsWith("kl")) return true; return deviceChip === targetChip; } /** * 給 UI 顯示用的裝置晶片代號(大寫,如 `KL520`);無法辨識時回傳原字串。 */ export function getHardwareLabel(deviceType: string): string { const chip = getChipFromDeviceType(deviceType); if (chip.startsWith("kl")) return chip.toUpperCase(); return deviceType || ""; }