Files
legal-ai/web-ui/src/components/cases/agent-status-widget.tsx
Chaim 1e4c5c1518
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 3m16s
Add Paperclip agent activity mirror to case detail page
New "Agents" tab in case detail shows all Paperclip agent comments,
issue status, and agent status for each case — eliminating the need
to switch between Legal-AI and Paperclip UIs.

Backend: 4 new DB query functions in paperclip_client.py (issues,
comments, agents, post_comment) + 2 new API endpoints (GET/POST
/api/cases/{case_number}/agents). Comment posting uses Board API
with DB+wakeup fallback to ensure CEO routing.

Frontend: agents.ts hooks (10s polling), AgentActivityFeed component
(markdown timeline + comment input), AgentStatusWidget (sidebar),
4th tab in case detail page.

Also includes new-company-setup-guide.md documenting the process
for setting up the betterment levy (CMPA) company.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 10:44:42 +00:00

78 lines
2.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import { useAgentActivity } from "@/lib/api/agents";
import type { PaperclipAgent } from "@/lib/api/agents";
import { Bot } from "lucide-react";
/* ── Status dot colors ───────────────────────────────────────── */
const STATUS_DOT: Record<string, string> = {
active: "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<string, string> = {
active: "פעיל",
idle: "ממתין",
error: "שגיאה",
};
function statusDot(status: string) {
return STATUS_DOT[status] ?? STATUS_DOT.idle;
}
/* ── Agent row ───────────────────────────────────────────────── */
function AgentRow({ agent }: { agent: PaperclipAgent }) {
return (
<div className="flex items-center gap-2 py-1">
<span
className={`w-2 h-2 rounded-full flex-shrink-0 ${statusDot(agent.status)}`}
/>
<span className="text-xs text-ink truncate">{agent.name}</span>
<span className="text-[10px] text-ink-faint mr-auto">
{STATUS_LABEL[agent.status] ?? agent.status}
</span>
</div>
);
}
/* ── Widget ───────────────────────────────────────────────────── */
export function AgentStatusWidget({
caseNumber,
}: {
caseNumber: string;
}) {
const { data } = useAgentActivity(caseNumber);
// Don't render if no Paperclip project yet
if (!data?.issues?.length) return null;
const agents = data.agents ?? [];
const activeCount = agents.filter((a) => a.status === "active").length;
return (
<div className="space-y-2">
<div className="flex items-center justify-between">
<div className="flex items-center gap-1.5 text-xs font-medium text-navy">
<Bot className="w-3.5 h-3.5" />
<span>סוכנים</span>
</div>
{agents.length > 0 && (
<span className="text-[10px] text-ink-faint">
{activeCount} פעילים מתוך {agents.length}
</span>
)}
</div>
<div className="space-y-0.5">
{agents.map((agent) => (
<AgentRow key={agent.id} agent={agent} />
))}
</div>
</div>
);
}