feat: integrate production cockpit AI assistant

This commit is contained in:
vee
2026-09-08 17:46:07 +08:00
parent 5e228e12ae
commit 93103c2579
66 changed files with 11046 additions and 374 deletions
@@ -18,6 +18,32 @@ from cognitive_agent.application.codex_assistant import (
from cognitive_agent.application.seat_service import SeatDemoService
ROOT = Path(__file__).resolve().parents[2]
REPOSITORY_MODE_IDS = frozenset(
path.stem
for path in (ROOT / "config" / "modes" / "vehicles" / "denza_n7").glob(
"*.yaml"
)
)
def _repository_catalog_modes(modes: object) -> list[Mapping[str, object]]:
assert REPOSITORY_MODE_IDS
assert isinstance(modes, list)
mode_ids = {
str(mode.get("id") or "")
for mode in modes
if isinstance(mode, Mapping)
}
assert "" not in mode_ids
assert len(mode_ids) == len(modes), "catalog mode ids must remain unique"
assert REPOSITORY_MODE_IDS <= mode_ids
repository_modes = [
mode
for mode in modes
if isinstance(mode, Mapping) and str(mode.get("id") or "") in REPOSITORY_MODE_IDS
]
assert {str(mode["id"]) for mode in repository_modes} == REPOSITORY_MODE_IDS
return repository_modes
@dataclass(frozen=True)
@@ -624,8 +650,7 @@ def test_every_catalog_mode_can_execute_through_the_assistant_tool_boundary(
catalog: AssistantCapabilityCatalog,
) -> None:
snapshot = catalog.snapshot()
modes = snapshot["modes"]
assert len(modes) == 13
modes = _repository_catalog_modes(snapshot["modes"])
for index, mode in enumerate(modes):
assert isinstance(mode, Mapping)
@@ -684,8 +709,7 @@ def test_every_catalog_mode_rejects_incompatible_explicit_seat_scopes(
vehicle_service: SeatDemoService,
catalog: AssistantCapabilityCatalog,
) -> None:
modes = catalog.snapshot()["modes"]
assert len(modes) == 13
modes = _repository_catalog_modes(catalog.snapshot()["modes"])
for mode_index, mode in enumerate(modes):
assert isinstance(mode, Mapping)
@@ -876,6 +876,41 @@ def test_question_shaped_mode_turns_never_modify_a_draft_or_touch_hardware(
assert not list(user_root.rglob("*.yaml"))
@pytest.mark.parametrize(
"message",
(
"能否创建一个观影模式?",
"构建一个观影模式,空调温度是25度还是26度?",
),
)
def test_create_shaped_questions_never_reach_hardware_or_scene_composer(
mode_service: tuple[SeatDemoService, Path],
message: str,
) -> None:
service, user_root = mode_service
with patch.object(
service.hardware_execution,
"reserve",
side_effect=AssertionError("mode-create question reached a hardware lease"),
):
result = service.preview_native_can(
message,
provider="local",
conversation_id="conv-create-question-" + str(abs(hash(message)))[:12],
execution_mode="hardware",
vehicle_id="denza_n7",
)
assert result["status"] == "needs_confirmation"
assert result["orchestration_route"] == "mode_profile_query"
assert result["execution_mode"] == "dry_run"
assert result["hardware_execution_allowed"] is False
assert result.get("mode_profile_draft") is None
assert _intent_actions(result) == []
assert not list(user_root.rglob("*.yaml"))
INVALID_PARAMETER_CASES = (
SceneCase("temperature-low", "非法低温模式", "climate.set_temperature", "vehicle", {"temperature_c": 17}),
SceneCase("temperature-high", "非法高温模式", "climate.set_temperature", "vehicle", {"temperature_c": 33}),
@@ -8,13 +8,14 @@ from unittest.mock import MagicMock, patch
import pytest
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.mode_profile_intent import (
is_mode_profile_query,
parse_mode_profile_detail_query,
parse_mode_profile_update,
)
from cognitive_agent.application.assistant_capabilities import AssistantCapabilityCatalog
from cognitive_agent.application.mode_profile import ModeProfileRegistry
from cognitive_agent.application.native_can_runtime import NativeCanCompileError
from cognitive_agent.application.seat_service import (
REPOSITORY_ROOT,
@@ -830,6 +831,91 @@ def test_device_property_mode_is_not_a_named_mode_profile_update(
assert SeatDemoService._parse_mode_profile_update(message) is None
@pytest.mark.parametrize(
"message",
(
"空调出风模式设置为吹面和吹脚,主驾空调温度设置为24度",
"空调出风模式设置为吹面和吹脚;副驾空调温度设置为24度",
"空调出风模式设置为吹面和吹脚,空调设置为自动控制",
"空调出风模式设置为吹面和吹脚,主驾座椅按摩模式设置为放松",
"主驾座椅按摩模式设置为放松,按摩强度设置为中等",
"把空调出风模式的出风方向设置为吹面和吹脚",
"调整主驾座椅按摩模式的强度为中等",
"副驾座椅零重力模式的状态设为开启",
"空调出风模式有哪些选项?",
"主驾座椅按摩模式是什么?",
),
)
def test_device_property_mode_commands_and_questions_are_not_saved_mode_queries(
message: str,
) -> None:
assert parse_mode_profile_detail_query(message) is None
assert not is_mode_profile_query(message)
assert parse_mode_profile_update(message) is None
@pytest.mark.parametrize(
"message",
(
"空调出风模式设置为吹面和吹脚,副驾空调温度设置为24度",
"主驾座椅按摩模式设置为放松,氛围灯亮度设置为3档",
),
)
def test_device_property_mode_combinations_continue_to_execute_as_vehicle_control(
vehicle_service: SeatDemoService,
message: str,
) -> None:
result = vehicle_service.process(
message,
provider="local",
conversation_id="conv-device-property-mode-control",
execution_mode="dry_run",
vehicle_id="denza_n7",
)
assert result["status"] == "succeeded"
assert result.get("orchestration_route") != "mode_profile_query"
assert not SeatDemoService.is_mode_profile_configuration_request(message)
def test_quoted_device_property_name_can_explicitly_address_a_saved_mode() -> None:
assert parse_mode_profile_detail_query("查看“空调出风模式”的配置") == (
"空调出风模式"
)
assert parse_mode_profile_update(
"把“空调出风模式”的温度调整到25度"
) == ("空调出风模式", "温度调整到25度")
@pytest.mark.parametrize(
"message",
(
"办公模式的设备?",
"办公模式配置?",
"办公模式下的动作?",
),
)
def test_terminal_question_mark_keeps_short_saved_mode_detail_queries_read_only(
message: str,
) -> None:
assert parse_mode_profile_detail_query(message) == "办公模式"
assert is_mode_profile_query(message)
@pytest.mark.parametrize(
"message",
(
"办公模式的设备。",
"办公模式配置。",
"空调出风模式设置为吹面和吹脚,温度设置为24度",
),
)
def test_plain_mode_nouns_without_a_read_cue_are_not_detail_queries(
message: str,
) -> None:
assert parse_mode_profile_detail_query(message) is None
@pytest.mark.parametrize(
("message", "expected"),
(
@@ -0,0 +1,562 @@
from __future__ import annotations
from pathlib import Path
from unittest.mock import MagicMock, patch
import pytest
from cognitive_agent.application.assistant_capabilities import (
AssistantCapabilityCatalog,
)
from cognitive_agent.application.codex_assistant import CodexAssistantService
from cognitive_agent.application.mode_profile import ModeProfile, ModeProfileRegistry
from cognitive_agent.application.seat_service import REPOSITORY_ROOT, SeatDemoService
READING_OPERATIONS: list[dict[str, object]] = [
{
"domain": "climate",
"capability": "climate.set_power",
"target_scope": "vehicle",
"operation": "set",
"parameters": {"state": "on"},
"reason": "阅读时保持空调开启。",
},
{
"domain": "climate",
"capability": "climate.set_temperature",
"target_scope": "vehicle",
"operation": "set",
"parameters": {"temperature_c": 24},
"reason": "阅读模式默认温度。",
},
{
"domain": "roof",
"capability": "roof.set_shade_position",
"target_scope": "vehicle",
"operation": "set",
"parameters": {"position_pct": 30},
"reason": "减少阅读眩光。",
},
{
"domain": "interior_light",
"capability": "interior_light.set_reading_power",
"target_scope": "all",
"operation": "set",
"parameters": {"state": "on"},
"reason": "打开阅读灯。",
},
]
@pytest.fixture
def vehicle_service(tmp_path: Path) -> SeatDemoService:
service = SeatDemoService(REPOSITORY_ROOT)
service.artifact_root = tmp_path / "runs"
service.mode_profiles = ModeProfileRegistry(
REPOSITORY_ROOT / "config" / "modes",
user_root=tmp_path / "user-modes",
)
return service
def _save_reading_mode(service: SeatDemoService) -> ModeProfile:
return service.mode_profiles.save_mode(
"阅读模式",
READING_OPERATIONS,
mode_id="user-reading",
aliases=["看书模式", "阅读空间模式"],
vehicle_id="denza_n7",
description="用户保存的阅读场景。",
instruction="空调24度,遮阳帘30%,打开阅读灯",
)
def _save_office_override(service: SeatDemoService) -> ModeProfile:
preset = service.mode_profiles.get_profile("office", "denza_n7")
return service.mode_profiles.save_mode(
preset.name,
list(preset.operations),
mode_id=preset.id,
aliases=list(preset.aliases),
vehicle_id="denza_n7",
description=preset.description,
icon=preset.icon,
instruction=preset.instruction,
command_flow=preset.command_flow,
timeline=preset.timeline,
)
def _temperature(profile: ModeProfile, scope: str) -> object:
return next(
operation.parameters["temperature_c"]
for operation in profile.operations
if operation.capability == "climate.set_temperature"
and operation.target_scope == scope
)
@pytest.mark.parametrize(
("message", "profile_factory", "mode_id", "target_scope", "temperature"),
(
(
"把阅读模式中空调温度调整到26度",
_save_reading_mode,
"user-reading",
"vehicle",
26,
),
(
"调整办公模式,把办公模式的副驾空调温度调整为26度。",
_save_office_override,
"office",
"passenger",
26,
),
(
"将看书模式里的空调温度改成25度",
_save_reading_mode,
"user-reading",
"vehicle",
25,
),
(
"请帮我把“阅读模式”里的空调温度改成25度吧。",
_save_reading_mode,
"user-reading",
"vehicle",
25,
),
),
)
def test_saved_mode_natural_language_update_is_control_plane_only(
vehicle_service: SeatDemoService,
message: str,
profile_factory: object,
mode_id: str,
target_scope: str,
temperature: int,
) -> None:
assert callable(profile_factory)
profile_factory(vehicle_service)
with patch.object(
vehicle_service.hardware_execution,
"reserve",
side_effect=AssertionError("saved-mode update acquired the hardware lease"),
):
result = vehicle_service.preview_native_can(
message,
provider="local",
conversation_id=f"conv-saved-mode-update-{temperature}-{mode_id}",
execution_mode="hardware",
vehicle_id="denza_n7",
)
updated = vehicle_service.mode_profiles.get_profile(mode_id, "denza_n7")
assert result["status"] == "succeeded"
assert result["orchestration_route"] == "mode_profile_update"
assert result["execution_mode"] == "dry_run"
assert result["hardware_execution_allowed"] is False
assert result["mode_profile"]["id"] == mode_id
assert result["command_plans"] == {}
assert result["can_commands"] == []
assert _temperature(updated, target_scope) == temperature
assert sum(
operation.capability == "climate.set_temperature"
and operation.target_scope == target_scope
for operation in updated.operations
) == 1
def test_builtin_mode_update_is_copy_on_write_and_delete_reveals_preset(
vehicle_service: SeatDemoService,
) -> None:
preset = vehicle_service.mode_profiles.get_profile("office", "denza_n7")
preset_path = Path(preset.source)
original_bytes = preset_path.read_bytes()
original_temperature = _temperature(preset, "passenger")
updated = vehicle_service.preview_native_can(
"把办公模式中的副驾空调温度调整到26度",
provider="local",
conversation_id="conv-office-copy-on-write",
execution_mode="hardware",
vehicle_id="denza_n7",
)
effective = vehicle_service.mode_profiles.get_profile("office", "denza_n7")
public = next(
item
for item in vehicle_service.mode_profiles.public_modes("denza_n7")
if item["id"] == "office"
)
assert updated["status"] == "succeeded"
assert updated["mode_profile"]["origin"] == "customized"
assert effective.user_defined is True
assert _temperature(effective, "passenger") == 26
assert preset_path.read_bytes() == original_bytes
assert public["origin"] == "customized"
deleted = vehicle_service.preview_native_can(
"删除办公模式",
provider="local",
conversation_id="conv-office-copy-on-write-delete",
execution_mode="hardware",
vehicle_id="denza_n7",
)
restored = vehicle_service.mode_profiles.get_profile("office", "denza_n7")
assert deleted["status"] == "succeeded"
assert restored.user_defined is False
assert _temperature(restored, "passenger") == original_temperature
assert preset_path.read_bytes() == original_bytes
@pytest.mark.parametrize(
("message", "capability", "target", "parameter", "expected"),
(
(
"把阅读模式中的阅读灯关闭",
"interior_light.set_reading_power",
"all",
"state",
"off",
),
(
"把阅读模式中的遮阳帘调整到80%",
"roof.set_shade_position",
"vehicle",
"position_pct",
80,
),
(
"把阅读模式中的左前车窗调整到20%",
"window.set_position",
"front_left",
"position_pct",
20,
),
(
"把阅读模式中的主驾座椅通风调整到2档",
"seat.set_driver_ventilation_native",
"driver",
"level",
2,
),
),
)
def test_saved_mode_update_persists_native_can_capability_families(
vehicle_service: SeatDemoService,
message: str,
capability: str,
target: str,
parameter: str,
expected: object,
) -> None:
_save_reading_mode(vehicle_service)
result = vehicle_service.preview_native_can(
message,
provider="local",
conversation_id=f"conv-native-mode-update-{parameter.replace('_', '-')}",
execution_mode="hardware",
vehicle_id="denza_n7",
)
updated = vehicle_service.mode_profiles.get_profile(
"user-reading",
"denza_n7",
)
operation = next(
item
for item in updated.operations
if item.capability == capability and item.target_scope == target
)
assert result["status"] == "succeeded"
assert result["deferred_requests"] == []
assert operation.parameters[parameter] == expected
def test_failed_saved_mode_update_is_atomic_and_reports_the_missing_mode(
vehicle_service: SeatDemoService,
) -> None:
_save_reading_mode(vehicle_service)
original = vehicle_service.mode_profiles.get_profile(
"user-reading", "denza_n7"
)
original_revision = vehicle_service.mode_profiles.profile_revision(original)
missing = vehicle_service.preview_native_can(
"把不存在模式中的空调温度调整到26度",
provider="local",
conversation_id="conv-saved-mode-update-missing",
execution_mode="hardware",
vehicle_id="denza_n7",
)
invalid = vehicle_service.preview_native_can(
"把阅读模式中的曲速引擎调整到100%",
provider="local",
conversation_id="conv-saved-mode-update-invalid",
execution_mode="hardware",
vehicle_id="denza_n7",
)
unchanged = vehicle_service.mode_profiles.get_profile(
"user-reading", "denza_n7"
)
assert missing["status"] == "needs_confirmation"
assert missing["orchestration_route"] == "mode_profile_update"
assert any(
item.get("code") == "MODE_PROFILE_NOT_FOUND"
for item in missing["validation"]
)
assert invalid["status"] != "succeeded"
assert invalid["orchestration_route"] == "mode_profile_update"
assert invalid["mode_profile"] is None
assert vehicle_service.mode_profiles.profile_revision(unchanged) == original_revision
@pytest.mark.parametrize(
"message",
(
"删除阅读模式",
"请帮我删除一下看书模式吧",
"把“阅读模式”删掉。",
),
)
def test_saved_user_mode_can_be_deleted_by_name_or_alias_without_hardware(
vehicle_service: SeatDemoService,
message: str,
) -> None:
saved = _save_reading_mode(vehicle_service)
with patch.object(
vehicle_service.hardware_execution,
"reserve",
side_effect=AssertionError("saved-mode deletion acquired the hardware lease"),
):
result = vehicle_service.preview_native_can(
message,
provider="local",
conversation_id="conv-saved-mode-delete-user",
execution_mode="hardware",
vehicle_id="denza_n7",
)
assert result["status"] == "succeeded"
assert result["orchestration_route"] == "mode_profile_delete"
assert result["execution_mode"] == "dry_run"
assert result["hardware_execution_allowed"] is False
assert result["deleted_mode_profile"]["id"] == saved.id
assert result["deleted_mode_profile"]["name"] == "阅读模式"
assert result["command_plans"] == {}
assert result["can_commands"] == []
assert vehicle_service.mode_profiles.resolve_exact_name(
"阅读模式", "denza_n7"
) is None
def test_delete_missing_and_builtin_modes_fails_closed_without_changing_registry(
vehicle_service: SeatDemoService,
) -> None:
preset = vehicle_service.mode_profiles.get_profile("office", "denza_n7")
preset_revision = vehicle_service.mode_profiles.profile_revision(preset)
missing = vehicle_service.preview_native_can(
"删除不存在模式",
provider="local",
conversation_id="conv-saved-mode-delete-missing",
execution_mode="hardware",
vehicle_id="denza_n7",
)
protected = vehicle_service.preview_native_can(
"删除办公模式",
provider="local",
conversation_id="conv-saved-mode-delete-protected",
execution_mode="hardware",
vehicle_id="denza_n7",
)
assert missing["status"] == "needs_confirmation"
assert missing["orchestration_route"] == "mode_profile_delete"
assert any(
item.get("code") == "MODE_PROFILE_NOT_FOUND"
for item in missing["validation"]
)
assert protected["status"] == "rejected"
assert protected["orchestration_route"] == "mode_profile_delete"
assert any(
item.get("code") == "MODE_PROFILE_DELETE_PROTECTED"
for item in protected["validation"]
)
remaining = vehicle_service.mode_profiles.get_profile("office", "denza_n7")
assert vehicle_service.mode_profiles.profile_revision(remaining) == preset_revision
@pytest.mark.parametrize(
"message",
(
"阅读模式中会控制哪些设备,执行哪些动作?",
"看书模式里有哪些设备和参数",
"阅读空间模式会做什么?",
),
)
def test_saved_mode_details_are_answered_from_the_live_registry_without_model(
vehicle_service: SeatDemoService,
message: str,
) -> None:
_save_reading_mode(vehicle_service)
catalog = AssistantCapabilityCatalog(vehicle_service)
snapshot = catalog.snapshot("denza_n7")
answer = catalog.fast_answer(message, snapshot)
assert answer is not None
assert answer.topic == "specific_mode_detail"
assert "阅读模式" in answer.answer
assert "空调" in answer.answer
assert "24" in answer.answer
assert "遮阳帘" in answer.answer
assert "阅读灯" in answer.answer
assert "未下发车辆控制" in answer.answer
def test_saved_mode_detail_query_reports_an_unknown_exact_name_without_guessing(
vehicle_service: SeatDemoService,
) -> None:
_save_reading_mode(vehicle_service)
catalog = AssistantCapabilityCatalog(vehicle_service)
snapshot = catalog.snapshot("denza_n7")
answer = catalog.fast_answer("火星模式包含哪些设备和动作?", snapshot)
assert answer is not None
assert answer.topic == "specific_mode_detail_not_found"
assert "火星模式" in answer.answer
assert "未找到" in answer.answer
assert "未下发车辆控制" in answer.answer
assert "阅读模式" not in answer.answer
@pytest.mark.parametrize(
"message",
(
"把阅读模式中空调温度调整到26度",
"删除阅读模式",
"执行阅读模式",
"把全车空调温度调整到26度",
),
)
def test_saved_mode_catalog_answer_never_intercepts_mutation_or_execution(
vehicle_service: SeatDemoService,
message: str,
) -> None:
_save_reading_mode(vehicle_service)
catalog = AssistantCapabilityCatalog(vehicle_service)
snapshot = catalog.snapshot("denza_n7")
assert catalog.fast_answer(message, snapshot) is None
def _assistant_turn(
service: SeatDemoService,
message: str,
conversation_id: str,
) -> tuple[dict[str, object], list[dict[str, object]], MagicMock]:
client = MagicMock()
client.available = False
client.status = "unavailable"
assistant = CodexAssistantService(client)
catalog = AssistantCapabilityCatalog(service)
snapshot = catalog.snapshot("denza_n7")
events: list[dict[str, object]] = []
def execute_control(
instruction: str,
progress: object,
_assistant_plan: object = None,
) -> dict[str, object]:
return service.preview_native_can(
instruction,
provider="local",
conversation_id=conversation_id,
execution_mode="hardware",
vehicle_id="denza_n7",
on_commands_validated=progress if callable(progress) else None,
)
response = assistant.stream(
message,
conversation_id=conversation_id,
principal="saved-mode-management-test",
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),
query_capabilities=catalog.query,
)
return response, events, client
def test_assistant_updates_saved_mode_without_waiting_for_codex_tool_call(
vehicle_service: SeatDemoService,
) -> None:
_save_reading_mode(vehicle_service)
with patch.object(
vehicle_service.hardware_execution,
"reserve",
side_effect=AssertionError("assistant update acquired the hardware lease"),
):
response, events, client = _assistant_turn(
vehicle_service,
"把阅读模式中空调温度调整到26度",
"conv-assistant-saved-mode-update",
)
assert response["route"] == "mode_profile_update"
assert response["success"] is True
assert "阅读模式" in response["answer"]
assert "26" in response["answer"]
assert "车辆控制未完成" not in response["answer"]
assert events[0]["route"] == "mode_profile_update"
assert events[0]["engine"] == "n7web-mode-profile-manager"
assert events[-1]["route"] == "mode_profile_update"
assert next(event for event in events if event["type"] == "action.completed")[
"success"
] is True
assert _temperature(
vehicle_service.mode_profiles.get_profile("user-reading", "denza_n7"),
"vehicle",
) == 26
client.start_thread.assert_not_called()
client.start_turn.assert_not_called()
def test_assistant_deletes_saved_user_mode_without_waiting_for_codex_tool_call(
vehicle_service: SeatDemoService,
) -> None:
_save_reading_mode(vehicle_service)
response, events, client = _assistant_turn(
vehicle_service,
"删除阅读模式",
"conv-assistant-saved-mode-delete",
)
assert response["route"] == "mode_profile_delete"
assert response["success"] is True
assert "阅读模式" in response["answer"]
assert "删除" in response["answer"]
assert "仍保留" not in response["answer"]
assert events[0]["route"] == "mode_profile_delete"
assert events[0]["engine"] == "n7web-mode-profile-manager"
assert events[-1]["route"] == "mode_profile_delete"
assert vehicle_service.mode_profiles.resolve_exact_name(
"阅读模式", "denza_n7"
) is None
client.start_thread.assert_not_called()
client.start_turn.assert_not_called()
@@ -0,0 +1,102 @@
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)
@@ -0,0 +1,514 @@
from __future__ import annotations
import hashlib
import json
from collections.abc import Callable, Mapping
from copy import deepcopy
from pathlib import Path
from unittest.mock import MagicMock, patch
import pytest
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
@pytest.fixture
def hybrid_service(
tmp_path: Path,
) -> tuple[SeatDemoService, AssistantCapabilityCatalog, Path]:
service = SeatDemoService(REPOSITORY_ROOT)
service.artifact_root = tmp_path / "runs"
user_root = tmp_path / "user-modes"
service.mode_profiles = ModeProfileRegistry(
REPOSITORY_ROOT / "config" / "modes",
user_root=user_root,
)
try:
yield service, AssistantCapabilityCatalog(service), user_root
finally:
service.close()
def _target(action: Mapping[str, object]) -> str:
target = action.get("target")
assert isinstance(target, Mapping)
return str(target.get("instance") or target.get("zone") or "")
def _actions(result: Mapping[str, object]) -> list[dict[str, object]]:
intent = result.get("intent_ir")
if isinstance(intent, Mapping):
spec = intent.get("spec")
raw_actions = spec.get("actions") if isinstance(spec, Mapping) else None
else:
raw_actions = result.get("actions")
assert isinstance(raw_actions, list)
assert all(isinstance(action, dict) for action in raw_actions)
return raw_actions
def _action_map(
result: Mapping[str, object],
) -> dict[tuple[str, str], dict[str, object]]:
return {
(str(action["capability"]), _target(action)): deepcopy(dict(action.get("parameters") or {}))
for action in _actions(result)
}
def _draft_reference(result: Mapping[str, object]) -> dict[str, str]:
draft = result.get("mode_profile_draft")
assert isinstance(draft, Mapping)
return {
"name": str(draft["name"]),
"source_request_id": str(draft["source_request_id"]),
"vehicle_id": str(draft["vehicle_id"]),
}
def _template_hashes() -> dict[str, str]:
root = REPOSITORY_ROOT / "config" / "scene_templates"
return {
path.name: hashlib.sha256(path.read_bytes()).hexdigest()
for path in sorted(root.glob("*.yaml"))
}
def _assistant_preview(
service: SeatDemoService,
catalog: AssistantCapabilityCatalog,
message: str,
*,
conversation_id: str,
) -> tuple[
dict[str, object],
dict[str, object],
list[dict[str, object]],
MagicMock,
list[dict[str, object] | None],
]:
client = MagicMock()
client.available = False
assistant = CodexAssistantService(client)
snapshot = catalog.snapshot(vehicle_id="denza_n7")
events: list[dict[str, object]] = []
raw_results: list[dict[str, object]] = []
passed_plans: list[dict[str, object] | None] = []
def execute_control(
instruction: str,
progress: Callable[[dict[str, object]], None],
assistant_plan: Mapping[str, object] | None = None,
) -> dict[str, object]:
plan = deepcopy(dict(assistant_plan)) if assistant_plan is not None else None
passed_plans.append(plan)
result = service.preview_native_can(
instruction,
provider="local",
conversation_id=conversation_id,
execution_mode="hardware",
vehicle_id="denza_n7",
on_commands_validated=progress,
assistant_plan=plan,
)
raw_results.append(result)
return result
response = assistant.stream(
message,
conversation_id=conversation_id,
principal="scene-template-hybrid-test",
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),
)
assert len(raw_results) == 1
return response, raw_results[0], events, client, passed_plans
def test_all_production_scene_templates_complete_the_full_local_dry_run(
hybrid_service: tuple[SeatDemoService, AssistantCapabilityCatalog, Path],
) -> None:
service, catalog, user_root = hybrid_service
snapshot = catalog.snapshot(vehicle_id="denza_n7")
templates = snapshot["scene_templates"]
assert isinstance(templates, list)
assert len(templates) == 12
assert all(template["assistant_callable"] is True for template in templates)
with patch.object(
service.hardware_execution,
"reserve",
side_effect=AssertionError("a scene template preview reached hardware execution"),
):
for index, template in enumerate(templates):
plan = deepcopy(template["plan"])
result = service.preview_native_can(
f"构建一个{template['name']}",
provider="local",
conversation_id=f"conv-template-matrix-{index:02d}",
execution_mode="hardware",
vehicle_id="denza_n7",
assistant_plan=plan,
)
assert result["status"] == "succeeded", template["id"]
assert result["execution_mode"] == "dry_run", template["id"]
assert result["hardware_execution_allowed"] is False, template["id"]
assert result["orchestration_route"] == "mode_profile_create_preview"
draft = result["mode_profile_draft"]
assert draft["generation_source"] == "scene_template_copy"
assert draft["operation_count"] == template["operation_count"]
assert draft["source_template_id"] == template["id"]
assert draft["source_template_revision"] == template["template_revision"]
assert "existing_mode_id" not in draft
expected = {
(
str(request["capability"]),
str(request["target_scope"]),
json.dumps(
{
parameter["name"]: parameter["value"]
for parameter in request["parameters"]
},
ensure_ascii=False,
sort_keys=True,
),
)
for request in plan["requests"]
}
actual = {
(
str(action["capability"]),
_target(action),
json.dumps(
action.get("parameters") or {},
ensure_ascii=False,
sort_keys=True,
),
)
for action in _actions(result)
}
assert actual == expected, template["id"]
assert not list(user_root.rglob("*.yaml"))
def test_viewing_template_creates_an_unbound_audited_copy_without_codex(
hybrid_service: tuple[SeatDemoService, AssistantCapabilityCatalog, Path],
) -> None:
service, catalog, user_root = hybrid_service
with patch.object(
service.hardware_execution,
"reserve",
side_effect=AssertionError("template copy reached hardware execution"),
):
response, raw_result, events, client, passed_plans = _assistant_preview(
service,
catalog,
"构建一个观影模式",
conversation_id="conv-template-viewing-copy",
)
draft = raw_result["mode_profile_draft"]
assert response["route"] == "scene_template"
assert response["success"] is True
assert raw_result["status"] == "succeeded"
assert raw_result["execution_mode"] == "dry_run"
assert raw_result["hardware_execution_allowed"] is False
assert draft["name"] == "观影模式"
assert draft["generation_source"] == "scene_template_copy"
assert draft["source_template_id"] == "cinema"
assert draft["source_template_revision"]
assert "existing_mode_id" not in draft
assert "existing_mode_revision" not in draft
assert raw_result["mode_creation"]["source_template_id"] == "cinema"
assert passed_plans[0]["metadata"]["source"] == "scene_template"
assert events[0]["engine"] == "n7web-scene-template"
assert "独立草稿" in response["answer"]
assert not list(user_root.rglob("*.yaml"))
client.start_structured_turn.assert_not_called()
client.start_turn.assert_not_called()
@pytest.mark.parametrize(
("case_id", "message", "expected_name", "template_id"),
(
(
"reading-purpose",
"帮我构建一个适合看书的功能模式",
"看书模式",
"reading",
),
(
"reading-purpose-preview",
"我想生成一个用来读书的模式并预览",
"读书模式",
"reading",
),
(
"relax-purpose",
"构建一个适合放松的功能模式",
"放松模式",
"relaxation",
),
(
"relax-purpose-polite",
"请生成用于放松的模式,先看看",
"放松模式",
"relaxation",
),
(
"cinema-purpose",
"帮我构建一个适合看电影的功能模式",
"看电影模式",
"cinema",
),
),
)
def test_purpose_descriptions_use_a_concise_name_and_zero_model_template_route(
hybrid_service: tuple[SeatDemoService, AssistantCapabilityCatalog, Path],
case_id: str,
message: str,
expected_name: str,
template_id: str,
) -> None:
service, catalog, user_root = hybrid_service
with patch.object(
service.hardware_execution,
"reserve",
side_effect=AssertionError("purpose template reached hardware execution"),
):
response, raw_result, events, client, passed_plans = _assistant_preview(
service,
catalog,
message,
conversation_id=f"conv-template-{case_id}",
)
template = service.scene_templates.get_template(template_id)
draft = raw_result["mode_profile_draft"]
assert response["route"] == "scene_template"
assert response["success"] is True
assert expected_name in response["answer"]
assert raw_result["status"] == "succeeded"
assert raw_result["execution_mode"] == "dry_run"
assert raw_result["hardware_execution_allowed"] is False
assert draft["name"] == expected_name
assert draft["generation_source"] == "scene_template_copy"
assert draft["source_template_id"] == template_id
assert draft["operation_count"] == len(template.operations)
assert passed_plans[0]["metadata"]["template_id"] == template_id
assert events[0]["engine"] == "n7web-scene-template"
assert not list(user_root.rglob("*.yaml"))
client.start_structured_turn.assert_not_called()
client.start_turn.assert_not_called()
def test_explicit_settings_on_a_purpose_scene_bypass_template_defaults(
hybrid_service: tuple[SeatDemoService, AssistantCapabilityCatalog, Path],
) -> None:
service, catalog, _user_root = hybrid_service
response, raw_result, events, client, passed_plans = _assistant_preview(
service,
catalog,
"构建一个适合看书的功能模式,空调温度调整到25度",
conversation_id="conv-template-purpose-explicit-settings",
)
draft = raw_result["mode_profile_draft"]
assert response["route"] == "vehicle_control"
assert response["success"] is True
assert draft["name"] == "看书模式"
assert draft["generation_source"] == "explicit_scene_requirements"
assert draft["operation_count"] == 1
assert passed_plans == [None]
assert events[0]["engine"] == "n7web-mode-builder"
client.start_structured_turn.assert_not_called()
client.start_turn.assert_not_called()
def test_template_metadata_cannot_authorize_modified_or_stale_template_actions(
hybrid_service: tuple[SeatDemoService, AssistantCapabilityCatalog, Path],
) -> None:
service, catalog, user_root = hybrid_service
snapshot = catalog.snapshot(vehicle_id="denza_n7")
template = next(
item for item in snapshot["scene_templates"] if item["id"] == "cinema"
)
modified = deepcopy(template["plan"])
modified["requests"][0]["parameters"][0]["value"] = "off"
with pytest.raises(ValueError, match="模板已更新"):
service.preview_native_can(
"构建一个观影模式",
provider="local",
conversation_id="conv-template-plan-tamper",
execution_mode="hardware",
vehicle_id="denza_n7",
assistant_plan=modified,
)
stale = deepcopy(template["plan"])
stale["metadata"]["template_revision"] = "0123456789abcdef"
with pytest.raises(ValueError, match="模板已更新"):
service.preview_native_can(
"构建一个观影模式",
provider="local",
conversation_id="conv-template-plan-stale",
execution_mode="hardware",
vehicle_id="denza_n7",
assistant_plan=stale,
)
assert not list(user_root.rglob("*.yaml"))
def test_template_alias_keeps_the_user_requested_draft_name(
hybrid_service: tuple[SeatDemoService, AssistantCapabilityCatalog, Path],
) -> None:
service, catalog, _user_root = hybrid_service
response, raw_result, _events, client, passed_plans = _assistant_preview(
service,
catalog,
"创建一个影院模式",
conversation_id="conv-template-alias-name",
)
draft = raw_result["mode_profile_draft"]
assert response["route"] == "scene_template"
assert draft["name"] == "影院模式"
assert draft["source_template_id"] == "cinema"
assert passed_plans[0]["metadata"]["template_id"] == "cinema"
client.start_structured_turn.assert_not_called()
client.start_turn.assert_not_called()
def test_template_copy_can_be_revised_twice_without_losing_sibling_actions(
hybrid_service: tuple[SeatDemoService, AssistantCapabilityCatalog, Path],
) -> None:
service, catalog, user_root = hybrid_service
conversation_id = "conv-template-viewing-revision-chain"
with patch.object(
service.hardware_execution,
"reserve",
side_effect=AssertionError("template draft revision reached hardware execution"),
):
_response, built, _events, _client, _plans = _assistant_preview(
service,
catalog,
"构建一个观影模式",
conversation_id=conversation_id,
)
shade_revised = service.preview_native_can(
"把观影模式的遮阳帘变成100%",
provider="local",
conversation_id=conversation_id,
execution_mode="hardware",
vehicle_id="denza_n7",
mode_profile_draft_context=_draft_reference(built),
)
final = service.preview_native_can(
"把观影模式的空调温度调整到25度",
provider="local",
conversation_id=conversation_id,
execution_mode="hardware",
vehicle_id="denza_n7",
mode_profile_draft_context=_draft_reference(shade_revised),
)
built_actions = _action_map(built)
shade_actions = _action_map(shade_revised)
final_actions = _action_map(final)
shade_key = ("roof.set_shade_position", "vehicle")
temperature_key = ("climate.set_temperature", "vehicle")
assert shade_revised["status"] == final["status"] == "succeeded"
assert shade_revised["execution_mode"] == final["execution_mode"] == "dry_run"
assert shade_revised["hardware_execution_allowed"] is False
assert final["hardware_execution_allowed"] is False
assert len(built_actions) == len(shade_actions) == len(final_actions) == 7
assert built_actions[shade_key] == {"position_pct": 0}
assert shade_actions[shade_key] == final_actions[shade_key] == {"position_pct": 100}
assert built_actions[temperature_key] == shade_actions[temperature_key] == {"temperature_c": 24}
assert final_actions[temperature_key] == {"temperature_c": 25}
untouched_keys = set(built_actions) - {shade_key, temperature_key}
assert {key: final_actions[key] for key in untouched_keys} == {
key: built_actions[key] for key in untouched_keys
}
first_draft = built["mode_profile_draft"]
second_draft = shade_revised["mode_profile_draft"]
final_draft = final["mode_profile_draft"]
assert first_draft["draft_revision"] == 1
assert second_draft["draft_revision"] == 2
assert final_draft["draft_revision"] == 3
assert second_draft["generation_source"] == "draft_revision"
assert final_draft["generation_source"] == "draft_revision"
assert second_draft["source_template_id"] == final_draft["source_template_id"] == ("cinema")
assert "existing_mode_id" not in final_draft
assert not list(user_root.rglob("*.yaml"))
def test_saving_a_template_copy_never_mutates_template_and_registered_mode_wins_next(
hybrid_service: tuple[SeatDemoService, AssistantCapabilityCatalog, Path],
) -> None:
service, catalog, user_root = hybrid_service
hashes_before = _template_hashes()
template_revision = service.scene_templates.get_template("cinema").revision
_response, built, _events, first_client, first_plans = _assistant_preview(
service,
catalog,
"构建一个观影模式",
conversation_id="conv-template-save-source",
)
draft = built["mode_profile_draft"]
saved = service.create_mode_profile_card(
str(draft["name"]),
str(draft["instruction"]),
str(draft["source_request_id"]),
str(draft["vehicle_id"]),
)
saved_profile = saved["mode_profile"]
assert saved["status"] == "succeeded"
assert saved_profile["name"] == "观影模式"
assert saved_profile["origin"] == "user"
assert saved_profile["id"] != "cinema"
assert list(user_root.rglob(f"{saved_profile['id']}.yaml"))
assert _template_hashes() == hashes_before
assert service.scene_templates.get_template("cinema").revision == template_revision
assert first_plans[0]["metadata"]["template_id"] == "cinema"
first_client.start_structured_turn.assert_not_called()
response, registered, events, second_client, passed_plans = _assistant_preview(
service,
catalog,
"构建一个观影模式",
conversation_id="conv-template-saved-mode-priority",
)
registered_draft = registered["mode_profile_draft"]
assert response["route"] == "vehicle_control"
assert response["success"] is True
assert events[0]["engine"] == "n7web-mode-builder"
assert passed_plans == [None]
assert registered_draft["generation_source"] == "registered_mode_profile"
assert registered_draft["existing_mode_id"] == saved_profile["id"]
assert "source_template_id" not in registered_draft
second_client.start_structured_turn.assert_not_called()
second_client.start_turn.assert_not_called()