Watch
0
0
Fork
You've already forked hyperhive
0
Commit graph hyperhive/frontend/packages/swarm-ui/src/pages/agents
Author SHA1 Message Date
atlas
3380c1915f swarm UI: show the accounts linked to each agent
GET /api/hives/{hive}/agents/{agent}/linked-accounts returns one row per
account linked to the agent, as kind, name and host: each matrix account
under swarm/agents/<agent>/matrix (with its homeserver, and the agent's own
`main` marked reserved), each forge label under swarm/agents/<agent>/forge
(with its url), and github when swarm/agents/<agent>/github-token exists
(host github.com, which is not stored). No credential field is in the
response type.

Listing those two directories needs a new controller grant: `list` on
secret/metadata/swarm/agents/+/matrix and .../+/forge only, pinned in
bao-grants.nix as the only metadata stanzas under agents/ beside the queue
revocation. Checked against a dev OpenBao 2.6.3: the grant lists those two
directories and is refused on agents/, agents/<agent>/, and a leaf.

The swarm UI agent detail panel shows all rows under "accounts"; the table
view's matrix column shows the matrix rows. The link badges stay.

Refs #4855
2026-10-02 21:20:40 +02:00
atlas
8e23feb01b github: PATs live in swarm bao; the agent fetches them itself
An operator links an agent's GitHub personal access token in the swarm UI
(LinkGithubAccountForm, "link github account" on /agents). swarm-controller's
PUT /api/hives/{hive}/agents/{agent}/github-account stores it at
swarm/agents/<agent>/github-token (swarm_secret_client::github), a flat leaf
under the agent's prefix that the agent's existing read grant already covers:
no policy change, and no list grant, since there is one token per agent.

In the agent, hive-agent-github-token (oneshot + 2-minute timer, as the agent
user, under its own store certificate, ordered before hive-github-notify)
reads that path and writes <state>/github-token, 0600 and agent-owned, the
file the gh wrapper, git credential helper and hive-github-notify already
read. It replaces the file by rename only when the bytes changed and never
deletes it: a hive-written github-token stays until a token is linked in the
swarm UI. It is installed only with a store address and
services.hyperhive.agent.github.enable.

Removed: the dashboard's CR3D3NTIALS page (credentials.html/js/css, its
build entries and H0M3 tile; GITHUB was its only tab), hive-c0re's
dashboard/matrix_accounts.rs with GET/POST /api/github-account,
priv_client::write_agent_github_token, the host socket's
SetAgentGithubToken and `hivectl github set-token`, and hive-priv's
WriteAgentGithubToken with write_agent_state_file, its only caller gone.

Docs: integrations/github.md and swarm/ui.md describe the swarm path,
swarm/credentials.md gains the store-path row, and the hive UI docs,
hivectl docs and security.md's hive-priv table drop the removed pieces.

Closes #4347
2026-10-02 17:48:27 +02:00
atlas
2c7e586f47 forge: external forge accounts live in swarm bao; the agent fetches them itself
An operator now links an agent's external forge account (label, base URL,
token) in the swarm UI. swarm-controller stores it at
swarm/agents/<agent>/forge/<label>. There is no index: the store's
listing of the agent's forge/ directory is the set of accounts.

In the agent, hive-agent-forge-accounts (oneshot + 2-minute timer, as
the agent user, under its own store certificate) lists
swarm/agents/<agent>/forge/ with the `list` #4866 grants an agent on its
own metadata subtree, reads each account, and writes
<state>/forge-<label>-token and forge-<label>.json in the names and shape
hive-forge -f already reads. An empty listing (a 404, which `bao kv list
-format=json` answers with `{}` and an empty stderr) is zero accounts; a
denial or an unreachable store fails the unit. It never deletes: files
for labels not listed, including ones the hive wrote, stay as they are.

Removed: the dashboard FORGES tab (credentials.js/html section and its
CSS), hive-c0re's extra_forges.rs and its routes, priv_client's
extra-forge calls, and hive-priv's WriteAgentExtraForgeAccount /
DeleteAgentExtraForgeAccount with their helpers. The GITHUB tab and
WriteAgentGithubToken stay.

Also: persistence.md's matrix avatar note names the exit-75 restart on a
changed account listing, not the dashboard, as what brings a linked
account up.

Refs #4348
2026-10-01 18:05:33 +02:00
iris
7bf4cfbc4c swarm-ui: fix specificity claim in AgentTermPreview.css comment
argus's review on PR #4784 caught a wrong technical claim: the
comment said the .ui-agent-term-preview-full override rules relied
on source order because they had equal specificity to the
un-modified rules above. They don't — each override selector adds
one more class (the .ui-agent-term-preview-full prefix) than what it
overrides, so they're strictly more specific and win regardless of
file order. Corrected the comment to say so.
2026-09-28 23:17:44 +02:00
iris
c460e91bd1 swarm-ui: full-tab agent terminal (#4506)
Adds a full, non-capped agent terminal reachable from a new expand
trigger on the embedded AgentTermPreview (the detail-panel preview on
AgentsPage stays as-is, just gains the trigger). Opens
/agents/:name/terminal in a new dynamic tab in Shell's header, next to
the static nav row — tabs persist across a reload via useDynamicTabs,
a small localStorage-backed hook built on @hive/shared's existing
settings-storage primitive.

AgentTermPreview gains two new props to support both mounts from one
component: fullHeight (drops the 12em preview cap, fills its page)
and showHeaderBadges (default true — lets a future caller that
already shows turn_state/model/ctx/cost elsewhere suppress this
cluster; AgentsPage doesn't use it, see below).

Deviation from the originally posted plan (issue comment 80596): that
plan proposed AgentsPage's embedded preview pass showHeaderBadges as
false, reasoning the detail panel already duplicates that info.
Checked the actual code before implementing — it doesn't; AgentRow/
AgentTypes.ts carry none of turn_state/model/ctx/cost, and
AgentTermPreview's own floating badges are the only place swarm-ui
shows them. Left the badges visible there instead of shipping a
regression the plan's own stated justification didn't hold up to.

Also fixed a same-tab pub/sub race found by actually rendering a cold
load of /agents/:name/terminal (headless chromium, not just reasoning
about the code): useLocalSetting subscribes inside a useEffect, and
mount effects fire children-before-parents, so a descendant's
mount-time write (AgentTerminalPage registering its own tab) can beat
an ancestor's (Shell's) subscription into existence, leaving Shell's
tab row silently empty on a direct/reload load. Fixed by having
useDynamicTabs re-sync from storage on every location change, not
just on notify() — the fix lives in the new hook itself, not in the
shared settings-storage primitive theme/motion overrides also use.
2026-09-28 23:17:44 +02:00
atlas
3b8df27dcf swarm-ui: show each agent's icon on its card
Each agent card now leads with the agent's icon, loaded as an `<img>`
from `GET /api/agents/<name>/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 `<img>`, never inline markup: the body is an agent-authored
SVG, and an image load does not run its script.
2026-09-28 13:47:37 +02:00
iris
d9c8b7ca8f swarm-ui: floating turn-state/model/ctx/cost badges on the agent term preview
Header-bar parity for the swarm-level agent terminal, per mara's ruling
"dont make it a header though - make it floating elements on top of the
terminal". Adds useSwarmAgentStateStream (SSE consumer for
swarm-controller's GET /api/agents/{name}/state/stream) and renders a
small read-only Badge cluster absolutely positioned in
AgentTermPreview's terminal box corner, reusing the same anchor pattern
@hive/shared/terminal.css's .tail-pill already uses.

Shows turn_state always, agent_state only when it isn't the boring "up"
case, model (with resolved-model tooltip), and ctx/cost usage. No badge
renders until the first header event lands - the swarm queue's
agent-state subject is transition-only with no seed/replay, and no
swarm-level endpoint today can seed turn_state/model/ctx/cost
synchronously.

Vocabulary (state tones, token-total/format helpers) ported from
@hive/agent's Root.tsx/lib/format.ts rather than imported, matching the
existing "small helper, not worth a cross-package hop" call
useSwarmTermStream's own appendRow already made.

Verified by rendering the real component tree against a stubbed
EventSource and screenshotting the result - the badge cluster initially
overlapped the terminal's first row of text, fixed by giving this
preview's own .live.terminal extra top padding.
2026-09-18 17:30:59 +02:00
iris
08aee4b704 swarm-ui: fix agent term preview box-sizing causing content to bleed past its wrap 2026-09-13 22:01:40 +02:00
iris
8db1e61cd3 swarm-ui: fix agent term preview placeholder wrapping one char per line 2026-09-13 21:47:23 +02:00
iris
e18619329d swarm-ui: fix treefmt formatting drift on the agent term files 2026-09-13 20:23:51 +02:00
iris
727bfb775b swarm-ui: fold the agent terminal into AgentsPage's detail panel, not a route
mara's steer on the issue, right as the previous commit's plan was
posted: the swarm-level term isn't a separate page, it's part of the
same pwa -- selecting an agent should show a small preview (no header,
no input) below the existing detail fields. That's the whole MVP for
this issue; the full terminal (+ sending input back to the agent) is
explicit follow-up scope.

AgentTermPage -> AgentTermPreview: drops the Panel wrapper, the
"terminal" nav badge + wouter route, and the back-link -- just the
inline preview, height-capped at 12em (@hive/shared/terminal.css's own
default is a much taller 72vh/60em, sized for a dedicated page rather
than a peek).
2026-09-13 20:23:51 +02:00
iris
593923375c swarm-ui: read-only agent terminal page consuming the swarm term stream
Moves the TermMsg rendering pipeline (Row.tsx, termMsg.ts, linkify.tsx,
markdown.ts) from @hive/agent into @hive/shared, so swarm-ui becomes a
second consumer of it instead of forking a copy -- CSS was already
shared (@hive/shared/terminal.css). marked+dompurify move from
@hive/agent's deps to @hive/shared's; swarm-ui picks them up
transitively, no new direct dep there.

New swarm-ui route /agents/:name/term (AgentTermPage), linked from
AgentsPage's detail panel via a "terminal" badge next to "link matrix
account". Consumes GET /api/agents/{name}/term/stream: unlike
@hive/agent's own useLiveStream (TermEnvelope-wrapped, history/backfill
dance), the swarm relay forwards one bare TermMsg per SSE event with no
envelope and no history endpoint -- useSwarmTermStream is a much
smaller hook for that shape (EventSource -> parse -> coalesce, nothing
to buffer/dedupe/backfill against).

Verified against a live SSE mock (screenshots in /agents/iris/state/screenshots/
3801-agents-detail-panel-terminal-badge.png and
3801-agent-term-page-live-rows.png -- real rows rendering through the
shared Row component, not just a build/typecheck pass).
2026-09-13 20:23:51 +02:00
iris
8a4c613e4e swarm-ui: drop the redundant outer dialog card, move close into the panel header
Dialog and Panel both drew their own bordered/backgrounded card in the
same --bg-elev, so a Panel-based dialog (create-agent, link-matrix-account)
rendered as two concentric cards with a floating close button on the
outer one and no purpose to it.

Give Dialog a "plain" mode that drops its own card chrome (border,
background, padding) and floating close button, and give Panel an
optional onClose that renders a close button at the end of its own
header row instead. AgentsPage's two Panel-backed dialogs now use
plain + Panel's onClose, so the Panel is the dialog's only visible
card. ConfirmDialog (no Panel of its own) is unaffected — plain
defaults to false, unchanged card + floating close button.

Added a ComponentsPage sample demonstrating the plain + onClose
pairing. Verified both dialog modes via a real headless-chromium
screenshot (plain dialog: single card, close button in the header
bar; default dialog: unchanged floating close button).
2026-09-13 00:58:53 +02:00
iris
1176de08bd swarm-ui/agents: move the split-out agent-page files into pages/agents/
mara, PR review: "make agentspage a subdir now that its split into
sub components". AgentsPage.tsx/.css, AgentCard.tsx/.css,
AgentTypes.ts, and WantedMenu.tsx move as a family into their own
pages/agents/ directory; CreateAgentForm and LinkMatrixAccountForm
stay in pages/ since they aren't part of this split (CreateAgentForm
is still rendered inside AgentsPage's own dialog but is a standalone,
independently-named form, not one of the pieces carved out of the
page itself).

Pure move: relative imports within the new pages/agents/ family are
unchanged (they were always siblings), only the ones reaching back
out to ui/ and the two forms above gained one more '../', plus
App.tsx's route import.
2026-09-11 22:35:44 +02:00