from __future__ import annotations import os import tempfile from pathlib import Path from unittest.mock import patch import pytest from cognitive_agent.application.seat_service import SeatDemoService from cognitive_agent.infrastructure.speech.understanding import ( UnderstandingTranscriptProcessor, ) REPOSITORY_ROOT = Path(__file__).resolve().parents[2] @pytest.mark.parametrize( ("utterance", "capability", "target", "parameters"), ( ( "打开一半车窗", "window.set_position", {"device": "window", "zone": "front_left"}, {"position_pct": 50}, ), ( "把副驾腿托向上调整到最大位置", "seat.set_legrest_height", {"device": "seat", "zone": "front_right", "instance": "passenger"}, {"position_pct": 100}, ), ( "把遮阳帘打开", "roof.set_shade_motion", {"device": "roof", "zone": "vehicle"}, {"motion": "open"}, ), ( "遮阳帘打开一半", "roof.set_shade_motion", {"device": "roof", "zone": "vehicle"}, {"motion": "half"}, ), ( "把遮阳帘打开到四分之一", "roof.set_shade_position", {"device": "roof", "zone": "vehicle"}, {"position_pct": 25}, ), ), ) def test_server_owned_speech_semantics_bypass_second_language_parse( utterance: str, capability: str, target: dict[str, str], parameters: dict[str, int], ) -> None: processor = UnderstandingTranscriptProcessor(REPOSITORY_ROOT) understanding = processor.process(utterance).to_dict() understanding["utterance_id"] = "bridge-regression" with tempfile.TemporaryDirectory() as directory, patch.dict( os.environ, { "COGNITIVE_AGENT_HARDWARE_EXECUTION_ENABLED": "false", "COGNITIVE_AGENT_VEHICLE_CAN_ENABLED": "false", "COGNITIVE_AGENT_VEHICLE_MQTT_ENABLED": "false", }, clear=False, ): service = SeatDemoService(REPOSITORY_ROOT) service.artifact_root = Path(directory) / "artifacts" with patch.object( service, "_interpret", side_effect=AssertionError("cleanText must not be parsed a second time"), ): result = service.process( understanding["clean_text"], provider="local", execution_mode="dry_run", _speech_understanding=understanding, ) assert result["status"] == "succeeded" assert result["provider_used"] == "speech_semantic" assert result["speech_understanding"]["raw_text"] == utterance actions = result["intent_ir"]["spec"]["actions"] assert len(actions) == 1 assert actions[0]["capability"] == capability assert actions[0]["target"] == target assert actions[0]["parameters"] == parameters assert actions[0]["provenance"]["parser"] == "speech_semantic" def test_non_executable_speech_cannot_enter_orchestration_bridge() -> None: processor = UnderstandingTranscriptProcessor(REPOSITORY_ROOT) understanding = processor.process("打开前大灯").to_dict() understanding["utterance_id"] = "bridge-unsupported" with patch.dict( os.environ, { "COGNITIVE_AGENT_HARDWARE_EXECUTION_ENABLED": "false", "COGNITIVE_AGENT_VEHICLE_CAN_ENABLED": "false", }, clear=False, ): service = SeatDemoService(REPOSITORY_ROOT) context = service._context_for_vehicle( service.conversations.snapshot("conv-speech-bridge"), service.vehicle_profiles.get(None), ) with pytest.raises(ValueError, match="not execution eligible"): service._adapt_speech_understanding( understanding, context, service.vehicle_profiles.get(None), ) def test_every_registered_native_runtime_capability_keeps_native_bridge_binding() -> None: def valid_value(spec: dict[str, object]) -> object: allowed = spec.get("allowed_values") if isinstance(allowed, list) and allowed: return allowed[0] value_type = str(spec.get("type", "string")) if value_type in {"integer", "number"}: return spec.get("minimum", 0) if value_type == "boolean": return True if value_type == "object": return {} if value_type == "array": return [] return "test" with patch.dict( os.environ, { "COGNITIVE_AGENT_HARDWARE_EXECUTION_ENABLED": "false", "COGNITIVE_AGENT_VEHICLE_CAN_ENABLED": "false", }, clear=False, ): service = SeatDemoService(REPOSITORY_ROOT) context = service._context_for_vehicle( service.conversations.snapshot("conv-native-speech-matrix"), service.vehicle_profiles.get(None), ) registered = { definition.name: definition for definition in service.capability_registry.definitions() if definition.name in service.native_can_runtime.supported_capabilities } assert registered for capability, definition in registered.items(): parameters = { str(spec["name"]): valid_value(spec) for spec in definition.parameters if spec.get("required") } target = definition.target_scopes[0] understanding = { "raw_text": f"native bridge matrix: {capability}", "execution_eligible": True, "commands": [ { "status": "active", "negated": False, "resolution_status": "executable", "validation_issues": [], "confidence": 1.0, "source_text": capability, "executor_payload": { "domain": definition.domain, "capability": capability, "target": target, "operation": "set", "parameters": parameters, }, } ], } parsed = service._adapt_speech_understanding( understanding, context, service.vehicle_profiles.get(None), ) assert parsed["deferred_requests"] == [], capability assert parsed["actions"] == [], capability assert parsed["domain_actions"] == [], capability assert [ action["capability"] for action in parsed["native_can_actions"] ] == [capability]