feat: route mode cards through AI assistant

This commit is contained in:
vee
2026-09-09 08:32:51 +08:00
parent 93103c2579
commit 2af8b8f9ac
8 changed files with 145 additions and 22 deletions
@@ -19,7 +19,7 @@ def test_console_contains_ai_assistant_surface():
def test_codex_assistant_assets_are_versioned_together_in_the_service_worker():
service_worker = (ROOT / "apps/web-console/service-worker.js").read_text(encoding="utf-8")
assert 'const CACHE_VERSION = "cognitive-agent-pad-v275"' in service_worker
assert 'const CACHE_VERSION = "cognitive-agent-pad-v276"' in service_worker
assert '"/assistant-chat.css?v=codex-assistant-26"' in service_worker
assert '"/assistant-chat.js?v=codex-assistant-26"' in service_worker
@@ -38,7 +38,7 @@ def test_energy_monitor_assets_are_versioned_and_cached() -> None:
assert html.index("/assistant-chat.js?v=codex-assistant-26") < html.index(
"/energy-monitor.js?v=energy-monitor-4"
)
assert 'const CACHE_VERSION = "cognitive-agent-pad-v275"' in service_worker
assert 'const CACHE_VERSION = "cognitive-agent-pad-v276"' in service_worker
def test_energy_monitor_uses_the_fifth_shared_dock_icon_and_starts_closed() -> None:
+1 -1
View File
@@ -47,7 +47,7 @@ def test_theme_asset_versions_are_consistent_with_the_pwa_shell() -> None:
):
assert asset in html
assert f'"{asset}"' in service_worker
assert 'const CACHE_VERSION = "cognitive-agent-pad-v275"' in service_worker
assert 'const CACHE_VERSION = "cognitive-agent-pad-v276"' in service_worker
def test_vehicle_twin_icons_and_nested_overlays_use_semantic_tokens() -> None:
+111
View File
@@ -248,3 +248,114 @@ def test_top_mode_action_formatter_uses_device_target_action_and_parameter_value
"action": "设置空调温度",
"parameters": "目标温度:25 ℃",
}
def test_mode_cards_open_assistant_and_submit_enter_mode_command() -> None:
app = (WEB / "app.js").read_text(encoding="utf-8")
start = app.index("function applyModeCommand")
end = app.index("\n\nfunction applyRuntimeTargetPolicy", start)
snippet = app[start:end]
script = "const snippet = " + json.dumps(snippet) + ";\n" + r"""
const vm = require("node:vm");
const calls = [];
const input = {
value: "",
dataset: { speechStage: "final", speechUtteranceId: "old", speechValue: "old" },
dispatchEvent(event) { calls.push(["input", event.type, event.bubbles, this.value]); },
};
const form = { requestSubmit() { calls.push(["submit", input.value]); } };
const runButton = { disabled: false };
const savedMode = {
id: "reading-user",
name: "阅读模式",
command_flow: { source_request_id: "saved-request" },
};
const context = {
Event: class Event {
constructor(type, options = {}) { this.type = type; this.bubbles = options.bubbles; }
},
window: {
CognitiveAgentAssistant: {
isPending() { return false; },
open() { calls.push(["open"]); },
},
},
modeProfiles() { return [savedMode]; },
setModeRailSelection(mode) { calls.push(["select", mode?.id]); },
closeModeGallery(options) { calls.push(["close", options.restoreFocus]); },
showToast(message) { calls.push(["toast", message]); },
$(selector) {
return { "#utterance": input, "#requestForm": form, "#runButton": runButton }[selector];
},
};
vm.createContext(context);
vm.runInContext(snippet + '\nthis.result = applyModeCommand(" 进入阅读模式 ", "reading-user");', context);
console.log(JSON.stringify({
result: context.result,
calls,
value: input.value,
speechDataset: input.dataset,
}));
"""
completed = subprocess.run(
[node_runtime(), "-e", script],
check=True,
capture_output=True,
text=True,
encoding="utf-8",
)
result = json.loads(completed.stdout)
assert result["result"] is True
assert result["calls"] == [
["select", "reading-user"],
["close", False],
["open"],
["input", "input", True, "进入阅读模式"],
["submit", "进入阅读模式"],
]
assert result["value"] == "进入阅读模式"
assert result["speechDataset"] == {}
assert "executeSavedModeProfile" not in snippet
def test_mode_cards_do_not_submit_while_assistant_is_busy() -> None:
app = (WEB / "app.js").read_text(encoding="utf-8")
start = app.index("function applyModeCommand")
end = app.index("\n\nfunction applyRuntimeTargetPolicy", start)
snippet = app[start:end]
script = "const snippet = " + json.dumps(snippet) + ";\n" + r"""
const vm = require("node:vm");
const calls = [];
const context = {
window: { CognitiveAgentAssistant: { isPending() { return true; } } },
showToast(message) { calls.push(message); },
};
vm.createContext(context);
vm.runInContext(snippet + '\nthis.result = applyModeCommand("进入办公模式", "office");', context);
console.log(JSON.stringify({ result: context.result, calls }));
"""
completed = subprocess.run(
[node_runtime(), "-e", script],
check=True,
capture_output=True,
text=True,
encoding="utf-8",
)
result = json.loads(completed.stdout)
assert result == {
"result": False,
"calls": ["AI助手正在处理上一条指令,请稍候"],
}
def test_top_and_management_mode_cards_share_the_assistant_submission_entrypoint() -> None:
app = (WEB / "app.js").read_text(encoding="utf-8")
install_start = app.index('document.addEventListener("DOMContentLoaded"')
handlers = app[install_start:]
assert handlers.count("if (button) applyModeCommand(") == 2
assert '$(".mode-chips").addEventListener("click"' in handlers
assert '$("#modeGalleryGroups").addEventListener("click"' in handlers
assert app.count('button.dataset.modeCommand = `进入${mode.name}`;') == 2