Watch
0
0
Fork
You've already forked hyperhive
0

swarm ui: the agent detail leaves out the config repo link for an archetype agent

An agent built from an archetype has no config repo on the forge, so the link
404ed. It shows again once the agent is turned into a custom one.
This commit is contained in:
iris 2026-11-11 00:58:15 +01:00 • committed by mara
commit 356390befb
3 changed files with 23 additions and 7 deletions

View file

@ -117,7 +117,9 @@ function OverviewRows({
actions: AgentActions; actions: AgentActions;
}) { }) {
const forge = useForgeBase(); const forge = useForgeBase();
const forgeLinks = forge ? agentForgeLinks(forge, row.name) : null; const forgeLinks = forge
? agentForgeLinks(forge, row.name, row.archetype === null)
: null;
return ( return (
<> <>
<dt>state</dt> <dt>state</dt>
@ -131,9 +133,11 @@ function OverviewRows({
<dt>forge</dt> <dt>forge</dt>
<dd class="ui-agent-detail-links"> <dd class="ui-agent-detail-links">
<ExternalLink href={forgeLinks.profile}>profile</ExternalLink> <ExternalLink href={forgeLinks.profile}>profile</ExternalLink>
<ExternalLink href={forgeLinks.configRepo}> {forgeLinks.configRepo ? (
config repo <ExternalLink href={forgeLinks.configRepo}>
</ExternalLink> config repo
</ExternalLink>
) : null}
</dd> </dd>
</> </>
) : null} ) : null}

View file

@ -4,7 +4,9 @@
// `GET /api/links`, the same list the header's links menu shows. // `GET /api/links`, the same list the header's links menu shows.
import type { MenuLink } from "@hive/shared/links-menu.js"; import type { MenuLink } from "@hive/shared/links-menu.js";
export type AgentForgeLinks = { profile: string; configRepo: string }; /** `configRepo` is null for an agent that has none: one built from an
* archetype, whose hive builds it from the archetype's module. */
export type AgentForgeLinks = { profile: string; configRepo: string | null };
/** The forge's base URL from the swarm's service links, or null without one. */ /** The forge's base URL from the swarm's service links, or null without one. */
export function forgeBase(links: MenuLink[]): string | null { export function forgeBase(links: MenuLink[]): string | null {
@ -13,10 +15,14 @@ export function forgeBase(links: MenuLink[]): string | null {
} }
/** The agent's profile and config repo on the forge at `base`. */ /** The agent's profile and config repo on the forge at `base`. */
export function agentForgeLinks(base: string, agent: string): AgentForgeLinks { export function agentForgeLinks(
base: string,
agent: string,
hasConfigRepo = true,
): AgentForgeLinks {
const name = encodeURIComponent(agent); const name = encodeURIComponent(agent);
return { return {
profile: `${base}/${name}`, profile: `${base}/${name}`,
configRepo: `${base}/agent-configs/${name}`, configRepo: hasConfigRepo ? `${base}/agent-configs/${name}` : null,
}; };
} }

View file

@ -39,3 +39,9 @@ test("the agent name is encoded", () => {
"https://forge.example/a%20b", "https://forge.example/a%20b",
); );
}); });
test("an agent without a config repo, one from an archetype, has no config link", () => {
const links = agentForgeLinks("https://forge.example", "iris", false);
assert.equal(links.configRepo, null);
assert.equal(links.profile, "https://forge.example/iris");
});