r"""UI journey: a native Codex session renders parity with its TUI (mock LLM). The native ``codex-native`` ("Codex") wrapper is terminal-first: a real ``codex`` CLI runs in the session terminal, the SPA's **Terminal** view attaches to that live TUI over a WebSocket, and the SPA's **Chat** view renders the SAME canonical transcript (``GET /v1/sessions/{id}/items``) the TUI prints. A native bridge forwards web-composer messages INTO the Codex app-server thread and forwards Codex's transcript back OUT as conversation items. This suite asserts that round-trips both ways and renders exactly once — the same three properties the claude native forwarder is pinned against. The LLM calls are served by the in-process mock LLM server rather than a real OpenAI endpoint. Before each test run a mock ``openai`` provider config is written to ``~/.omnigent/config.yaml`` (see ``native_codex_mock_session`` in ``conftest.py``), redirecting the runner's ``OPENAI_BASE_URL`` to the mock server. Tokens are pre-generated and queued via content-based routing so the mock returns the expected assistant token for each turn regardless of how many extra LLM calls Codex makes internally. """ from __future__ import annotations import logging import uuid import pytest from playwright.sync_api import Page, expect from tests.e2e_ui.conftest import configure_mock_llm, reset_mock_llm, set_fallback_mock_llm # Reuse the custom-agent suite's helpers — both surfaces render from the same # canonical transcript, so parity / dedup / ordering are asserted identically. from .test_message_render_parity import ( _ASSISTANT, _USER, _WORKING, _assert_no_duplicate_render, _assert_transcript_parity, _ensure_chat_view, _send, _turn_prompt, ) _log = logging.getLogger(__name__) _TERMINAL_VIEW = '[data-testid="terminal-view"]' # xterm.js routes all keystrokes through a hidden helper