fix: restore mode clicks and compose seat-aware assistant scenes

This commit is contained in:
vee
2026-09-12 13:33:38 +08:00
parent 76057be044
commit d09b5967f8
28 changed files with 1247 additions and 44 deletions
@@ -0,0 +1,235 @@
from __future__ import annotations
from unittest.mock import patch
import pytest
from cognitive_agent.application.assistant_capabilities import AssistantCapabilityCatalog
from cognitive_agent.application.mode_profile import ModeProfileRegistry
from cognitive_agent.application.scene_composer import normalize_scene_output
from cognitive_agent.application.seat_service import REPOSITORY_ROOT, SeatDemoService
from cognitive_agent.application.semantic_ir import resolve_scene_seat_scopes
@pytest.fixture(scope="module")
def scene_service(tmp_path_factory):
service = SeatDemoService()
service.artifact_root = tmp_path_factory.mktemp("scene-explicit-seat-scope")
service.mode_profiles = ModeProfileRegistry(
REPOSITORY_ROOT / "config" / "modes",
user_root=tmp_path_factory.mktemp("scene-explicit-seat-user-modes"),
)
try:
yield service, AssistantCapabilityCatalog(service).scene_composition_context()
finally:
service.close()
def _plan(context, scopes):
requests = []
if "driver" in scopes:
requests.append({
"capability": "seat.set_driver_massage_native",
"target_scope": "driver",
"parameters": {"action": "mode", "mode": "relax"},
})
if "passenger" in scopes:
requests.append({
"capability": "seat.set_backrest_recline",
"target_scope": "passenger",
"parameters": {"position_pct": 45},
})
requests.append({
"capability": "climate.set_temperature",
"target_scope": "vehicle",
"parameters": {"temperature_c": 24},
})
return normalize_scene_output({
"requests": requests, "ambiguities": [], "confidence": 0.95,
}, context)
def _preview(
scene_service, message, scopes=("driver", "passenger"), *, execution_mode="hardware",
):
service, context = scene_service
with patch.object(
service.hardware_execution, "reserve",
side_effect=AssertionError("scene scope validation must not execute hardware"),
):
return service.preview_native_can(
message,
provider="local",
conversation_id="conv-explicit-scene-seat-scope",
execution_mode=execution_mode,
vehicle_id="denza_n7",
assistant_plan=_plan(context, scopes),
)
@pytest.mark.parametrize("message", (
"构建一个主驾座椅舒适模式",
"创建一个仅主驾舒适模式",
"创建一个只给驾驶员坐着放松的功能模式",
"构建一个副驾座椅舒适模式",
"构建一个仅副驾舒适模式",
"构建一个右前座椅舒适模式",
"构建一个后排座椅舒适模式",
"构建一个主驾座椅与副驾空调舒适模式",
"构建一个主驾阅读灯与副驾座椅舒适模式",
))
def test_explicit_scene_seat_scope_rejects_cross_seat_plan_atomically(scene_service, message):
result = _preview(scene_service, message)
assert result["status"] != "succeeded"
assert result.get("mode_profile_draft") is None
assert result["hardware_execution_allowed"] is False
assert result.get("command_plan") is None
assert result.get("command_plans") == {}
intent = result.get("intent_ir") or {}
assert (intent.get("spec") or {}).get("actions", []) == []
assert any("座位范围" in item["message"] for item in result["validation"])
@pytest.mark.parametrize(("message", "scopes"), (
("构建一个主驾座椅舒适模式", ("driver",)),
("构建一个副驾座椅舒适模式", ("passenger",)),
("创建一个仅主驾舒适模式", ("driver",)),
("构建一个主驾和副驾座椅舒适模式", ("driver", "passenger")),
("构建一个主副驾座椅舒适模式", ("driver", "passenger")),
("构建一个云端座椅舒适模式", ("driver", "passenger")),
("构建一个副驾空调与座椅舒适模式", ("driver", "passenger")),
("构建一个座椅舒适与副驾阅读灯模式", ("driver", "passenger")),
("构建一个主驾座椅与副驾空调舒适模式", ("driver",)),
("构建一个主驾阅读灯与副驾座椅舒适模式", ("passenger",)),
))
def test_scene_scope_preserves_supported_targets_without_borrowing_other_device_zones(
scene_service, message, scopes,
):
result = _preview(scene_service, message, scopes)
assert result["status"] == "succeeded", result.get("validation")
assert result["mode_profile_draft"]
assert result["execution_mode"] == "dry_run"
assert result["hardware_execution_allowed"] is False
actions = result["intent_ir"]["spec"]["actions"]
assert {
action["target"]["instance"]
for action in actions if action["domain"] == "seat"
} == set(scopes)
@pytest.mark.parametrize("message", (
"构建一个主驾舒适模式,副驾不要动",
"构建一个主驾舒适模式,不要动副驾",
"构建一个舒展模式,座椅靠背调整到45%",
))
def test_explicit_atomic_requirements_do_not_receive_scene_scope_relaxation(
scene_service, message,
):
result = _preview(scene_service, message, execution_mode="dry_run")
assert result["status"] != "succeeded"
assert result.get("mode_profile_draft") is None
assert result["hardware_execution_allowed"] is False
def test_explicit_atomic_requirements_override_label_without_adding_model_actions(scene_service):
result = _preview(scene_service, "构建一个主驾舒适模式,副驾靠背调整到45%")
assert result["status"] == "succeeded"
assert result["execution_mode"] == "dry_run"
actions = result["intent_ir"]["spec"]["actions"]
assert len(actions) == 1
assert actions[0]["capability"] == "seat.set_backrest_recline"
assert actions[0]["target"]["instance"] == "passenger"
assert actions[0]["parameters"]["position_pct"] == 45
def test_rear_window_scene_is_not_rejected_as_an_unsupported_seat(scene_service):
service, context = scene_service
plan = normalize_scene_output({
"requests": [{
"capability": "window.set_position",
"target_scope": "rear_right",
"parameters": {"position_pct": 45},
}],
"ambiguities": [], "confidence": 0.95,
}, context)
result = service.preview_native_can(
"构建一个后排换气模式", provider="local",
conversation_id="conv-rear-window-not-seat",
execution_mode="dry_run", vehicle_id="denza_n7", assistant_plan=plan,
)
assert result["status"] == "succeeded"
assert result["mode_profile_draft"]
@pytest.mark.parametrize(("text", "expected"), (
("进入主驾舒适模式", frozenset({"driver"})),
("进入仅副驾舒适模式", frozenset({"passenger"})),
("进入主副驾座椅舒适模式", frozenset({"driver", "passenger"})),
("进入主驾座椅与副驾的空调舒适模式", frozenset({"driver"})),
("进入副驾座椅与主驾的阅读灯模式", frozenset({"passenger"})),
("进入座椅舒适与右前车窗模式", None),
("进入座椅舒适与后排阅读灯模式", None),
("进入后排座椅舒适模式", frozenset({"unsupported"})),
))
def test_scene_scope_resolution_only_uses_seat_or_unqualified_scene_targets(text, expected):
assert resolve_scene_seat_scopes(text) == expected
def test_new_creation_cannot_borrow_draft_reference_to_bypass_explicit_scope(scene_service):
service, context = scene_service
built = _preview(scene_service, "构建一个主驾独享舒适模式", ("driver",))
reference = {key: built["mode_profile_draft"][key] for key in (
"name", "source_request_id", "vehicle_id",
)}
result = service.preview_native_can(
"构建一个主驾独享舒适模式", provider="local",
conversation_id="conv-explicit-scene-seat-scope", execution_mode="dry_run",
vehicle_id="denza_n7", assistant_plan=_plan(context, ("driver", "passenger")),
mode_profile_draft_context=reference,
)
assert result["status"] != "succeeded"
assert not result.get("mode_profile_draft")
@pytest.mark.parametrize(("initial_scope", "name", "change", "added_capability"), (
("driver", "主驾释压舒适模式", "副驾座椅通风调整为1档", "seat.set_ventilation"),
("passenger", "副驾释压舒适模式", "主驾座椅通风调整为低档", "seat.set_driver_ventilation_native"),
))
def test_explicit_revision_can_extend_old_label_scope_then_save_and_replay(
scene_service, initial_scope, name, change, added_capability,
):
service, _context = scene_service
built = _preview(scene_service, f"构建一个{name}", (initial_scope,))
source_draft = built["mode_profile_draft"]
reference = {key: source_draft[key] for key in (
"name", "source_request_id", "vehicle_id",
)}
revised = service.preview_native_can(
f"把{name}的{change}", provider="local",
conversation_id="conv-explicit-scene-seat-scope", execution_mode="dry_run",
vehicle_id="denza_n7", mode_profile_draft_context=reference,
)
assert revised["status"] == "succeeded", revised.get("validation")
draft = revised["mode_profile_draft"]
assert draft["generation_source"] == "draft_revision"
assert draft["operation_count"] == source_draft["operation_count"] + 1
actions = revised["intent_ir"]["spec"]["actions"]
assert added_capability in {action["capability"] for action in actions}
assert {
action["target"]["instance"] for action in actions if action["domain"] == "seat"
} == {"driver", "passenger"}
saved = service.create_mode_profile_card(
draft["name"], draft["instruction"], draft["source_request_id"], draft["vehicle_id"],
)
assert saved["status"] == "succeeded"
replayed = service.execute_mode_profile_card(
saved["mode_profile"]["id"], execution_mode="dry_run", vehicle_id="denza_n7",
)
assert replayed["status"] == "succeeded", replayed.get("validation")
assert {
(action["capability"], action["target"]["instance"])
for action in replayed["intent_ir"]["spec"]["actions"] if action["domain"] == "seat"
} == {
(action["capability"], action["target"]["instance"])
for action in actions if action["domain"] == "seat"
}