c812a1a595
Integrate the remote firmware workbench, OTA delivery, and timed mode schedules while preserving the local N7 scene and runtime changes.
125 lines
6.5 KiB
Python
125 lines
6.5 KiB
Python
from __future__ import annotations
|
|
|
|
from copy import deepcopy
|
|
|
|
import pytest
|
|
|
|
from cognitive_agent.application.codex_assistant import (
|
|
CodexAssistantService,
|
|
_authorize_vehicle_request,
|
|
_validated_mode_profile_draft_context,
|
|
)
|
|
from cognitive_agent.application.mode_profile_intent import (
|
|
is_mode_profile_update_shape,
|
|
parse_mode_profile_update,
|
|
)
|
|
|
|
DRAFT_REFERENCE = {
|
|
"name": "躺平模式", "source_request_id": "req-augmentation-source-123456", "vehicle_id": "denza_n7",
|
|
}
|
|
CONTROL_TERMS = ("空调", "氛围灯", "阅读灯", "车窗", "座椅")
|
|
|
|
|
|
@pytest.mark.parametrize("prefix", ["在", "给", "为", "往", "向", ""])
|
|
@pytest.mark.parametrize("verb", ["加入", "添加", "增加", "补充", "加上", "追加", "新增"])
|
|
def test_named_mode_device_augmentation_is_recognized(prefix, verb):
|
|
message = f"{prefix}躺平模式中{verb}空调、氛围灯、阅读灯、车窗等设备动作"
|
|
assert parse_mode_profile_update(message) == ("躺平模式", f"{verb}空调、氛围灯、阅读灯、车窗等设备动作")
|
|
assert _validated_mode_profile_draft_context(DRAFT_REFERENCE, message=message) == DRAFT_REFERENCE
|
|
authorization = _authorize_vehicle_request(message, CONTROL_TERMS, DRAFT_REFERENCE)
|
|
assert authorization.instruction == message
|
|
assert authorization.reason == "explicit_mode_profile_draft_update"
|
|
|
|
|
|
@pytest.mark.parametrize(("message", "change"), [
|
|
("请在躺平模式里补充空调", "补充空调"),
|
|
("帮我给躺平模式添加空调", "添加空调"),
|
|
("为躺平模式新增阅读灯", "新增阅读灯"),
|
|
("躺平模式再补充车窗", "补充车窗"),
|
|
("躺平模式中再加入阅读灯", "再加入阅读灯"),
|
|
("在躺平模式中加入空调24度、阅读灯打开", "加入空调24度、阅读灯打开"),
|
|
("把空调24度、阅读灯打开加入到躺平模式中", "加入空调24度、阅读灯打开"),
|
|
("将车窗、氛围灯追加进躺平模式", "追加车窗、氛围灯"),
|
|
("请把空调加入躺平模式吧", "加入空调"),
|
|
("把副驾空调温度25.5度补充到躺平模式", "补充副驾空调温度25.5度"),
|
|
("在“躺平模式”中添加空调", "添加空调"),
|
|
])
|
|
def test_append_word_order_preserves_device_parameters_and_scoped_name(message, change):
|
|
parsed = parse_mode_profile_update(message)
|
|
assert parsed is not None and parsed[0] == "躺平模式"
|
|
# A leading 再 modifier is harmless; neither parameters nor target words
|
|
# may be lost when the reverse-order request is normalized.
|
|
assert parsed[1].removeprefix("再") == change.removeprefix("再")
|
|
|
|
|
|
@pytest.mark.parametrize("message", [
|
|
"不要在躺平模式中加入空调", "在躺平模式中不要加入空调",
|
|
"躺平模式中先不要补充阅读灯", "给躺平模式添加空调,但不要执行",
|
|
"给躺平模式添加空调,算了", "给躺平模式添加空调,撤销",
|
|
"躺平模式中取消加入空调", "如何在躺平模式中加入空调?",
|
|
"在躺平模式中加入空调好吗?", "在躺平模式中能否加入空调",
|
|
"把空调加入到躺平模式会怎样?", "解释在躺平模式中加入空调这句话",
|
|
"在躺平模式中加入哪些设备?", "引用在躺平模式中加入空调",
|
|
"在空调出风模式中加入阅读灯", "在副驾按摩模式中添加车窗",
|
|
"在躺平模式中加入", "给躺平模式补充",
|
|
])
|
|
def test_negated_read_only_or_device_property_requests_do_not_authorize_augmentation(message):
|
|
assert parse_mode_profile_update(message) is None
|
|
assert _validated_mode_profile_draft_context(DRAFT_REFERENCE, message=message) is None
|
|
authorization = _authorize_vehicle_request(message, CONTROL_TERMS, DRAFT_REFERENCE)
|
|
assert authorization.reason not in {"explicit_mode_profile_draft_update", "explicit_mode_profile_update"}
|
|
|
|
|
|
def test_other_named_mode_never_borrows_the_selected_draft_reference():
|
|
message = "在阅读模式中加入空调"
|
|
assert parse_mode_profile_update(message) == ("阅读模式", "加入空调")
|
|
assert _validated_mode_profile_draft_context(DRAFT_REFERENCE, message=message) is None
|
|
assert _authorize_vehicle_request(message, CONTROL_TERMS, DRAFT_REFERENCE).reason == "explicit_mode_profile_update"
|
|
|
|
|
|
def test_augmentation_reference_cannot_include_browser_supplied_device_actions():
|
|
reference = {**DRAFT_REFERENCE, "operations": [{"capability": "seat.anything"}]}
|
|
with pytest.raises(ValueError, match="fields are invalid"):
|
|
_validated_mode_profile_draft_context(reference, message="在躺平模式中加入空调")
|
|
|
|
|
|
def test_speech_update_shape_preserves_named_augmentation_even_when_negated():
|
|
assert is_mode_profile_update_shape("在躺平模式中加入空调,但不要执行")
|
|
assert parse_mode_profile_update("在躺平模式中加入空调,但不要执行") is None
|
|
|
|
|
|
def test_device_augmentation_bypasses_general_agent_and_partial_control_paths():
|
|
client = type("UnavailableClient", (), {"available": False})()
|
|
assistant = CodexAssistantService(client)
|
|
message = "在躺平模式中加入空调、氛围灯、阅读灯、车窗等设备动作"
|
|
calls = []
|
|
events = []
|
|
|
|
def execute_control(instruction, _progress):
|
|
calls.append(instruction)
|
|
return {
|
|
"request_id": "req-revised-123456", "status": "succeeded", "execution_mode": "dry_run",
|
|
"hardware_execution_allowed": False,
|
|
"orchestration_route": "mode_profile_create_preview",
|
|
"intent_ir": {"spec": {"actions": [{"domain": "climate"}]}},
|
|
"mode_profile_draft": {
|
|
"name": "躺平模式", "source_request_id": "req-revised-123456", "vehicle_id": "denza_n7",
|
|
"instruction": "进入躺平模式", "operation_count": 1,
|
|
"generation_source": "draft_revision", "draft_revision": 2,
|
|
},
|
|
}
|
|
|
|
reference = deepcopy(DRAFT_REFERENCE)
|
|
result = assistant.stream(
|
|
message, conversation_id="conv-augmentation-intent-123456", principal="test",
|
|
history=[], emit=events.append, execute_control=execute_control,
|
|
preview_control=lambda *_args: pytest.fail("augmentation must not run partial hardware controls"),
|
|
supplement_control=lambda *_args: pytest.fail("augmentation must not become a vehicle supplement"),
|
|
mode_profile_draft_context=reference, control_terms=CONTROL_TERMS,
|
|
)
|
|
assert calls == [message]
|
|
assert result["success"] is True
|
|
assert result["result"]["mode_profile_draft"]["name"] == "躺平模式"
|
|
assert reference == DRAFT_REFERENCE
|
|
assert events[0]["route"] == "vehicle_control"
|