init
This commit is contained in:
Executable
+1
@@ -0,0 +1 @@
|
||||
"""Unit tests for shared cognitive agent infrastructure."""
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Executable
+58
@@ -0,0 +1,58 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import unittest
|
||||
|
||||
from cognitive_agent.auth import (
|
||||
AuthConfig,
|
||||
SessionCodec,
|
||||
SlidingWindowLimiter,
|
||||
hash_password,
|
||||
verify_password,
|
||||
)
|
||||
|
||||
|
||||
def auth_config() -> AuthConfig:
|
||||
return AuthConfig(
|
||||
enabled=True,
|
||||
username="demo-user",
|
||||
password_hash=hash_password(
|
||||
"correct horse battery staple",
|
||||
salt=b"0123456789abcdef",
|
||||
iterations=100_000,
|
||||
),
|
||||
session_secret=b"s" * 64,
|
||||
session_ttl_seconds=3600,
|
||||
login_attempts=3,
|
||||
login_window_seconds=60,
|
||||
requests_per_minute=10,
|
||||
trust_proxy_headers=False,
|
||||
)
|
||||
|
||||
|
||||
class AuthenticationUnitTests(unittest.TestCase):
|
||||
def test_password_hash_verification(self) -> None:
|
||||
encoded = auth_config().password_hash
|
||||
|
||||
self.assertTrue(verify_password("correct horse battery staple", encoded))
|
||||
self.assertFalse(verify_password("wrong password", encoded))
|
||||
self.assertNotIn("correct horse battery staple", encoded)
|
||||
|
||||
def test_signed_session_rejects_tampering_and_expiry(self) -> None:
|
||||
codec = SessionCodec(auth_config())
|
||||
token = codec.issue("demo-user", now=1000)
|
||||
|
||||
self.assertEqual(codec.verify(token, now=1001), "demo-user")
|
||||
self.assertIsNone(codec.verify(token + "x", now=1001))
|
||||
self.assertIsNone(codec.verify(token, now=4600))
|
||||
|
||||
def test_sliding_window_limiter_returns_retry_after(self) -> None:
|
||||
limiter = SlidingWindowLimiter(limit=2, window_seconds=60)
|
||||
|
||||
limiter.record("client", now=100)
|
||||
limiter.record("client", now=110)
|
||||
self.assertEqual(limiter.retry_after("client", now=120), 40)
|
||||
self.assertEqual(limiter.retry_after("client", now=161), 0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Executable
+57
@@ -0,0 +1,57 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import unittest
|
||||
|
||||
from cognitive_agent.application.capability_registry import CapabilityRegistry
|
||||
from cognitive_agent.application.seat_service import REPOSITORY_ROOT
|
||||
from cognitive_agent.infrastructure.llm.openai_responses import build_intent_schema
|
||||
|
||||
|
||||
class CapabilityRegistryTests(unittest.TestCase):
|
||||
def test_loads_domain_owned_capabilities_and_execution_availability(self) -> None:
|
||||
snapshot = CapabilityRegistry(REPOSITORY_ROOT, {"seat"}).snapshot()
|
||||
domains = {item["domain"]: item for item in snapshot["domains"]}
|
||||
|
||||
self.assertEqual(domains["seat"]["availability"], "executable")
|
||||
self.assertEqual(domains["climate"]["availability"], "catalog_only")
|
||||
seat_capabilities = {item["name"] for item in domains["seat"]["capabilities"]}
|
||||
self.assertIn("seat.set_backrest_recline", seat_capabilities)
|
||||
self.assertIn("seat.set_legrest_extension", seat_capabilities)
|
||||
self.assertIn("seat.save_posture_preset", seat_capabilities)
|
||||
self.assertIn("seat.apply_posture_preset", seat_capabilities)
|
||||
self.assertNotIn("seat.set_height", seat_capabilities)
|
||||
self.assertIn(
|
||||
"prefer_executable_when_equally_suitable",
|
||||
snapshot["execution_policy"]["capability_selection"],
|
||||
)
|
||||
self.assertFalse(snapshot["execution_policy"]["named_preset_required"])
|
||||
self.assertEqual(
|
||||
snapshot["execution_policy"]["planning_environment"],
|
||||
"dry_run_candidate_synthesis",
|
||||
)
|
||||
self.assertIn(
|
||||
"vehicle",
|
||||
next(
|
||||
item
|
||||
for item in domains["climate"]["capabilities"]
|
||||
if item["name"] == "climate.set_fan_level"
|
||||
)["target_scopes"],
|
||||
)
|
||||
|
||||
def test_structured_output_schema_is_derived_from_registry(self) -> None:
|
||||
snapshot = CapabilityRegistry(REPOSITORY_ROOT, {"seat"}).snapshot()
|
||||
schema = build_intent_schema(snapshot)
|
||||
properties = schema["properties"]
|
||||
|
||||
self.assertIn("climate", properties["detected_domains"]["items"]["enum"])
|
||||
request = properties["requests"]["items"]["properties"]
|
||||
self.assertIn("climate.set_fan_level", request["capability"]["enum"])
|
||||
self.assertIn("seat.set_cushion_tilt", request["capability"]["enum"])
|
||||
self.assertIn("seat.save_posture_preset", request["capability"]["enum"])
|
||||
self.assertIn("save", request["operation"]["enum"])
|
||||
self.assertIn("apply", request["operation"]["enum"])
|
||||
self.assertIn("vehicle", request["target_scope"]["enum"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Executable
+45
@@ -0,0 +1,45 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from cognitive_agent.application.gesture_bridge import GestureCapabilityBridge
|
||||
|
||||
|
||||
def _write_bundled_assets(repository: Path) -> Path:
|
||||
config = repository / "config" / "gesture" / "default.yaml"
|
||||
config.parent.mkdir(parents=True)
|
||||
config.write_text(
|
||||
"recognition:\n action_hold_ms: 720\n armed_idle_timeout_ms: 3100\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
asset_root = repository / "apps" / "web-console" / "assets" / "gesture"
|
||||
asset_root.mkdir(parents=True)
|
||||
(asset_root / "gesture_recognizer.task").write_bytes(b"model")
|
||||
return asset_root
|
||||
|
||||
|
||||
def test_gesture_bridge_uses_bundled_assets(tmp_path: Path):
|
||||
asset_root = _write_bundled_assets(tmp_path)
|
||||
bridge = GestureCapabilityBridge(tmp_path, asset_root)
|
||||
info = bridge.runtime_info()
|
||||
|
||||
assert bridge.available
|
||||
assert bridge.model_path == asset_root / "gesture_recognizer.task"
|
||||
assert info["asset_strategy"] == "bundled"
|
||||
assert info["source"] == "cognitive-agent-bundled-assets"
|
||||
assert info["safety"]["action_hold_ms"] == 720
|
||||
assert info["safety"]["armed_idle_timeout_ms"] == 3100
|
||||
assert info["actions"]["GUN_UP"]["action"] == "LEGREST_EXTEND"
|
||||
|
||||
|
||||
def test_gesture_bridge_fails_closed_when_bundled_model_is_missing(tmp_path: Path):
|
||||
config = tmp_path / "config" / "gesture" / "default.yaml"
|
||||
config.parent.mkdir(parents=True)
|
||||
config.write_text("recognition: {}\n", encoding="utf-8")
|
||||
|
||||
bridge = GestureCapabilityBridge(tmp_path)
|
||||
info = bridge.runtime_info()
|
||||
|
||||
assert not bridge.available
|
||||
assert not info["model_available"]
|
||||
assert info["safety"]["min_action_frames"] == 8
|
||||
Executable
+169
@@ -0,0 +1,169 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import unittest
|
||||
import urllib.error
|
||||
from unittest.mock import patch
|
||||
|
||||
from cognitive_agent.infrastructure.llm.openai_responses import OpenAIIntentInterpreter
|
||||
|
||||
|
||||
INTENT = {
|
||||
"detected_domains": ["seat"],
|
||||
"requests": [
|
||||
{
|
||||
"domain": "seat",
|
||||
"capability": "seat.set_ventilation",
|
||||
"target_scope": "driver",
|
||||
"operation": "activate",
|
||||
"parameters": [
|
||||
{"name": "state", "value": "on"},
|
||||
{"name": "level", "value": 1},
|
||||
],
|
||||
"reason": "Driver requested seat ventilation.",
|
||||
}
|
||||
],
|
||||
"ambiguities": [],
|
||||
"decision_summary": ["打开主驾座椅通风"],
|
||||
"confidence": 0.99,
|
||||
}
|
||||
|
||||
|
||||
class FakeResponse:
|
||||
def __init__(self, body: str) -> None:
|
||||
self.body = body.encode("utf-8")
|
||||
|
||||
def __enter__(self) -> FakeResponse:
|
||||
return self
|
||||
|
||||
def __exit__(self, *_args: object) -> None:
|
||||
return None
|
||||
|
||||
def read(self) -> bytes:
|
||||
return self.body
|
||||
|
||||
|
||||
class OpenAIResponsesTests(unittest.TestCase):
|
||||
def test_non_streaming_structured_output(self) -> None:
|
||||
response_body = json.dumps({"output_text": json.dumps(INTENT)})
|
||||
environment = {
|
||||
"OPENAI_API_KEY": "test-key",
|
||||
"OPENAI_STREAM": "false",
|
||||
}
|
||||
|
||||
with patch.dict(os.environ, environment, clear=False):
|
||||
interpreter = OpenAIIntentInterpreter()
|
||||
with patch(
|
||||
"cognitive_agent.infrastructure.llm.openai_responses.urllib.request.urlopen",
|
||||
return_value=FakeResponse(response_body),
|
||||
) as urlopen:
|
||||
result = interpreter.interpret(
|
||||
"主驾还有点闷",
|
||||
{
|
||||
"last_target": "driver",
|
||||
"devices": {
|
||||
"driver": {
|
||||
"ventilation": {"state": "on", "level": 1}
|
||||
}
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
request_payload = json.loads(urlopen.call_args.args[0].data.decode("utf-8"))
|
||||
self.assertEqual(result, INTENT)
|
||||
self.assertNotIn("stream", request_payload)
|
||||
self.assertIn("capability registry", request_payload["input"][1]["content"][0]["text"])
|
||||
self.assertIn('"level": 1', request_payload["input"][2]["content"][0]["text"])
|
||||
|
||||
def test_streaming_structured_output(self) -> None:
|
||||
intent_text = json.dumps(INTENT, ensure_ascii=False)
|
||||
stream_body = "\n".join(
|
||||
[
|
||||
"event: response.output_text.delta",
|
||||
f"data: {json.dumps({'type': 'response.output_text.delta', 'delta': intent_text[:30]}, ensure_ascii=False)}",
|
||||
"",
|
||||
"event: response.output_text.done",
|
||||
f"data: {json.dumps({'type': 'response.output_text.done', 'text': intent_text}, ensure_ascii=False)}",
|
||||
"",
|
||||
"data: [DONE]",
|
||||
]
|
||||
)
|
||||
environment = {
|
||||
"OPENAI_API_KEY": "test-key",
|
||||
"OPENAI_STREAM": "true",
|
||||
}
|
||||
|
||||
with patch.dict(os.environ, environment, clear=False):
|
||||
interpreter = OpenAIIntentInterpreter()
|
||||
with patch(
|
||||
"cognitive_agent.infrastructure.llm.openai_responses.urllib.request.urlopen",
|
||||
return_value=FakeResponse(stream_body),
|
||||
) as urlopen:
|
||||
result = interpreter.interpret("打开主驾座椅通风")
|
||||
|
||||
request_payload = json.loads(urlopen.call_args.args[0].data.decode("utf-8"))
|
||||
self.assertEqual(result, INTENT)
|
||||
self.assertTrue(request_payload["stream"])
|
||||
|
||||
def test_retries_transient_network_failure(self) -> None:
|
||||
response_body = json.dumps({"output_text": json.dumps(INTENT)})
|
||||
environment = {
|
||||
"OPENAI_API_KEY": "test-key",
|
||||
"OPENAI_STREAM": "false",
|
||||
"OPENAI_MAX_RETRIES": "1",
|
||||
}
|
||||
|
||||
with patch.dict(os.environ, environment, clear=False):
|
||||
interpreter = OpenAIIntentInterpreter()
|
||||
with patch(
|
||||
"cognitive_agent.infrastructure.llm.openai_responses.urllib.request.urlopen",
|
||||
side_effect=[urllib.error.URLError("temporary TLS EOF"), FakeResponse(response_body)],
|
||||
) as urlopen, patch(
|
||||
"cognitive_agent.infrastructure.llm.openai_responses.time.sleep"
|
||||
) as sleep:
|
||||
result = interpreter.interpret("打开主驾座椅通风")
|
||||
|
||||
self.assertEqual(result, INTENT)
|
||||
self.assertEqual(urlopen.call_count, 2)
|
||||
sleep.assert_called_once_with(1)
|
||||
|
||||
def test_retries_transient_error_inside_stream(self) -> None:
|
||||
error_stream = "data: " + json.dumps(
|
||||
{
|
||||
"type": "error",
|
||||
"error": {
|
||||
"type": "service_unavailable_error",
|
||||
"code": "server_is_overloaded",
|
||||
"message": "try again",
|
||||
},
|
||||
}
|
||||
)
|
||||
intent_text = json.dumps(INTENT, ensure_ascii=False)
|
||||
success_stream = "data: " + json.dumps(
|
||||
{"type": "response.output_text.done", "text": intent_text},
|
||||
ensure_ascii=False,
|
||||
)
|
||||
environment = {
|
||||
"OPENAI_API_KEY": "test-key",
|
||||
"OPENAI_STREAM": "true",
|
||||
"OPENAI_MAX_RETRIES": "1",
|
||||
}
|
||||
|
||||
with patch.dict(os.environ, environment, clear=False):
|
||||
interpreter = OpenAIIntentInterpreter()
|
||||
with patch(
|
||||
"cognitive_agent.infrastructure.llm.openai_responses.urllib.request.urlopen",
|
||||
side_effect=[FakeResponse(error_stream), FakeResponse(success_stream)],
|
||||
) as urlopen, patch(
|
||||
"cognitive_agent.infrastructure.llm.openai_responses.time.sleep"
|
||||
) as sleep:
|
||||
result = interpreter.interpret("打开主驾座椅通风")
|
||||
|
||||
self.assertEqual(result, INTENT)
|
||||
self.assertEqual(urlopen.call_count, 2)
|
||||
sleep.assert_called_once_with(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user