diff --git a/docs/swarm/README.md b/docs/swarm/README.md index d498fddf..9c233eb6 100644 --- a/docs/swarm/README.md +++ b/docs/swarm/README.md @@ -465,7 +465,8 @@ credential publishes it: the queue grants that credential none of the bucket. The harness writes once per start, because a config change reaches an agent by restarting its container. An agent with no icon deletes its key. Swarm-side, `GET /api/agents//icon` serves the stored bytes, and 404 -means the agent has no icon. +means the agent has no icon. swarm-ui's agent cards load it as an `` and show the +dimmed hyperhive mark for an agent without one, as the hive dashboard does. ### Swarm-wide forge objects diff --git a/frontend/packages/swarm-ui/src/pages/agents/AgentCard.css b/frontend/packages/swarm-ui/src/pages/agents/AgentCard.css index 90a81e33..e548aa9f 100644 --- a/frontend/packages/swarm-ui/src/pages/agents/AgentCard.css +++ b/frontend/packages/swarm-ui/src/pages/agents/AgentCard.css @@ -22,3 +22,37 @@ white-space: normal; word-break: break-word; } +/* Icon beside the name/message, sized and dimmed like the hive + dashboard's `.container-icon` (dashboard.css). */ +.ui-agent-card-row { + display: flex; + align-items: flex-start; + gap: 0.7em; +} +.ui-agent-card-body { + display: flex; + flex-direction: column; + gap: 0.35em; + flex: 1; + min-width: 0; +} +.ui-agent-card-icon { + position: relative; + overflow: hidden; + flex: none; + width: 5em; + aspect-ratio: 1; + border-radius: 6px; + background-color: color-mix(in srgb, var(--crust) 60%, transparent); +} +.ui-agent-card-icon > img { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + object-fit: contain; +} +.ui-agent-card-icon-none { + filter: grayscale(1); + opacity: 0.4; +} diff --git a/frontend/packages/swarm-ui/src/pages/agents/AgentCard.tsx b/frontend/packages/swarm-ui/src/pages/agents/AgentCard.tsx index e1ea8803..894b7c44 100644 --- a/frontend/packages/swarm-ui/src/pages/agents/AgentCard.tsx +++ b/frontend/packages/swarm-ui/src/pages/agents/AgentCard.tsx @@ -12,6 +12,7 @@ // `WantedMenu` below keeps its own clicks (mouse or keyboard-synthesized, // `WantedMenu` hosts real `