diff --git a/web-ui/src/components/cases/agent-status-widget.tsx b/web-ui/src/components/cases/agent-status-widget.tsx index bfa0f8f..6bb13ce 100644 --- a/web-ui/src/components/cases/agent-status-widget.tsx +++ b/web-ui/src/components/cases/agent-status-widget.tsx @@ -8,12 +8,14 @@ import { Bot } from "lucide-react"; const STATUS_DOT: Record = { active: "bg-emerald-500 shadow-[0_0_6px_rgba(16,185,129,0.6)]", + running: "bg-emerald-500 shadow-[0_0_6px_rgba(16,185,129,0.6)]", idle: "bg-gray-300", error: "bg-red-500", }; const STATUS_LABEL: Record = { active: "פעיל", + running: "פעיל", idle: "ממתין", error: "שגיאה", }; @@ -51,7 +53,7 @@ export function AgentStatusWidget({ if (!data?.issues?.length) return null; const agents = data.agents ?? []; - const activeCount = agents.filter((a) => a.status === "active").length; + const activeCount = agents.filter((a) => a.status === "active" || a.status === "running").length; return (
diff --git a/web/app.py b/web/app.py index d5267d1..1698e66 100644 --- a/web/app.py +++ b/web/app.py @@ -38,6 +38,7 @@ from web.gitea_client import create_repo, setup_remote_and_push from web.paperclip_client import ( create_project as pc_create_project, create_workflow_issue as pc_create_workflow_issue, + get_agents_for_case as pc_get_agents_for_case, get_agents_for_company as pc_get_agents, get_case_issues as pc_get_case_issues, get_issue_comments as pc_get_issue_comments, @@ -2232,7 +2233,7 @@ async def api_case_agents(case_number: str): issue_ids = [i["id"] for i in issues] company_id = issues[0]["company_id"] - comments, agents = await pc_get_issue_comments(issue_ids), await pc_get_agents(company_id) + comments, agents = await pc_get_issue_comments(issue_ids), await pc_get_agents_for_case(company_id, issue_ids) return {"issues": issues, "comments": comments, "agents": agents} diff --git a/web/paperclip_client.py b/web/paperclip_client.py index 6f15c5f..9497937 100644 --- a/web/paperclip_client.py +++ b/web/paperclip_client.py @@ -408,6 +408,43 @@ async def get_agents_for_company(company_id: str) -> list[dict]: await conn.close() +async def get_agents_for_case(company_id: str, issue_ids: list[str]) -> list[dict]: + """Get agents with per-case status (running on *this* case vs globally).""" + conn = await asyncpg.connect(PAPERCLIP_DB_URL) + try: + rows = await conn.fetch( + """SELECT a.id, a.name, a.role, a.title, a.icon, + a.status AS global_status, a.last_heartbeat_at, + EXISTS( + SELECT 1 FROM heartbeat_runs hr + JOIN agent_wakeup_requests wr ON hr.wakeup_request_id = wr.id + WHERE hr.agent_id = a.id + AND hr.status = 'running' + AND wr.payload->>'issueId' = ANY($2::text[]) + ) AS active_on_case + FROM agents a + WHERE a.company_id = $1::uuid + ORDER BY a.role, a.name""", + company_id, issue_ids, + ) + return [ + { + "id": str(r["id"]), + "name": r["name"], + "role": r["role"], + "title": r["title"], + "status": "running" if r["active_on_case"] else ( + "idle" if r["global_status"] == "running" else r["global_status"] + ), + "icon": r["icon"], + "last_heartbeat_at": r["last_heartbeat_at"].isoformat() if r["last_heartbeat_at"] else None, + } + for r in rows + ] + finally: + await conn.close() + + async def post_comment(issue_id: str, company_id: str, body: str) -> dict: """Post a comment on a Paperclip issue.