优化语音输入/普通文本输入

This commit is contained in:
minghanchen
2026-09-03 13:36:40 +08:00
parent 009d8ca73e
commit 32d179143f
26 changed files with 2318 additions and 53 deletions
+10 -1
View File
@@ -416,6 +416,15 @@
return [...unique.values()];
}
function parsedCommandSourceLabel(source) {
return {
direct_control: "设备控件",
saved_mode_command_flow: "模式卡片",
local_rule: "本地规则",
speech_semantic: "语音语义",
}[source] || "云端模型";
}
function renderParsedCanCommands(result, { message = "" } = {}) {
const panel = $("#v2CanCommandPanel");
const list = $("#v2CanCommandList");
@@ -429,7 +438,7 @@
<li data-can-channel="${escapeHtml(item.channel)}" data-delivery-state="${escapeHtml(item.deliveryState)}">
<span>
<b class="v2-can-command-channel">${escapeHtml(item.channel)}</b>
${item.parseSource ? `<b class="v2-can-command-source" data-parse-source="${escapeHtml(item.parseSource)}">${item.parseSource === "direct_control" ? "设备控件" : item.parseSource === "saved_mode_command_flow" ? "模式卡片" : item.parseSource === "local_rule" ? "本地规则" : "云端模型"}</b>` : ""}
${item.parseSource ? `<b class="v2-can-command-source" data-parse-source="${escapeHtml(item.parseSource)}">${parsedCommandSourceLabel(item.parseSource)}</b>` : ""}
<b class="v2-can-command-delivery" data-delivery-state="${escapeHtml(item.deliveryState)}" title="${escapeHtml(`${item.deliveryTransport} · ${item.deliveryLabel}`)}">${escapeHtml(item.deliveryLabel)}</b>
<i class="v2-can-command-category">${escapeHtml(item.category)}</i>
</span>
+2 -2
View File
@@ -19,10 +19,10 @@
<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-114" defer></script>
<script src="/speech-input.js?v=sensevoice-6" defer></script>
<script src="/speech-input.js?v=sensevoice-7" 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=delivery-state-54" defer></script>
<script src="/console-v2.js?v=delivery-state-55" defer></script>
<script src="/self-extension.js?v=gscu-tcp-41" defer></script>
</head>
<body class="console-v2">
+3 -3
View File
@@ -1,4 +1,4 @@
const CACHE_VERSION = "cognitive-agent-pad-v227";
const CACHE_VERSION = "cognitive-agent-pad-v228";
const SHELL_CACHE = `${CACHE_VERSION}-shell`;
const RUNTIME_CACHE = `${CACHE_VERSION}-runtime`;
const APP_SHELL = [
@@ -10,11 +10,11 @@ const APP_SHELL = [
"/gesture-control.js?v=android-pad-9",
"/pwa.js?v=android-pad-3",
"/console-v2.css?v=delivery-state-50",
"/console-v2.js?v=delivery-state-54",
"/console-v2.js?v=delivery-state-55",
"/self-extension.css?v=gscu-tcp-42",
"/self-extension.js?v=gscu-tcp-41",
"/speech-input.css?v=sensevoice-5",
"/speech-input.js?v=sensevoice-6",
"/speech-input.js?v=sensevoice-7",
"/speech-audio-worklet.js?v=sensevoice-4",
"/assets/pets/self-extension-cat.png?v=3",
"/assets/pets/self-extension-cat-entrance.png?v=3",
+13 -3
View File
@@ -380,15 +380,21 @@
const { input } = elements();
if (!input) throw new Error("没有找到一句话编排输入框");
const cleanText = String(result.clean_text || result.text || "").trim();
const peripheralEligible = result.peripheral_routing?.execution_eligible === true;
const inputText = peripheralEligible
? String(result.routing_text || result.raw_text || cleanText).trim()
: cleanText;
const commands = Array.isArray(result.commands) ? result.commands : [];
if (!cleanText || commands.length === 0) {
if (!inputText || (commands.length === 0 && !peripheralEligible)) {
window.dispatchEvent(new CustomEvent("cognitive-agent:speech-result", { detail: result }));
return false;
}
speech.applyingResult = true;
input.value = cleanText.slice(0, input.maxLength || 1000);
input.value = inputText.slice(0, input.maxLength || 1000);
input.dataset.speechUncertain = String(result.uncertain === true);
input.dataset.speechExecutionEligible = String(result.execution_eligible === true);
input.dataset.speechExecutionEligible = String(
result.execution_eligible === true || peripheralEligible,
);
input.dataset.speechSemanticStatus = String(result.semantic_status || "");
input.dataset.speechValue = input.value.trim();
input.dataset.speechUtteranceId = String(result.utterance_id || "");
@@ -423,6 +429,10 @@
if (!applied) {
setPhase("success", `未形成可执行控制指令 · ${latency} ms`);
announce("已保留原始转录,但没有激活控制指令");
} else if (result.peripheral_routing?.execution_eligible === true) {
const count = Number(result.peripheral_routing.action_count || 1);
setPhase("success", `已识别为 ${count} 条外设控制指令 · ${latency} ms`);
announce("语音已匹配当前 NFC 外设的已学习控制指令");
} else if (result.semantic_status === "recognized_unsupported") {
setPhase("success", `已识别,但当前车辆能力不支持 · ${latency} ms`);
announce("已完整保留用户语义,但当前车辆能力不支持执行");