forked from cleveragents/cleveragents-core
e7df15d453
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
185 lines
5.2 KiB
Python
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")
|