99 lines
3.5 KiB
Python
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
|