Watch
0
0
Fork
You've already forked hyperhive
0

swarm-ui: split pages/agents into two pages and the agent components

pages/agents held the roster page, the terminal page and every component under them. It keeps the two pages; the components move to src/agent, by concern: roster (card, wanted menu, actions), detail (panel body, dialog, inference, linked accounts, link menu) and terminal (preview, input, subagents, stream hooks, favicon), with the shared row type and icon at the top. Moves and import rewrites only.
This commit is contained in:
iris 2026-10-12 00:02:15 +02:00
commit 74e588415b
27 changed files with 28 additions and 25 deletions

View file

@ -1,38 +0,0 @@
// useAgentFavicon — while the calling page is mounted, the browser tab's icon
// is this agent's icon, so tabs of different agents tell apart at a glance.
//
// The icon comes from swarm-controller's `GET /api/agents/{name}/icon`, an
// SVG that is a 404 for an agent with none. A `<link>` can't report a failed
// load, so an off-screen image loads it first and the tab icon switches only
// once that succeeds: an agent with no icon, or an unreachable controller,
// keeps the hyperhive mark. Leaving the page puts the page's own icon back.
import { useEffect } from "preact/hooks";
export function useAgentFavicon(agent: string): void {
useEffect(() => {
const link = document.querySelector<HTMLLinkElement>('link[rel="icon"]');
if (link === null) return;
const original = {
href: link.getAttribute("href"),
type: link.getAttribute("type"),
};
const url = `/api/agents/${encodeURIComponent(agent)}/icon`;
let cancelled = false;
const probe = new Image();
probe.onload = () => {
if (cancelled) return;
link.setAttribute("type", "image/svg+xml");
link.setAttribute("href", url);
};
probe.src = url;
return () => {
cancelled = true;
for (const [attr, value] of Object.entries(original)) {
if (value === null) link.removeAttribute(attr);
else link.setAttribute(attr, value);
}
};
}, [agent]);
}