Fleet glance: runway on agent cards + low-funds alert in the sidebar - #111
Merged
Conversation
… (buzz#76) Task: buzz#76, part of the agent-fleet-money epic (toon-meta#261 decision 9/10). #80 (buzz#106) shipped the Money tab's Network spend block and its NetworkSpendState/agentNetworkFlow runway derivation; this ticket reuses that seam for the fleet-wide glance — runway badges on AgentIdentityCard in the Agents grid, starving agents sorted to the top, and a low-funds SidebarCompactActionCard, per the issue's own explicit instruction to consume #80's wiring rather than re-derive it. Key decisions: - New desktop/src/features/agents/lib/agentFleetRunway.ts: pure derivation from NetworkSpendState to a critical/warning badge, using days-of-runway thresholds (1 day critical, 3 days warning) rather than absolute USDC, so a threshold survives a pricing change. `unavailable`/`relay`/`pending` states and self-funding agents map to no badge — never a fabricated figure. `sortByFleetRunway` is a stable sort so starving agents rise to the top without reshuffling ties; `countLowFundsAgents` backs the sidebar alert's count. - Respected the issue's two documented live constraints rather than working around them: only the identity this desktop process itself pays as (account index 0) has a live channel read today — no toon-clientd spawn/lifecycle exists for managed agents (buzz#79's ADR 0006) and no account-index lookup is exposed to the frontend. `useAgentFleetRunwayBadges` gates on `pubkey === currentPubkey` per agent, so almost every managed agent honestly reads "no badge" today; the badge/sort/alert plumbing is fully wired and unit-tested (including the "demonstrated against a deliberately drained agent" AC, via a synthetic depleted NetworkFlowRead) and activates the moment the per-agent reads follow-up ticket lands. - AgentIdentityCard's statusBadge slot already carries "Configuration missing"/"Restart required" warnings; factored the ternary (previously duplicated across AgentPersonaCard/StandaloneAgentCard) into one AgentStatusBadge helper that adds the runway badge as a third, lowest- priority case — same slot, no layout change, per the AC. - SidebarLowFundsCard follows SidebarRelayConnectionCard's SidebarCompactActionCard idiom (icon, title, one action, dismissible, role=alert, click-through to the fleet via onSelectAgents) but is fully self-contained (own dismiss state, own visibility predicate in sidebarLowFundsCardVisibility.ts) so AppSidebar.tsx — already at 997/1000 lines against the file-size ratchet — only grows by 2 lines. - Did not add the optional SidebarMenuBadge count on the Agents nav item; the issue marks it optional and current data would always read zero. Files changed: desktop/src/features/agents/lib/{agentFleetRunway, useAgentFleetRunwayBadges}.ts (new, +test), desktop/src/features/agents/ui/ UnifiedAgentsSection.tsx, desktop/src/features/sidebar/ui/{SidebarLowFundsCard, sidebarLowFundsCardVisibility}.ts (new, +test), AppSidebar.tsx. Verified: fmt-check, desktop-tauri-fmt-check, clippy (workspace, -D warnings), test-unit (864 tests), desktop-check (incl. file-size ratchet — AppSidebar.tsx now 999/1000 lines), desktop-test (4293 passed), desktop-build, web-check, web-build — all green. Blockers/notes for next iteration: the badge/sort/alert are inert for real managed agents until the per-agent reads follow-up ticket lands (toon-clientd lifecycle + account-index lookup exposed to the frontend, tracked separately per the issue's own comments) — this is the documented, expected state, not a bug. Optional SidebarMenuBadge count on the Agents nav item left undone (explicitly optional in the issue). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Signed-off-by: Claude Sonnet 5 <noreply@anthropic.com>
Array.sort's comparator was calling badgeOf() on every comparison (O(n log n) times). For the Agents grid's group sort, badgeOf calls pickProfileAgent(), which does its own internal sort — so the same group's profile agent was recomputed repeatedly instead of once. Decorate-sort-undecorate evaluates badgeOf per item up front instead. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Signed-off-by: Claude Sonnet 5 <noreply@anthropic.com>
This was referenced Aug 4, 2026
ALLiDoizCode
pushed a commit
that referenced
this pull request
Aug 4, 2026
* RALPH: earning badge on AgentIdentityCard, close out net-flow Money tab (buzz#86) Task: #86, part of the agent-fleet-money epic (toon-meta#262 decision 9). Per the issue's own re-dispatch comment, AC1/AC2 (income beside spend, income-aware runway) landed in PR #97 (agentNetworkFlow.ts) and were wired to real data in #108/#106 (PR #113, #106). AC4 (suppress the low-funds alert for a self-funding agent) was already implemented and tested by buzz#76/PR #111 — `deriveAgentFleetRunwayBadge` returns no badge once `deriveNetworkRunway` concludes an agent is self-funding, which flows straight through `countLowFundsAgents`/`shouldShowSidebarLowFundsCard` — confirmed via the existing "self-funding agents show no badge" test, no code change needed. This lands the one true remaining gap: AC3, an earning indicator on `AgentIdentityCard` in the Agents grid. Key decisions: - New `isAgentFleetEarning(state: NetworkSpendState): boolean` (agentFleetRunway.ts) wraps `agentNetworkFlow.ts`'s `isEarning` behind the same `state.kind !== "quoted"` gate `deriveAgentFleetRunwayBadge` already uses, so the earning badge and the low-funds suppression share one trusted-income bar and can never disagree about whether an agent is self-funding. - New `useAgentFleetEarningBadges` hook mirrors `useAgentFleetRunwayBadges`'s `isSelf`-only gate exactly (same documented buzz#79 ADR 0006 gap — no per-agent channel read exists for any identity but the one this desktop process itself pays as). Kept as its own hook rather than folding into the existing runway hook: the runway hook's `Map<pubkey, AgentFleetRunwayBadge>` return type is consumed as-is by two call sites (`UnifiedAgentsSection.tsx`, `SidebarLowFundsCard.tsx`), and `SidebarLowFundsCard.tsx` has no need for earning state, so widening its shape would be churn for one consumer's benefit. - `AgentStatusBadge` (the card's single-warning slot, `UnifiedAgentsSection.tsx`) gets a third, lowest-priority branch: operational issues, then a low-funds runway warning, then "Earning" (success-variant badge, `TrendingUp` icon) — same slot, no layout change. The three are mutually exclusive in practice (self-funding agents never carry a runway badge), but priority order is defensive. Files changed: desktop/src/features/agents/lib/{agentFleetRunway.ts (+3 tests),useAgentFleetEarningBadges.ts (new)}, desktop/src/features/agents/ui/UnifiedAgentsSection.tsx. Verified: fmt-check, desktop-tauri-fmt-check, clippy (workspace, -D warnings), test-unit (864 tests), desktop-check, desktop-test (4334 passed), desktop-build, web-check, web-build — all green. Blockers/notes for next iteration: the earning badge is wired but inert against real data today — `networkSpendState.ts`'s `deriveNetworkSpendState` hardcodes `incomeRateBaseUnitsPerSec: 0`/`incomeSampleCount: 0` (no live inbound-payment event feed exists yet, only `networkSpendLiveStore.ts`'s outbound `onPaidWrite` — documented in agentNetworkFlow.ts's module doc since PR #113), so `isEarning`/`isAgentFleetEarning` cannot return true from a real read until that income-rate feed lands. This is the same documented, pre-existing gap AC1/AC2's runway already ships ahead of, not new scope this ticket introduces. Signed-off-by: Claude Sonnet 5 <noreply@anthropic.com> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> Signed-off-by: toon-backlog-bot[bot] <294337193+toon-backlog-bot[bot]@users.noreply.github.com> * Dedupe fleet-status hooks: one useNetworkSpend read for badges + earning UnifiedAgentsSection called useAgentFleetRunwayBadges and the new useAgentFleetEarningBadges together, each independently calling useNetworkSpend(true)/useIdentityQuery and duplicating the same isSelf-matching loop — doubling the connector fetch on every mount. Fold both into useAgentFleetStatus, which computes runway badges and the earning set from a single self-spend read; useAgentFleetRunwayBadges becomes a thin wrapper so SidebarLowFundsCard is unaffected. Signed-off-by: toon-backlog-bot[bot] <294337193+toon-backlog-bot[bot]@users.noreply.github.com> --------- Signed-off-by: Claude Sonnet 5 <noreply@anthropic.com> Signed-off-by: toon-backlog-bot[bot] <294337193+toon-backlog-bot[bot]@users.noreply.github.com> Co-authored-by: toon-backlog-bot[bot] <294337193+toon-backlog-bot[bot]@users.noreply.github.com> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds fleet runway estimates to agent cards and a low-funds alert in the sidebar so operators can spot agents at risk of running out of funds at a glance.
Part of #76
This PR was produced by the sandcastle
agent:implementrunner and is awaiting human review.🤖 Generated with Claude Code