feat: serialize public hardware execution

This commit is contained in:
vee
2026-08-03 09:25:38 +08:00
parent a6d974cb29
commit 85b4740d29
10 changed files with 308 additions and 16 deletions
+23 -6
View File
@@ -2790,8 +2790,11 @@ async function loadRuntime() {
const profileText = (hardware.firmware_profiles || []).join(" / ") || "未选择 profile";
const flashText = hardware.auto_flash_enabled ? "自动烧录已启用" : "自动烧录未启用";
const approvalText = hardware.approval_required ? "需授权令牌" : "调试免令牌";
const concurrencyText = hardware.concurrency_policy === "single_flight_fail_fast"
? " · 单请求独占"
: "";
$("#hardwareNote").textContent = hardware.configured
? `${hardware.backend} · ${hardware.bitrate / 1000} kbit/s · ${profileText} · ${flashText} · ${approvalText}`
? `${hardware.backend} · ${hardware.bitrate / 1000} kbit/s · ${profileText} · ${flashText} · ${approvalText}${concurrencyText}`
: `真实执行已锁定:${profileText};请完成服务端启用、适配器、固件镜像${hardware.approval_required ? "和令牌" : ""}配置`;
$("#hardwareAliasNote").textContent = "副驾座椅 → t2g_primary_seat(统一电机、加热和通风执行器)";
$("#autoFlashNote").textContent = hardware.auto_flash_enabled
@@ -2802,7 +2805,7 @@ async function loadRuntime() {
? '<i data-lucide="shield-check"></i>硬件已配置'
: '<i data-lucide="shield-off"></i>硬件锁定';
$("#hardwareCoverage").textContent = hardware.configured
? `可选 · ${approvalText}`
? `可选 · ${approvalText}${concurrencyText}`
: "已阻断";
$("#hardwareCoverage").className = hardware.configured ? "available" : "blocked";
const modeAvailable = state.executionMode === "hardware"
@@ -3684,7 +3687,14 @@ async function submitRequest(event) {
window.location.replace("/login");
return;
}
if (!response.ok) throw new Error(payload.message || payload.error || `HTTP ${response.status}`);
if (!response.ok) {
const requestError = new Error(payload.message || payload.error || `HTTP ${response.status}`);
requestError.code = payload.error;
requestError.retryAfter = Number(
payload.retry_after_seconds || response.headers.get("Retry-After") || 0,
);
throw requestError;
}
renderResult(payload);
if (state.executionMode === "hardware") {
await synchronizePhysicalSeatState();
@@ -3701,9 +3711,16 @@ async function submitRequest(event) {
} catch (error) {
window.clearInterval(state.progressTimer);
resetPipeline();
setRunStatus("failed", "FAILED");
$("#resultTitle").textContent = "请求处理失败";
showToast(error.message);
if (error.code === "hardware_busy") {
setRunStatus("failed", "BENCH BUSY");
$("#resultTitle").textContent = "真实台架正在使用";
const retryHint = error.retryAfter > 0 ? ` 建议 ${error.retryAfter} 秒后重试。` : "";
showToast(`${error.message}${retryHint}`);
} else {
setRunStatus("failed", "FAILED");
$("#resultTitle").textContent = "请求处理失败";
showToast(error.message);
}
} finally {
button.disabled = false;
button.classList.remove("loading");
+1 -1
View File
@@ -15,7 +15,7 @@
<script src="/vendor/three/0.147.0/fflate.min.js" defer></script>
<script src="/vendor/three/0.147.0/FBXLoader.js" defer></script>
<script src="/network.js?v=android-pad-1" defer></script>
<script src="/app.js?v=seat-hil-7" defer></script>
<script src="/app.js?v=seat-hil-8" defer></script>
<script type="module" src="/gesture-control.js?v=android-pad-1"></script>
<script src="/pwa.js?v=android-pad-1" defer></script>
</head>
+2 -2
View File
@@ -1,4 +1,4 @@
const CACHE_VERSION = "cognitive-agent-pad-v7";
const CACHE_VERSION = "cognitive-agent-pad-v8";
const SHELL_CACHE = `${CACHE_VERSION}-shell`;
const RUNTIME_CACHE = `${CACHE_VERSION}-runtime`;
const APP_SHELL = [
@@ -6,7 +6,7 @@ const APP_SHELL = [
"/index.html",
"/styles.css?v=android-pad-2",
"/network.js?v=android-pad-1",
"/app.js?v=seat-hil-7",
"/app.js?v=seat-hil-8",
"/gesture-control.js?v=android-pad-1",
"/pwa.js?v=android-pad-1",
"/manifest.webmanifest",