diff --git a/src/agent_mailer/routes/admin.py b/src/agent_mailer/routes/admin.py index 649e40e..1c5e5f3 100644 --- a/src/agent_mailer/routes/admin.py +++ b/src/agent_mailer/routes/admin.py @@ -138,7 +138,8 @@ def _parse_agent(row) -> dict: async def admin_list_agents(request: Request, user: dict = Depends(get_current_user)): db = request.app.state.db cursor = await db.execute( - "SELECT * FROM agents WHERE user_id = ? ORDER BY created_at", (user["id"],) + "SELECT * FROM agents WHERE user_id = ? AND COALESCE(status, 'active') != 'deleted' ORDER BY created_at", + (user["id"],), ) rows = await cursor.fetchall() return [AgentResponse(**_parse_agent(row)) for row in rows] @@ -224,7 +225,7 @@ async def agents_stats(request: Request, user: dict = Depends(get_current_user)) SUM(CASE WHEN action = 'forward' THEN 1 ELSE 0 END) AS forward_count FROM messages GROUP BY from_agent ) sent ON sent.from_agent = a.address - WHERE a.user_id = ? + WHERE a.user_id = ? AND COALESCE(a.status, 'active') != 'deleted' ORDER BY a.created_at """, (user["id"],)) rows = await cursor.fetchall() diff --git a/src/agent_mailer/routes/teams.py b/src/agent_mailer/routes/teams.py index dca1ef7..6587e54 100644 --- a/src/agent_mailer/routes/teams.py +++ b/src/agent_mailer/routes/teams.py @@ -59,7 +59,9 @@ async def list_teams(request: Request, user: dict = Depends(get_current_user)): cursor = await db.execute( """SELECT t.*, COUNT(a.id) AS agent_count FROM teams t - LEFT JOIN agents a ON a.team_id = t.id + LEFT JOIN agents a + ON a.team_id = t.id + AND COALESCE(a.status, 'active') != 'deleted' WHERE t.user_id = ? GROUP BY t.id ORDER BY t.created_at""", @@ -80,7 +82,8 @@ async def get_team(team_id: str, request: Request, user: dict = Depends(get_curr raise HTTPException(status_code=404, detail="Team not found") cursor = await db.execute( - "SELECT * FROM agents WHERE team_id = ? ORDER BY created_at", (team_id,) + "SELECT * FROM agents WHERE team_id = ? AND COALESCE(status, 'active') != 'deleted' ORDER BY created_at", + (team_id,), ) agent_rows = await cursor.fetchall() agents = [AgentResponse(**_parse_agent(r)) for r in agent_rows] diff --git a/tests/test_admin.py b/tests/test_admin.py index 161c64f..f323a62 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -572,6 +572,21 @@ async def test_delete_agent_preserves_messages(client, agents): assert len(thread_resp.json()) == 1 +async def test_soft_deleted_agent_hidden_from_admin_agents_and_stats(client, agents): + agent_id = agents["coder"]["id"] + + delete_resp = await client.delete(f"/users/me/agents/{agent_id}") + assert delete_resp.status_code == 200 + + agents_resp = await client.get("/admin/agents") + assert agents_resp.status_code == 200 + assert agent_id not in {a["id"] for a in agents_resp.json()} + + stats_resp = await client.get("/admin/agents/stats") + assert stats_resp.status_code == 200 + assert agent_id not in {a["agent_id"] for a in stats_resp.json()} + + # --- Agent Tags --- async def test_update_agent_tags(client, agents): diff --git a/tests/test_teams.py b/tests/test_teams.py index dbfa50d..a120386 100644 --- a/tests/test_teams.py +++ b/tests/test_teams.py @@ -73,6 +73,29 @@ async def test_get_team_detail(client): assert data["agents"] == [] +async def test_deleted_agent_hidden_from_team_count_and_detail(client): + create_resp = await client.post("/admin/teams", json={"name": "Soft Deleted"}) + team_id = create_resp.json()["id"] + agent = await _register_agent(client, "softdel") + + add_resp = await client.post(f"/admin/teams/{team_id}/agents", json={"agent_id": agent["id"]}) + assert add_resp.status_code == 200 + + delete_resp = await client.delete(f"/users/me/agents/{agent['id']}") + assert delete_resp.status_code == 200 + + teams_resp = await client.get("/admin/teams") + assert teams_resp.status_code == 200 + team = next(t for t in teams_resp.json() if t["id"] == team_id) + assert team["agent_count"] == 0 + + detail_resp = await client.get(f"/admin/teams/{team_id}") + assert detail_resp.status_code == 200 + detail = detail_resp.json() + assert detail["agent_count"] == 0 + assert detail["agents"] == [] + + async def test_get_team_not_found(client): resp = await client.get("/admin/teams/nonexistent-id") assert resp.status_code == 404