Files
Cognitive_Agent/tests/unit/test_scene_composer_app_server_contract.py
T

99 lines
3.5 KiB
Python

from __future__ import annotations
import json
import sys
from pathlib import Path
from cognitive_agent.application.scene_composer import (
SCENE_COMPOSER_INSTRUCTIONS,
build_scene_output_schema,
)
from cognitive_agent.infrastructure.codex.app_server import CodexAppServerClient
ROOT = Path(__file__).resolve().parents[2]
FAKE_SERVER = ROOT / "tests" / "fixtures" / "fake_codex_app_server.py"
MCP_SERVER = ROOT / "src/cognitive_agent/infrastructure/codex/vehicle_mcp_server.py"
CALLBACK_URL = "http://127.0.0.1:8765/api/internal/codex/vehicle-control"
CALLBACK_TOKEN = "test-internal-token-123456"
def _context() -> dict[str, object]:
return {
"schema_version": "n7web-scene-capabilities/v1",
"planner_contract": "stable-absolute-set-actions-only",
"composition_revision": "composition-test-a",
"vehicle": {"id": "denza_n7", "name": "腾势 N7"},
"capabilities": [
{
"id": "climate.set_temperature",
"domain": "climate",
"target_scopes": ["vehicle", "driver", "passenger"],
"parameters": [
{
"name": "temperature_c",
"type": "number",
"minimum": 16,
"maximum": 32,
"required": True,
}
],
}
],
}
def test_scene_planner_uses_replaced_instructions_and_app_server_output_schema(
tmp_path: Path,
) -> None:
context = _context()
output_schema = build_scene_output_schema(context)
client = CodexAppServerClient(
cwd=tmp_path,
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,
)
try:
client.start(CALLBACK_URL, CALLBACK_TOKEN)
thread_id = client.start_thread(
developer_instructions=SCENE_COMPOSER_INSTRUCTIONS,
ephemeral=True,
replace_developer_instructions=True,
)
turn = client.start_structured_turn(
thread_id,
"构建一个专注模式",
application_context=context,
output_schema=output_schema,
)
client.finish_turn(turn, timeout=2)
finally:
client.close()
wire = [
json.loads(line)
for line in (tmp_path / "wire.jsonl").read_text(encoding="utf-8").splitlines()
]
thread_request = next(item for item in wire if item.get("method") == "thread/start")
instructions = thread_request["params"]["developerInstructions"]
assert instructions == SCENE_COMPOSER_INSTRUCTIONS.strip()
assert "n7_vehicle.execute_cockpit_request" not in instructions
assert "request_token" not in instructions
turn_request = next(item for item in wire if item.get("method") == "turn/start")
params = turn_request["params"]
model_input = params["input"][0]["text"]
assert params["outputSchema"] == output_schema
assert params["effort"] == "low"
assert params["approvalPolicy"] == "never"
assert params["sandboxPolicy"] == {"type": "readOnly", "networkAccess": False}
assert "N7WEB_SCENE_CAPABILITY_CONTEXT" in model_input
assert '"composition_revision":"composition-test-a"' in model_input
assert "构建一个专注模式" in model_input
assert "request_token" not in model_input
assert CALLBACK_TOKEN not in model_input