fix: compose named cockpit modes from capabilities

This commit is contained in:
vee
2026-09-07 20:52:19 +08:00
parent cf9b89508c
commit 6b2b644ee6
23 changed files with 2917 additions and 124 deletions
+158
View File
@@ -67,6 +67,7 @@ def _guard(
plan: dict[str, object],
*,
trusted_local: dict[str, object] | None = None,
allow_scene_composition: bool = False,
):
return guard_assistant_plan(
plan,
@@ -74,6 +75,7 @@ def _guard(
capability_context=service.capability_context,
executable_capabilities=_executable_capabilities(service),
trusted_local=trusted_local,
allow_scene_composition=allow_scene_composition,
)
@@ -85,6 +87,162 @@ def _operations(result: dict[str, object]) -> list[dict[str, object]]:
]
def test_scene_composition_relaxes_only_text_evidence_for_an_atomic_dry_run(
service: SeatDemoService,
) -> None:
scene_plan = _plan(
_request(
"climate",
"climate.set_temperature",
"vehicle",
{"temperature_c": 24},
),
_request(
"roof",
"roof.set_shade_position",
"vehicle",
{"position_pct": 0},
),
)
ordinary = _guard(service, "进入午休模式", scene_plan)
scene = _guard(
service,
"进入午休模式",
scene_plan,
allow_scene_composition=True,
)
assert ordinary.plan["requests"] == []
assert [item["capability"] for item in scene.plan["requests"]] == [
"climate.set_temperature",
"roof.set_shade_position",
]
assert scene.rejected_requests == ()
@pytest.mark.parametrize(
"plan",
(
_plan(
_request(
"seat",
"seat.save_posture_preset",
"passenger",
{"preset_name": "午休"},
operation="save",
)
),
_plan(
_request(
"climate",
"climate.set_temperature",
"vehicle",
{"temperature_c": 24},
operation="increase",
)
),
_plan(
_request(
"climate",
"climate.set_temperature",
"vehicle",
{"temperature_c": 24},
duration_ms=3_000,
)
),
_plan(
_request(
"climate",
"climate.set_temperature",
"vehicle",
{"temperature_c": 24},
),
_request(
"climate",
"climate.set_temperature",
"vehicle",
{"temperature_c": 25},
),
),
{
**_plan(
_request(
"climate",
"climate.set_temperature",
"vehicle",
{"temperature_c": 24},
)
),
"ambiguities": [{"field": "temperature", "question": "24 or 25"}],
},
),
)
def test_scene_composition_rejects_non_repeatable_or_non_atomic_plans(
service: SeatDemoService,
plan: dict[str, object],
) -> None:
guarded = _guard(
service,
"进入午休模式",
plan,
allow_scene_composition=True,
)
assert guarded.plan["requests"] == []
assert guarded.rejected_requests
def test_scene_composition_rejects_the_whole_plan_when_one_capability_is_unknown(
service: SeatDemoService,
) -> None:
guarded = _guard(
service,
"进入午休模式",
_plan(
_request(
"climate",
"climate.set_temperature",
"vehicle",
{"temperature_c": 24},
),
_request("flight", "vehicle.fly", "vehicle", {"altitude_m": 100}),
),
allow_scene_composition=True,
)
assert guarded.plan["requests"] == []
assert len(guarded.rejected_requests) == 1
def test_scene_composition_uses_native_fan_bounds_and_rejects_siblings_atomically(
service: SeatDemoService,
) -> None:
guarded = _guard(
service,
"进入静享模式",
_plan(
_request(
"climate",
"climate.set_fan_level",
"vehicle",
{"level": 0},
),
_request(
"climate",
"climate.set_temperature",
"vehicle",
{"temperature_c": 24},
),
),
allow_scene_composition=True,
)
assert guarded.plan["requests"] == []
assert len(guarded.rejected_requests) == 1
assert "1-7" in guarded.rejected_requests[0]["question"]
@pytest.mark.parametrize(
("text", "plan_request", "expected_capability", "expected_parameters"),
[