The agent card's overview gets a forge row with two links, built from the forge entry of the swarm's service links.
40 lines
1.2 KiB
TypeScript
40 lines
1.2 KiB
TypeScript
// The swarm forge's base URL, from `GET /api/links`. Fetched once and shared by
|
|
// every agent card, so opening many cards sends one request. A failed fetch
|
|
// is not kept, so the next card retries; the links just stay hidden meanwhile.
|
|
import { useEffect, useState } from "preact/hooks";
|
|
import type { MenuLink } from "@hive/shared/links-menu.js";
|
|
import { forgeBase } from "./forge-links.js";
|
|
|
|
let pending: Promise<string | null> | null = null;
|
|
|
|
function loadForgeBase(): Promise<string | null> {
|
|
if (!pending) {
|
|
pending = fetch("/api/links")
|
|
.then((r) =>
|
|
r.ok
|
|
? (r.json() as Promise<MenuLink[]>)
|
|
: Promise.reject(new Error(`http ${r.status}`)),
|
|
)
|
|
.then(forgeBase)
|
|
.catch(() => {
|
|
pending = null;
|
|
return null;
|
|
});
|
|
}
|
|
return pending;
|
|
}
|
|
|
|
/** The forge's base URL, or null until known (or when the swarm lists none). */
|
|
export function useForgeBase(): string | null {
|
|
const [base, setBase] = useState<string | null>(null);
|
|
useEffect(() => {
|
|
let live = true;
|
|
void loadForgeBase().then((b) => {
|
|
if (live) setBase(b);
|
|
});
|
|
return () => {
|
|
live = false;
|
|
};
|
|
}, []);
|
|
return base;
|
|
}
|