from __future__ import annotations from pathlib import Path import pytest from cognitive_agent.infrastructure.speech.understanding import ( UnderstandingTranscriptProcessor, ) REPOSITORY_ROOT = Path(__file__).resolve().parents[2] @pytest.fixture(scope="module") def processor() -> UnderstandingTranscriptProcessor: return UnderstandingTranscriptProcessor(REPOSITORY_ROOT) def test_preview_only_request_preserves_duration_and_governing_connector( processor: UnderstandingTranscriptProcessor, ) -> None: result = processor.process( "主驾座椅靠背向后移动3s,先不要下发,给出解析的控制指令" ) assert result.assistant_text == ( "将主驾座椅靠背向后移动3秒,先不要下发,给出解析的控制指令。" ) assert result.clean_text == "将主驾座椅靠背向后移动3秒。" assert len(result.commands) == 1 command = result.commands[0] assert command.capability == "seat.set_driver_axis_native" assert command.parameters == { "axis": "backrest", "direction": "backward", "duration_ms": 3000, } assert "angle_delta_deg" not in command.parameters assert command.resolution_status == "unsupported" assert any("工程上限2000" in issue for issue in command.validation_issues) assert not result.execution_eligible @pytest.mark.parametrize( ("spoken", "duration_ms", "display"), ( ("2s", 2000, "2秒"), ("1.5秒", 1500, "1.5秒"), ("300ms", 300, "300毫秒"), ("300毫秒", 300, "300毫秒"), ("一秒", 1000, "1秒"), ("两秒", 2000, "2秒"), ("半秒", 500, "500毫秒"), ("一点五秒", 1500, "1.5秒"), ), ) def test_explicit_duration_units_remain_explicit_in_structured_and_display_text( processor: UnderstandingTranscriptProcessor, spoken: str, duration_ms: int, display: str, ) -> None: result = processor.process(f"主驾椅背向后移动{spoken}") assert result.commands[0].parameters["duration_ms"] == duration_ms assert "duration_ms" not in result.commands[0].qualifiers.get( "implicit_parameters", () ) assert display in result.clean_text assert display in result.assistant_text assert "angle_delta_deg" not in result.commands[0].parameters @pytest.mark.parametrize( ("spoken", "duration_ms"), (("3s", 3000), ("三秒", 3000), ("1分钟", 60_000)), ) def test_out_of_range_time_stays_a_duration_and_fails_closed( processor: UnderstandingTranscriptProcessor, spoken: str, duration_ms: int, ) -> None: result = processor.process(f"主驾座椅靠背向后移动{spoken}") command = result.commands[0] assert command.capability == "seat.set_driver_axis_native" assert command.parameters["duration_ms"] == duration_ms assert "angle_delta_deg" not in command.parameters assert command.resolution_status == "unsupported" assert not result.execution_eligible def test_time_unit_is_not_reinterpreted_as_passenger_backrest_angle( processor: UnderstandingTranscriptProcessor, ) -> None: result = processor.process("副驾座椅靠背向后移动3s") assert result.assistant_text == "副驾座椅靠背向后移动3s。" assert result.commands[0].parameters == {} assert result.commands[0].resolution_status == "incomplete" assert "seat_timed_motion_not_registered_for_scope" in result.reasons assert not result.execution_eligible def test_default_driver_axis_duration_remains_implicit( processor: UnderstandingTranscriptProcessor, ) -> None: result = processor.process("主驾座椅靠背向后移动") command = result.commands[0] assert command.parameters["duration_ms"] == 500 assert "duration_ms" in command.qualifiers["implicit_parameters"] assert "500" not in result.assistant_text assert result.assistant_text == "将主驾座椅靠背向后调整。"