import {
DEFAULT_DESCRIPTOR,
buildManualCommand,
cloneDescriptor,
parseInstruction,
splitAliases,
} from "./parser-engine.js";
const $ = (selector, root = document) => root.querySelector(selector);
const $$ = (selector, root = document) => [...root.querySelectorAll(selector)];
let descriptor = cloneDescriptor();
let latestPayload = null;
const categoryLabels = {
vehicle_electrical: "车端电器",
seat: "座椅设备",
peripheral: "扩展外设",
};
const transportLabels = {
native_can: "原生 CAN",
domain_runtime: "领域执行器",
gscu_tcp: "红外网关",
mqtt: "MQTT",
};
const exampleTemplates = [
(name) => `开启${name}`,
(name) => `把${name}温度调到4度`,
(name) => `将${name}设为速冷模式`,
(name) => `关闭${name}`,
(name) => `把${name}调到零下10度`,
];
function escapeHtml(value) {
return String(value ?? "")
.replaceAll("&", "&")
.replaceAll("<", "<")
.replaceAll(">", ">")
.replaceAll('"', """)
.replaceAll("'", "'");
}
function fillIdentityForm() {
$("#deviceName").value = descriptor.device.name;
$("#deviceId").value = descriptor.device.id;
$("#deviceDomain").value = descriptor.device.domain;
$("#deviceCategory").value = descriptor.device.category;
$("#deviceAliases").value = descriptor.device.aliases.join("、");
$("#deviceScope").value = descriptor.device.defaultScope;
$("#deviceTransport").value = descriptor.device.transport;
}
function syncIdentityFromForm() {
descriptor.device.name = $("#deviceName").value.trim() || "未命名设备";
descriptor.device.id = $("#deviceId").value.trim() || "unnamed_device";
descriptor.device.domain = $("#deviceDomain").value.trim() || "custom";
descriptor.device.category = $("#deviceCategory").value;
descriptor.device.aliases = splitAliases($("#deviceAliases").value);
descriptor.device.defaultScope = $("#deviceScope").value;
descriptor.device.targetScopes = [descriptor.device.defaultScope];
descriptor.device.transport = $("#deviceTransport").value;
descriptor.device.targetDevice = descriptor.device.id;
renderAll({ preserveResult: true });
}
function renderCapabilityEditor() {
$("#capabilityEditor").innerHTML = descriptor.capabilities.map((capability, capabilityIndex) => `
${escapeHtml(category)} · ${escapeHtml(transport)} · ${escapeHtml(descriptor.device.defaultScope)}${escapeHtml(capability.id)}
${escapeHtml(descriptor.device.name)}
没有已启用功能。
"}功能控件只生成结构化演示数据;执行映射为虚拟引用,不连接现有服务。
`; } function compactDescriptor() { return { version: descriptor.version, device: descriptor.device, capabilities: descriptor.capabilities.map((capability) => ({ id: capability.id, property: capability.property, target_scopes: descriptor.device.targetScopes, parameters: capability.parameters, intents: capability.intents, risk_level: capability.risk, confirmation_policy: capability.confirmationPolicy, executor: capability.executor, enabled: capability.enabled, })), }; } function renderDescriptor() { $("#descriptorPreview").textContent = JSON.stringify(compactDescriptor(), null, 2); } function renderAll({ preserveResult = false } = {}) { renderCapabilityEditor(); renderExamples(); renderDeviceCard(); renderDescriptor(); if (!preserveResult) renderResult(null); } function resultPresentation(result) { if (!result) return { status: "idle", title: "等待解析", message: "输入一句话,查看设备、功能和参数的匹配过程。" }; if (result.source === "card_control") { return { status: "success", title: "已生成卡片控制载荷", message: `已生成 ${result.commands.length} 条结构化演示指令;实验页面不会发送到车辆。`, }; } if (result.semantic_status === "recognized_executable") { return { status: "success", title: "已匹配可执行功能", message: `${result.clean_text} 当前仅生成演示载荷。` }; } if (result.semantic_status === "ambiguous" || result.semantic_status === "incomplete") { return { status: "warning", title: "需要补充信息", message: result.issues.join(";") }; } return { status: "error", title: "未生成控制指令", message: result.issues.join(";") || "没有匹配到设备能力。" }; } function renderResult(result) { const presentation = resultPresentation(result); $("#resultBanner").dataset.status = presentation.status; $("#resultTitle").textContent = presentation.title; $("#resultMessage").textContent = presentation.message; $("#traceList").innerHTML = result?.trace?.length ? result.trace.map((item) => `