feat: make mode creation preview-only and cache-safe
This commit is contained in:
@@ -60,6 +60,27 @@ def _action_map(
|
||||
}
|
||||
|
||||
|
||||
def _assert_default_control_bundle(result: Mapping[str, object]) -> None:
|
||||
actions = _action_map(result)
|
||||
assert actions["climate.set_power", "vehicle"] == {"state": "on"}
|
||||
assert ("climate.set_temperature", "vehicle") in actions
|
||||
assert ("climate.set_fan_level", "vehicle") in actions
|
||||
assert ("climate.set_cycle_mode", "vehicle") in actions
|
||||
for target in ("front_left", "front_right", "rear_left", "rear_right"):
|
||||
assert actions["window.set_position", target] == {"position_pct": 0}
|
||||
assert ("roof.set_shade_position", "vehicle") in actions
|
||||
assert actions["seat.set_ventilation", "passenger"] == {
|
||||
"state": "on",
|
||||
"level": 1,
|
||||
}
|
||||
assert ("seat.set_backrest_recline", "passenger") in actions
|
||||
assert ("seat.set_legrest_height", "passenger") in actions
|
||||
assert any(
|
||||
capability.startswith("ambient_light.")
|
||||
for capability, _target in actions
|
||||
)
|
||||
|
||||
|
||||
def _draft_reference(result: Mapping[str, object]) -> dict[str, str]:
|
||||
draft = result.get("mode_profile_draft")
|
||||
assert isinstance(draft, Mapping)
|
||||
@@ -225,7 +246,7 @@ def test_all_production_scene_templates_complete_the_full_local_dry_run(
|
||||
assert not list(user_root.rglob("*.yaml"))
|
||||
|
||||
|
||||
def test_viewing_template_creates_an_unbound_audited_copy_without_codex(
|
||||
def test_viewing_template_seeds_a_complete_unbound_preview_without_codex(
|
||||
hybrid_service: tuple[SeatDemoService, AssistantCapabilityCatalog, Path],
|
||||
) -> None:
|
||||
service, catalog, user_root = hybrid_service
|
||||
@@ -249,15 +270,16 @@ def test_viewing_template_creates_an_unbound_audited_copy_without_codex(
|
||||
assert raw_result["execution_mode"] == "dry_run"
|
||||
assert raw_result["hardware_execution_allowed"] is False
|
||||
assert draft["name"] == "观影模式"
|
||||
assert draft["generation_source"] == "scene_template_copy"
|
||||
assert draft["source_template_id"] == "cinema"
|
||||
assert draft["source_template_revision"]
|
||||
assert draft["generation_source"] == "codex_scene_composition"
|
||||
assert "source_template_id" not in draft
|
||||
assert "source_template_revision" not in draft
|
||||
assert "existing_mode_id" not in draft
|
||||
assert "existing_mode_revision" not in draft
|
||||
assert raw_result["mode_creation"]["source_template_id"] == "cinema"
|
||||
assert passed_plans[0]["metadata"]["source"] == "scene_template"
|
||||
assert "source_template_id" not in raw_result["mode_creation"]
|
||||
assert "metadata" not in passed_plans[0]
|
||||
_assert_default_control_bundle(raw_result)
|
||||
assert events[0]["engine"] == "n7web-scene-template"
|
||||
assert "独立草稿" in response["answer"]
|
||||
assert "创建阶段不会下发" in response["answer"]
|
||||
assert not list(user_root.rglob("*.yaml"))
|
||||
client.start_structured_turn.assert_not_called()
|
||||
client.start_turn.assert_not_called()
|
||||
@@ -319,7 +341,6 @@ def test_purpose_descriptions_use_a_concise_name_and_zero_model_template_route(
|
||||
conversation_id=f"conv-template-{case_id}",
|
||||
)
|
||||
|
||||
template = service.scene_templates.get_template(template_id)
|
||||
draft = raw_result["mode_profile_draft"]
|
||||
assert response["route"] == "scene_template"
|
||||
assert response["success"] is True
|
||||
@@ -328,13 +349,11 @@ def test_purpose_descriptions_use_a_concise_name_and_zero_model_template_route(
|
||||
assert raw_result["execution_mode"] == "dry_run"
|
||||
assert raw_result["hardware_execution_allowed"] is False
|
||||
assert draft["name"] == expected_name
|
||||
assert draft["generation_source"] == "scene_template_copy"
|
||||
assert draft["source_template_id"] == template_id
|
||||
assert draft["operation_count"] == sum(
|
||||
operation.domain != "seat" or operation.target_scope == "passenger"
|
||||
for operation in template.operations
|
||||
)
|
||||
assert passed_plans[0]["metadata"]["template_id"] == template_id
|
||||
assert draft["generation_source"] == "codex_scene_composition"
|
||||
assert "source_template_id" not in draft
|
||||
assert draft["operation_count"] == len(_actions(raw_result))
|
||||
assert "metadata" not in passed_plans[0]
|
||||
_assert_default_control_bundle(raw_result)
|
||||
assert events[0]["engine"] == "n7web-scene-template"
|
||||
assert not list(user_root.rglob("*.yaml"))
|
||||
client.start_structured_turn.assert_not_called()
|
||||
@@ -396,7 +415,14 @@ def test_seating_comfort_requests_preview_only_passenger_with_no_model_or_hardwa
|
||||
assert result["execution_mode"] == "dry_run"
|
||||
assert result["hardware_execution_allowed"] is False
|
||||
assert result["mode_profile_draft"]["name"] == expected_name
|
||||
assert result["mode_profile_draft"]["source_template_id"] == template_id
|
||||
if "座椅" in message:
|
||||
assert result["mode_profile_draft"]["source_template_id"] == template_id
|
||||
else:
|
||||
assert result["mode_profile_draft"]["generation_source"] == (
|
||||
"codex_scene_composition"
|
||||
)
|
||||
assert "source_template_id" not in result["mode_profile_draft"]
|
||||
_assert_default_control_bundle(result)
|
||||
seat_actions = {
|
||||
(capability, target): parameters
|
||||
for (capability, target), parameters in _action_map(result).items()
|
||||
@@ -524,8 +550,10 @@ def test_template_alias_keeps_the_user_requested_draft_name(
|
||||
draft = raw_result["mode_profile_draft"]
|
||||
assert response["route"] == "scene_template"
|
||||
assert draft["name"] == "影院模式"
|
||||
assert draft["source_template_id"] == "cinema"
|
||||
assert passed_plans[0]["metadata"]["template_id"] == "cinema"
|
||||
assert draft["generation_source"] == "codex_scene_composition"
|
||||
assert "source_template_id" not in draft
|
||||
assert "metadata" not in passed_plans[0]
|
||||
_assert_default_control_bundle(raw_result)
|
||||
client.start_structured_turn.assert_not_called()
|
||||
client.start_turn.assert_not_called()
|
||||
|
||||
@@ -574,7 +602,7 @@ def test_template_copy_can_be_revised_twice_without_losing_sibling_actions(
|
||||
assert shade_revised["execution_mode"] == final["execution_mode"] == "dry_run"
|
||||
assert shade_revised["hardware_execution_allowed"] is False
|
||||
assert final["hardware_execution_allowed"] is False
|
||||
assert len(built_actions) == len(shade_actions) == len(final_actions) == 10
|
||||
assert len(built_actions) == len(shade_actions) == len(final_actions) == 16
|
||||
assert built_actions[shade_key] == {"position_pct": 0}
|
||||
assert shade_actions[shade_key] == final_actions[shade_key] == {"position_pct": 100}
|
||||
assert built_actions[temperature_key] == shade_actions[temperature_key] == {"temperature_c": 24}
|
||||
@@ -592,7 +620,8 @@ def test_template_copy_can_be_revised_twice_without_losing_sibling_actions(
|
||||
assert final_draft["draft_revision"] == 3
|
||||
assert second_draft["generation_source"] == "draft_revision"
|
||||
assert final_draft["generation_source"] == "draft_revision"
|
||||
assert second_draft["source_template_id"] == final_draft["source_template_id"] == ("cinema")
|
||||
assert "source_template_id" not in second_draft
|
||||
assert "source_template_id" not in final_draft
|
||||
assert "existing_mode_id" not in final_draft
|
||||
assert not list(user_root.rglob("*.yaml"))
|
||||
|
||||
@@ -626,7 +655,8 @@ def test_saving_a_template_copy_never_mutates_template_and_registered_mode_wins_
|
||||
assert list(user_root.rglob(f"{saved_profile['id']}.yaml"))
|
||||
assert _template_hashes() == hashes_before
|
||||
assert service.scene_templates.get_template("cinema").revision == template_revision
|
||||
assert first_plans[0]["metadata"]["template_id"] == "cinema"
|
||||
assert "metadata" not in first_plans[0]
|
||||
_assert_default_control_bundle(built)
|
||||
first_client.start_structured_turn.assert_not_called()
|
||||
|
||||
response, registered, events, second_client, passed_plans = _assistant_preview(
|
||||
|
||||
Reference in New Issue
Block a user