Files
Cognitive_Agent/tests/integration/test_scene_composer_end_to_end.py
T

103 lines
3.9 KiB
Python

from __future__ import annotations
import sys
from pathlib import Path
from unittest.mock import patch
from cognitive_agent.application.assistant_capabilities import AssistantCapabilityCatalog
from cognitive_agent.application.codex_assistant import CodexAssistantService
from cognitive_agent.application.mode_profile import ModeProfileRegistry
from cognitive_agent.application.seat_service import REPOSITORY_ROOT, SeatDemoService
from cognitive_agent.infrastructure.codex.app_server import CodexAppServerClient
FAKE_SERVER = REPOSITORY_ROOT / "tests" / "fixtures" / "fake_codex_app_server.py"
MCP_SERVER = (
REPOSITORY_ROOT / "src/cognitive_agent/infrastructure/codex/vehicle_mcp_server.py"
)
CALLBACK_URL = "http://127.0.0.1:8765/api/internal/codex/vehicle-control"
def test_structured_scene_turn_reaches_the_complete_local_dry_run_pipeline(
tmp_path: Path,
) -> None:
service = SeatDemoService(REPOSITORY_ROOT)
service.artifact_root = tmp_path / "runs"
service.mode_profiles = ModeProfileRegistry(
REPOSITORY_ROOT / "config" / "modes",
user_root=tmp_path / "user-modes",
)
client = CodexAppServerClient(
cwd=tmp_path / "codex-workspace",
codex_command=[sys.executable, "-u", str(FAKE_SERVER)],
model="gpt-test-fast",
reasoning_effort="low",
request_timeout=2,
startup_timeout=2,
environment={"OPENAI_BASE_URL": "https://api.openai.com/v1"},
mcp_server_path=MCP_SERVER,
)
assistant = CodexAssistantService(client)
catalog = AssistantCapabilityCatalog(service)
snapshot = catalog.snapshot()
events: list[dict[str, object]] = []
def execute_control(
instruction: str,
progress: object,
assistant_plan: object,
) -> dict[str, object]:
assert isinstance(assistant_plan, dict)
return service.preview_native_can(
instruction,
provider="local",
conversation_id="conv-scene-e2e-pipeline",
execution_mode="hardware",
vehicle_id="denza_n7",
on_commands_validated=progress if callable(progress) else None,
assistant_plan=assistant_plan,
)
try:
assistant.start(CALLBACK_URL)
with patch.object(
service.hardware_execution,
"reserve",
side_effect=AssertionError("scene preview must never reserve hardware"),
):
response = assistant.stream(
"构建一个星夜模式",
conversation_id="conv-scene-e2e-pipeline",
principal="scene-e2e-user",
history=[],
emit=lambda event: events.append(event) or True,
execute_control=execute_control,
capability_snapshot=snapshot,
capability_context=catalog.compact_context(snapshot),
scene_capability_context=catalog.scene_composition_context(snapshot),
control_terms=catalog.control_terms(snapshot),
)
finally:
assistant.close()
result = response["result"]
draft = result["mode_profile_draft"]
assert response["route"] == "scene_composer"
assert response["success"] is True
assert result["status"] == "succeeded"
assert result["execution_mode"] == "dry_run"
assert result["hardware_execution_allowed"] is False
assert result["orchestration_route"] == "mode_profile_create_preview"
assert draft["name"] == "星夜模式"
assert draft["generation_source"] == "codex_scene_composition"
assert draft["operation_count"] == 2
capabilities = {
action["capability"] for action in result["actions"]
}
assert capabilities == {
"climate.set_temperature",
"roof.set_shade_position",
}
assert not list((tmp_path / "user-modes").rglob("*.yaml"))
assert any(event.get("type") == "action.completed" for event in events)
assert all("request_token" not in str(event) for event in events)