完善模式卡片、NFC及多设备控制流程

This commit is contained in:
minghanchen
2026-09-01 16:18:57 +08:00
parent ca26259e63
commit cbf230182d
15 changed files with 1092 additions and 191 deletions
+176 -1
View File
@@ -621,7 +621,7 @@ operations:
if item["id"] == "office"
)
self.assertEqual(persisted["name"], "专注办公模式")
with self.assertRaisesRegex(ValueError, "重新点击执行"):
with self.assertRaisesRegex(ValueError, "生成指令"):
self.service.save_mode_profile_card(
"office",
"专注办公模式",
@@ -630,6 +630,181 @@ operations:
"denza_n7",
)
def test_saved_mode_card_executes_without_reinterpreting_instruction(self) -> None:
mode_root = Path(self.temporary_directory.name) / "direct-mode-presets"
user_root = Path(self.temporary_directory.name) / "direct-mode-user"
preset = mode_root / "vehicles" / "denza_n7" / "office.yaml"
preset.parent.mkdir(parents=True)
preset.write_text(
"""
id: office
name: 办公模式
icon: briefcase
scope:
vehicle_ids: [denza_n7]
operations:
- domain: climate
capability: climate.set_temperature
target_scope: driver
parameters:
temperature_c: 24
""".strip()
+ "\n",
encoding="utf-8",
)
self.service.mode_profiles = ModeProfileRegistry(
mode_root, user_root=user_root
)
instruction = "空调温度设置为25度,风速设置为1档"
generated = self.service.preview_native_can(
instruction,
provider="local",
conversation_id="conv-generate-office-card",
execution_mode="dry_run",
vehicle_id="denza_n7",
)
saved = self.service.save_mode_profile_card(
"office",
"办公模式",
instruction,
generated["request_id"],
"denza_n7",
)
with patch.object(
self.service,
"_interpret",
side_effect=AssertionError("saved mode must not reinterpret natural language"),
):
executed = self.service.execute_mode_profile_card(
"office",
conversation_id="conv-execute-office-card",
execution_mode="dry_run",
vehicle_id="denza_n7",
)
operations = [
operation
for config in executed.get("function_configs", {}).values()
for operation in config.get("spec", {}).get("operations", [])
]
self.assertEqual(executed["status"], "succeeded")
self.assertEqual(executed["utterance"], "办公模式")
self.assertEqual(executed["provider_used"], "saved_mode_command_flow")
self.assertEqual(executed["orchestration_route"], "saved_mode_command_flow")
self.assertEqual(
[
(
operation["capability"],
operation["target"]["zone"],
operation["parameters"],
operation["parse_source"],
)
for operation in operations
],
[
(
"climate.set_temperature",
"driver",
{"temperature_c": 25},
"saved_mode_command_flow",
),
(
"climate.set_fan_level",
"vehicle",
{"level": 1},
"saved_mode_command_flow",
),
],
)
self.assertEqual(
saved["mode_profile"]["command_flow"]["execution_steps"], []
)
def test_saved_mode_card_replays_front_right_dynamic_target_as_passenger(
self,
) -> None:
mode_root = Path(self.temporary_directory.name) / "dynamic-mode-presets"
user_root = Path(self.temporary_directory.name) / "dynamic-mode-user"
self.service.mode_profiles = ModeProfileRegistry(
mode_root,
user_root=user_root,
)
self.service.mode_profiles.save_mode(
"小憩模式",
[
{
"domain": "seat",
"capability": "seat.start_dynamic_mode",
"target_scope": "front_right",
"parameters": {"mode_id": 2},
},
{
"domain": "climate",
"capability": "climate.set_power",
"target_scope": "vehicle",
"parameters": {"state": "on"},
},
{
"domain": "roof",
"capability": "roof.set_shade_motion",
"target_scope": "vehicle",
"parameters": {"motion": "open"},
},
],
mode_id="nap",
vehicle_id="denza_n7",
instruction="打开摇篮模式,开启空调",
command_flow={
"schema": "cognitive-agent-mode-command-flow/v1",
"source_request_id": "req-saved-dynamic-mode",
"plans": {
"local_seat": {
"spec": {
"commands": [
{
"message": "Seat_Dynamic_Mode_Virtual",
"signals": {"Dynamic_Mode_ID": 2},
}
]
}
}
},
},
)
with patch.object(
self.service,
"_interpret",
side_effect=AssertionError("saved mode must not reinterpret natural language"),
):
executed = self.service.execute_mode_profile_card(
"nap",
conversation_id="conv-execute-saved-dynamic-card",
execution_mode="dry_run",
vehicle_id="denza_n7",
)
self.assertEqual(executed["status"], "succeeded")
self.assertEqual(executed["utterance"], "小憩模式")
self.assertEqual(executed["provider_used"], "saved_mode_command_flow")
self.assertFalse(
[item for item in executed.get("validation", []) if item["severity"] == "error"]
)
dynamic_request = next(
item
for item in executed["model_requests"]
if item["capability"] == "seat.start_dynamic_mode"
)
self.assertEqual(dynamic_request["target_scope"], "passenger")
self.assertTrue(executed["command_plans"])
replayed_capabilities = {
operation["capability"]
for config in executed["function_configs"].values()
for operation in config["spec"]["operations"]
}
self.assertIn("roof.set_shade_motion", replayed_capabilities)
def test_build_named_mode_executes_and_persists_in_one_turn(self) -> None:
mode_root = Path(self.temporary_directory.name) / "modes"
self.service.mode_profiles = ModeProfileRegistry(mode_root)