fix: compose named cockpit modes from capabilities
This commit is contained in:
@@ -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"),
|
||||
[
|
||||
|
||||
Reference in New Issue
Block a user