diff --git a/src/components/agents/AgentCard.tsx b/src/components/agents/AgentCard.tsx index 95743755..3b4274a2 100644 --- a/src/components/agents/AgentCard.tsx +++ b/src/components/agents/AgentCard.tsx @@ -1,8 +1,8 @@ -import { useState } from 'preact/hooks'; -import TeamAvatar from './TeamAvatar'; -import AgentConfigModal from './AgentConfigModal'; -import type { AgentTeamProfile } from '../../lib/agent-profile'; -import type { SwarmWorkCommand } from '../../lib/forge-agent-protocol'; +import { useState } from "preact/hooks"; +import TeamAvatar from "./TeamAvatar"; +import AgentConfigModal from "./AgentConfigModal"; +import type { AgentTeamProfile } from "../../lib/agent-profile"; +import type { SwarmWorkCommand } from "../../lib/forge-agent-protocol"; type TaskStats = { total: number; @@ -58,38 +58,52 @@ export default function AgentCard({ swarmPulse = false, }: Props) { const [configOpen, setConfigOpen] = useState(false); - const stats = taskStats ?? { total: 0, completed: 0, failed: 0, running: 0, pending: 0 }; - const completionPct = stats.total > 0 ? Math.round((stats.completed / stats.total) * 100) : 0; - const pendingPct = stats.total > 0 ? Math.round((stats.pending / stats.total) * 100) : 0; - const failedPct = stats.total > 0 ? Math.round((stats.failed / stats.total) * 100) : 0; + const stats = taskStats ?? { + total: 0, + completed: 0, + failed: 0, + running: 0, + pending: 0, + }; + const completionPct = + stats.total > 0 ? Math.round((stats.completed / stats.total) * 100) : 0; + const pendingPct = + stats.total > 0 ? Math.round((stats.pending / stats.total) * 100) : 0; + const failedPct = + stats.total > 0 ? Math.round((stats.failed / stats.total) * 100) : 0; const isRunning = stats.running > 0 || Boolean(agent.currentWork); - const isWorking = isRunning || agent.status === 'actif'; - const isDisabled = agent.raw?.disabledInDb || /désactiv|desactiv/i.test(agent.status); - const activityScore = stats.running * 6 + stats.pending * 2 + stats.completed + (commandBusy ? 3 : 0); + const isWorking = isRunning || agent.status === "actif"; + const isDisabled = + agent.raw?.disabledInDb || /désactiv|desactiv/i.test(agent.status); + const activityScore = + stats.running * 6 + + stats.pending * 2 + + stats.completed + + (commandBusy ? 3 : 0); - let stateLabel = 'Veille'; - let statusCls = 'border-gray-200 bg-gray-50 text-gray-500'; - let dotCls = 'bg-gray-300'; - let glowCls = 'opacity-0'; + let stateLabel = "Veille"; + let statusCls = "border-gray-200 bg-gray-50 text-gray-500"; + let dotCls = "bg-gray-300"; + let glowCls = "opacity-0"; if (isDisabled) { - stateLabel = 'Désactivé'; - statusCls = 'border-gray-200 bg-gray-100 text-gray-400'; - dotCls = 'bg-gray-300'; + stateLabel = "Désactivé"; + statusCls = "border-gray-200 bg-gray-100 text-gray-400"; + dotCls = "bg-gray-300"; } else if (isRunning) { - stateLabel = 'En mission'; - statusCls = 'border-blue-200 bg-blue-50 text-blue-700'; - dotCls = 'bg-blue-500 animate-ping'; - glowCls = 'opacity-100'; + stateLabel = "En mission"; + statusCls = "border-blue-200 bg-blue-50 text-blue-700"; + dotCls = "bg-blue-500 animate-ping"; + glowCls = "opacity-100"; } else if (isWorking) { - stateLabel = 'Disponible'; - statusCls = 'border-emerald-200 bg-emerald-50 text-emerald-700'; - dotCls = 'bg-emerald-500 animate-pulse'; - glowCls = 'opacity-70'; + stateLabel = "Disponible"; + statusCls = "border-emerald-200 bg-emerald-50 text-emerald-700"; + dotCls = "bg-emerald-500 animate-pulse"; + glowCls = "opacity-70"; } else if (stats.pending > 0) { - stateLabel = 'File active'; - statusCls = 'border-amber-200 bg-amber-50 text-amber-700'; - dotCls = 'bg-amber-500'; + stateLabel = "File active"; + statusCls = "border-amber-200 bg-amber-50 text-amber-700"; + dotCls = "bg-amber-500"; } const swarmHref = `/swarm/${encodeURIComponent(agent.id)}`; @@ -98,41 +112,62 @@ export default function AgentCard({
-
+
- +
{swarmPulse && (
)} -
- -
+
+ +
-
+
{stateLabel}

{teamProfile.displayName}

-

{teamProfile.role}

+

+ {teamProfile.role} +

{isRunning && ( @@ -144,11 +179,17 @@ export default function AgentCard({
-

Modèle

-

{agent.model || 'Auto'}

+

+ Modèle +

+

+ {agent.model || "Auto"} +

-

Activité

+

+ Activité +

{activityScore}

@@ -158,14 +199,20 @@ export default function AgentCard({

Mission en cours

-

+

{agent.currentWork?.title || (stats.running > 0 ? `${stats.running} mission(s) marquée(s) running — ouvrez la chronologie pour le détail` - : '—')} + : "—")}

{agent.currentWork?.delegatedAgentId && ( -

+

Délégué · {agent.currentWork.delegatedAgentId}

)} @@ -175,38 +222,68 @@ export default function AgentCard({
{stats.total}
-
Total
+
+ Total +
{stats.running}
-
Run
+
+ Run +
-
{stats.completed}
-
OK
+
+ {stats.completed} +
+
+ OK +
{stats.failed}
-
Fail
+
+ Fail +
{stats.total > 0 ? (
- Flux missions - {completionPct}% OK + + Flux missions + + + {completionPct}% OK +
-
0 ? Math.round((stats.running / stats.total) * 100) : 0}%` }} /> -
-
-
+
0 ? Math.round((stats.running / stats.total) * 100) : 0}%`, + }} + /> +
+
+
) : (
- En attente de mission + + En attente de mission +
)} @@ -219,18 +296,47 @@ export default function AgentCard({
- {(['start_work', 'stop_work'] as SwarmWorkCommand[]).map((cmd) => ( + {(["start_work", "stop_work"] as SwarmWorkCommand[]).map((cmd) => ( ))} @@ -239,22 +345,46 @@ export default function AgentCard({ e.preventDefault(); setConfigOpen(true); }} - class="rounded-xl border border-gray-200 bg-white p-2 text-gray-400 transition-all hover:border-[#175B37]/30 hover:text-[#175B37]" + class="rounded-xl border border-gray-200 bg-white p-2 text-gray-400 transition-all hover:border-[#175B37]/30 hover:text-[#175B37] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#175B37]" title="Configurer cet agent (outils, prompt)" + aria-label="Configurer cet agent" > - - - +
-
{wakeStatusLabel || stateLabel}
-
e.preventDefault()}> +
+ {wakeStatusLabel || stateLabel} +
+
e.preventDefault()}>
-
${(agent.estimatedCostUsd ?? 0).toFixed(4)}
+
+ ${(agent.estimatedCostUsd ?? 0).toFixed(4)} +
- setConfigOpen(false)} /> + setConfigOpen(false)} + />
); }