Files
cleveragents-core/benchmarks/ui_render_bench.py
freemo e7df15d453 feat(ui): add TUI/Web interface
Implement UI data-provider interface backed by local services.
Add Textual-based TUI with plan list, plan detail, diff viewer,
and validation summary panes. Add Web UI stub with local-only
read-only routes. Configure auto-refresh and manual keybinds.

ISSUES CLOSED: #341
2026-03-24 20:30:54 +00:00

185 lines
5.2 KiB
Python

"""ASV benchmarks for UI data provider and web route overhead.
Measures the performance of:
- LocalUIDataProvider plan list retrieval
- LocalUIDataProvider plan detail retrieval
- Web UI route handler response times
"""
from __future__ import annotations
import importlib
import sys
from pathlib import Path
from unittest.mock import MagicMock
# Ensure the local *source* tree is importable even when ASV has an
# older build of the package installed.
_SRC = str(Path(__file__).resolve().parents[1] / "src")
if _SRC not in sys.path:
sys.path.insert(0, _SRC)
import cleveragents # noqa: E402
importlib.reload(cleveragents)
from cleveragents.ui.data_provider import ( # noqa: E402
DiffItem,
LocalUIDataProvider,
LogEntry,
PlanDetail,
PlanSummary,
SessionSummary,
ValidationResult,
)
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
def _mock_plan(
plan_id: str = "plan-1",
name: str = "plan-alpha",
status: str = "draft",
) -> MagicMock:
p = MagicMock()
p.id = plan_id
p.name = name
p.status = status
p.created_at = "2025-01-01T00:00:00"
p.prompt = "Do something"
p.decisions = []
p.linked_resources = []
p.project_id = "proj-1"
return p
class _StubProvider:
"""Trivial UIDataProvider for benchmarks."""
def get_plans(self, project_id: str) -> list[PlanSummary]:
return [
PlanSummary(
plan_id=f"plan-{i}",
name=f"plan-{i}",
status="draft",
created_at="2025-01-01T00:00:00",
project_id=project_id,
)
for i in range(50)
]
def get_plan_detail(self, plan_id: str) -> PlanDetail | None:
return PlanDetail(
plan_id=plan_id,
name="plan-alpha",
status="draft",
created_at="2025-01-01T00:00:00",
project_id="proj-1",
prompt="Do something",
decisions=[
{"id": f"d{i}", "type": "approval", "status": "pending"}
for i in range(10)
],
linked_resources=[f"res-{i}" for i in range(5)],
)
def get_sessions(self) -> list[SessionSummary]:
return []
def get_validations(self, plan_id: str) -> list[ValidationResult]:
return []
def get_diffs(self, plan_id: str) -> list[DiffItem]:
return []
def get_logs(self, plan_id: str, level: str = "INFO") -> list[LogEntry]:
return []
_STUB = _StubProvider()
# ---------------------------------------------------------------------------
# Data provider benchmarks
# ---------------------------------------------------------------------------
class TimeDataProvider:
"""Benchmark LocalUIDataProvider backed by mock services."""
timeout = 30
def setup(self) -> None:
"""Prepare provider with mock plan service."""
self._mock_svc = MagicMock()
plans = [_mock_plan(f"plan-{i}", f"plan-{i}") for i in range(50)]
self._mock_svc.list_plans.return_value = plans
detail = _mock_plan()
detail.decisions = [MagicMock(id="d1", type="a", status="p")]
detail.linked_resources = ["r1"]
detail.project_id = "proj-1"
self._mock_svc.get_plan.return_value = detail
self._provider = LocalUIDataProvider(plan_service=self._mock_svc)
def time_get_plans(self) -> None:
"""Benchmark plan list retrieval."""
self._provider.get_plans("proj-1")
def time_get_plan_detail(self) -> None:
"""Benchmark plan detail retrieval."""
self._provider.get_plan_detail("plan-1")
def time_get_validations(self) -> None:
"""Benchmark validation retrieval."""
self._provider.get_validations("plan-1")
def time_get_diffs(self) -> None:
"""Benchmark diff retrieval."""
self._provider.get_diffs("plan-1")
def time_get_logs(self) -> None:
"""Benchmark log retrieval."""
self._provider.get_logs("plan-1")
# ---------------------------------------------------------------------------
# Web route benchmarks
# ---------------------------------------------------------------------------
class TimeWebRoutes:
"""Benchmark FastAPI web UI route handler overhead."""
timeout = 30
def setup(self) -> None:
"""Prepare test client with stub provider."""
from fastapi.testclient import TestClient
from cleveragents.ui.web_app import create_web_app
web = create_web_app(provider=_STUB)
self._client = TestClient(web)
def time_list_plans(self) -> None:
"""Benchmark plans list route."""
self._client.get("/ui/plans")
def time_plan_detail(self) -> None:
"""Benchmark plan detail route."""
self._client.get("/ui/plans/plan-1")
def time_sessions(self) -> None:
"""Benchmark sessions route."""
self._client.get("/ui/sessions")
def time_diffs(self) -> None:
"""Benchmark diffs route."""
self._client.get("/ui/diffs/plan-1")
def time_health(self) -> None:
"""Benchmark health route."""
self._client.get("/ui/health")