feat(mesh): live gossip topology, MeshLLM headline, inferred inbound work

Drops the relay/roster overlay from the topology in favour of a single source:
the runtime's own gossip view. A node is drawn because we are connected to it
right now, not because a status note is still inside its 120s freshness window.
That window is why a departed device could sit on the graph as a solid,
capacity-contributing dot for up to two minutes — a reconciliation problem this
removes rather than referees. Community-roster ghosts go too: a member who never
starts a node discloses no hardware, so they added a denominator and little else.

New mesh_live_view command projects peers[] (label, state, capacity honoring the
peer's own cap, models, rtt). Client-mode peers report vram_gb: 0, normalized to
absent so the UI never prints "0 GB" for a machine that shares none. The relay
snapshot is retained for exactly one job: the headline when no local runtime
exists, where it is the only view available.

Card headline is now "MeshLLM · 115 GB, 2 peers", with the participation hint
below it: "You're sharing", "· serving another member", or the consuming split.

Inbound work turns out to be derivable after all. mesh-llm exposes no counter
for it (fronted_request_count merely aliases request_count), but sharing, with
inflight > 0, while our own dispatch count stays flat between samples, means the
work cannot be ours. inferInboundWork encodes that. It is sampled, so it can
undercount a request that starts and ends between polls — it never over-claims,
which is the direction that matters.

Also corrects the inverted doc comments on MeshServingUsage, which still
described the backwards model that caused the original card bug.

UX only — no routing, admission, or lifecycle change.

Signed-off-by: Michael Neale <michael.neale@gmail.com>
This commit is contained in:
Michael Neale
2026-08-04 19:38:07 +10:00
parent 76debee19d
commit a031fc96f5
17 changed files with 1172 additions and 426 deletions
@@ -0,0 +1,31 @@
//! Live gossip view of the mesh — the peers this machine's runtime is actually
//! connected to right now.
//!
//! Separate from `mesh_llm.rs` because that file sits at the 1000-line ceiling
//! enforced by `desktop/scripts/check-file-sizes.mjs`, and separate from
//! `mesh_snapshot.rs` because the two answer different questions: the snapshot
//! reports every member's last published note (valid 120s, readable with no
//! local node), while this reports live adjacency. See `mesh_llm/peers.rs` for
//! why both exist.
use crate::app_state::AppState;
use crate::commands::CmdResult;
use crate::mesh_llm;
use tauri::State;
/// This machine's live gossip view of the mesh: the peers our runtime is
/// actually connected to right now.
///
/// `connected: false` with no peers means we are not participating, which is
/// distinct from "participating but alone". Never errors on absence — a stopped
/// node is a normal state, not a failure.
#[tauri::command]
pub async fn mesh_live_view(state: State<'_, AppState>) -> CmdResult<mesh_llm::MeshLiveView> {
let runtime = state.mesh_llm_runtime.lock().await;
match runtime.as_ref() {
// A runtime that exists but is mid-start has no gossip view yet; report
// "not connected" rather than surfacing a transient error.
Some(runtime) => Ok(runtime.live_view().await.unwrap_or_default()),
None => Ok(mesh_llm::MeshLiveView::default()),
}
}
+4
View File
@@ -31,6 +31,8 @@ mod media_gif;
mod media_snapshot_png;
mod media_transcode;
#[cfg(feature = "mesh-llm")]
mod mesh_live_view;
#[cfg(feature = "mesh-llm")]
pub(crate) mod mesh_llm;
#[cfg(feature = "mesh-llm")]
mod mesh_snapshot;
@@ -88,6 +90,8 @@ pub use link_preview::*;
pub use media::*;
pub use media_download::*;
#[cfg(feature = "mesh-llm")]
pub use mesh_live_view::*;
#[cfg(feature = "mesh-llm")]
pub use mesh_llm::*;
#[cfg(feature = "mesh-llm")]
pub use mesh_snapshot::*;
+1
View File
@@ -774,6 +774,7 @@ pub fn run() {
mesh_installed_models,
mesh_model_catalog,
mesh_snapshot,
mesh_live_view,
update_managed_agent,
discover_backend_providers,
probe_backend_provider,
+16
View File
@@ -33,6 +33,9 @@ pub(crate) use recovery::{
MeshRuntimeRecovery,
};
mod peers;
pub use peers::{live_view_from_payload, MeshLiveView};
mod usage;
pub use usage::{serving_usage_from_payload, MeshServingUsage};
@@ -635,6 +638,19 @@ impl DesktopMeshRuntime {
Ok(serving_usage_from_payload(&status.payload))
}
/// This machine's live gossip view of the mesh — who we are actually
/// connected to right now. Distinct from the relay snapshot, which reports
/// last-published notes valid for 120s. See [`peers`] for why both exist.
pub async fn live_view(&self) -> anyhow::Result<MeshLiveView> {
let mut handle = self.handle.lock().await;
Self::promote_finished_startup(&mut handle).await;
let DesktopMeshHandle::Ready(ready) = &*handle else {
anyhow::bail!("mesh management status is not ready");
};
let status = ready.status().await?;
Ok(live_view_from_payload(&status.payload))
}
pub async fn dial_endpoint_addr(&self, endpoint_addr: impl Into<String>) -> anyhow::Result<()> {
let endpoint_addr = endpoint_addr.into();
let validated = validate_advertised_endpoint(&endpoint_addr)?;
+263
View File
@@ -0,0 +1,263 @@
use serde::{Deserialize, Serialize};
/// A node this machine's mesh runtime is **actually talking to right now**.
///
/// ## Why this exists instead of reusing the relay snapshot
///
/// Buzz has two views of the mesh and they answer different questions:
///
/// - **Relay status notes** (`snapshot.rs`) — every member's last published
/// note, valid for 120s. Readable with no local node, so it is the only way
/// to see the pool *before* joining. But a note outlives the node that wrote
/// it: a machine that vanished 30s ago still looks present, and still counts
/// toward capacity.
/// - **Live peers** (this file) — the runtime's own gossip view. A node appears
/// here because our node is connected to it. No freshness window to guess at,
/// no reconciliation rule to invent.
///
/// A topology view has to be trustworthy, so it draws *this*. Mixing the two
/// sources meant refereeing disagreements between them, which produced a graph
/// that showed devices gossip already knew were gone.
///
/// The tradeoff, stated plainly: with no local node there are no peers, and the
/// relay snapshot remains the only available view.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct MeshPeer {
/// Short node id from the runtime. Stable within a session.
pub id: String,
/// Human label — hostname as the peer reports it.
pub label: String,
/// Coarse role/state, normalized. See [`MeshPeerState`].
pub state: MeshPeerState,
/// Shared AI memory in GB, honoring the peer's own `--max-vram` cap.
/// `None` when the peer reports nothing (a client-mode node reports 0, which
/// is normalized to `None` rather than displayed as "0 GB").
pub capacity_gb: Option<f64>,
/// Models this peer is serving right now. Empty for a consuming peer.
pub models: Vec<String>,
/// Round-trip latency in ms, when measured.
pub rtt_ms: Option<u64>,
}
/// What a peer is doing, as *it* reports — never inferred from traffic.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum MeshPeerState {
/// Advertising at least one model.
Serving,
/// Warming up — a host that has not advertised a model yet.
Loading,
/// Present and able to host, but advertising nothing.
Standby,
/// Client-mode: on the mesh to consume, not to contribute.
Consuming,
}
/// This machine's live view of the mesh.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
#[serde(rename_all = "camelCase")]
pub struct MeshLiveView {
/// True when a local runtime is up. Distinguishes "no peers" (alone on the
/// mesh) from "unknown" (not participating, so nothing to report).
pub connected: bool,
/// This machine's own shared capacity, when serving.
pub self_capacity_gb: Option<f64>,
/// Peers currently connected, sharing first then by label.
pub peers: Vec<MeshPeer>,
}
fn f64_at(value: &serde_json::Value, key: &str) -> Option<f64> {
value.get(key).and_then(serde_json::Value::as_f64)
}
/// Normalize a peer's reported role/state into [`MeshPeerState`].
///
/// Trusts the peer's own `state`/`role` first and only falls back to inferring
/// from advertised models. A client-mode node that happens to list a model is
/// still consuming: role wins over model presence.
fn peer_state(value: &serde_json::Value, has_models: bool) -> MeshPeerState {
let raw = value
.get("state")
.or_else(|| value.get("role"))
.and_then(serde_json::Value::as_str)
.unwrap_or_default()
.to_ascii_lowercase();
match raw.as_str() {
"client" => MeshPeerState::Consuming,
"serving" => MeshPeerState::Serving,
"loading" => MeshPeerState::Loading,
"standby" => MeshPeerState::Standby,
_ if has_models => MeshPeerState::Serving,
_ => MeshPeerState::Standby,
}
}
fn string_list(value: &serde_json::Value, key: &str) -> Vec<String> {
value
.get(key)
.and_then(serde_json::Value::as_array)
.map(|items| {
items
.iter()
.filter_map(serde_json::Value::as_str)
.map(str::to_string)
.collect()
})
.unwrap_or_default()
}
/// Pure extractor: project a raw SDK status payload into [`MeshLiveView`].
///
/// Defensive throughout (missing → absent) so an SDK shape change degrades to
/// "no peers shown" rather than an error.
pub fn live_view_from_payload(payload: &serde_json::Value) -> MeshLiveView {
let mut peers = payload
.get("peers")
.and_then(serde_json::Value::as_array)
.map(|items| {
items
.iter()
.filter_map(|peer| {
let id = peer
.get("id")
.and_then(serde_json::Value::as_str)
.unwrap_or_default()
.to_string();
if id.is_empty() {
return None;
}
let mut models = string_list(peer, "serving_models");
if models.is_empty() {
models = string_list(peer, "hosted_models");
}
models.sort();
models.dedup();
let label = peer
.get("hostname")
.and_then(serde_json::Value::as_str)
.filter(|hostname| !hostname.is_empty())
.map(str::to_string)
// Fall back to a short id rather than "Unknown": the id
// is at least actionable in logs.
.unwrap_or_else(|| id.chars().take(10).collect());
Some(MeshPeer {
state: peer_state(peer, !models.is_empty()),
// 0 GB means "did not report" (client mode), not "has no
// memory" — keep it absent so the UI omits the figure.
capacity_gb: f64_at(peer, "vram_gb").filter(|gb| *gb > 0.0),
models,
rtt_ms: peer
.get("rtt_ms")
.and_then(serde_json::Value::as_u64)
.or_else(|| peer.get("latency_ms").and_then(serde_json::Value::as_u64)),
id,
label,
})
})
.collect::<Vec<_>>()
})
.unwrap_or_default();
peers.sort_by(|a, b| {
let serving = |peer: &MeshPeer| peer.state == MeshPeerState::Serving;
serving(b)
.cmp(&serving(a))
.then_with(|| a.label.cmp(&b.label))
});
MeshLiveView {
connected: true,
self_capacity_gb: f64_at(payload, "my_vram_gb").filter(|gb| *gb > 0.0),
peers,
}
}
#[cfg(test)]
mod tests {
use super::*;
fn payload(peers: serde_json::Value) -> serde_json::Value {
serde_json::json!({ "my_vram_gb": 115.0, "peers": peers })
}
#[test]
fn projects_a_serving_peer_with_its_reported_figures() {
let view = live_view_from_payload(&payload(serde_json::json!([{
"id": "abc123def456",
"hostname": "studio54.lan",
"state": "serving",
"vram_gb": 64.0,
"rtt_ms": 30,
"serving_models": ["gemma-4"],
}])));
assert!(view.connected);
assert_eq!(view.self_capacity_gb, Some(115.0));
assert_eq!(view.peers.len(), 1);
let peer = &view.peers[0];
assert_eq!(peer.label, "studio54.lan");
assert_eq!(peer.state, MeshPeerState::Serving);
assert_eq!(peer.capacity_gb, Some(64.0));
assert_eq!(peer.rtt_ms, Some(30));
assert_eq!(peer.models, vec!["gemma-4".to_string()]);
}
#[test]
fn a_client_peer_reports_no_capacity_rather_than_zero_gb() {
// Client-mode nodes report vram_gb: 0. Showing "0 GB" would imply a
// machine with no memory instead of one that shares none.
let view = live_view_from_payload(&payload(serde_json::json!([{
"id": "cli1",
"hostname": "mac.lan",
"state": "client",
"vram_gb": 0.0,
}])));
assert_eq!(view.peers[0].state, MeshPeerState::Consuming);
assert_eq!(view.peers[0].capacity_gb, None);
}
#[test]
fn a_declared_role_wins_over_advertised_models() {
// A client that lists a model is still consuming.
let view = live_view_from_payload(&payload(serde_json::json!([{
"id": "cli2",
"hostname": "host.lan",
"state": "client",
"serving_models": ["gemma-4"],
}])));
assert_eq!(view.peers[0].state, MeshPeerState::Consuming);
}
#[test]
fn serving_peers_sort_before_consumers() {
let view = live_view_from_payload(&payload(serde_json::json!([
{ "id": "b", "hostname": "zulu.lan", "state": "client" },
{ "id": "a", "hostname": "alpha.lan", "state": "serving", "serving_models": ["m"] },
])));
assert_eq!(view.peers[0].label, "alpha.lan");
assert_eq!(view.peers[1].label, "zulu.lan");
}
#[test]
fn peers_without_an_id_are_dropped() {
let view = live_view_from_payload(&payload(serde_json::json!([
{ "hostname": "nameless.lan", "state": "serving" },
])));
assert!(view.peers.is_empty());
}
#[test]
fn a_missing_peers_array_is_alone_not_broken() {
let view = live_view_from_payload(&serde_json::json!({ "my_vram_gb": 8.0 }));
assert!(view.connected);
assert!(view.peers.is_empty());
}
#[test]
fn an_unlabelled_peer_falls_back_to_a_short_id() {
let view = live_view_from_payload(&payload(serde_json::json!([
{ "id": "0123456789abcdef", "state": "standby" },
])));
assert_eq!(view.peers[0].label, "0123456789");
}
}
+27 -12
View File
@@ -1,31 +1,46 @@
use serde::{Deserialize, Serialize};
/// Host-side "who is using the compute I'm sharing" snapshot.
/// This node's own routing activity, plus the peers it can currently see.
///
/// Read-only projection of the serving node's own runtime metrics (the same
/// `routing_metrics` / `inflight_requests` the SDK already exposes on the local
/// console). No new trust surface: it reads the node's own status payload.
/// Read-only projection of the node's own status payload — no new trust
/// surface.
///
/// The local/remote/endpoint attempt split is what distinguishes *my own*
/// agent (local) from *another member consuming my compute* (remote/endpoint).
/// **Direction matters.** Every counter here comes from `routing_metrics`,
/// which is incremented only by this node's local OpenAI ingress
/// (`network/openai/transport.rs`) when *this* node dispatches a request. The
/// inbound peer-serving path (`mesh/stage_transport.rs`) never touches it — it
/// only observes inflight. So the attempt/served split says *where my requests
/// ran*, never *who asked me*:
///
/// - local → my own GPU ran it
/// - remote → a peer ran it for me (I am CONSUMING someone else's compute)
///
/// mesh-llm exposes no inbound counter (`fronted_request_count` merely aliases
/// `request_count`), so nothing here may be labelled "served for others".
/// Inbound work can only be *inferred*: serving, with inflight > 0, while our
/// own dispatch count stays flat, means the work is necessarily not ours.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
#[serde(rename_all = "camelCase")]
pub struct MeshServingUsage {
/// Requests being served right now.
/// Inference in flight on this node right now. Does NOT distinguish a local
/// agent's request from a remote member's — the only live signal available.
pub inflight: u64,
/// Highest concurrent in-flight seen this session.
pub peak_inflight: u64,
/// Total requests routed through this node.
/// Requests this node's ingress has routed (outbound), NOT work served for
/// others. Named `requests_served` for wire compatibility; treat as
/// "requests routed".
pub requests_served: u64,
/// Completion tokens produced.
/// Completion tokens this node observed on requests it dispatched.
pub tokens_served: u64,
/// Recent decode throughput.
pub tokens_per_second: f64,
/// Requests served for this machine's own agents.
/// Attempts this node dispatched to its own GPU.
pub local_attempts: u64,
/// Requests served for a remote peer (someone else consuming my compute).
/// Attempts this node dispatched to a peer — i.e. this machine consuming
/// someone else's compute.
pub remote_attempts: u64,
/// Requests served via an advertised endpoint (also a remote consumer).
/// Attempts this node dispatched to a configured endpoint.
pub endpoint_attempts: u64,
/// Other nodes currently visible as peers.
pub peers: u64,
+5
View File
@@ -47,3 +47,8 @@ pub async fn mesh_model_catalog() -> CmdResult<serde_json::Value> {
pub async fn mesh_snapshot(_state: State<'_, AppState>) -> CmdResult<serde_json::Value> {
Err("mesh-llm feature not enabled".to_string())
}
#[tauri::command]
pub async fn mesh_live_view(_state: State<'_, AppState>) -> CmdResult<()> {
Err("mesh-llm feature is not enabled".to_string())
}
@@ -0,0 +1,57 @@
import * as React from "react";
import { type MeshLiveView, meshLiveView } from "@/shared/api/tauriMesh";
/**
* Poll this machine's live gossip view of the mesh.
*
* Faster than the relay snapshot's 30s cadence because this is local IPC
* reading an in-process status payload — no relay round trip — and peers join
* and leave on a human timescale that a 30s poll makes look broken.
*
* Only polls while a runtime is expected to exist: with no node there is
* nothing to report, and hammering a command that always returns
* `connected:false` is waste.
*/
const POLL_MS = 5000;
export function useMeshLiveView(enabled: boolean): {
view: MeshLiveView | null;
refresh: () => void;
} {
const [view, setView] = React.useState<MeshLiveView | null>(null);
const [nonce, setNonce] = React.useState(0);
// biome-ignore lint/correctness/useExhaustiveDependencies: nonce is an intentional re-run trigger for refresh(), never a value read in the body — bumping it re-polls the live view immediately after a local node transition
React.useEffect(() => {
if (!enabled) {
// Drop the stale view rather than leaving the last peers on screen after
// the node stops — they are no longer reachable.
setView(null);
return;
}
let cancelled = false;
const tick = async () => {
try {
const next = await meshLiveView();
if (!cancelled) {
setView(next);
}
} catch {
// A transient IPC failure is not evidence the mesh is empty; keep the
// previous view rather than blanking the topology.
}
};
void tick();
const timer = setInterval(() => void tick(), POLL_MS);
return () => {
cancelled = true;
clearInterval(timer);
};
}, [enabled, nonce]);
return {
view,
refresh: React.useCallback(() => setNonce((value) => value + 1), []),
};
}
@@ -0,0 +1,133 @@
import type { MeshServingUsage } from "@/shared/api/tauriMesh";
/**
* Inferring inbound work — the "someone is using my machine" signal.
*
* mesh-llm exposes no inbound counter. `routing_metrics` is incremented only by
* this node's own OpenAI ingress, and `fronted_request_count` merely aliases
* `request_count`, so there is no field that counts work done for other
* members.
*
* But it is still *derivable*, because two facts we do hold are enough:
*
* 1. `inflight` counts inference in flight on this node, whoever asked.
* 2. `requestsServed` (= `request_count`) counts requests **we** dispatched.
*
* So if we are serving, there is work in flight, and our own dispatch count has
* not moved between samples — that work is not ours. It arrived from a peer.
* This is inference by elimination from data we already poll, not a guess.
*
* Its one weakness, stated so nobody mistakes it for a counter: it is sampled.
* A request that starts and finishes entirely between two polls is invisible,
* so the signal can undercount. It never *over*-claims, which is the direction
* that matters — we would rather miss a flicker than assert traffic that never
* happened.
*/
export type MeshActivitySample = {
/** `inflight` at the time of the sample. */
inflight: number;
/** `requestsServed` (outbound dispatch count) at the time of the sample. */
requestsRouted: number;
};
export function activitySample(
usage: MeshServingUsage | null,
): MeshActivitySample | null {
if (!usage) {
return null;
}
return { inflight: usage.inflight, requestsRouted: usage.requestsServed };
}
/**
* Is the work currently in flight coming from someone else?
*
* Requires a previous sample: without one we cannot tell whether our own
* dispatch count is moving, so we decline to claim anything.
*/
export function inferInboundWork({
isSharing,
current,
previous,
}: {
isSharing: boolean;
current: MeshActivitySample | null;
previous: MeshActivitySample | null;
}): boolean {
// Only a sharing node can receive inbound work at all.
if (!isSharing || !current || !previous) {
return false;
}
if (current.inflight === 0) {
return false;
}
// Our own dispatch count moved, so at least some of this is ours. Attributing
// it to a peer would be a claim we cannot support.
return current.requestsRouted === previous.requestsRouted;
}
/**
* Where this machine's completed requests actually ran.
*
* Uses the `pressure` split, which counts *completed* requests rather than
* attempts, so it is a fact about our own consumption rather than a retry
* artefact. Returns null before anything completes rather than claiming
* "0 remote".
*/
export function describeRequestOrigin(
usage: MeshServingUsage | null,
): string | null {
if (!usage) {
return null;
}
const remote = usage.remotelyServed + usage.endpointServed;
const total = usage.locallyServed + remote;
if (total === 0) {
return null;
}
const label = (n: number, noun: string) =>
`${n} ${n === 1 ? noun : `${noun}s`}`;
if (remote === 0) {
return `${label(total, "request")} ran here`;
}
if (usage.locallyServed === 0) {
return `${label(remote, "request")} ran on shared compute`;
}
return `${remote} of ${total} requests ran on shared compute`;
}
/**
* The one-line participation hint under the card headline.
*
* Ordered by what the operator most wants to know: live inbound work first
* (their machine is earning its keep), then live work generally, then the
* cumulative record. Never asserts inbound work without the elimination check
* above holding.
*/
export function describeParticipationHint({
isSharing,
isConsuming,
inboundWork,
usage,
}: {
isSharing: boolean;
isConsuming: boolean;
inboundWork: boolean;
usage: MeshServingUsage | null;
}): string {
if (isConsuming) {
return describeRequestOrigin(usage) ?? "Using shared compute";
}
if (!isSharing) {
return "Share compute to run models";
}
if (inboundWork) {
return "You're sharing · serving another member";
}
if ((usage?.inflight ?? 0) > 0) {
return "You're sharing · working now";
}
const origin = describeRequestOrigin(usage);
return origin ? `You're sharing · ${origin}` : "You're sharing";
}
@@ -15,7 +15,7 @@ import assert from "node:assert/strict";
import {
describeMeshCapacity,
describeParticipation,
describeMeshHeadline,
describeReadyModels,
deriveMeshCardModel,
formatCapacityGb,
@@ -57,11 +57,42 @@ function snapshot(overrides = {}) {
models: ["unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q4_K_M"],
devices: [device()],
includesSelf: false,
memberCount: 1,
reason: null,
...overrides,
};
}
function usage(overrides = {}) {
return {
inflight: 0,
peakInflight: 0,
requestsServed: 0,
tokensServed: 0,
tokensPerSecond: 0,
localAttempts: 0,
remoteAttempts: 0,
endpointAttempts: 0,
peers: 0,
locallyServed: 0,
remotelyServed: 0,
endpointServed: 0,
...overrides,
};
}
function peer(overrides = {}) {
return {
id: "peer-1",
label: "studio54.lan",
state: "serving",
capacityGb: 64,
models: ["m"],
rttMs: 30,
...overrides,
};
}
function derive(overrides = {}) {
return deriveMeshCardModel({
snapshot: snapshot(),
@@ -69,8 +100,9 @@ function derive(overrides = {}) {
toggle: OFF_TOGGLE,
pendingAction: null,
canShare: true,
busyNow: false,
requestsRouted: 0,
view: null,
usage: usage(),
inboundWork: false,
...overrides,
});
}
@@ -138,105 +170,129 @@ test("ready models collapse to a count past one", () => {
test("consuming never renders as sharing", () => {
const model = derive({
toggle: CONSUMING_TOGGLE,
snapshot: snapshot({ devices: [device({ label: "Mac Mini" })] }),
usage: usage({ remotelyServed: 4 }),
});
assert.equal(model.tone, "consuming");
assert.equal(model.switchOn, false, "the Share switch must stay off");
assert.match(model.headline, /Using shared compute/);
assert.match(model.detail, /Mac Mini/);
// The headline names the mesh; the detail line carries this machine's role,
// and must say we are taking rather than giving.
assert.match(model.detail, /ran on shared compute/);
assert.ok(
!/You're sharing/.test(model.detail),
`consuming must not read as sharing: ${model.detail}`,
);
// A consuming client may be replaced by a serve runtime, so the switch stays
// usable rather than locked.
assert.equal(model.switchDisabled, false);
});
test("sharing leads with mesh capacity and omits the model name", () => {
const SERVE_STATUS = {
state: "running",
mode: "serve",
health: { status: "ok", reason: null },
modelId: "unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q4_K_M",
modelName: null,
apiBaseUrl: null,
consoleUrl: null,
};
test("the headline names MeshLLM, live capacity and peer count", () => {
assert.equal(
describeMeshHeadline({
view: {
connected: true,
selfCapacityGb: 115,
peers: [peer({ capacityGb: 64 })],
},
snapshot: snapshot(),
}),
"MeshLLM · 179 GB, 1 peer",
);
});
test("a consuming-only mesh shows peers without inventing capacity", () => {
// Client-mode peers share no memory, so a mesh of consumers has no GB to
// report — but the peers are still really there.
assert.equal(
describeMeshHeadline({
view: {
connected: true,
selfCapacityGb: null,
peers: [peer({ capacityGb: null, state: "consuming" })],
},
snapshot: snapshot(),
}),
"MeshLLM · 1 peer",
);
});
test("with no runtime the headline falls back to the relay snapshot", () => {
// Peers are unknowable without a node, so the community view is all we have.
assert.equal(
describeMeshHeadline({
view: { connected: false, selfCapacityGb: null, peers: [] },
snapshot: snapshot({ sharingDeviceCount: 3, sharedCapacityGb: 42 }),
}),
"42 GB · 3 devices",
);
});
test("sharing omits the model name and hints participation", () => {
const model = derive({
toggle: SHARING_TOGGLE,
status: {
state: "running",
mode: "serve",
health: { status: "ok", reason: null },
modelId: "unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q4_K_M",
modelName: null,
apiBaseUrl: null,
consoleUrl: null,
},
snapshot: snapshot({
sharingDeviceCount: 1,
sharedCapacityGb: 115,
devices: [device({ isSelf: true })],
includesSelf: true,
}),
status: SERVE_STATUS,
view: { connected: true, selfCapacityGb: 115, peers: [peer()] },
});
assert.equal(model.tone, "sharing");
assert.equal(model.switchOn, true);
assert.equal(model.headline, "115 GB · 1 device");
assert.equal(model.headline, "MeshLLM · 179 GB, 1 peer");
assert.match(model.detail, /You're sharing/);
// The model belongs in the detail view, not on a 256px card.
assert.ok(!/Gemma/i.test(model.detail ?? ""), "card must not name the model");
});
test("inflight work reads as working, never as 'someone is using you'", () => {
test("inferred inbound work is the one place a peer may be named", () => {
const model = derive({
toggle: SHARING_TOGGLE,
status: {
state: "running",
mode: "serve",
health: { status: "ok", reason: null },
modelId: "m",
modelName: null,
apiBaseUrl: null,
consoleUrl: null,
},
busyNow: true,
status: SERVE_STATUS,
usage: usage({ inflight: 1 }),
inboundWork: true,
});
assert.match(model.detail, /serving another member/);
});
test("inflight work alone reads as working, never as being used", () => {
// Without the elimination check the work may be our own agent's, so the copy
// must not attribute it to anyone.
const model = derive({
toggle: SHARING_TOGGLE,
status: SERVE_STATUS,
usage: usage({ inflight: 1 }),
inboundWork: false,
});
assert.match(model.detail, /working now/);
});
test("routed requests are a subtle used-ness signal, not a served claim", () => {
const model = derive({
toggle: SHARING_TOGGLE,
status: {
state: "running",
mode: "serve",
health: { status: "ok", reason: null },
modelId: "m",
modelName: null,
apiBaseUrl: null,
consoleUrl: null,
},
requestsRouted: 7,
});
assert.match(model.detail, /7 requests this session/);
});
test("participation copy never claims work was served for other members", () => {
// mesh-llm exposes no inbound counter, so no wording here may imply that
// another member consumed this machine's compute.
const claims = [
describeParticipation({ busyNow: false, requestsRouted: 0 }),
describeParticipation({ busyNow: true, requestsRouted: 3 }),
describeParticipation({ busyNow: false, requestsRouted: 3 }),
];
assert.deepEqual(claims, [
"Sharing · ready",
"Sharing · working now",
"Sharing · 3 requests this session",
]);
for (const claim of claims) {
assert.ok(
!/served|for (others|members|someone)|consumed/i.test(claim),
`must not claim served-for-others: ${claim}`,
);
}
});
test("one routed request is singular", () => {
assert.equal(
describeParticipation({ busyNow: false, requestsRouted: 1 }),
"Sharing · 1 request this session",
assert.ok(
!/another member|someone|served for/i.test(model.detail),
`must not attribute the work: ${model.detail}`,
);
});
test("a solo sharer is a live-view fact, not a lone relay note", () => {
// One status note may simply be a stale one; only gossip can say "alone".
const alone = derive({
toggle: SHARING_TOGGLE,
status: SERVE_STATUS,
view: { connected: true, selfCapacityGb: 115, peers: [] },
});
assert.equal(alone.isSolo, true);
const populated = derive({
toggle: SHARING_TOGGLE,
status: SERVE_STATUS,
view: { connected: true, selfCapacityGb: 115, peers: [peer()] },
});
assert.equal(populated.isSolo, false);
});
test("a serve node with no advertised model is warming up, not serving", () => {
const model = derive({
toggle: SHARING_TOGGLE,
@@ -294,34 +350,3 @@ test("an unknown runtime occupant is not silently replaceable", () => {
});
assert.equal(model.switchDisabled, true);
});
test("a solo sharer gets the waiting hint; a populated mesh does not", () => {
const sharingStatus = {
state: "running",
mode: "serve",
health: { status: "ok", reason: null },
modelId: "m",
modelName: null,
apiBaseUrl: null,
consoleUrl: null,
};
const solo = derive({
toggle: SHARING_TOGGLE,
status: sharingStatus,
snapshot: snapshot({ devices: [device({ isSelf: true })] }),
});
assert.equal(solo.showSoloHint, true);
const populated = derive({
toggle: SHARING_TOGGLE,
status: sharingStatus,
snapshot: snapshot({
sharingDeviceCount: 2,
devices: [
device({ isSelf: true }),
device({ deviceId: "e2", label: "Studio 2" }),
],
}),
});
assert.equal(populated.showSoloHint, false);
});
@@ -1,8 +1,11 @@
import type {
MeshLiveView,
MeshNodeStatus,
MeshServingUsage,
MeshSnapshot,
MeshSnapshotDevice,
} from "@/shared/api/tauriMesh";
import { describeParticipationHint } from "./meshActivity";
import type { MeshShareToggleModel } from "./shareToggleState";
/**
@@ -93,6 +96,41 @@ export function describeMeshCapacity(snapshot: MeshSnapshot | null): string {
: `${formatCapacityGb(gb)} · ${devices}`;
}
/**
* The card headline once we have a live view: name the mesh, its capacity, and
* how many nodes we can actually see.
*
* Prefers the live gossip view over the relay snapshot. Peers listed here are
* ones our runtime is talking to *now*, whereas relay status notes stay valid
* for 120s and so outlive the node that wrote them — a graph built on notes
* shows devices gossip already knows are gone.
*
* Capacity sums this machine plus its serving peers. Consuming peers contribute
* a peer count but no GB, because they share none.
*/
export function describeMeshHeadline({
view,
snapshot,
}: {
view: MeshLiveView | null;
snapshot: MeshSnapshot | null;
}): string {
// Not participating: the relay snapshot is the only view of the pool, and the
// reason to consider joining.
if (!view?.connected) {
return describeMeshCapacity(snapshot);
}
const capacityGb = [
view.selfCapacityGb ?? 0,
...view.peers.map((peer) => peer.capacityGb ?? 0),
].reduce((total, gb) => total + gb, 0);
const peerCount = view.peers.length;
const peers = `${peerCount} ${plural(peerCount, "peer")}`;
return capacityGb > 0
? `MeshLLM · ${formatCapacityGb(capacityGb)}, ${peers}`
: `MeshLLM · ${peers}`;
}
/** Short label for what is ready to run, or null when nothing is. */
export function describeReadyModels(
snapshot: MeshSnapshot | null,
@@ -107,30 +145,6 @@ export function describeReadyModels(
return `${models.length} models ready`;
}
/**
* The sharing detail line: proof this machine is participating, and that the
* mesh has actually been used.
*
* Scrupulously avoids claiming someone else consumed this machine's compute —
* mesh-llm exposes no inbound counter, so "requests routed" is the strongest
* true statement available. Worded as "requests" without "served for others".
*/
export function describeParticipation({
busyNow,
requestsRouted,
}: {
busyNow: boolean;
requestsRouted: number;
}): string {
if (busyNow) {
return "Sharing · working now";
}
if (requestsRouted > 0) {
return `Sharing · ${requestsRouted} ${plural(requestsRouted, "request")} this session`;
}
return "Sharing · ready";
}
/**
* Trim a model reference down to something that fits a 256px sidebar.
* `unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q4_K_M` → `Gemma 4 26B A4B`.
@@ -161,8 +175,9 @@ export function deriveMeshCardModel({
toggle,
pendingAction,
canShare,
busyNow,
requestsRouted,
view,
usage,
inboundWork,
}: {
snapshot: MeshSnapshot | null;
status: MeshNodeStatus | null;
@@ -170,27 +185,28 @@ export function deriveMeshCardModel({
pendingAction: "start" | "stop" | null;
/** False when no model can be resolved yet (catalog still loading). */
canShare: boolean;
/** Live gossip view. Null/disconnected falls back to the relay snapshot. */
view: MeshLiveView | null;
/** This node's own routing counters. All outbound — see `meshActivity.ts`. */
usage: MeshServingUsage | null;
/**
* This node has inference in flight (`inflight > 0`).
*
* Honest but coarse: mesh-llm's inflight counter does not say whether the
* work is for a local agent or a remote member, so this only ever claims
* "working", never "someone is using your compute".
* Inbound work inferred by elimination (serving + inflight + our own dispatch
* count flat). Sampled, so it can undercount; it never over-claims.
*/
busyNow: boolean;
/**
* Requests this node's ingress has routed this session (`request_count`).
*
* Outbound routing, NOT work served for others — mesh-llm exposes no inbound
* counter. Used only as a subtle "this has been used" signal.
*/
requestsRouted: number;
inboundWork: boolean;
}): MeshCardModel {
const devices = snapshot?.devices ?? [];
const participantCount = devices.length;
const capacity = describeMeshCapacity(snapshot);
const headline = describeMeshHeadline({ view, snapshot });
const ready = describeReadyModels(snapshot);
const isSolo = participantCount === 1;
// Solo means "connected but nobody else is here" — a live-view fact. The
// relay snapshot cannot tell us this: a lone note may just be a stale one.
const isSolo = view?.connected === true && view.peers.length === 0;
const hint = describeParticipationHint({
isSharing: toggle.isSharing,
isConsuming: toggle.isConsuming,
inboundWork,
usage,
});
const base = {
devices,
@@ -232,16 +248,11 @@ export function deriveMeshCardModel({
// Consuming: this machine is TAKING compute, not giving it. Say so plainly —
// the switch is off here and that must not read as "nothing is happening".
if (toggle.isConsuming) {
const peer = devices.find(
(device) => !device.isSelf && device.state === "serving",
);
return {
...base,
tone: "consuming",
headline: "Using shared compute",
detail: peer
? `Running on ${peer.label}. Turn on to share this computer too.`
: "Running on another member's computer.",
headline,
detail: hint,
showSoloHint: false,
};
}
@@ -274,8 +285,8 @@ export function deriveMeshCardModel({
return {
...base,
tone: "sharing",
headline: capacity,
detail: describeParticipation({ busyNow, requestsRouted }),
headline,
detail: hint,
showSoloHint: isSolo,
};
}
@@ -285,8 +296,8 @@ export function deriveMeshCardModel({
return {
...base,
tone: "idle",
headline: capacity,
detail: ready ?? "Share compute to run models.",
headline,
detail: ready ?? hint,
showSoloHint: false,
};
}
@@ -10,10 +10,11 @@ import test from "node:test";
*/
import {
describeActivity,
describeParticipationHint,
describeRequestOrigin,
deriveMeshDetailModel,
} from "./meshDetailModel.ts";
inferInboundWork,
} from "./meshActivity.ts";
import { describeActivity, deriveMeshDetailModel } from "./meshDetailModel.ts";
function usage(overrides = {}) {
return {
@@ -45,6 +46,27 @@ function device(overrides = {}) {
};
}
function peer(overrides = {}) {
return {
id: "peer-1",
label: "studio54.lan",
state: "serving",
capacityGb: 64,
models: ["m"],
rttMs: 30,
...overrides,
};
}
function view(overrides = {}) {
return {
connected: true,
selfCapacityGb: 115,
peers: [],
...overrides,
};
}
function snapshot(overrides = {}) {
return {
sharingDeviceCount: 1,
@@ -61,15 +83,15 @@ function snapshot(overrides = {}) {
test("request origin distinguishes borrowed compute from local work", () => {
assert.equal(
describeRequestOrigin(usage({ locallyServed: 5 })),
"5 requests · all on this computer",
"5 requests ran here",
);
assert.equal(
describeRequestOrigin(usage({ remotelyServed: 4 })),
"4 requests · all on shared compute",
"4 requests ran on shared compute",
);
assert.equal(
describeRequestOrigin(usage({ locallyServed: 9, remotelyServed: 3 })),
"3 of 12 requests on shared compute",
"3 of 12 requests ran on shared compute",
);
});
@@ -77,7 +99,7 @@ test("endpoint-served requests count as shared, not local", () => {
// An endpoint is not this machine's GPU, so it must not read as local work.
assert.equal(
describeRequestOrigin(usage({ locallyServed: 1, endpointServed: 1 })),
"1 of 2 requests on shared compute",
"1 of 2 requests ran on shared compute",
);
});
@@ -89,97 +111,219 @@ test("no completed requests yields no origin claim, never '0 remote'", () => {
test("singular grammar for a single request", () => {
assert.equal(
describeRequestOrigin(usage({ locallyServed: 1 })),
"1 request · all on this computer",
"1 request ran here",
);
});
test("activity reports inflight work without attributing it to anyone", () => {
const live = describeActivity(usage({ inflight: 2 }), true);
const live = describeActivity({
usage: usage({ inflight: 2 }),
isSharing: true,
inboundWork: false,
});
assert.equal(live, "2 requests in flight");
// The counter cannot distinguish a local agent from a remote member, so the
// Without the elimination check the work may be our own agent's, so the
// phrasing must never imply someone else is using this machine.
assert.ok(
!/(served|for (others|members|someone)|using your|consumed)/i.test(live),
!/(served|for (others|members|someone)|using your|consumed|another member)/i.test(
live,
),
`must not attribute inbound work: ${live}`,
);
});
test("inferred inbound work is the one case a peer may be credited", () => {
assert.equal(
describeActivity({
usage: usage({ inflight: 2 }),
isSharing: true,
inboundWork: true,
}),
"2 requests in flight · from another member",
);
});
test("a warm sharing runtime with no traffic is its own state", () => {
assert.equal(describeActivity(usage(), true), "Ready · no requests yet");
assert.equal(
describeActivity({ usage: usage(), isSharing: true, inboundWork: false }),
"Ready · no requests yet",
);
// Not sharing and idle is not noteworthy — stay silent.
assert.equal(describeActivity(usage(), false), null);
assert.equal(describeActivity(null, true), null);
assert.equal(
describeActivity({ usage: usage(), isSharing: false, inboundWork: false }),
null,
);
assert.equal(
describeActivity({ usage: null, isSharing: true, inboundWork: false }),
null,
);
});
test("participation names the roster denominator", () => {
const model = deriveMeshDetailModel({
snapshot: snapshot({
sharingDeviceCount: 2,
memberCount: 12,
sharedCapacityGb: 115,
devices: [device({ isSelf: true }), device({ deviceId: "d2" })],
test("inbound work requires two samples and a flat dispatch count", () => {
const base = { isSharing: true };
// Our own dispatch count moved, so at least some of the work is ours.
assert.equal(
inferInboundWork({
...base,
current: { inflight: 1, requestsRouted: 6 },
previous: { inflight: 0, requestsRouted: 5 },
}),
usage: usage(),
isSharing: true,
});
assert.equal(model.participationLabel, "2 of 12 members sharing");
assert.equal(model.capacityLabel, "115 GB");
// 12 members, 2 with published status notes -> 10 ghosts.
assert.equal(model.ghostCount, 10);
});
test("ghost count never goes negative when the roster lags devices", () => {
// A device can report while a stale roster page omits it. A negative ghost
// count is nonsense, so it clamps at zero.
const model = deriveMeshDetailModel({
snapshot: snapshot({
memberCount: 1,
devices: [device({ isSelf: true }), device({ deviceId: "d2" })],
false,
);
// Flat dispatch count with work in flight: it cannot be ours.
assert.equal(
inferInboundWork({
...base,
current: { inflight: 1, requestsRouted: 5 },
previous: { inflight: 0, requestsRouted: 5 },
}),
usage: usage(),
isSharing: true,
});
assert.equal(model.ghostCount, 0);
true,
);
// No history yet — decline to claim anything.
assert.equal(
inferInboundWork({
...base,
current: { inflight: 1, requestsRouted: 5 },
previous: null,
}),
false,
);
// Nothing in flight, and a non-sharing node cannot receive inbound work.
assert.equal(
inferInboundWork({
...base,
current: { inflight: 0, requestsRouted: 5 },
previous: { inflight: 0, requestsRouted: 5 },
}),
false,
);
assert.equal(
inferInboundWork({
isSharing: false,
current: { inflight: 1, requestsRouted: 5 },
previous: { inflight: 0, requestsRouted: 5 },
}),
false,
);
});
test("an empty roster falls back to a device count", () => {
test("participation counts live peers, not relay notes", () => {
const model = deriveMeshDetailModel({
snapshot: snapshot({ sharingDeviceCount: 1, memberCount: 0 }),
view: view({ peers: [peer(), peer({ id: "p2", label: "mac.lan" })] }),
snapshot: snapshot(),
usage: usage(),
isSharing: true,
inboundWork: false,
});
assert.equal(model.participationLabel, "1 device sharing");
assert.equal(model.participationLabel, "2 peers connected");
assert.equal(model.connected, true);
// 115 self + 64 + 64 peers.
assert.equal(model.capacityLabel, "243 GB");
});
test("unknown capacity drops the figure rather than printing 0 GB", () => {
const model = deriveMeshDetailModel({
snapshot: snapshot({ sharedCapacityGb: null }),
test("connected but alone is distinct from not participating", () => {
const alone = deriveMeshDetailModel({
view: view({ peers: [] }),
snapshot: snapshot(),
usage: usage(),
isSharing: true,
inboundWork: false,
});
assert.equal(alone.participationLabel, "No other devices yet");
assert.equal(alone.connected, true);
// With no runtime, peers are unknowable and the relay view is all we have.
const off = deriveMeshDetailModel({
view: { connected: false, selfCapacityGb: null, peers: [] },
snapshot: snapshot({ sharingDeviceCount: 3 }),
usage: usage(),
isSharing: false,
inboundWork: false,
});
assert.equal(off.participationLabel, "3 sharing in this community");
assert.equal(off.connected, false);
});
test("consuming peers add presence but never invented capacity", () => {
const model = deriveMeshDetailModel({
view: view({
selfCapacityGb: null,
peers: [peer({ capacityGb: null, state: "consuming", models: [] })],
}),
snapshot: snapshot(),
usage: usage(),
isSharing: false,
inboundWork: false,
});
assert.equal(model.participationLabel, "1 peer connected");
// Nobody reported a figure, so no GB is claimed rather than "0 GB".
assert.equal(model.capacityLabel, null);
});
test("a null snapshot is renderable and claims nothing", () => {
test("a null view and snapshot are renderable and claim nothing", () => {
const model = deriveMeshDetailModel({
view: null,
snapshot: null,
usage: null,
isSharing: false,
inboundWork: false,
});
assert.equal(model.capacityLabel, null);
assert.equal(model.ghostCount, 0);
assert.equal(model.connected, false);
assert.equal(model.busyNow, false);
assert.equal(model.activityLabel, null);
assert.equal(model.originLabel, null);
assert.equal(model.modelCount, 0);
});
test("capacity formatting keeps small figures meaningful", () => {
assert.equal(
deriveMeshDetailModel({
snapshot: snapshot({ sharedCapacityGb: 4.62 }),
view: view({ selfCapacityGb: 4.62, peers: [] }),
snapshot: snapshot(),
usage: usage(),
isSharing: true,
inboundWork: false,
}).capacityLabel,
"4.6 GB",
);
});
test("the card hint distinguishes giving, taking, and neither", () => {
assert.equal(
describeParticipationHint({
isSharing: false,
isConsuming: false,
inboundWork: false,
usage: usage(),
}),
"Share compute to run models",
);
assert.equal(
describeParticipationHint({
isSharing: true,
isConsuming: false,
inboundWork: false,
usage: usage(),
}),
"You're sharing",
);
assert.equal(
describeParticipationHint({
isSharing: true,
isConsuming: false,
inboundWork: true,
usage: usage({ inflight: 1 }),
}),
"You're sharing · serving another member",
);
assert.equal(
describeParticipationHint({
isSharing: false,
isConsuming: true,
inboundWork: false,
usage: usage({ remotelyServed: 3, locallyServed: 1 }),
}),
"3 of 4 requests ran on shared compute",
);
});
@@ -1,13 +1,23 @@
import type { MeshServingUsage, MeshSnapshot } from "@/shared/api/tauriMesh";
import type {
MeshLiveView,
MeshServingUsage,
MeshSnapshot,
} from "@/shared/api/tauriMesh";
import { describeRequestOrigin } from "./meshActivity";
/**
* Pure projection for the mesh detail popover.
*
* The popover answers three questions the 256px card cannot:
* 1. How big is the pool, and how much of the community is in it?
* 2. Is the spice flowing — is work actually happening right now?
* 1. Who is on the mesh right now, and how much do they bring?
* 2. Is the spice flowing — is work actually happening?
* 3. Am I running on someone else's machine, or my own?
*
* Peers come from the **live gossip view**, not the relay snapshot. Status notes
* stay valid for 120s and so outlive the node that wrote them; a topology built
* on notes shows devices gossip already knows are gone. The relay snapshot is
* used only when no local runtime exists, where it is the sole available view.
*
* The hard constraint this file exists to encode: **mesh-llm exposes no inbound
* counter.** `routing_metrics` is incremented only by this node's own OpenAI
* ingress, so every number available describes work *this machine dispatched*.
@@ -15,66 +25,34 @@ import type { MeshServingUsage, MeshSnapshot } from "@/shared/api/tauriMesh";
*
* - "I used someone else's machine" → provable (`remotelyServed`)
* - "my own GPU did the work" → provable (`locallyServed`)
* - "someone used MY machine" → NOT provable, only ever hinted
* - "someone used MY machine" → no counter; INFERRED by elimination
*
* `inflight` is the one live signal, and it does not say who the work is for.
* That is why the busy state is worded "working" and never "someone is using
* your compute".
* That last one is derivable without a counter: sharing, with work in flight,
* while our own dispatch count stays flat, means the work is not ours. See
* `inferInboundWork` in `meshActivity.ts`. It is sampled, so it can undercount
* — but it never over-claims, which is the direction that matters.
*/
/** Ghost = a community member with no published status note. */
export type MeshDetailModel = {
/** e.g. "115 GB" — pool capacity, or null when nobody reported a figure. */
/** e.g. "115 GB" — live pool capacity, or null when nothing is shared. */
capacityLabel: string | null;
/** e.g. "2 of 12 members sharing". */
/** e.g. "2 peers connected", or the relay view when not participating. */
participationLabel: string;
/** Members with no status note at all. Count only — never GB. */
ghostCount: number;
/** True when inference is in flight on this node right now. */
busyNow: boolean;
/**
* Live activity phrase, or null when idle. Deliberately vague about *who*:
* the counters cannot attribute inbound work.
* Live activity phrase, or null when idle. Only claims inbound work when the
* elimination check in `meshActivity.ts` holds.
*/
activityLabel: string | null;
/** Where this machine's completed requests actually ran. */
originLabel: string | null;
/** Distinct models ready across the pool. */
/** Distinct models serving across the live mesh. */
modelCount: number;
/** True when a local runtime is up, so peers are knowable at all. */
connected: boolean;
};
function plural(n: number, one: string, many = `${one}s`): string {
return n === 1 ? one : many;
}
/**
* Where this machine's work ran — the honest "am I borrowing someone's GPU"
* line.
*
* `remotelyServed` counts *completed* requests a peer answered for us, so it is
* a fact about our own consumption, not a guess. Returns null before any
* request completes rather than claiming "0 remote".
*/
export function describeRequestOrigin(
usage: MeshServingUsage | null,
): string | null {
if (!usage) {
return null;
}
const remote = usage.remotelyServed + usage.endpointServed;
const total = usage.locallyServed + remote;
if (total === 0) {
return null;
}
if (remote === 0) {
return `${total} ${plural(total, "request")} · all on this computer`;
}
if (usage.locallyServed === 0) {
return `${remote} ${plural(remote, "request")} · all on shared compute`;
}
return `${remote} of ${total} requests on shared compute`;
}
/**
* The live "spice is flowing" phrase.
*
@@ -82,13 +60,20 @@ export function describeRequestOrigin(
* this node without distinguishing a local agent from a remote member, so this
* may never assert that someone else is using this machine.
*/
export function describeActivity(
usage: MeshServingUsage | null,
isSharing: boolean,
): string | null {
export function describeActivity({
usage,
isSharing,
inboundWork,
}: {
usage: MeshServingUsage | null;
isSharing: boolean;
inboundWork: boolean;
}): string | null {
const inflight = usage?.inflight ?? 0;
if (inflight > 0) {
return `${inflight} ${plural(inflight, "request")} in flight`;
const requests = `${inflight} ${inflight === 1 ? "request" : "requests"} in flight`;
// Only name a peer as the source when elimination proves it isn't ours.
return inboundWork ? `${requests} · from another member` : requests;
}
if (!usage) {
return null;
@@ -102,35 +87,58 @@ export function describeActivity(
}
export function deriveMeshDetailModel({
view,
snapshot,
usage,
isSharing,
inboundWork,
}: {
view: MeshLiveView | null;
snapshot: MeshSnapshot | null;
usage: MeshServingUsage | null;
isSharing: boolean;
inboundWork: boolean;
}): MeshDetailModel {
const devices = snapshot?.devices ?? [];
const sharing = snapshot?.sharingDeviceCount ?? 0;
const members = snapshot?.memberCount ?? 0;
// Members who published nothing. Clamped at 0: a device may report without
// appearing in a stale roster page, and a negative ghost count is nonsense.
const ghostCount = Math.max(0, members - devices.length);
const capacityGb = snapshot?.sharedCapacityGb ?? null;
const connected = view?.connected === true;
const peers = view?.peers ?? [];
// Capacity from the live mesh: this machine plus serving peers. A consuming
// peer contributes presence but no GB, because it shares none.
const liveCapacity = connected
? [
view?.selfCapacityGb ?? 0,
...peers.map((peer) => peer.capacityGb ?? 0),
].reduce((total, gb) => total + gb, 0)
: 0;
const capacityGb = connected
? liveCapacity > 0
? liveCapacity
: null
: (snapshot?.sharedCapacityGb ?? null);
const models = new Set(peers.flatMap((peer) => peer.models));
if (isSharing) {
for (const model of snapshot?.devices.find((d) => d.isSelf)?.models ?? []) {
models.add(model);
}
}
return {
connected,
capacityLabel:
capacityGb === null
? null
: `${capacityGb >= 10 ? Math.round(capacityGb) : Math.round(capacityGb * 10) / 10} GB`,
participationLabel:
members === 0
? `${sharing} ${plural(sharing, "device")} sharing`
: `${sharing} of ${members} ${plural(members, "member")} sharing`,
ghostCount,
participationLabel: connected
? peers.length === 0
? "No other devices yet"
: `${peers.length} ${peers.length === 1 ? "peer" : "peers"} connected`
: // Not participating: the relay snapshot is all we have, and it is the
// reason to consider joining.
`${snapshot?.sharingDeviceCount ?? 0} sharing in this community`,
busyNow: (usage?.inflight ?? 0) > 0,
activityLabel: describeActivity(usage, isSharing),
activityLabel: describeActivity({ usage, isSharing, inboundWork }),
originLabel: describeRequestOrigin(usage),
modelCount: snapshot?.models.length ?? 0,
modelCount: models.size,
};
}
@@ -1,4 +1,8 @@
import type { MeshServingUsage, MeshSnapshot } from "@/shared/api/tauriMesh";
import type {
MeshLiveView,
MeshServingUsage,
MeshSnapshot,
} from "@/shared/api/tauriMesh";
import { Popover, PopoverContent, PopoverTrigger } from "@/shared/ui/popover";
import { POPOVER_SHADOW_STYLE } from "@/shared/ui/popoverSurface";
import { deriveMeshDetailModel } from "../meshDetailModel";
@@ -10,25 +14,38 @@ import { MeshTopologyRadial } from "./MeshTopologyRadial";
* Anchored rather than a centred dialog: this is a glance, not a task. It sits
* beside the thing it explains, and dismisses on outside click.
*
* Every figure here is one this machine can actually vouch for. In particular
* there is no "N requests served for others" line, because mesh-llm exposes no
* inbound counter — only a soft hint when the pool is live. See
* `meshDetailModel.ts` for the full constraint.
* Every figure here is one this machine can actually vouch for. Peers come from
* live gossip, so a node shown is a node we are connected to — not a relay note
* that may have outlived its writer. Inbound work has no counter, so it is
* inferred by elimination and only named when that inference holds. See
* `meshDetailModel.ts` and `meshActivity.ts`.
*/
export function MeshDetailPopover({
children,
view,
snapshot,
usage,
isSharing,
inboundWork,
onOpenComputeSettings,
}: {
children: React.ReactNode;
/** Live gossip view — the source for the topology. */
view: MeshLiveView | null;
/** Relay snapshot, used only when no local runtime exists. */
snapshot: MeshSnapshot | null;
usage: MeshServingUsage | null;
isSharing: boolean;
inboundWork: boolean;
onOpenComputeSettings?: () => void;
}) {
const model = deriveMeshDetailModel({ snapshot, usage, isSharing });
const model = deriveMeshDetailModel({
view,
snapshot,
usage,
isSharing,
inboundWork,
});
return (
<Popover>
@@ -53,11 +70,14 @@ export function MeshDetailPopover({
</p>
</div>
<MeshTopologyRadial
busyNow={model.busyNow}
devices={snapshot?.devices ?? []}
ghostCount={model.ghostCount}
/>
{model.connected ? (
<MeshTopologyRadial
busyNow={model.busyNow}
isSharing={isSharing}
peers={view?.peers ?? []}
selfCapacityGb={view?.selfCapacityGb ?? null}
/>
) : null}
<div className="flex flex-col gap-1">
{model.activityLabel ? (
@@ -95,13 +115,11 @@ export function MeshDetailPopover({
) : null}
</div>
{model.ghostCount > 0 ? (
{model.connected ? null : (
<p className="border-border/60 border-t pt-2 text-2xs leading-snug text-muted-foreground">
{model.ghostCount === 1
? "1 member isn't sharing yet."
: `${model.ghostCount} members aren't sharing yet.`}
Turn on sharing to see who's on the mesh.
</p>
) : null}
)}
{onOpenComputeSettings ? (
<button
@@ -1,125 +1,115 @@
import { motion, useReducedMotion } from "motion/react";
import type { MeshSnapshotDevice } from "@/shared/api/tauriMesh";
import type { MeshPeer } from "@/shared/api/tauriMesh";
import { cn } from "@/shared/lib/cn";
import { formatCapacityGb, shortModelLabel } from "../meshCardModel";
/**
* Radial mesh field for the detail popover: this computer at the centre,
* participating devices around it, unshared members as ghosts.
* Radial mesh field: this computer at the centre, live peers around it.
*
* ## What the geometry does and does not claim
* ## One source of truth
*
* The spokes mean **"in the same mesh as you"** — nothing more. The relay
* snapshot carries no adjacency: it tells us who is participating and what each
* advertises, but not who is connected to whom, and the activity counters are
* node-local rather than edge-attributed. So a spoke is a membership line, and
* **nothing is ever animated along one** — a packet gliding down a chosen edge
* would be invented data.
* Every node drawn here comes from the runtime's own gossip view, so a node is
* on screen because we are *connected to it right now*. This deliberately does
* not overlay relay status notes (valid for 120s, so they outlive the node that
* wrote them) or community roster members who never started a node. Mixing
* those in meant refereeing disagreements between sources and produced a graph
* showing devices gossip already knew were gone.
*
* What *is* animated is the centre: this node's own inflight work. That is a
* fact we hold directly. Peers pulse only on their own published `serving`
* state, never on inferred traffic.
* ## What the geometry claims
*
* Ghosts are members with no published status note. They are drawn dashed, with
* no capacity and no label, because a member who never starts a node discloses
* no hardware — by design. Their contribution to the picture is a count, and
* they exist here to make joining feel like joining something, not to imply
* capacity nobody offered.
* A spoke means **"connected to you"** — and that much is true, because this is
* our own adjacency. Nothing is animated *along* a spoke: the activity counters
* are node-local rather than edge-attributed, so a packet gliding down a chosen
* link would be invented.
*
* The centre pulses on this node's own inflight work, which we hold directly.
* Peers pulse only on the state they publish about themselves, never on
* inferred traffic.
*/
const CENTER = 60;
const RADIUS = 42;
const GHOST_RADIUS = 54;
/** Beyond this, ghosts collapse into a count so the ring stays legible. */
const MAX_GHOST_DOTS = 10;
const STATE_FILL: Record<MeshSnapshotDevice["state"], string> = {
const STATE_FILL: Record<MeshPeer["state"], string> = {
serving: "fill-emerald-500 dark:fill-emerald-400",
loading: "fill-amber-500 dark:fill-amber-400",
standby: "fill-muted-foreground/40",
consuming: "fill-sky-500 dark:fill-sky-400",
};
function pointOnRing(
index: number,
count: number,
radius: number,
): { x: number; y: number } {
function pointOnRing(index: number, count: number): { x: number; y: number } {
// Start at the top and go clockwise; -90° puts the first node at 12 o'clock.
const angle = (index / Math.max(1, count)) * Math.PI * 2 - Math.PI / 2;
return {
x: CENTER + Math.cos(angle) * radius,
y: CENTER + Math.sin(angle) * radius,
x: CENTER + Math.cos(angle) * RADIUS,
y: CENTER + Math.sin(angle) * RADIUS,
};
}
function deviceTitle(device: MeshSnapshotDevice): string {
const parts = [device.isSelf ? `${device.label} (you)` : device.label];
if (device.capacityGb !== null) {
parts.push(formatCapacityGb(device.capacityGb));
function peerTitle(peer: MeshPeer): string {
const parts = [peer.label];
if (peer.capacityGb !== null) {
parts.push(formatCapacityGb(peer.capacityGb));
} else if (peer.state === "consuming") {
parts.push("using shared compute");
}
if (device.models.length > 0) {
parts.push(shortModelLabel(device.models[0]));
if (peer.models.length > 0) {
parts.push(shortModelLabel(peer.models[0]));
}
if (peer.rttMs !== null) {
parts.push(`${peer.rttMs}ms`);
}
return parts.join(" · ");
}
export function MeshTopologyRadial({
devices,
ghostCount,
peers,
selfCapacityGb,
isSharing,
busyNow,
}: {
devices: MeshSnapshotDevice[];
ghostCount: number;
peers: MeshPeer[];
selfCapacityGb: number | null;
/** Whether this machine is contributing, which sets the centre's colour. */
isSharing: boolean;
/** This node has inference in flight — the only honest live signal. */
busyNow: boolean;
}) {
const shouldReduceMotion = useReducedMotion();
const self = devices.find((device) => device.isSelf);
const others = devices.filter((device) => !device.isSelf);
const ghostDots = Math.min(ghostCount, MAX_GHOST_DOTS);
const ghostOverflow = ghostCount - ghostDots;
// Ghosts sit on an outer ring, offset half a step so they interleave with
// real devices rather than hiding behind them.
const ghostOffset = others.length > 0 ? 0.5 : 0;
// Resolve geometry and keys up front. Peers key on device identity; ghosts
// have none to key on (a member with no status note publishes nothing), so
// their ring slot is the key, named explicitly rather than taken from a
// render-time array index.
const peerNodes = others.map((device, index) => ({
device,
key: device.deviceId ?? `${device.label}-${index}`,
// Resolve geometry and keys up front so render maps over identities rather
// than array positions.
const nodes = peers.map((peer, index) => ({
peer,
pulseDelay: index * 0.35,
...pointOnRing(index, others.length, RADIUS),
...pointOnRing(index, peers.length),
}));
const ghostNodes = Array.from({ length: ghostDots }, (_, slot) => ({
key: `ghost-slot-${slot}`,
...pointOnRing(
slot + ghostOffset,
Math.max(ghostDots, others.length),
GHOST_RADIUS,
),
}));
const selfTitle = [
"This computer",
isSharing && selfCapacityGb !== null
? formatCapacityGb(selfCapacityGb)
: null,
isSharing ? null : "not sharing",
]
.filter(Boolean)
.join(" · ");
return (
<div className="flex flex-col items-center">
<svg
aria-label="Mesh participants"
aria-label="Mesh peers connected to this computer"
className="h-[120px] w-[120px]"
role="img"
viewBox="0 0 120 120"
>
{/* Membership spokes. Not traffic — see the file comment. */}
{/* Adjacency, not traffic — see the file comment. */}
<g>
{peerNodes.map((node) => (
{nodes.map((node) => (
<line
className="stroke-border"
key={`spoke-${node.key}`}
key={`spoke-${node.peer.id}`}
strokeWidth={0.75}
x1={CENTER}
x2={node.x}
@@ -127,44 +117,17 @@ export function MeshTopologyRadial({
y2={node.y}
/>
))}
{ghostNodes.map((node) => (
<line
className="stroke-border/40"
key={`spoke-${node.key}`}
strokeDasharray="2 3"
strokeWidth={0.5}
x1={CENTER}
x2={node.x}
y1={CENTER}
y2={node.y}
/>
))}
</g>
{/* Ghost members: dashed, unlabelled, no capacity claimed. */}
{ghostNodes.map((node) => (
<circle
className="fill-transparent stroke-muted-foreground/30"
cx={node.x}
cy={node.y}
data-mesh-ghost="true"
key={node.key}
r={2.5}
strokeDasharray="1.5 1.5"
strokeWidth={0.75}
/>
))}
{/* Participating peers. Pulse reflects their own published state. */}
{peerNodes.map(({ device, key, pulseDelay, x, y }) => {
const isPulsing = device.state === "serving" && !shouldReduceMotion;
{nodes.map(({ peer, pulseDelay, x, y }) => {
const isPulsing = peer.state === "serving" && !shouldReduceMotion;
return (
<g key={`node-${key}`}>
<title>{deviceTitle(device)}</title>
<g key={peer.id}>
<title>{peerTitle(peer)}</title>
{isPulsing ? (
<motion.circle
animate={{ opacity: [0.45, 0, 0.45], scale: [1, 2.2, 1] }}
className={STATE_FILL[device.state]}
className={STATE_FILL[peer.state]}
cx={x}
cy={y}
r={4}
@@ -178,22 +141,20 @@ export function MeshTopologyRadial({
/>
) : null}
<circle
className={STATE_FILL[device.state]}
className={STATE_FILL[peer.state]}
cx={x}
cy={y}
data-mesh-device-state={device.state}
data-mesh-peer-state={peer.state}
r={4}
/>
</g>
);
})}
{/* This computer, at the centre. The only node whose activity we can
honestly animate, because inflight is our own counter. */}
{/* This computer. The only node whose activity we can honestly animate,
because inflight is our own counter. */}
<g>
<title>
{self ? deviceTitle(self) : "This computer (not participating)"}
</title>
<title>{selfTitle}</title>
{busyNow && !shouldReduceMotion ? (
<motion.circle
animate={{ opacity: [0.5, 0, 0.5], scale: [1, 2.4, 1] }}
@@ -212,23 +173,18 @@ export function MeshTopologyRadial({
<circle
className={cn(
"stroke-background",
self ? STATE_FILL[self.state] : "fill-muted-foreground/30",
isSharing
? "fill-emerald-500 dark:fill-emerald-400"
: "fill-sky-500 dark:fill-sky-400",
)}
cx={CENTER}
cy={CENTER}
data-mesh-self="true"
data-mesh-self-state={self?.state ?? "absent"}
r={6}
strokeWidth={1.5}
/>
</g>
</svg>
{ghostOverflow > 0 ? (
<span className="text-3xs text-muted-foreground">
+{ghostOverflow} more not sharing
</span>
) : null}
</div>
);
}
@@ -8,10 +8,12 @@ import { meshStartNode, meshStopNode } from "@/shared/api/tauriMesh";
import type { MeshModelCatalog } from "@/shared/api/tauriMesh";
import { meshModelCatalog } from "@/shared/api/tauriMesh";
import { useMeshLiveView } from "../hooks/useMeshLiveView";
import { useMeshNodeStatus } from "../hooks/useMeshNodeStatus";
import { useMeshServingUsage } from "../hooks/useMeshServingUsage";
import { useMeshSnapshot } from "../hooks/useMeshSnapshot";
import { deriveMeshShareToggle } from "../shareToggleState";
import { activitySample, inferInboundWork } from "../meshActivity";
import { deriveMeshCardModel, type MeshCardTone } from "../meshCardModel";
import { MeshDetailPopover } from "./MeshDetailPopover";
import { MeshTopologyStrip } from "./MeshTopologyStrip";
@@ -22,7 +24,7 @@ import { MeshTopologyStrip } from "./MeshTopologyStrip";
* Answers three questions at a glance, which is the whole reason it exists:
* - Am I sharing this computer? → switch on, "Sharing this computer"
* - Am I using someone else's? → switch off, "Using shared compute"
* - What does the community have? → "3 devices sharing · 42 GB"
* - What does the community have? → "MeshLLM · 115 GB, 2 peers"
*
* Deliberately NOT a model picker. Turning it on shares the hardware-appropriate
* curated recommendation (`catalog.recommended`); choosing a specific model,
@@ -90,8 +92,24 @@ export function SidebarMeshComputeCard({
// are all OUTBOUND (incremented by this node's own ingress), so a remote/
// endpoint attempt means this machine is CONSUMING, not being consumed.
// Reading them as "someone is using my compute" is exactly backwards.
const busyNow = (usage?.inflight ?? 0) > 0;
const requestsRouted = usage?.requestsServed ?? 0;
// Live gossip view: peers we are actually connected to. Only meaningful while
// a runtime exists, so it is gated on slot occupancy.
const { view } = useMeshLiveView(toggle.isSharing || toggle.isConsuming);
// Inbound work has no counter in mesh-llm, so it is inferred by elimination
// across two samples: serving, inflight > 0, and our own dispatch count flat
// means the work is not ours. Keeping the previous sample in a ref (not
// state) avoids a re-render purely to remember history.
const sample = activitySample(usage);
const previousSampleRef = React.useRef<typeof sample>(null);
const inboundWork = inferInboundWork({
isSharing: toggle.isSharing,
current: sample,
previous: previousSampleRef.current,
});
React.useEffect(() => {
previousSampleRef.current = sample;
}, [sample]);
// One-shot catalog fetch: the card needs the hardware-appropriate
// recommendation so the switch can start sharing without a model picker.
@@ -123,8 +141,9 @@ export function SidebarMeshComputeCard({
toggle,
pendingAction,
canShare: Boolean(recommended),
busyNow,
requestsRouted,
view,
usage,
inboundWork,
});
async function handleToggle(next: boolean) {
@@ -191,10 +210,12 @@ export function SidebarMeshComputeCard({
Switch in a button would nest interactive elements.
*/}
<MeshDetailPopover
inboundWork={inboundWork}
isSharing={toggle.isSharing}
onOpenComputeSettings={onOpenComputeSettings}
snapshot={snapshot}
usage={usage}
view={view}
>
<button
className="min-w-0 flex-1 rounded-md text-left focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"
+38
View File
@@ -186,3 +186,41 @@ export type MeshSnapshot = {
export async function meshSnapshot(): Promise<MeshSnapshot> {
return await invokeTauri<MeshSnapshot>("mesh_snapshot");
}
/** What a peer is doing, as *it* reports. Never inferred from traffic. */
export type MeshPeerState = "serving" | "loading" | "standby" | "consuming";
/**
* A node this machine's runtime is **actually connected to right now**.
*
* Distinct from `MeshSnapshotDevice`, which comes from relay status notes valid
* for 120s and therefore outlives the node that published it. Peers come from
* live gossip: present here means reachable now. See Rust `mesh_llm/peers.rs`.
*/
export type MeshPeer = {
id: string;
label: string;
state: MeshPeerState;
/** `null` when the peer shares none (client mode reports 0, shown as absent). */
capacityGb: number | null;
models: string[];
rttMs: number | null;
};
export type MeshLiveView = {
/**
* True when a local runtime is up. Distinguishes "no peers" (alone on the
* mesh) from "unknown" (not participating, nothing to report).
*/
connected: boolean;
selfCapacityGb: number | null;
peers: MeshPeer[];
};
/**
* This machine's live gossip view of the mesh. Empty and `connected:false` when
* no node is running — a normal state, not an error.
*/
export async function meshLiveView(): Promise<MeshLiveView> {
return await invokeTauri<MeshLiveView>("mesh_live_view");
}