Files
Cognitive_Agent/tests/unit/test_assistant_validated_control_projection.py
T

427 lines
16 KiB
Python

from __future__ import annotations
import json
import threading
import unittest
from copy import deepcopy
from cognitive_agent.application.codex_assistant import (
CodexAssistantService,
_VehicleAuthorization,
_VehicleTurnContext,
)
UTTERANCE = "空调温度设置到23度,打开闪烁灯"
def compiled_mixed_result() -> dict[str, object]:
return {
"request_id": "req-assistant-local-mixed",
"utterance": UTTERANCE,
"status": "processing",
"phase": "commands_validated",
"provider_used": "local_rules+infrared_local_rules",
"execution_mode": "dry_run",
"control_transport": "wired_can",
"parallel_dispatch": {
"enabled": True,
"preflight_status": "succeeded",
"dispatch": {
"started_skew_ms": 1.2,
"total_ms": 120.5,
},
},
"function_configs": {
"native_climate": {
"spec": {
"domain": "climate",
"operations": [
{
"id": "climate-temperature-1",
"capability": "climate.set_temperature",
"target": {"zone": "driver"},
"parameters": {"temperature_c": 23},
"parse_source": "local_rule",
}
],
}
},
"self_extension": {
"spec": {
"domain": "self_extension",
"operations": [
{
"id": "infrared-1",
"capability": "infrared.emit",
"target": {"device": "toy-001", "name": "闪灯玩具"},
"parameters": {"action": "开启", "slot": 1},
"parse_source": "local_rule",
}
],
}
},
},
"command_plans": {
"self_extension": {
"spec": {
"domain": "self_extension",
"commands": [
{
"operation_ref": "unrelated-operation",
"message": "Native_0xBAD",
"signals": {
"debug_command": "must-not-cross-tool-boundary",
"frame_id": "0xBAD",
"data_hex": "DE AD BE EF",
},
},
{
"operation_ref": "infrared-1",
"bus": "TCP",
"message": "infrared.emit",
"signals": {"slot": 1},
},
],
}
},
"native_climate": {
"spec": {
"domain": "climate",
"commands": [
{
"operation_ref": "climate-temperature-1",
"bus": "body_can",
"message": "Native_0x1DE",
"signals": {
"debug_command": "ac temp driver 23",
"frame_id": "0x1DE",
"data_hex": "00 00 00 00 17 00 00 00",
},
}
],
}
},
},
"trace_events": [
{"stage": "intent_parse", "duration_ms": 2},
{"stage": "context_resolve", "duration_ms": 1},
{"stage": "domain_route", "duration_ms": 1},
{"stage": "function_generate", "duration_ms": 2},
{"stage": "schema_validate", "duration_ms": 1},
{"stage": "compile", "duration_ms": 2},
{"stage": "execute", "duration_ms": 999},
],
"raw_can": "must-not-cross-tool-boundary",
}
class ValidatedControlProjectionTest(unittest.TestCase):
def test_projection_exposes_only_exact_display_commands(self) -> None:
projection = CodexAssistantService._validated_control_payload(
compiled_mixed_result()
)
self.assertIsNotNone(projection)
assert projection is not None
commands = projection["validated_control_commands"]
assert isinstance(commands, list)
self.assertEqual(len(commands), 2)
by_capability = {
command["operation"]["capability"]: command for command in commands
}
climate = by_capability["climate.set_temperature"]
infrared = by_capability["infrared.emit"]
self.assertEqual(climate["actual_command"], "ac temp driver 23")
self.assertEqual(
climate["frames"],
[
{
"label": "CAN1 帧",
"value": "0x1DE · 00 00 00 00 17 00 00 00",
}
],
)
self.assertEqual(infrared["actual_command"], "infrared emit 1")
self.assertEqual(
infrared["frames"],
[
{
"label": "GSCU1B TCP",
"value": '{"action":"emit","data":{"no":1},"type":"infrared"}',
}
],
)
self.assertEqual(
[event["stage"] for event in projection["trace_events"]],
[
"intent_parse",
"context_resolve",
"domain_route",
"function_generate",
"schema_validate",
"compile",
],
)
self.assertEqual(
projection["parallel_dispatch"]["preflight_status"],
"succeeded",
)
serialized = json.dumps(projection, ensure_ascii=False)
self.assertNotIn("command_plans", serialized)
self.assertNotIn("data_hex", serialized)
self.assertNotIn("raw_can", serialized)
self.assertNotIn("must-not-cross-tool-boundary", serialized)
def test_projection_drops_secrets_and_sensitive_nested_keys(self) -> None:
result = compiled_mixed_result()
secret = "projection-secret-token"
climate_config = result["function_configs"]["native_climate"]
climate_config["spec"]["domain"] = f"climate-{secret}"
operation = climate_config["spec"]["operations"][0]
operation["target"].update(
{
"api_key": "API-LEAK",
"cookie": "COOKIE-LEAK",
}
)
operation["parameters"].update(
{
"credential": "CRED-LEAK",
"access_key": "ACCESS-LEAK",
}
)
operation["parse_source"] = f"local-{secret}"
result["command_plans"]["native_climate"]["spec"]["commands"][0][
"signals"
]["debug_command"] = f"ac temp driver 23 {secret}"
projection = CodexAssistantService._validated_control_payload(
result,
secret=secret,
)
self.assertIsNotNone(projection)
assert projection is not None
serialized = json.dumps(projection, ensure_ascii=False)
for forbidden in (
secret,
"API-LEAK",
"COOKIE-LEAK",
"CRED-LEAK",
"ACCESS-LEAK",
"api_key",
"credential",
"access_key",
):
self.assertNotIn(forbidden, serialized)
climate = next(
item
for item in projection["validated_control_commands"]
if item["operation"]["capability"] == "climate.set_temperature"
)
self.assertEqual(climate["domain"], "")
self.assertNotIn("parse_source", climate["operation"])
self.assertEqual(climate["operation"]["target"], {"zone": "driver"})
self.assertEqual(
climate["operation"]["parameters"],
{"temperature_c": 23},
)
self.assertEqual(climate["actual_command"], "")
def test_projection_drops_operation_when_identity_contains_secret(self) -> None:
result = compiled_mixed_result()
secret = "projection-secret-token"
operation = result["function_configs"]["native_climate"]["spec"][
"operations"
][0]
operation["id"] = f"climate-{secret}"
result["command_plans"]["native_climate"]["spec"]["commands"][0][
"operation_ref"
] = operation["id"]
projection = CodexAssistantService._validated_control_payload(
result,
secret=secret,
)
self.assertIsNotNone(projection)
assert projection is not None
serialized = json.dumps(projection, ensure_ascii=False)
self.assertNotIn(secret, serialized)
self.assertEqual(
[
item["operation"]["capability"]
for item in projection["validated_control_commands"]
],
["infrared.emit"],
)
def test_duplicate_operation_refs_never_cross_configuration_boundaries(self) -> None:
result = {
"function_configs": {
"native_climate": {
"spec": {
"domain": "climate",
"operations": [
{
"id": "op-1",
"capability": "climate.set_temperature",
"target": {"zone": "driver"},
"parameters": {"temperature_c": 23},
}
],
}
},
"native_seat": {
"spec": {
"domain": "seat",
"operations": [
{
"id": "op-1",
"capability": "seat.set_heating",
"target": {"zone": "passenger"},
"parameters": {"level": 2},
}
],
}
},
},
"command_plans": {
"native_seat": {
"spec": {
"domain": "seat",
"commands": [
{
"operation_ref": "op-1",
"bus": "seat_can0",
"signals": {
"debug_command": "seat passenger heat 2"
},
}
],
}
}
},
}
projection = CodexAssistantService._validated_control_payload(result)
self.assertIsNotNone(projection)
assert projection is not None
commands = projection["validated_control_commands"]
self.assertEqual(len(commands), 1)
self.assertEqual(
commands[0]["operation"]["capability"],
"seat.set_heating",
)
self.assertEqual(commands[0]["actual_command"], "seat passenger heat 2")
def test_compiled_semantic_operation_is_kept_without_debug_command(self) -> None:
result = deepcopy(compiled_mixed_result())
climate_command = result["command_plans"]["native_climate"]["spec"][
"commands"
][0]
climate_command["signals"].pop("debug_command")
projection = CodexAssistantService._validated_control_payload(result)
self.assertIsNotNone(projection)
assert projection is not None
climate = next(
item
for item in projection["validated_control_commands"]
if item["operation"]["capability"] == "climate.set_temperature"
)
self.assertEqual(climate["actual_command"], "")
self.assertEqual(
climate["frames"][0]["value"],
"0x1DE · 00 00 00 00 17 00 00 00",
)
def test_direct_stream_emits_projection_before_progress_and_completion(self) -> None:
client = type("UnavailableClient", (), {"available": False})()
assistant = CodexAssistantService(client)
events: list[dict[str, object]] = []
def execute_control(instruction, progress):
self.assertEqual(instruction, UTTERANCE)
result = compiled_mixed_result()
progress(result)
return {**result, "status": "succeeded"}
result = assistant.stream(
UTTERANCE,
conversation_id="conv-validated-projection",
principal="local-test",
history=[],
emit=events.append,
execute_control=execute_control,
control_terms=("空调", "闪烁灯"),
quick_control_commands=[UTTERANCE],
)
event_types = [event["type"] for event in events]
validated_index = event_types.index("validated_control_commands")
self.assertLess(validated_index, event_types.index("action.progress"))
self.assertLess(validated_index, event_types.index("action.completed"))
self.assertLess(validated_index, event_types.index("answer.completed"))
self.assertEqual(result["route"], "vehicle_control")
self.assertEqual(result["success"], True)
safe_result = CodexAssistantService._safe_vehicle_result(
compiled_mixed_result()
)
self.assertNotIn("command_plans", safe_result)
self.assertNotIn("validated_control_commands", safe_result)
self.assertEqual(
safe_result["parallel_dispatch"]["preflight_status"],
"succeeded",
)
def test_agent_tool_path_queues_projection_for_the_browser_thread(self) -> None:
client = type("UnavailableClient", (), {"available": False})()
assistant = CodexAssistantService(client)
request_token = "projection-secret-token"
def execute_control(instruction, progress):
self.assertEqual(instruction, UTTERANCE)
result = compiled_mixed_result()
progress(result)
return {**result, "status": "succeeded"}
context = _VehicleTurnContext(
original_message=UTTERANCE,
execute_control=execute_control,
authorization=_VehicleAuthorization(
instruction=UTTERANCE,
reason="explicit_registered_control",
),
capability_snapshot={},
query_capabilities=lambda _snapshot, _query: {},
lock=threading.Lock(),
)
assistant._tool_contexts[request_token] = context
safe_result = assistant.execute_vehicle_control(request_token, UTTERANCE)
queued_events = []
while not context.events.empty():
queued_events.append(context.events.get_nowait())
event_types = [event["type"] for event in queued_events]
self.assertEqual(event_types[0], "action.started")
self.assertLess(
event_types.index("validated_control_commands"),
event_types.index("action.progress"),
)
self.assertLess(
event_types.index("validated_control_commands"),
event_types.index("action.completed"),
)
self.assertNotIn("command_plans", safe_result)
self.assertNotIn(request_token, json.dumps(queued_events, ensure_ascii=False))
if __name__ == "__main__":
unittest.main()