feat: improve mode and peripheral orchestration
This commit is contained in:
+19
-1
@@ -17,6 +17,8 @@ function createConversationId() {
|
||||
return createOpaqueId("conv");
|
||||
}
|
||||
|
||||
const HARDWARE_CLIENT_ID_PATTERN = /^hwc-[a-z0-9-]{8,80}$/;
|
||||
|
||||
function loadConversationId() {
|
||||
const stored = sessionStorage.getItem("cognitive-agent.conversation-id");
|
||||
// A browser runtime restart is a new virtual run. Do not reuse the old
|
||||
@@ -33,12 +35,19 @@ function loadConversationId() {
|
||||
function loadHardwareClientId() {
|
||||
const key = "cognitive-agent.hardware-client-id";
|
||||
const stored = localStorage.getItem(key);
|
||||
if (/^hwc-[a-z0-9-]{8,80}$/.test(stored || "")) return stored;
|
||||
if (HARDWARE_CLIENT_ID_PATTERN.test(stored || "")) return stored;
|
||||
const clientId = createOpaqueId("hwc");
|
||||
localStorage.setItem(key, clientId);
|
||||
return clientId;
|
||||
}
|
||||
|
||||
function validatedHardwareClientId() {
|
||||
if (!HARDWARE_CLIENT_ID_PATTERN.test(state.hardwareClientId || "")) {
|
||||
state.hardwareClientId = loadHardwareClientId();
|
||||
}
|
||||
return state.hardwareClientId;
|
||||
}
|
||||
|
||||
function loadControlTransport() {
|
||||
const stored = localStorage.getItem("cognitive-agent.control-transport");
|
||||
return ["wired_can", "wireless_mqtt"].includes(stored) ? stored : "wired_can";
|
||||
@@ -5131,6 +5140,7 @@ const MODE_DOMAIN_LABELS = {
|
||||
window: "车窗",
|
||||
front_light: "车灯",
|
||||
vehicle_status: "车辆状态",
|
||||
android: "车机媒体",
|
||||
};
|
||||
|
||||
const MODE_TARGET_LABELS = {
|
||||
@@ -5140,6 +5150,7 @@ const MODE_TARGET_LABELS = {
|
||||
front_right: "右前 / 副驾",
|
||||
rear_left: "左后",
|
||||
rear_right: "右后",
|
||||
headunit: "车机",
|
||||
front_row: "前排",
|
||||
rear_row: "后排",
|
||||
vehicle: "全车",
|
||||
@@ -8241,6 +8252,7 @@ const CONFIG_DOMAIN_META = {
|
||||
window: { label: "车窗", icon: "panels-top-left", className: "generic" },
|
||||
outlet: { label: "电动风口", icon: "wind", className: "climate" },
|
||||
interior_light: { label: "车内灯", icon: "lightbulb", className: "ambient" },
|
||||
android: { label: "车机媒体", icon: "clapperboard", className: "generic" },
|
||||
};
|
||||
|
||||
const CONFIG_CAPABILITY_LABELS = {
|
||||
@@ -8286,6 +8298,7 @@ const CONFIG_CAPABILITY_LABELS = {
|
||||
"roof.set_shade_position": "设置遮阳帘位置",
|
||||
"roof.set_shade_motion": "控制遮阳帘动作",
|
||||
"roof.set_automatic_dimming": "设置自动调光",
|
||||
"android.launch_app": "打开视频媒体",
|
||||
};
|
||||
|
||||
const CONFIG_PARAMETER_LABELS = {
|
||||
@@ -8309,6 +8322,8 @@ const CONFIG_PARAMETER_LABELS = {
|
||||
outlet_mode: "出风模式",
|
||||
mode: "工作模式",
|
||||
mode_id: "固件模式编号",
|
||||
package_name: "应用包名",
|
||||
activity_name: "启动页面",
|
||||
};
|
||||
|
||||
function makeConfigElement(tagName, className, textValue) {
|
||||
@@ -9412,6 +9427,9 @@ window.CognitiveAgentConsole = {
|
||||
getExecutionMode() {
|
||||
return state.executionMode;
|
||||
},
|
||||
getHardwareClientId() {
|
||||
return validatedHardwareClientId();
|
||||
},
|
||||
getConversationId() {
|
||||
return state.conversationId;
|
||||
},
|
||||
|
||||
@@ -548,6 +548,7 @@
|
||||
"door.set_rear_lock": "后排门锁",
|
||||
"door.set_vehicle_lock": "整车门锁",
|
||||
"infrared.emit": "红外外设",
|
||||
"android.launch_app": "打开视频媒体",
|
||||
};
|
||||
|
||||
function assistantControlCategory(operation = {}, fallback = "控制指令") {
|
||||
@@ -745,6 +746,22 @@
|
||||
const brightness = numericValue(parameters.brightness_level);
|
||||
if (brightness !== null) return `${brightness}级`;
|
||||
const level = numericValue(parameters.level ?? parameters.fan_level);
|
||||
const capability = String(item.operation?.capability || "");
|
||||
if (capability === "android.launch_app") {
|
||||
const packageName = String(parameters.package_name || "").trim();
|
||||
const activityName = String(parameters.activity_name || "").trim();
|
||||
return [
|
||||
packageName ? `应用 ${packageName}` : "视频应用",
|
||||
activityName ? `页面 ${activityName}` : "",
|
||||
].filter(Boolean).join(" · ");
|
||||
}
|
||||
if (
|
||||
level !== null
|
||||
&& ["seat.set_driver_ventilation_native", "seat.set_driver_heating_native"]
|
||||
.includes(capability)
|
||||
) {
|
||||
return ({ 1: "3档", 2: "1档" })[level] || "档位待确认";
|
||||
}
|
||||
if (level !== null) return `${level}档`;
|
||||
const state = parameters.motion
|
||||
?? parameters.state
|
||||
@@ -769,6 +786,7 @@
|
||||
if (capability.startsWith("seat.") || category.includes("座椅")) return "armchair";
|
||||
if (capability.startsWith("door.") || category.includes("门锁")) return "lock-keyhole";
|
||||
if (capability === "infrared.emit") return "radio-tower";
|
||||
if (capability === "android.launch_app") return "clapperboard";
|
||||
return "binary";
|
||||
}
|
||||
|
||||
@@ -985,6 +1003,7 @@
|
||||
"ambient_light.set_power": "氛围灯",
|
||||
"ambient_light.set_mode": "氛围灯模式",
|
||||
"infrared.emit": "红外外设",
|
||||
"android.launch_app": "打开视频媒体",
|
||||
};
|
||||
|
||||
const zeroGravityIndexes = actions
|
||||
@@ -1166,9 +1185,10 @@
|
||||
? `${params.position_pct}%${params.angle_deg != null ? `(${params.angle_deg}°)` : ""}`
|
||||
: motionLabel(params.state || params.mode_id);
|
||||
if (["seat.set_driver_ventilation_native", "seat.set_driver_heating_native"].includes(capability)) {
|
||||
// CH1 driver controls encode high as 1 and low as 2; passenger
|
||||
// comfort levels use a different scale and must not reuse this map.
|
||||
const level = { 1: "高档", 2: "低档" }[params.level ?? 2] || "档位待确认";
|
||||
// CH1 encodes high as 1 and low as 2 internally. Present the
|
||||
// occupant-facing three-speed scale instead of leaking CAN enums.
|
||||
const level = { 1: "3档(高)", 2: "1档(低)" }[params.level ?? 2]
|
||||
|| "档位待确认";
|
||||
value = params.state === "off" ? "关闭"
|
||||
: params.state === "on" ? `开启 · ${level}` : "开关状态待确认";
|
||||
} else if (["seat.set_ventilation", "seat.set_heating"].includes(capability)) {
|
||||
@@ -1529,10 +1549,23 @@
|
||||
return /(?:构建|创建|新建|新增|生成|添加)(?:一下)?(?:一个|个|一套|套)?[^,。!?!?]{1,64}?模式/.test(compact);
|
||||
}
|
||||
|
||||
function validatedHardwareClientId() {
|
||||
const sharedClientId = window.CognitiveAgentConsole?.getHardwareClientId?.();
|
||||
let storedClientId = null;
|
||||
try {
|
||||
storedClientId = localStorage.getItem("cognitive-agent.hardware-client-id");
|
||||
} catch (_error) {
|
||||
// The shared console identity remains authoritative when storage is unavailable.
|
||||
}
|
||||
return [sharedClientId, storedClientId]
|
||||
.map((value) => String(value || "").trim())
|
||||
.find((value) => /^hwc-[a-z0-9-]{8,80}$/.test(value)) || null;
|
||||
}
|
||||
|
||||
function requestBody(message) {
|
||||
const configuredExecutionMode = window.CognitiveAgentConsole?.getExecutionMode?.() || "dry_run";
|
||||
const controlTransport = localStorage.getItem("cognitive-agent.control-transport") || "wired_can";
|
||||
const hardwareClientId = localStorage.getItem("cognitive-agent.hardware-client-id");
|
||||
const hardwareClientId = validatedHardwareClientId();
|
||||
const vehicleId = $("#vehicleSelect")?.value || null;
|
||||
const modeProfileDraftContext = requestModeDraftContext(message);
|
||||
const modeConfigurationPreview = Boolean(modeProfileDraftContext)
|
||||
@@ -1967,6 +2000,11 @@
|
||||
&& result?.schedule_execution?.status === "running";
|
||||
const dryRun = result?.execution_mode === "dry_run";
|
||||
const waitingForFeedback = result?.execution_outcome === "submitted_unverified";
|
||||
const delegatedCount = Array.isArray(result?.deferred_requests)
|
||||
? result.deferred_requests.filter(
|
||||
(item) => item?.execution_backend === "n7_vehicle_transfer",
|
||||
).length
|
||||
: 0;
|
||||
|
||||
let content = `${modeName}执行未完成,请查看控制指令状态。`;
|
||||
let statusText = "功能模式执行未完成";
|
||||
@@ -1991,8 +2029,15 @@
|
||||
: "功能模式执行已完成";
|
||||
statusState = "success";
|
||||
} else if (status === "partially_succeeded") {
|
||||
content = `${modeName}仅部分完成,请查看未完成的控制指令。`;
|
||||
statusText = "功能模式部分完成";
|
||||
content = delegatedCount > 0
|
||||
? `${modeName}指令已提交,未由 PC 执行的 ${delegatedCount} 项动作将由车机继续处理。`
|
||||
: waitingForFeedback
|
||||
? `${modeName}指令已提交,正在等待车辆状态确认。`
|
||||
: `${modeName}执行结果已更新,请查看各控制指令状态。`;
|
||||
statusText = waitingForFeedback || delegatedCount > 0
|
||||
? "功能模式指令已提交"
|
||||
: "功能模式执行结果已更新";
|
||||
statusState = waitingForFeedback || delegatedCount > 0 ? "working" : "success";
|
||||
}
|
||||
|
||||
setMessageContent(message, content, { final: true });
|
||||
|
||||
@@ -571,9 +571,20 @@
|
||||
const explicitlyBlocked = executionStatus === "blocked"
|
||||
|| verificationStatus === "blocked"
|
||||
|| Boolean(telemetry.authorization_reason);
|
||||
const executionFailed = executionStatus === "failed"
|
||||
// Closed-loop evidence is authoritative. Some MQTT window executors
|
||||
// retain a legacy `failed` operation status even after fresh 0x388
|
||||
// feedback confirms the requested target; do not render that as a
|
||||
// failed dispatch once the physical result is verified.
|
||||
const verified = !aborted && (
|
||||
verificationStatus === "verified_success"
|
||||
|| telemetry.physical_effect_confirmed === true
|
||||
|| telemetry.feedback_match === true
|
||||
);
|
||||
const executionFailed = !verified && (
|
||||
executionStatus === "failed"
|
||||
|| explicitlyBlocked
|
||||
|| verificationStatus === "failed_or_blocked";
|
||||
|| verificationStatus === "failed_or_blocked"
|
||||
);
|
||||
const missingWindowFeedback = /0x388/i.test(failureMessage) && (
|
||||
/no fresh valid/i.test(failureMessage)
|
||||
|| /未收到.*(?:有效|新鲜).*车窗位置/.test(failureMessage)
|
||||
@@ -591,11 +602,6 @@
|
||||
|| /thermal protection|热保护/i.test(failureMessage)
|
||||
);
|
||||
const dispatchFailed = executionFailed && !submitted && !safetyBlocked;
|
||||
const verified = !executionFailed && !aborted && (
|
||||
verificationStatus === "verified_success"
|
||||
|| telemetry.physical_effect_confirmed === true
|
||||
|| telemetry.feedback_match === true
|
||||
);
|
||||
const deliveryState = aborted
|
||||
? "aborted"
|
||||
: safetyBlocked
|
||||
@@ -1325,7 +1331,7 @@
|
||||
}
|
||||
|
||||
const levelOptions = [
|
||||
["off", "关闭"], ["high", "1 档(高)"], ["low", "2 档(低)"],
|
||||
["off", "关闭"], ["low", "1 档(低)"], ["high", "3 档(高)"],
|
||||
];
|
||||
const toggleOptions = [["off", "关闭"], ["on", "开启"]];
|
||||
const massageModeOptions = [
|
||||
|
||||
@@ -39,13 +39,13 @@
|
||||
<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-2" defer></script>
|
||||
<script src="/app.js?v=dual-seat-145-n7-dispatch" defer></script>
|
||||
<script src="/app.js?v=dual-seat-147-video-media" defer></script>
|
||||
<script src="/speech-input.js?v=sensevoice-13" defer></script>
|
||||
<script type="module" src="/gesture-control.js?v=android-pad-9"></script>
|
||||
<script src="/pwa.js?v=android-pad-3" defer></script>
|
||||
<script src="/console-v2.js?v=local-first-77-performance" defer></script>
|
||||
<script src="/self-extension.js?v=nfc-mqtt-56" defer></script>
|
||||
<script src="/assistant-chat.js?v=codex-assistant-35" defer></script>
|
||||
<script src="/console-v2.js?v=local-first-79-cinema-status" defer></script>
|
||||
<script src="/self-extension.js?v=nfc-persistent-57" defer></script>
|
||||
<script src="/assistant-chat.js?v=codex-assistant-39-video-media" defer></script>
|
||||
<script src="/energy-monitor.js?v=energy-monitor-5-performance" defer></script>
|
||||
<script src="/firmware-workbench-entry.js?v=3" defer></script>
|
||||
</head>
|
||||
|
||||
@@ -382,6 +382,8 @@
|
||||
};
|
||||
let peripheralCatalogRevision = null;
|
||||
let peripheralCatalogSyncQueue = Promise.resolve();
|
||||
let durablePeripheralCatalog = [];
|
||||
let durablePeripheralCatalogHydrated = false;
|
||||
let petCardSnapshot = {
|
||||
revision: -1,
|
||||
cards: [],
|
||||
@@ -1973,11 +1975,40 @@
|
||||
}).filter((item) => item.device_id && item.card_uid && validSlot(item.slot));
|
||||
}
|
||||
|
||||
function applyDurablePeripheralCatalog(
|
||||
catalog,
|
||||
revision = null,
|
||||
{ render = true } = {},
|
||||
) {
|
||||
const nextCatalog = (Array.isArray(catalog) ? catalog : [])
|
||||
.filter((item) => item && typeof item === "object"
|
||||
&& item.id && item.device_id && normalizeCardUid(item.card_uid)
|
||||
&& validSlot(item.slot))
|
||||
.map((item) => ({ ...item, card_uid: normalizeCardUid(item.card_uid) }));
|
||||
const changed = JSON.stringify(durablePeripheralCatalog) !== JSON.stringify(nextCatalog)
|
||||
|| !durablePeripheralCatalogHydrated;
|
||||
durablePeripheralCatalog = nextCatalog;
|
||||
durablePeripheralCatalogHydrated = true;
|
||||
if (revision != null && String(revision).trim()) {
|
||||
peripheralCatalogRevision = String(revision).trim();
|
||||
}
|
||||
if (changed) unifiedExtensionDirty = true;
|
||||
if (render && changed) renderUnifiedExtensionView?.({ force: true });
|
||||
return changed;
|
||||
}
|
||||
|
||||
async function hydratePeripheralCatalog() {
|
||||
const payload = await api("peripherals");
|
||||
peripheralCatalogRevision = payload.catalog_revision || peripheralCatalogRevision;
|
||||
const catalog = Array.isArray(payload.catalog) ? payload.catalog : [];
|
||||
if (!catalog.length) return 0;
|
||||
applyDurablePeripheralCatalog(
|
||||
catalog,
|
||||
payload.catalog_revision,
|
||||
{ render: false },
|
||||
);
|
||||
if (!catalog.length) {
|
||||
renderAll();
|
||||
return 0;
|
||||
}
|
||||
const restoredDeviceIds = new Set();
|
||||
catalog.forEach((item) => {
|
||||
if (!item || typeof item !== "object" || !item.id || !validSlot(item.slot)) return;
|
||||
@@ -3806,12 +3837,13 @@
|
||||
}
|
||||
|
||||
async function syncPeripheralCatalog(device = null, { throwOnError = false } = {}) {
|
||||
const nextCatalog = peripheralCatalog();
|
||||
const operation = peripheralCatalogSyncQueue
|
||||
.catch(() => null)
|
||||
.then(() => api("display-sync", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
peripherals: peripheralCatalog(),
|
||||
peripherals: nextCatalog,
|
||||
device,
|
||||
catalog_revision: peripheralCatalogRevision,
|
||||
}),
|
||||
@@ -3819,7 +3851,10 @@
|
||||
peripheralCatalogSyncQueue = operation.catch(() => null);
|
||||
try {
|
||||
const result = await operation;
|
||||
peripheralCatalogRevision = result.catalog_revision || peripheralCatalogRevision;
|
||||
applyDurablePeripheralCatalog(
|
||||
nextCatalog,
|
||||
result.catalog_revision,
|
||||
);
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.warn("外设能力同步失败", error);
|
||||
@@ -4169,6 +4204,18 @@
|
||||
status: item.status,
|
||||
enabled: item.enabled,
|
||||
})),
|
||||
durableCatalogHydrated: durablePeripheralCatalogHydrated,
|
||||
durableCatalog: durablePeripheralCatalog.map((item) => ({
|
||||
id: item.id,
|
||||
deviceId: item.device_id,
|
||||
deviceName: item.device_name,
|
||||
deviceType: item.device_type,
|
||||
typeLabel: item.type_label,
|
||||
action: item.action,
|
||||
cardUid: item.card_uid,
|
||||
status: item.status,
|
||||
enabled: item.enabled,
|
||||
})),
|
||||
lastAction: snapshot?.extension?.last_action ? {
|
||||
command: snapshot.extension.last_action.command,
|
||||
type: snapshot.extension.last_action.type,
|
||||
@@ -4249,27 +4296,28 @@
|
||||
const sharedCatalog = Array.isArray(snapshot?.extension?.catalog)
|
||||
? snapshot.extension.catalog
|
||||
: [];
|
||||
const mergedCatalog = [...sharedCatalog, ...peripheralCatalog()]
|
||||
const fallbackCatalog = [...sharedCatalog, ...peripheralCatalog()]
|
||||
.filter((item, index, catalog) => {
|
||||
const identity = item.id || `${item.device_id}:${item.action}`;
|
||||
return catalog.findIndex((candidate) => (
|
||||
candidate.id || `${candidate.device_id}:${candidate.action}`
|
||||
) === identity) === index;
|
||||
});
|
||||
const persistentCatalog = (
|
||||
durablePeripheralCatalogHydrated
|
||||
? durablePeripheralCatalog
|
||||
: fallbackCatalog
|
||||
).filter((item) => (
|
||||
normalizeCardUid(item.card_uid)
|
||||
&& item.status === "learned"
|
||||
));
|
||||
const nfcReader = nfcSnapshot.reader || {};
|
||||
const nfcCard = nfcSnapshot.card;
|
||||
const sensedCardUid = normalizeCardUid(nfcCard?.uid);
|
||||
const nfcDevice = linkedDeviceForCard(sensedCardUid);
|
||||
const nfcPet = linkedPetForCard(sensedCardUid);
|
||||
const activeCatalog = sensedCardUid
|
||||
? mergedCatalog.filter((item) => (
|
||||
normalizeCardUid(item.card_uid) === sensedCardUid
|
||||
&& item.status === "learned"
|
||||
&& item.enabled !== false
|
||||
))
|
||||
: [];
|
||||
const grouped = new Map();
|
||||
activeCatalog.forEach((item) => {
|
||||
persistentCatalog.forEach((item) => {
|
||||
const deviceId = item.device_id || "external-device";
|
||||
if (!grouped.has(deviceId)) grouped.set(deviceId, {
|
||||
id: deviceId,
|
||||
@@ -4278,7 +4326,10 @@
|
||||
cardUid: item.card_uid || null,
|
||||
actions: [],
|
||||
});
|
||||
grouped.get(deviceId).actions.push(item.action || item.name || "已学习能力");
|
||||
const actionName = item.action || item.name || "已学习能力";
|
||||
grouped.get(deviceId).actions.push(
|
||||
item.enabled === false ? `${actionName}(已停用)` : actionName,
|
||||
);
|
||||
});
|
||||
const devices = [...grouped.values()];
|
||||
const lastAction = snapshot?.extension?.last_action;
|
||||
@@ -4294,8 +4345,10 @@
|
||||
: petCardSnapshot.publisher?.state === "burst_failed"
|
||||
? "宠物消息发送失败"
|
||||
: "已感应宠物 NFC"
|
||||
: devices.length
|
||||
: nfcDevice
|
||||
? "已感应 NFC 外设"
|
||||
: devices.length
|
||||
? `${devices.length} 个外设已绑定`
|
||||
: sensedCardUid
|
||||
? "当前 NFC 暂无已授权命令"
|
||||
: nfcReader.online
|
||||
@@ -4361,11 +4414,11 @@
|
||||
<div>${device.actions.slice(0, 8).map((action) => `<span>${escapeHtml(action)}</span>`).join("")}</div>
|
||||
</article>`).join("") : nfcPet ? "" : `
|
||||
<div class="v2-extension-empty">
|
||||
<i data-lucide="${sensedCardUid ? "badge-alert" : "scan-line"}"></i><div><strong>${sensedCardUid ? "当前 NFC 暂无已授权命令" : "当前未感应到外设"}</strong><span>${sensedCardUid ? "请检查设备 ID 绑定及命令复选框" : "将已绑定设备 ID 的 NFC 卡靠近读卡器后显示命令"}</span></div>
|
||||
<i data-lucide="link-2-off"></i><div><strong>当前没有已绑定外设</strong><span>外设绑定 NFC 后将持续显示,解除绑定后移除</span></div>
|
||||
</div>`}
|
||||
</div>
|
||||
<footer class="v2-extension-linkage" data-active="${String(Boolean(visibleLastAction))}">
|
||||
<i data-lucide="workflow"></i><div><small>最近联动</small><strong>${escapeHtml(visibleLastAction?.command || visibleLastAction?.type || "等待 NFC 外设感应")}</strong></div>
|
||||
<i data-lucide="workflow"></i><div><small>最近联动</small><strong>${escapeHtml(visibleLastAction?.command || visibleLastAction?.type || "暂无外设联动")}</strong></div>
|
||||
<span>${escapeHtml(visibleLastAction ? (lastResult?.status || lastResult?.message || "STANDBY") : "STANDBY")}</span>
|
||||
</footer>`;
|
||||
unifiedExtensionFingerprint = renderFingerprint;
|
||||
@@ -4377,6 +4430,17 @@
|
||||
|
||||
window.addEventListener("cognitive-agent:display-sync", (event) => {
|
||||
snapshot = event.detail || null;
|
||||
const extensionSnapshot = snapshot?.extension;
|
||||
if (
|
||||
Array.isArray(extensionSnapshot?.catalog)
|
||||
&& extensionSnapshot?.result?.catalog_revision
|
||||
) {
|
||||
applyDurablePeripheralCatalog(
|
||||
extensionSnapshot.catalog,
|
||||
extensionSnapshot.result.catalog_revision,
|
||||
{ render: false },
|
||||
);
|
||||
}
|
||||
if (snapshot?.extension_health?.nfc) {
|
||||
applyNfcSnapshot(snapshot.extension_health.nfc, { announce: false });
|
||||
}
|
||||
@@ -4402,8 +4466,8 @@
|
||||
void hydratePeripheralCatalog()
|
||||
.catch((error) => {
|
||||
console.warn("恢复后端红外能力目录失败,将保留浏览器本地目录。", error);
|
||||
})
|
||||
.finally(() => syncPeripheralCatalog());
|
||||
return syncPeripheralCatalog();
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const CACHE_VERSION = "cognitive-agent-pad-v329-mode-preview";
|
||||
const CACHE_VERSION = "cognitive-agent-pad-v334-video-media";
|
||||
const SHELL_CACHE = `${CACHE_VERSION}-shell`;
|
||||
const RUNTIME_CACHE = `${CACHE_VERSION}-runtime`;
|
||||
const APP_SHELL = [
|
||||
@@ -6,18 +6,18 @@ const APP_SHELL = [
|
||||
"/index.html",
|
||||
"/styles.css?v=dual-seat-24-dialog-size",
|
||||
"/network.js?v=android-pad-2",
|
||||
"/app.js?v=dual-seat-145-n7-dispatch",
|
||||
"/app.js?v=dual-seat-147-video-media",
|
||||
"/gesture-control.js?v=android-pad-9",
|
||||
"/pwa.js?v=android-pad-3",
|
||||
"/console-v2.css?v=delivery-state-69",
|
||||
"/console-v2.js?v=local-first-77-performance",
|
||||
"/console-v2.js?v=local-first-79-cinema-status",
|
||||
"/self-extension.css?v=pet-settings-54-dialog-size",
|
||||
"/self-extension.js?v=nfc-mqtt-56",
|
||||
"/self-extension.js?v=nfc-persistent-57",
|
||||
"/speech-input.css?v=sensevoice-7",
|
||||
"/speech-input.js?v=sensevoice-13",
|
||||
"/speech-audio-worklet.js?v=sensevoice-5",
|
||||
"/assistant-chat.css?v=codex-assistant-30",
|
||||
"/assistant-chat.js?v=codex-assistant-35",
|
||||
"/assistant-chat.js?v=codex-assistant-39-video-media",
|
||||
"/energy-monitor.css?v=energy-monitor-5-dialog-size",
|
||||
"/energy-monitor.js?v=energy-monitor-5-performance",
|
||||
"/ui-consistency.css?v=spatial-ui-8",
|
||||
|
||||
Reference in New Issue
Block a user