feat: complete dual-seat whole-vehicle orchestration
This commit is contained in:
@@ -19,6 +19,7 @@ from cognitive_agent.application.self_extension import (
|
||||
build_gateway_command,
|
||||
validate_slot,
|
||||
)
|
||||
from cognitive_agent.application.zcan_seat_executor import ZcanBridgeSeatExecutor
|
||||
|
||||
|
||||
class SelfExtensionTests(unittest.TestCase):
|
||||
@@ -138,7 +139,7 @@ class SelfExtensionTests(unittest.TestCase):
|
||||
"_request_gpt_plan",
|
||||
return_value=json.dumps(proposed),
|
||||
):
|
||||
with self.assertRaisesRegex(ExtensionIntegrationError, "CH1"):
|
||||
with self.assertRaisesRegex(ExtensionIntegrationError, "双通道"):
|
||||
service.plan(
|
||||
{
|
||||
"utterance": "打开座椅通风",
|
||||
@@ -225,7 +226,59 @@ class SelfExtensionTests(unittest.TestCase):
|
||||
command_schema = request_payload["text"]["format"]["schema"]["properties"][
|
||||
"steps"
|
||||
]["items"]["properties"]["command"]
|
||||
self.assertEqual(command_schema["enum"], ["", "ac off"])
|
||||
self.assertEqual(command_schema["type"], "string")
|
||||
self.assertEqual(command_schema["maxLength"], 300)
|
||||
|
||||
def test_plan_accepts_bounded_passenger_position_for_declared_ch0_executor(
|
||||
self,
|
||||
) -> None:
|
||||
service = SelfExtensionService(SimulationGateway())
|
||||
proposed = {
|
||||
"summary": "调整副驾",
|
||||
"needs_confirmation": False,
|
||||
"question": "",
|
||||
"steps": [
|
||||
{
|
||||
"kind": "vehicle",
|
||||
"capability_id": "",
|
||||
"command": "副驾水平调到63%",
|
||||
"label": "副驾水平位置 63%",
|
||||
"delay_ms": 0,
|
||||
}
|
||||
],
|
||||
}
|
||||
payload = {
|
||||
"utterance": "副驾水平位置调到63%",
|
||||
"peripherals": [],
|
||||
"vehicle_devices": [
|
||||
{
|
||||
"id": "passenger-seat",
|
||||
"name": "副驾座椅",
|
||||
"channel": "CH0",
|
||||
"actions": [
|
||||
{"name": "副驾水平 50%", "command": "副驾水平调到50%"}
|
||||
],
|
||||
}
|
||||
],
|
||||
}
|
||||
with patch.dict(os.environ, {"OPENAI_API_KEY": "test-key"}, clear=False):
|
||||
with patch.object(
|
||||
service,
|
||||
"_request_gpt_plan",
|
||||
return_value=json.dumps(proposed, ensure_ascii=False),
|
||||
):
|
||||
result = service.plan(payload)
|
||||
self.assertEqual(result["steps"][0]["command"], "副驾水平调到63%")
|
||||
|
||||
proposed["steps"][0]["command"] = "副驾水平调到101%"
|
||||
with patch.dict(os.environ, {"OPENAI_API_KEY": "test-key"}, clear=False):
|
||||
with patch.object(
|
||||
service,
|
||||
"_request_gpt_plan",
|
||||
return_value=json.dumps(proposed, ensure_ascii=False),
|
||||
):
|
||||
with self.assertRaisesRegex(ExtensionIntegrationError, "双通道"):
|
||||
service.plan(payload)
|
||||
|
||||
def test_vehicle_execution_reuses_the_same_orchestration_service(self) -> None:
|
||||
with patch.dict(
|
||||
@@ -515,6 +568,93 @@ class SelfExtensionTests(unittest.TestCase):
|
||||
self.assertFalse(rejected["success"])
|
||||
self.assertFalse(rejected["physical_feedback_confirmed"])
|
||||
|
||||
def test_ch0_passenger_feedback_requires_shared_runtime_physical_snapshot(
|
||||
self,
|
||||
) -> None:
|
||||
operation = {
|
||||
"ref": "passenger-longitudinal-63",
|
||||
"domain": "seat",
|
||||
"status": "succeeded",
|
||||
"telemetry": {
|
||||
"transport": "shared_can_runtime",
|
||||
"channel": 0,
|
||||
"simulated": False,
|
||||
"hardware_feedback": True,
|
||||
"feedback_required": True,
|
||||
"feedback_observed": True,
|
||||
"feedback_match": True,
|
||||
"physical_state": {
|
||||
"source": "physical_can",
|
||||
"channel": 0,
|
||||
"target": {
|
||||
"device": "seat",
|
||||
"zone": "front_right",
|
||||
"instance": "passenger",
|
||||
},
|
||||
"position": {
|
||||
"longitudinal": {
|
||||
"position_pct": 63,
|
||||
"position_valid": True,
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
verified = SelfExtensionService._authoritative_vehicle_feedback_state(
|
||||
operation
|
||||
)
|
||||
self.assertIsNotNone(verified)
|
||||
self.assertEqual(verified["verification"]["channel"], 0)
|
||||
|
||||
operation["telemetry"]["transport"] = "untrusted_bridge"
|
||||
self.assertIsNone(
|
||||
SelfExtensionService._authoritative_vehicle_feedback_state(operation)
|
||||
)
|
||||
|
||||
def test_ch0_bridge_report_exposes_verified_passenger_snapshot(self) -> None:
|
||||
function_config = {
|
||||
"metadata": {"request_id": "req-ch0-extension"},
|
||||
"spec": {
|
||||
"operations": [
|
||||
{
|
||||
"id": "passenger-longitudinal-63",
|
||||
"capability": "seat.set_longitudinal_position",
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
bridge_result = {
|
||||
"result": "PASS",
|
||||
"details": {
|
||||
"summary": "物理反馈达到目标",
|
||||
"motors": [
|
||||
{
|
||||
"position": 6300 if index == 0 else 5000,
|
||||
"position_valid": True,
|
||||
"active": False,
|
||||
}
|
||||
for index in range(4)
|
||||
],
|
||||
"thermal": [0x01],
|
||||
},
|
||||
}
|
||||
report = ZcanBridgeSeatExecutor._report(
|
||||
function_config,
|
||||
"2026-08-11T00:00:00Z",
|
||||
bridge_result,
|
||||
None,
|
||||
)
|
||||
physical_state = report["spec"]["physical_state"]
|
||||
self.assertEqual(physical_state["source"], "physical_can")
|
||||
self.assertEqual(physical_state["channel"], 0)
|
||||
self.assertEqual(
|
||||
physical_state["position"]["longitudinal"]["position_pct"], 63
|
||||
)
|
||||
verified = SelfExtensionService._authoritative_vehicle_feedback_state(
|
||||
report["spec"]["results"][0]
|
||||
)
|
||||
self.assertIsNotNone(verified)
|
||||
|
||||
def test_vehicle_execution_ignores_browser_routing_overrides(self) -> None:
|
||||
with patch.dict(
|
||||
os.environ,
|
||||
|
||||
Reference in New Issue
Block a user