Watch
0
0
Fork
You've already forked hyperhive
0

swarm UI: an agent that needs a Claude login shows it on its card

The agent's turn-state header ($SWARM.agent-state.<agent>) gains
`needs_login`, set by hive-agent from its own LoginState, so the flag
reaches the swarm without hive-c0re (mara on #5268: "id prefer the agent
container sending the info it needs login without hive").

- swarm-queue-client: `agent_login::Login`, the shared wire type, beside
  `agent_inference::Effective`. `needs_login: Option<bool>` with
  `#[serde(default)]`: a header from an older agent decodes as `None`
  (unknown), never as "needs login" or "logged in".
- hive-agent: the header publisher reads the shared LoginState cell.
  Every writer of that cell emits a status on the bus afterwards, so a
  login change goes out on the next rebuild, not the 60 s refresh.
- swarm-controller: `agent_login::Reported` follows every agent's header
  and keeps the latest flag; `GET /api/agents/status` merges it into each
  row as `needs_login` (null when unknown).
- swarm-ui: AgentCard shows a warning-tone "login needed" badge when the
  row's `needs_login` is true.

Refs #5268
This commit is contained in:
atlas 2026-10-14 19:32:05 +02:00
commit afeb0f9794

View file

@ -65,6 +65,13 @@ pub struct AgentStatusRow {
/// here would blur that boundary for the same reason `config_pr`
/// doesn't merge forge state in directly.
pub wanted: Option<String>,
/// Whether the agent's latest turn-state header said its claude needs a
/// login. `None` when no header since swarm-controller started carried
/// the flag. Same rule as `config_pr`: always `None` out of this reader,
/// filled in by the `GET /api/agents/status` handler from
/// `AppState::agent_login` — this reader sees the hive's bucket, and the
/// flag comes from the agent itself.
pub needs_login: Option<bool>,
}
/// A snapshot as retained by the bucket, with the hive it was published
@ -186,6 +193,7 @@ fn render(
snapshot: None,
config_pr: None,
wanted: None,
needs_login: None,
},
})
.collect();
@ -230,6 +238,7 @@ fn row(
snapshot: offered.payload.clone(),
config_pr: None,
wanted: None,
needs_login: None,
}
}