From c42db99f276027264d3522e0b936415a7ea5bd12 Mon Sep 17 00:00:00 2001 From: iris Date: Thu, 12 Nov 2026 09:35:06 +0100 Subject: [PATCH] swarm-ui: the badge tooltips are built by a tested helper --- .../swarm-ui/src/agent/state/StateBadges.tsx | 16 ++++++----- .../swarm-ui/src/agent/state/badge-titles.ts | 22 +++++++++++++++ .../swarm-ui/test/badge-titles.test.mjs | 27 +++++++++++++++++++ 3 files changed, 58 insertions(+), 7 deletions(-) create mode 100644 frontend/packages/swarm-ui/src/agent/state/badge-titles.ts create mode 100644 frontend/packages/swarm-ui/test/badge-titles.test.mjs diff --git a/frontend/packages/swarm-ui/src/agent/state/StateBadges.tsx b/frontend/packages/swarm-ui/src/agent/state/StateBadges.tsx index 365a3f348..1560b1858 100644 --- a/frontend/packages/swarm-ui/src/agent/state/StateBadges.tsx +++ b/frontend/packages/swarm-ui/src/agent/state/StateBadges.tsx @@ -1,6 +1,7 @@ import { Badge, type BadgeTone } from "@hive/shared/badge.js"; import { BadgePopover } from "../../ui/badge-popover/BadgePopover.js"; import { AgentInference } from "../detail/AgentInference.js"; +import { effortTitle, modelTitle } from "./badge-titles.js"; import { RelativeTime } from "../../ui/relative-time/RelativeTime.js"; import { useSwarmAgentStateStream, @@ -59,9 +60,6 @@ export function StateBadges({ // when clicked. Omitted: the badges only display. agent?: string; }) { - const modelTitle = header.resolved_model - ? `resolved to ${header.resolved_model}` - : undefined; return ( <> + ) : ( @@ -102,13 +104,13 @@ export function StateBadges({ ) : ( diff --git a/frontend/packages/swarm-ui/src/agent/state/badge-titles.ts b/frontend/packages/swarm-ui/src/agent/state/badge-titles.ts new file mode 100644 index 000000000..0652a13f5 --- /dev/null +++ b/frontend/packages/swarm-ui/src/agent/state/badge-titles.ts @@ -0,0 +1,22 @@ +// The tooltips of the model and effort badges in an agent's terminal header. +// Clickable ones, which open the agent's inference settings, say so; the plain +// ones, on a subagent's terminal and in the details table, only say where the +// value comes from. + +const OPENS = "Click for the inference settings"; + +/** The model badge's tooltip: what the alias resolved to, when known. */ +export function modelTitle( + resolvedModel: string | null | undefined, + clickable: boolean, +): string | undefined { + const resolved = resolvedModel ? `resolved to ${resolvedModel}` : undefined; + if (!clickable) return resolved; + return resolved ? `${resolved}. ${OPENS}` : OPENS; +} + +/** The effort badge's tooltip: where the effort comes from. */ +export function effortTitle(source: string, clickable: boolean): string { + const from = `set by: ${source}`; + return clickable ? `${from}. ${OPENS}` : from; +} diff --git a/frontend/packages/swarm-ui/test/badge-titles.test.mjs b/frontend/packages/swarm-ui/test/badge-titles.test.mjs new file mode 100644 index 000000000..6a5323470 --- /dev/null +++ b/frontend/packages/swarm-ui/test/badge-titles.test.mjs @@ -0,0 +1,27 @@ +// The model and effort badge tooltips. Run by `npm test`, which Node runs with +// its built-in test runner and type stripping. +import assert from "node:assert/strict"; +import { test } from "node:test"; +import { effortTitle, modelTitle } from "../src/agent/state/badge-titles.ts"; + +test("a plain model badge says what the alias resolved to, or nothing", () => { + assert.equal(modelTitle("claude-x-1", false), "resolved to claude-x-1"); + assert.equal(modelTitle(undefined, false), undefined); + assert.equal(modelTitle("", false), undefined); +}); + +test("a clickable model badge says it opens the settings", () => { + assert.equal( + modelTitle("claude-x-1", true), + "resolved to claude-x-1. Click for the inference settings", + ); + assert.equal(modelTitle(undefined, true), "Click for the inference settings"); +}); + +test("the effort badge names its source and, when clickable, the click", () => { + assert.equal(effortTitle("swarm", false), "set by: swarm"); + assert.equal( + effortTitle("swarm", true), + "set by: swarm. Click for the inference settings", + ); +});