mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-09-30 06:53:14 +00:00
* Revert "fix: schedule usage snapshot runs with explicit empty input (#1470)" This reverts commit49aa638c58. * Revert "feat: out-of-process usage-snapshot builder (Phase 1) (#1468)" This reverts commit798cc6edf1.
218 lines
8 KiB
Python
218 lines
8 KiB
Python
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from agent.dashboard import agent_usage
|
|
|
|
|
|
class FakeStore:
|
|
def __init__(self, values: dict[tuple[tuple[str, ...], str], dict] | None = None):
|
|
self.values = values or {}
|
|
self.puts: list[tuple[list[str], str, dict]] = []
|
|
|
|
async def get_item(self, namespace: list[str], key: str) -> dict | None:
|
|
value = self.values.get((tuple(namespace), key))
|
|
return {"value": value} if value is not None else None
|
|
|
|
async def put_item(self, namespace: list[str], key: str, value: dict) -> None:
|
|
self.puts.append((namespace, key, value))
|
|
self.values[(tuple(namespace), key)] = value
|
|
|
|
|
|
class FakeThreads:
|
|
def __init__(self, threads: list[dict]):
|
|
self.threads = threads
|
|
self.calls: list[dict] = []
|
|
|
|
async def search(self, **kwargs) -> list[dict]:
|
|
self.calls.append(kwargs)
|
|
offset = kwargs.get("offset") or 0
|
|
limit = kwargs.get("limit") or len(self.threads)
|
|
return self.threads[offset : offset + limit]
|
|
|
|
|
|
class FakeClient:
|
|
def __init__(self, *, store: FakeStore | None = None, threads: FakeThreads | None = None):
|
|
self.store = store or FakeStore()
|
|
self.threads = threads or FakeThreads([])
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_cached_usage_payload_returns_stale_snapshot_and_schedules_refresh(monkeypatch):
|
|
usage_snapshot = {
|
|
"period": "30d",
|
|
"total_members": 2,
|
|
"users": [
|
|
{
|
|
"rank": 1,
|
|
"key": "github:octo",
|
|
"name": "octo",
|
|
"github_login": "octo",
|
|
"email": "octo@example.com",
|
|
"favorite_model": "claude",
|
|
"agent_runs": 3,
|
|
"prs_opened": 2,
|
|
"merged_prs": 1,
|
|
"agent_loc": 10,
|
|
"additions": 8,
|
|
"deletions": 2,
|
|
},
|
|
{
|
|
"rank": 2,
|
|
"key": "email:private@example.com",
|
|
"name": "private",
|
|
"github_login": None,
|
|
"email": "private@example.com",
|
|
"favorite_model": "default",
|
|
"agent_runs": 1,
|
|
"prs_opened": 0,
|
|
"merged_prs": 0,
|
|
"agent_loc": 0,
|
|
"additions": 0,
|
|
"deletions": 0,
|
|
},
|
|
],
|
|
}
|
|
reviewer_snapshot = {
|
|
"period": "30d",
|
|
"reviewed_prs": 1,
|
|
"prs_with_findings": 1,
|
|
"findings_recorded": 1,
|
|
"surfaced_findings": 1,
|
|
"addressed_findings": 0,
|
|
"resolved_after_update": 0,
|
|
"dismissed_findings": 0,
|
|
"unresolved_surfaced_findings": 1,
|
|
"resolution_rate": 0.0,
|
|
"human_replies": 0,
|
|
"severity_counts": {"medium": 1},
|
|
"top_categories": [{"name": "correctness", "count": 1}],
|
|
}
|
|
store = FakeStore(
|
|
{
|
|
(tuple(agent_usage.USAGE_LEADERBOARD_CACHE_NAMESPACE), "30d"): {
|
|
"generated_at_ms": 1,
|
|
"snapshot": usage_snapshot,
|
|
},
|
|
(tuple(agent_usage.REVIEWER_STATS_CACHE_NAMESPACE), "30d"): {
|
|
"generated_at_ms": 1,
|
|
"snapshot": reviewer_snapshot,
|
|
},
|
|
}
|
|
)
|
|
monkeypatch.setattr(agent_usage, "_client", lambda: FakeClient(store=store))
|
|
monkeypatch.setattr(agent_usage, "_now_ms", lambda: agent_usage._CACHE_TTL_MS + 2)
|
|
|
|
usage_refreshes: list[str] = []
|
|
reviewer_refreshes: list[str] = []
|
|
payload = await agent_usage.list_agent_usage_leaderboard(
|
|
period="30d",
|
|
limit=1,
|
|
current_login="octo",
|
|
current_email="octo@example.com",
|
|
schedule_usage_refresh=usage_refreshes.append,
|
|
schedule_reviewer_refresh=reviewer_refreshes.append,
|
|
)
|
|
|
|
assert usage_refreshes == ["30d"]
|
|
assert reviewer_refreshes == ["30d"]
|
|
assert payload["rows"][0]["user"]["email"] == "octo@example.com"
|
|
assert payload["total_members"] == 2
|
|
assert payload["reviewer_stats"]["surfaced_findings"] == 1
|
|
assert store.puts == []
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_reviewer_stats_snapshot_counts_surfaced_and_resolved_findings(monkeypatch):
|
|
threads = [
|
|
{
|
|
"created_at": "2025-01-01T00:00:00Z",
|
|
"metadata": {
|
|
"kind": "reviewer",
|
|
"head_sha": "fixed-sha",
|
|
"pr": {"owner": "langchain-ai", "name": "open-swe", "number": 1},
|
|
"findings": [
|
|
{
|
|
"id": "f_1",
|
|
"status": "resolved",
|
|
"severity": "high",
|
|
"category": "correctness",
|
|
"first_seen_sha": "buggy-sha",
|
|
"github_thread_resolved": True,
|
|
"github_review_comment_id": 10,
|
|
"resolution_note": "Fixed in a follow-up commit.",
|
|
"interactions": [{"kind": "human_reply"}],
|
|
},
|
|
{
|
|
"id": "f_2",
|
|
"status": "open",
|
|
"severity": "medium",
|
|
"category": "performance",
|
|
"github_review_comment_id": 11,
|
|
},
|
|
{
|
|
"id": "f_3",
|
|
"status": "dismissed",
|
|
"severity": "low",
|
|
"category": "style",
|
|
"github_review_id": 12,
|
|
},
|
|
],
|
|
},
|
|
}
|
|
]
|
|
monkeypatch.setattr(agent_usage, "_client", lambda: FakeClient(threads=FakeThreads(threads)))
|
|
|
|
snapshot = await agent_usage._build_reviewer_stats_snapshot("all")
|
|
|
|
assert snapshot["reviewed_prs"] == 1
|
|
assert snapshot["prs_with_findings"] == 1
|
|
assert snapshot["findings_recorded"] == 3
|
|
assert snapshot["surfaced_findings"] == 3
|
|
assert snapshot["addressed_findings"] == 1
|
|
assert snapshot["resolved_after_update"] == 1
|
|
assert snapshot["dismissed_findings"] == 1
|
|
assert snapshot["unresolved_surfaced_findings"] == 1
|
|
assert snapshot["human_replies"] == 1
|
|
assert snapshot["severity_counts"] == {"high": 1, "medium": 1, "low": 1}
|
|
assert snapshot["top_categories"] == [
|
|
{"name": "correctness", "count": 1},
|
|
{"name": "performance", "count": 1},
|
|
{"name": "style", "count": 1},
|
|
]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_reviewer_stats_paginates_reviewer_threads(monkeypatch):
|
|
threads = [
|
|
{"created_at": "2025-01-03T00:00:00Z", "metadata": {"kind": "reviewer", "findings": []}},
|
|
{"created_at": "2025-01-02T00:00:00Z", "metadata": {"kind": "reviewer", "findings": []}},
|
|
{"created_at": "2025-01-01T00:00:00Z", "metadata": {"kind": "reviewer", "findings": []}},
|
|
]
|
|
fake_threads = FakeThreads(threads)
|
|
monkeypatch.setattr(agent_usage, "_CACHE_SEARCH_LIMIT", 2)
|
|
monkeypatch.setattr(agent_usage, "_client", lambda: FakeClient(threads=fake_threads))
|
|
|
|
snapshot = await agent_usage._build_reviewer_stats_snapshot("all")
|
|
|
|
assert snapshot["reviewed_prs"] == 3
|
|
assert [call["offset"] for call in fake_threads.calls] == [0, 2]
|
|
assert all(call["sort_by"] == "created_at" for call in fake_threads.calls)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_reviewer_stats_stops_after_page_older_than_cutoff(monkeypatch):
|
|
threads = [
|
|
{"created_at": "2025-01-03T00:00:00Z", "metadata": {"kind": "reviewer", "findings": []}},
|
|
{"created_at": "2025-01-01T00:00:00Z", "metadata": {"kind": "reviewer", "findings": []}},
|
|
{"created_at": "2024-12-31T00:00:00Z", "metadata": {"kind": "reviewer", "findings": []}},
|
|
]
|
|
fake_threads = FakeThreads(threads)
|
|
monkeypatch.setattr(agent_usage, "_CACHE_SEARCH_LIMIT", 2)
|
|
monkeypatch.setattr(agent_usage, "_client", lambda: FakeClient(threads=fake_threads))
|
|
cutoff_ms = agent_usage._timestamp_ms("2025-01-02T00:00:00Z")
|
|
|
|
pages = [page async for page in agent_usage._iter_reviewer_thread_pages(cutoff_ms)]
|
|
|
|
assert len(pages) == 1
|
|
assert [call["offset"] for call in fake_threads.calls] == [0]
|