feat: integrate calibration extension and self-repair modules
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import unittest
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
from cognitive_agent.application.self_extension import (
|
||||
GatewayError,
|
||||
SelfExtensionService,
|
||||
SimulationGateway,
|
||||
build_gateway_command,
|
||||
validate_slot,
|
||||
)
|
||||
|
||||
|
||||
class SelfExtensionTests(unittest.TestCase):
|
||||
def test_gateway_command_contracts_and_slot_validation(self) -> None:
|
||||
command = build_gateway_command("learn", {"slot": 17})
|
||||
self.assertEqual(command["type"], "infrared")
|
||||
self.assertEqual(command["action"], "learn")
|
||||
self.assertEqual(command["data"], {"no": 17})
|
||||
self.assertTrue(str(command["messageId"]).startswith("bridge-"))
|
||||
|
||||
self.assertEqual(validate_slot("248"), 248)
|
||||
with self.assertRaises(GatewayError):
|
||||
validate_slot(0)
|
||||
with self.assertRaises(GatewayError):
|
||||
build_gateway_command("erase", {"confirm": "wrong"})
|
||||
|
||||
def test_simulation_gateway_executes_without_physical_confirmation(self) -> None:
|
||||
service = SelfExtensionService(SimulationGateway())
|
||||
result = service.execute_gateway("emit", {"slot": 3, "repeat": 2})
|
||||
|
||||
self.assertTrue(result["success"])
|
||||
self.assertEqual(result["transport"], "simulation")
|
||||
self.assertFalse(result["physical_state_confirmed"])
|
||||
self.assertEqual(len(result["device_response"]), 2)
|
||||
|
||||
def test_plan_only_accepts_learned_catalog_capabilities(self) -> None:
|
||||
service = SelfExtensionService(SimulationGateway())
|
||||
proposed = {
|
||||
"summary": "先开玩具灯,再打开阅读灯",
|
||||
"needs_confirmation": False,
|
||||
"question": "",
|
||||
"steps": [
|
||||
{
|
||||
"kind": "peripheral",
|
||||
"capability_id": "cap-light-on",
|
||||
"command": "",
|
||||
"label": "ignored",
|
||||
},
|
||||
{
|
||||
"kind": "peripheral",
|
||||
"capability_id": "invented-capability",
|
||||
"command": "",
|
||||
"label": "ignored",
|
||||
},
|
||||
{
|
||||
"kind": "vehicle",
|
||||
"capability_id": "",
|
||||
"command": "打开全部阅读灯",
|
||||
"label": "车内灯光 · 阅读灯",
|
||||
},
|
||||
],
|
||||
}
|
||||
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(
|
||||
{
|
||||
"utterance": "打开玩具灯和阅读灯",
|
||||
"peripherals": [
|
||||
{
|
||||
"id": "cap-light-on",
|
||||
"status": "learned",
|
||||
"device_name": "灯光测试玩具",
|
||||
"action": "开启",
|
||||
"risk": "low",
|
||||
}
|
||||
],
|
||||
"vehicle_devices": [],
|
||||
}
|
||||
)
|
||||
|
||||
self.assertEqual(len(result["steps"]), 2)
|
||||
self.assertEqual(result["steps"][0]["capability_id"], "cap-light-on")
|
||||
self.assertEqual(result["steps"][1]["command"], "打开全部阅读灯")
|
||||
|
||||
def test_vehicle_execution_reuses_the_same_orchestration_service(self) -> None:
|
||||
service = SelfExtensionService(SimulationGateway())
|
||||
vehicle_service = Mock()
|
||||
vehicle_service.process.return_value = {
|
||||
"status": "succeeded",
|
||||
"provider_used": "local_rules",
|
||||
"request_id": "req-extension-1",
|
||||
"decision_summary": ["打开阅读灯"],
|
||||
"validation": [],
|
||||
"execution_report": {"spec": {"results": [{"status": "succeeded"}]}},
|
||||
"deferred_requests": [],
|
||||
}
|
||||
|
||||
result = service.execute_vehicle(
|
||||
{"command": "打开全部阅读灯", "vehicle_id": "denza_n7"},
|
||||
vehicle_service,
|
||||
hardware_access_bypass=True,
|
||||
)
|
||||
|
||||
self.assertTrue(result["success"])
|
||||
self.assertEqual(result["request_id"], "req-extension-1")
|
||||
vehicle_service.process.assert_called_once()
|
||||
self.assertEqual(vehicle_service.process.call_args.args[0], "打开全部阅读灯")
|
||||
self.assertTrue(vehicle_service.process.call_args.kwargs["hardware_access_bypass"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user