From 3b8df27dcf22bb6dcfc0a5130dae0af8eb75b62f Mon Sep 17 00:00:00 2001 From: atlas Date: Mon, 28 Sep 2026 11:09:46 +0200 Subject: [PATCH] swarm-ui: show each agent's icon on its card Each agent card now leads with the agent's icon, loaded as an `` from `GET /api/agents//icon`: the same 5em square, background and fallback as the hive dashboard's container row. An agent with no icon (the route's 404), or any other failed load, shows the dimmed hyperhive mark (`/favicon.svg`) instead of a broken image. Only ever an ``, never inline markup: the body is an agent-authored SVG, and an image load does not run its script. --- docs/swarm/README.md | 3 +- .../swarm-ui/src/pages/agents/AgentCard.css | 34 ++++++ .../swarm-ui/src/pages/agents/AgentCard.tsx | 115 ++++++++++++------ 3 files changed, 112 insertions(+), 40 deletions(-) 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 `