compute view mesh map

Signed-off-by: Alessandro Joabar <sandro@squareup.com>
This commit is contained in:
Alessandro Joabar
2026-08-06 13:15:23 -04:00
parent 5ed5925a51
commit d232290a47
26 changed files with 3367 additions and 74 deletions

View File

@@ -33,6 +33,7 @@ export default defineConfig({
"**/add-community-screenshots.spec.ts",
"**/hosted-communities-settings-screenshots.spec.ts",
"**/invites-settings-screenshots.spec.ts",
"**/mesh-compute-screenshots.spec.ts",
"**/messaging.spec.ts",
"**/message-feedback-snapshots.spec.ts",
"**/custom-emoji.spec.ts",

View File

@@ -218,7 +218,9 @@ async fn query_mesh_discovery_events_at(
}
}
async fn query_mesh_discovery_events(state: &AppState) -> Result<Vec<nostr::Event>, String> {
pub(super) async fn query_mesh_discovery_events(
state: &AppState,
) -> Result<Vec<nostr::Event>, String> {
query_mesh_discovery_events_at(state, &relay::relay_ws_url_with_override(state)).await
}

View File

@@ -22,15 +22,12 @@ type CmdResult<T> = Result<T, String>;
/// state. A genuine relay/transport failure still returns `Err`.
#[tauri::command]
pub async fn mesh_snapshot(state: State<'_, AppState>) -> CmdResult<mesh_llm::MeshSnapshot> {
let events = crate::relay::query_relay(
&state,
&[
mesh_llm::mesh_status_filter(),
mesh_llm::relay_membership_filter(),
],
)
.await
.map_err(|error| format!("Shared compute status query failed: {error}"))?;
// Reuse discovery's author-scoped, composite-cursor pagination. A direct
// two-filter query stops at the status filter's 100-event page size and
// silently undercounts larger communities.
let events = super::mesh_llm::query_mesh_discovery_events(&state)
.await
.map_err(|error| format!("Shared compute status query failed: {error}"))?;
// Identify this member's own device so the card can say "including yours".
// A missing/locked identity is not fatal here — the snapshot is still

View File

@@ -26,7 +26,7 @@ use serde::{Deserialize, Serialize};
use super::discovery::{
device_name_from_status, endpoint_binding_is_valid, endpoint_id_from_status,
latest_membership_list, owner_id_from_status_event, status_is_fresh,
latest_membership_list, owner_id_from_status_event, status_is_fresh, STATUS_FRESHNESS_SECS,
};
use super::{MeshServeTarget, MESH_STATUS_KIND};
@@ -62,6 +62,13 @@ pub struct MeshSnapshotDevice {
pub state: MeshDeviceState,
/// Whether this is the local member's own device.
pub is_self: bool,
/// Community member who signed this status note. Safe for profile lookup;
/// endpoint tokens, owner signatures, and raw hardware remain excluded.
pub member_pubkey: Option<String>,
/// Relay event creation time, in Unix seconds.
pub reported_at: Option<u64>,
/// Approximate hosted-model footprint reported by MeshLLM, when available.
pub model_size_gb: Option<f64>,
}
/// What the community's shared compute looks like right now.
@@ -70,10 +77,15 @@ pub struct MeshSnapshotDevice {
pub struct MeshSnapshot {
/// Devices advertising at least one routable model.
pub sharing_device_count: usize,
/// Unique current members with at least one ready serving device.
pub contributor_member_count: usize,
/// Summed shared capacity across sharing devices. `None` when no sharing
/// device published a figure — the UI then shows a count with no GB, never
/// a misleading `0 GB`.
pub shared_capacity_gb: Option<f64>,
/// Summed model footprint only when every sharing device reports it.
/// `None` preserves mixed-version honesty instead of presenting a partial sum.
pub allocated_capacity_gb: Option<f64>,
/// Distinct models ready to use, deduped across devices.
pub models: Vec<String>,
/// Per-device rows, for the topology view. Sharing devices first.
@@ -87,6 +99,10 @@ pub struct MeshSnapshot {
/// note, so their hardware is unknown by design — they never consented to
/// disclose it. Ghost nodes in the topology are a count, never GB.
pub member_count: usize,
/// When this projection was evaluated, in Unix seconds.
pub observed_at: u64,
/// Maximum age of a relay-reported serving status.
pub freshness_seconds: u64,
/// Why the snapshot is empty, when it is. Never a hard error: an empty
/// mesh is a normal, expected state.
pub reason: Option<String>,
@@ -95,6 +111,8 @@ pub struct MeshSnapshot {
impl MeshSnapshot {
fn empty(reason: impl Into<String>) -> Self {
Self {
observed_at: nostr::Timestamp::now().as_secs(),
freshness_seconds: STATUS_FRESHNESS_SECS,
reason: Some(reason.into()),
..Default::default()
}
@@ -204,6 +222,9 @@ pub fn snapshot_from_events(
state: device_state(&content, !models.is_empty()),
models,
is_self,
member_pubkey: Some(event.pubkey.to_hex()),
reported_at: Some(event.created_at.as_secs()),
model_size_gb: f64_field(&content, "model_size_gb"),
},
);
}
@@ -224,6 +245,11 @@ pub fn snapshot_from_events(
.filter(|device| device.state == MeshDeviceState::Serving)
.collect::<Vec<_>>();
let sharing_device_count = sharing.len();
let contributor_member_count = sharing
.iter()
.filter_map(|device| device.member_pubkey.as_ref())
.collect::<std::collections::BTreeSet<_>>()
.len();
let includes_self = sharing.iter().any(|device| device.is_self);
// Sum only reported figures; keep `None` when nobody reported one so the
// UI can drop the number instead of printing `0 GB`.
@@ -231,6 +257,14 @@ pub fn snapshot_from_events(
.iter()
.filter_map(|device| device.capacity_gb)
.fold(None::<f64>, |acc, gb| Some(acc.unwrap_or(0.0) + gb));
let allocated_capacity_gb = (!sharing.is_empty()
&& sharing.iter().all(|device| device.model_size_gb.is_some()))
.then(|| {
sharing
.iter()
.filter_map(|device| device.model_size_gb)
.sum()
});
let mut models = sharing
.iter()
.flat_map(|device| device.models.iter().cloned())
@@ -246,11 +280,15 @@ pub fn snapshot_from_events(
MeshSnapshot {
member_count: members.len(),
contributor_member_count,
sharing_device_count,
shared_capacity_gb,
allocated_capacity_gb,
models,
devices,
includes_self,
observed_at: now,
freshness_seconds: STATUS_FRESHNESS_SECS,
reason,
}
}
@@ -265,6 +303,8 @@ mod tests {
assert_eq!(snapshot.sharing_device_count, 0);
assert_eq!(snapshot.shared_capacity_gb, None);
assert!(snapshot.reason.is_some());
assert_eq!(snapshot.freshness_seconds, STATUS_FRESHNESS_SECS);
assert!(snapshot.observed_at > 0);
}
#[test]

View File

@@ -0,0 +1,234 @@
import type {
CommunityComputeDeviceInput,
CommunityComputeSnapshotInput,
} from "./communityComputeMapModel";
export type CommunityComputeTutorialFixtureId =
| "empty"
| "single-device"
| "small-company"
| "large-dense-500";
export type CommunityComputeTutorialFixture = {
id: CommunityComputeTutorialFixtureId;
title: string;
description: string;
snapshot: CommunityComputeSnapshotInput;
};
const MODEL_REFS = [
"unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q4_K_M",
"Qwen/Qwen3.5-35B-A3B-GGUF:Q4_K_M",
"mistralai/Ministral-3-14B-Instruct-GGUF:Q4_K_M",
"bartowski/Llama-3.3-70B-Instruct-GGUF:Q4_K_M",
] as const;
export const EMPTY_COMMUNITY_COMPUTE_FIXTURE: CommunityComputeTutorialFixture =
{
id: "empty",
title: "New community",
description: "No member has shared compute yet.",
snapshot: {
sharingDeviceCount: 0,
contributorMemberCount: 0,
sharedCapacityGb: null,
allocatedCapacityGb: null,
models: [],
devices: [],
includesSelf: false,
memberCount: 8,
reason: "No sharing devices found",
},
};
export const SINGLE_DEVICE_COMMUNITY_COMPUTE_FIXTURE: CommunityComputeTutorialFixture =
{
id: "single-device",
title: "First deployment",
description: "One member is sharing a single workstation.",
snapshot: snapshotFromDevices(
[
device({
index: 0,
id: "studio-workstation",
label: "Morgan’s Studio",
capacityGb: 24,
modelSizeGb: 18,
isSelf: true,
}),
],
1,
),
};
export const SMALL_COMPANY_COMMUNITY_COMPUTE_FIXTURE: CommunityComputeTutorialFixture =
{
id: "small-company",
title: "Small company",
description: "A mixed fleet across a small distributed team.",
snapshot: snapshotFromDevices(
[
...[
{ capacityGb: 24, modelSizeGb: 18 },
{ capacityGb: 24, modelSizeGb: 18 },
{ capacityGb: 36, modelSizeGb: 28 },
{ capacityGb: 36, modelSizeGb: 28 },
{ capacityGb: 48, modelSizeGb: 36 },
{ capacityGb: 48, modelSizeGb: 36 },
{ capacityGb: 64, modelSizeGb: 48 },
{ capacityGb: 64, modelSizeGb: 48 },
{ capacityGb: 96, modelSizeGb: 72 },
{ capacityGb: 96, modelSizeGb: 72 },
].map(({ capacityGb, modelSizeGb }, index) =>
device({
index,
id: `team-macbook-${String(index + 1).padStart(2, "0")}`,
label: `Team MacBook ${String(index + 1).padStart(2, "0")}`,
capacityGb,
modelSizeGb,
isSelf: index === 0,
}),
),
device({
index: 10,
id: "intensive-model-host-a",
label: "Intensive model host A",
capacityGb: 768,
modelRef: "unsloth/Kimi-K2-Thinking-GGUF:UD-Q4_K_XL",
modelSizeGb: 646,
}),
device({
index: 11,
id: "intensive-model-host-b",
label: "Intensive model host B",
capacityGb: 1_440,
modelRef: "unsloth/DeepSeek-V3.2-GGUF:UD-Q4_K_XL",
modelSizeGb: 1_000,
}),
],
24,
),
};
/** Deterministic stress fixture using only the production snapshot contract. */
export const LARGE_DENSE_COMMUNITY_COMPUTE_FIXTURE: CommunityComputeTutorialFixture =
{
id: "large-dense-500",
title: "Large company",
description:
"Five hundred deterministic reporting devices for density testing.",
snapshot: createLargeDenseSnapshot(500),
};
export const COMMUNITY_COMPUTE_TUTORIAL_FIXTURES: Readonly<
Record<CommunityComputeTutorialFixtureId, CommunityComputeTutorialFixture>
> = {
empty: EMPTY_COMMUNITY_COMPUTE_FIXTURE,
"single-device": SINGLE_DEVICE_COMMUNITY_COMPUTE_FIXTURE,
"small-company": SMALL_COMPANY_COMMUNITY_COMPUTE_FIXTURE,
"large-dense-500": LARGE_DENSE_COMMUNITY_COMPUTE_FIXTURE,
};
export function createLargeDenseSnapshot(
deviceCount = 500,
): CommunityComputeSnapshotInput {
const count = Math.max(0, Math.floor(deviceCount));
const capacities = [8, 16, 24, 32, 48, 64, 96, 128] as const;
const devices = Array.from({ length: count }, (_, index) => {
const capacityGb = capacities[index % capacities.length];
const state =
index % 41 === 0 ? "loading" : index % 17 === 0 ? "standby" : "serving";
const largeIndex = [49, 149, 249, 349, 449, 499].indexOf(index);
const largeSizes = [170, 230, 350, 480, 700, 1_000] as const;
const largeCapacities = [192, 256, 384, 512, 768, 1_440] as const;
const modelSizeGb =
largeIndex >= 0
? largeSizes[largeIndex]
: roundCapacity(capacityGb * 0.72);
return device({
index,
id: `dense-device-${String(index + 1).padStart(4, "0")}`,
label:
largeIndex >= 0
? `${largeCapacities[largeIndex]} GB model host`
: `Compute ${String(index + 1).padStart(4, "0")}`,
capacityGb: largeIndex >= 0 ? largeCapacities[largeIndex] : capacityGb,
modelRef:
largeIndex >= 0
? `community/Large-${modelSizeGb}GB-Instruct:FP8`
: undefined,
modelSizeGb,
state,
models: state === "serving" ? undefined : [],
isSelf: index === 0,
});
});
return snapshotFromDevices(devices, Math.ceil(count * 1.37));
}
type DeviceOptions = {
index: number;
id: string;
label: string;
capacityGb: number;
modelRef?: string;
modelSizeGb?: number;
models?: string[];
state?: CommunityComputeDeviceInput["state"];
isSelf?: boolean;
};
function device(options: DeviceOptions): CommunityComputeDeviceInput {
const model =
options.modelRef ?? MODEL_REFS[options.index % MODEL_REFS.length];
return {
deviceId: options.id,
label: options.label,
capacityGb: options.capacityGb,
models: options.models ?? [model],
state: options.state ?? "serving",
isSelf: options.isSelf ?? false,
memberPubkey: `tutorial-member-${String(options.index + 1).padStart(4, "0")}`,
reportedAt: 1_786_032_000,
modelSizeGb: options.modelSizeGb ?? null,
};
}
function roundCapacity(value: number): number {
return Math.round(value * 10) / 10;
}
function snapshotFromDevices(
devices: CommunityComputeDeviceInput[],
memberCount: number,
): CommunityComputeSnapshotInput {
const serving = devices.filter(
(item) => item.state === "serving" && item.models.length > 0,
);
const models = [...new Set(serving.flatMap((item) => item.models))].sort();
const sharedCapacityGb = completeSum(serving.map((item) => item.capacityGb));
const allocatedCapacityGb = completeSum(
serving.map((item) => item.modelSizeGb ?? null),
);
return {
sharingDeviceCount: serving.length,
contributorMemberCount: new Set(
serving.map((item) => item.memberPubkey ?? item.deviceId),
).size,
sharedCapacityGb,
allocatedCapacityGb,
models,
devices,
includesSelf: serving.some((item) => item.isSelf),
memberCount,
observedAt: 1_786_032_000,
freshnessSeconds: 120,
reason: serving.length === 0 ? "No sharing devices found" : null,
};
}
function completeSum(values: readonly (number | null)[]): number | null {
return values.length > 0 && values.every((value) => value !== null)
? values.reduce<number>((total, value) => total + (value ?? 0), 0)
: null;
}

View File

@@ -0,0 +1,358 @@
import assert from "node:assert/strict";
import test from "node:test";
import {
hexCoordinateKey,
hexDistance,
hexNeighbours,
hexTerritoryBoundaryEdges,
hexTerritoryInteriorEdges,
isContiguousHexTerritory,
layoutCommunityComputeHexTerritories,
} from "./communityComputeHexLayout.ts";
import { LARGE_DENSE_COMMUNITY_COMPUTE_FIXTURE } from "./communityComputeFixtures.ts";
import { deriveCommunityComputeMapModel } from "./communityComputeMapModel.ts";
function assertStructuralInvariants(layout) {
const occupied = new Set(layout.cells.map(hexCoordinateKey));
assert.equal(occupied.size, layout.cells.length, "cells must not overlap");
assert.ok(
layout.territories.every((territory) =>
isContiguousHexTerritory(territory.cells),
),
"every territory must be contiguous",
);
if (layout.cells.length > 0) {
const reached = new Set([hexCoordinateKey(layout.cells[0])]);
const queue = [layout.cells[0]];
for (let cursor = 0; cursor < queue.length; cursor += 1) {
for (const neighbour of hexNeighbours(queue[cursor])) {
const key = hexCoordinateKey(neighbour);
if (occupied.has(key) && !reached.has(key)) {
reached.add(key);
queue.push(neighbour);
}
}
}
assert.equal(
reached.size,
occupied.size,
"occupied mesh must be connected",
);
}
}
function organicGaps(layout) {
const occupied = new Set(layout.cells.map(hexCoordinateKey));
const empty = new Map();
for (const cell of layout.cells) {
for (const neighbour of hexNeighbours(cell)) {
const key = hexCoordinateKey(neighbour);
if (!occupied.has(key)) empty.set(key, neighbour);
}
}
return [...empty.values()].filter(
(cell) =>
hexNeighbours(cell).filter((neighbour) =>
occupied.has(hexCoordinateKey(neighbour)),
).length >= 2,
);
}
function assertBalancedSparseFrontier(layout, deploymentCount) {
const points = layout.cells.map((cell) => ({
x: Math.sqrt(3) * (cell.q + cell.r / 2),
y: 1.5 * cell.r,
}));
const width =
Math.max(...points.map(({ x }) => x)) -
Math.min(...points.map(({ x }) => x)) +
Math.sqrt(3);
const height =
Math.max(...points.map(({ y }) => y)) -
Math.min(...points.map(({ y }) => y)) +
2;
const aspectRatio = width / height;
assert.ok(
aspectRatio >= 0.8 && aspectRatio <= 1.3,
`${deploymentCount} deployments have unbalanced aspect ratio ${aspectRatio}`,
);
const radius = Math.max(
...layout.cells.map((cell) => hexDistance(cell, { q: 0, r: 0 })),
);
const directionalRadii = Array(6).fill(0);
for (const cell of layout.cells) {
const projections = [
cell.q,
-cell.r,
-cell.q - cell.r,
-cell.q,
cell.r,
cell.q + cell.r,
];
for (const [index, projection] of projections.entries()) {
directionalRadii[index] = Math.max(directionalRadii[index], projection);
}
}
assert.ok(
Math.max(...directionalRadii) - Math.min(...directionalRadii) <= 2,
`${deploymentCount} deployments must reach every side evenly`,
);
const outerOccupancy =
layout.cells.filter((cell) => hexDistance(cell, { q: 0, r: 0 }) === radius)
.length /
(6 * radius);
assert.ok(
outerOccupancy >= 0.1 && outerOccupancy <= 0.55,
`${deploymentCount} deployments need a sparse, notched outer edge (${outerOccupancy})`,
);
}
function deployments(count) {
const buckets = [1, 2, 4, 7];
return Array.from({ length: count }, (_, index) => ({
id: `deployment-${String(index + 1).padStart(4, "0")}`,
cellCount: buckets[index % buckets.length],
}));
}
test("layout is deterministic and independent of input order", () => {
const input = deployments(80);
const first = layoutCommunityComputeHexTerritories(input);
const second = layoutCommunityComputeHexTerritories([...input].reverse());
assert.deepEqual(first, second);
});
test("growing layouts stay balanced with sparse outer frontiers", () => {
for (const count of [24, 250, 1_000]) {
const layout = layoutCommunityComputeHexTerritories(deployments(count));
assertStructuralInvariants(layout);
assertBalancedSparseFrontier(layout, count);
assert.ok(
organicGaps(layout).length > 0,
`${count} deployments should leave deterministic pockets or edge gaps`,
);
}
});
test("canonical territory order remains stable when previous placement is reused", () => {
const input = deployments(60);
const initial = layoutCommunityComputeHexTerritories(input);
const next = layoutCommunityComputeHexTerritories([...input].reverse(), {
previous: initial,
});
assert.deepEqual(
next.territories.map(({ deploymentId }) => deploymentId),
initial.territories.map(({ deploymentId }) => deploymentId),
);
});
test("payload changes preserve positions because IDs own the slots", () => {
const initial = deployments(40);
const changed = initial.map((deployment) => ({
...deployment,
label: `Changed ${deployment.id}`,
health: "degraded",
}));
assert.deepEqual(
layoutCommunityComputeHexTerritories(initial),
layoutCommunityComputeHexTerritories(changed),
);
});
test("surviving IDs keep positions as deployments are added and removed", () => {
const initialInput = deployments(40);
const initial = layoutCommunityComputeHexTerritories(initialInput);
const nextInput = [
...initialInput.filter((_, index) => index % 4 !== 0),
...deployments(6).map((item, index) => ({
...item,
id: `new-deployment-${index}`,
})),
];
const next = layoutCommunityComputeHexTerritories(nextInput, {
previous: initial,
});
const initialCenters = new Map(
initial.territories.map((territory) => [
territory.deploymentId,
territory.center,
]),
);
for (const territory of next.territories) {
const oldCenter = initialCenters.get(territory.deploymentId);
if (oldCenter !== undefined) {
assert.deepEqual(territory.center, oldCenter);
}
}
assert.equal(
new Set(next.cells.map(hexCoordinateKey)).size,
next.cells.length,
);
});
test("every supported territory shape is contiguous", () => {
const layout = layoutCommunityComputeHexTerritories([
{ id: "one", cellCount: 1 },
{ id: "two", cellCount: 2 },
{ id: "four", cellCount: 4 },
{ id: "seven", cellCount: 7 },
]);
const expected = new Map([
["one", 1],
["two", 2],
["four", 4],
["seven", 7],
]);
for (const territory of layout.territories) {
assert.equal(territory.cells.length, expected.get(territory.deploymentId));
assert.ok(
isContiguousHexTerritory(territory.cells),
`${territory.deploymentId} must be contiguous`,
);
}
});
test("fused boundaries omit interior edges for 1, 2, 4, and 7 cells", () => {
const shapes = [
[{ q: 0, r: 0 }],
[
{ q: 0, r: 0 },
{ q: 1, r: 0 },
],
[
{ q: 0, r: 0 },
{ q: 1, r: 0 },
{ q: 1, r: -1 },
{ q: 0, r: -1 },
],
[{ q: 0, r: 0 }, ...hexNeighbours({ q: 0, r: 0 })],
];
for (const [index, cells] of shapes.entries()) {
const sharedPairs =
cells.reduce(
(total, cell) =>
total +
hexNeighbours(cell).filter((neighbour) =>
cells.some(
(candidate) =>
hexCoordinateKey(candidate) === hexCoordinateKey(neighbour),
),
).length,
0,
) / 2;
const boundary = hexTerritoryBoundaryEdges(cells);
assert.equal(boundary.length, 6 * cells.length - 2 * sharedPairs);
const endpointDegree = new Map();
for (const edge of boundary) {
assert.notDeepEqual(edge.start, edge.end);
for (const point of [edge.start, edge.end]) {
const key = `${point.x.toFixed(8)},${point.y.toFixed(8)}`;
endpointDegree.set(key, (endpointDegree.get(key) ?? 0) + 1);
}
}
assert.ok(
[...endpointDegree.values()].every((degree) => degree === 2),
`shape ${index} boundary must form closed loops without dangling edges`,
);
}
const edgeKey = (edge) =>
[edge.start, edge.end]
.map((point) => `${point.x.toFixed(8)},${point.y.toFixed(8)}`)
.sort()
.join("|");
assert.deepEqual(
hexTerritoryBoundaryEdges(shapes[3]).map(edgeKey).sort(),
hexTerritoryBoundaryEdges([...shapes[3]].reverse())
.map(edgeKey)
.sort(),
"edge membership must not depend on cell order",
);
});
test("interior edges contain each shared device boundary exactly once", () => {
const cells = [{ q: 0, r: 0 }, ...hexNeighbours({ q: 0, r: 0 })];
const interior = hexTerritoryInteriorEdges(cells);
const edgeKey = (edge) =>
[edge.start, edge.end]
.map((point) => `${point.x.toFixed(8)},${point.y.toFixed(8)}`)
.sort()
.join("|");
assert.equal(interior.length, 12);
assert.equal(new Set(interior.map(edgeKey)).size, interior.length);
assert.deepEqual(
interior.map(edgeKey).sort(),
hexTerritoryInteriorEdges([...cells].reverse())
.map(edgeKey)
.sort(),
"shared edge membership must not depend on cell order",
);
assert.deepEqual(hexTerritoryInteriorEdges([{ q: 0, r: 0 }]), []);
});
test("territories never emit duplicate occupied cells", () => {
const layout = layoutCommunityComputeHexTerritories(deployments(250));
const coordinates = layout.cells.map(hexCoordinateKey);
assert.equal(new Set(coordinates).size, coordinates.length);
assert.equal(
new Set(layout.cells.map((cell) => cell.id)).size,
layout.cells.length,
);
});
test("duplicate deployment IDs are rejected rather than overlapped", () => {
assert.throws(
() =>
layoutCommunityComputeHexTerritories([
{ id: "same", cellCount: 1 },
{ id: "same", cellCount: 7 },
]),
/Duplicate community compute deployment ID: same/,
);
});
test("empty layout has no fabricated bounds", () => {
assert.deepEqual(layoutCommunityComputeHexTerritories([]), {
territories: [],
cells: [],
bounds: null,
});
});
test("500-deployment fixture lays out uniquely and contiguously", () => {
const model = deriveCommunityComputeMapModel(
LARGE_DENSE_COMMUNITY_COMPUTE_FIXTURE.snapshot,
);
const input = model.deployments.map(({ id, cellCount }) => ({
id,
cellCount,
}));
const layout = layoutCommunityComputeHexTerritories(input);
assert.equal(layout.territories.length, model.deployments.length);
assert.equal(
layout.cells.length,
model.deployments.reduce(
(total, deployment) => total + deployment.cellCount,
0,
),
);
assert.equal(
new Set(layout.cells.map(hexCoordinateKey)).size,
layout.cells.length,
);
assert.ok(
layout.territories.every((territory) =>
isContiguousHexTerritory(territory.cells),
),
);
assert.ok(layout.bounds !== null);
});

View File

@@ -0,0 +1,448 @@
import type { HexCellCount } from "./communityComputeMapModel";
/** Axial coordinates for a pointy-top hex grid. */
export type HexCoordinate = {
q: number;
r: number;
};
/** Cartesian point in pointy-top hex geometry. */
export type HexPoint = {
x: number;
y: number;
};
/** One exposed side of a fused hex territory boundary. */
export type HexBoundaryEdge = {
start: HexPoint;
end: HexPoint;
};
export type CommunityComputeLayoutInput = {
id: string;
cellCount: HexCellCount;
};
export type CommunityComputeHexCell = HexCoordinate & {
id: string;
deploymentId: string;
index: number;
};
export type CommunityComputeHexTerritory = {
deploymentId: string;
center: HexCoordinate;
cells: readonly CommunityComputeHexCell[];
};
export type CommunityComputeHexBounds = {
minQ: number;
maxQ: number;
minR: number;
maxR: number;
};
export type CommunityComputeHexLayout = {
territories: readonly CommunityComputeHexTerritory[];
cells: readonly CommunityComputeHexCell[];
bounds: CommunityComputeHexBounds | null;
};
export type CommunityComputeHexLayoutOptions = {
/**
* Reuse centres for IDs that are still present. Supplying the last layout
* keeps a live map steady while deployments arrive, leave, or change size.
*/
previous?: CommunityComputeHexLayout | null;
};
const HEX_DIRECTIONS: readonly HexCoordinate[] = [
{ q: 1, r: 0 },
{ q: 1, r: -1 },
{ q: 0, r: -1 },
{ q: -1, r: 0 },
{ q: -1, r: 1 },
{ q: 0, r: 1 },
];
/**
* Lay deployments out as one organic, edge-connected honeycomb.
*
* Input order never affects the result. Stable hashes choose territory
* orientation, while a deterministic low-discrepancy permutation spreads each
* ring's placements around the whole current frontier. Completed inner rings
* remain dense; only the growing outer layers carry deliberate notches. With a
* previous layout, collision-free surviving shapes retain their exact cells;
* new shapes take the first non-overlapping frontier position that shares an
* edge with the occupied mesh.
*/
export function layoutCommunityComputeHexTerritories(
deployments: readonly CommunityComputeLayoutInput[],
options: CommunityComputeHexLayoutOptions = {},
): CommunityComputeHexLayout {
const seenIds = new Set<string>();
for (const deployment of deployments) {
if (seenIds.has(deployment.id)) {
throw new Error(
`Duplicate community compute deployment ID: ${deployment.id}`,
);
}
seenIds.add(deployment.id);
}
const ordered = [...deployments].sort(
(left, right) =>
stableHash(left.id) - stableHash(right.id) ||
left.id.localeCompare(right.id),
);
// Previous cells are retained only when they remain collision-free. New
// territories search the compact spiral for the first candidate that both
// fits and touches the occupied frontier.
const previousById = new Map(
(options.previous?.territories ?? []).map((territory) => [
territory.deploymentId,
territory,
]),
);
const retainableIds = connectedRetainedTerritoryIds(ordered, previousById);
const occupied = new Set<string>();
const territories: CommunityComputeHexTerritory[] = [];
const placementOrder = [...ordered].sort(
(left, right) =>
Number(retainableIds.has(right.id)) -
Number(retainableIds.has(left.id)) ||
ordered.indexOf(left) - ordered.indexOf(right),
);
for (const deployment of placementOrder) {
const previous = retainableIds.has(deployment.id)
? previousById.get(deployment.id)
: undefined;
const retained =
previous?.cells.length === deployment.cellCount
? previous.cells.map(({ q, r }) => ({ q, r }))
: null;
const retainedFits = retained?.every(
(cell) => !occupied.has(hexCoordinateKey(cell)),
);
const orientation = stableHash(`${deployment.id}:orientation`) % 6;
let center = retainedFits ? previous?.center : undefined;
let coordinates = retainedFits ? retained : null;
if (!coordinates || !center) {
for (let slot = 0; ; slot += 1) {
const candidate = balancedSpiralCoordinate(slot);
const offsets = territoryOffsets(deployment.cellCount, orientation);
const candidateCells = offsets.map((offset) => ({
q: candidate.q + offset.q,
r: candidate.r + offset.r,
}));
const fits = candidateCells.every(
(cell) => !occupied.has(hexCoordinateKey(cell)),
);
const touches =
occupied.size === 0 ||
candidateCells.some((cell) =>
hexNeighbours(cell).some((neighbour) =>
occupied.has(hexCoordinateKey(neighbour)),
),
);
if (fits && touches) {
center = candidate;
coordinates = candidateCells;
break;
}
}
}
const cells = coordinates.map(({ q, r }, index) => {
occupied.add(hexCoordinateKey({ q, r }));
return {
id: `${deployment.id}@${q},${r}`,
deploymentId: deployment.id,
index,
q,
r,
};
});
territories.push({ deploymentId: deployment.id, center, cells });
}
territories.sort(
(left, right) =>
ordered.findIndex((item) => item.id === left.deploymentId) -
ordered.findIndex((item) => item.id === right.deploymentId),
);
const cells = territories.flatMap((territory) => territory.cells);
return { territories, cells, bounds: findBounds(cells) };
}
/** The six axial neighbours of a cell, in stable clockwise order. */
export function hexNeighbours(coordinate: HexCoordinate): HexCoordinate[] {
return HEX_DIRECTIONS.map((direction) => ({
q: coordinate.q + direction.q,
r: coordinate.r + direction.r,
}));
}
/**
* Return only the exposed unit-hex sides of a territory.
*
* Coordinates use pointy-top axial geometry. Shared sides are omitted, so the
* result can be stroked as one fused territory rather than as overlapping
* individual hexagons. Edge direction is stable and follows each cell's
* perimeter; callers may chain matching endpoints when an ordered path is
* required.
*/
export function hexTerritoryBoundaryEdges(
cells: readonly HexCoordinate[],
): HexBoundaryEdge[] {
const occupied = new Set(cells.map(hexCoordinateKey));
const edges: HexBoundaryEdge[] = [];
for (const cell of cells) {
for (let direction = 0; direction < HEX_DIRECTIONS.length; direction += 1) {
const neighbour = {
q: cell.q + HEX_DIRECTIONS[direction].q,
r: cell.r + HEX_DIRECTIONS[direction].r,
};
if (!occupied.has(hexCoordinateKey(neighbour))) {
edges.push(hexEdge(cell, direction));
}
}
}
return edges;
}
/**
* Return each side shared by two cells in a territory exactly once.
*
* Fused model territories do not render these edges. Split deployments use
* them to show the device boundaries without drawing inset outlines around
* every cell or accidentally doubling a shared stroke.
*/
export function hexTerritoryInteriorEdges(
cells: readonly HexCoordinate[],
): HexBoundaryEdge[] {
const occupied = new Set(cells.map(hexCoordinateKey));
const edges: HexBoundaryEdge[] = [];
for (const cell of cells) {
const cellKey = hexCoordinateKey(cell);
for (let direction = 0; direction < HEX_DIRECTIONS.length; direction += 1) {
const neighbour = {
q: cell.q + HEX_DIRECTIONS[direction].q,
r: cell.r + HEX_DIRECTIONS[direction].r,
};
const neighbourKey = hexCoordinateKey(neighbour);
if (occupied.has(neighbourKey) && cellKey < neighbourKey) {
edges.push(hexEdge(cell, direction));
}
}
}
return edges;
}
function hexEdge(cell: HexCoordinate, direction: number): HexBoundaryEdge {
const center = {
x: Math.sqrt(3) * (cell.q + cell.r / 2),
y: 1.5 * cell.r,
};
const corners = Array.from({ length: 6 }, (_, index) => {
const angle = ((-30 + index * 60) * Math.PI) / 180;
return {
x: normalizeHexPointComponent(center.x + Math.cos(angle)),
y: normalizeHexPointComponent(center.y + Math.sin(angle)),
};
});
return {
start: corners[(6 - direction) % 6],
end: corners[(7 - direction) % 6],
};
}
function normalizeHexPointComponent(value: number): number {
return Math.abs(value) < Number.EPSILON * 8 ? 0 : value;
}
/** Axial hex distance, useful to consumers for borders and transitions. */
export function hexDistance(left: HexCoordinate, right: HexCoordinate): number {
const dq = left.q - right.q;
const dr = left.r - right.r;
return Math.max(Math.abs(dq), Math.abs(dr), Math.abs(dq + dr));
}
/** True when every cell can be reached from every other through shared edges. */
export function isContiguousHexTerritory(
cells: readonly HexCoordinate[],
): boolean {
if (cells.length === 0) {
return false;
}
const remaining = new Set(cells.map(hexCoordinateKey));
const queue: HexCoordinate[] = [cells[0]];
remaining.delete(hexCoordinateKey(cells[0]));
for (let cursor = 0; cursor < queue.length; cursor += 1) {
for (const neighbour of hexNeighbours(queue[cursor])) {
const key = hexCoordinateKey(neighbour);
if (remaining.delete(key)) {
queue.push(neighbour);
}
}
}
return remaining.size === 0;
}
export function hexCoordinateKey(coordinate: HexCoordinate): string {
return `${coordinate.q},${coordinate.r}`;
}
/** Keep only the edge-connected component of valid surviving territories. */
function connectedRetainedTerritoryIds(
ordered: readonly CommunityComputeLayoutInput[],
previousById: ReadonlyMap<string, CommunityComputeHexTerritory>,
): Set<string> {
const valid = ordered
.map((deployment) => previousById.get(deployment.id))
.filter(
(territory): territory is CommunityComputeHexTerritory =>
territory !== undefined &&
territory.cells.length ===
ordered.find((item) => item.id === territory.deploymentId)?.cellCount,
);
if (valid.length === 0) return new Set();
const owner = new Map<string, string>();
for (const territory of valid) {
for (const cell of territory.cells) {
const key = hexCoordinateKey(cell);
if (owner.has(key)) return new Set();
owner.set(key, territory.deploymentId);
}
}
const retained = new Set([valid[0].deploymentId]);
const queue = [valid[0].deploymentId];
const byId = new Map(
valid.map((territory) => [territory.deploymentId, territory]),
);
for (let cursor = 0; cursor < queue.length; cursor += 1) {
const territory = byId.get(queue[cursor]);
if (!territory) continue;
for (const cell of territory.cells) {
for (const neighbour of hexNeighbours(cell)) {
const neighbourOwner = owner.get(hexCoordinateKey(neighbour));
if (neighbourOwner && !retained.has(neighbourOwner)) {
retained.add(neighbourOwner);
queue.push(neighbourOwner);
}
}
}
}
return retained;
}
function territoryOffsets(
count: HexCellCount,
orientation: number,
): HexCoordinate[] {
const center = { q: 0, r: 0 };
if (count === 1) {
return [center];
}
if (count === 2) {
return [center, HEX_DIRECTIONS[orientation]];
}
if (count === 4) {
return [
center,
HEX_DIRECTIONS[orientation],
HEX_DIRECTIONS[(orientation + 1) % 6],
HEX_DIRECTIONS[(orientation + 2) % 6],
];
}
return [center, ...HEX_DIRECTIONS];
}
/**
* Zero-based spiral slot: origin, then complete radius-one, radius-two, … rings.
* Runtime is O(radius), which is O(sqrt(n)); even at dense fixture sizes the
* largest radius remains small.
*/
function balancedSpiralCoordinate(index: number): HexCoordinate {
if (index === 0) {
return { q: 0, r: 0 };
}
let radius = 1;
let ringStart = 1;
while (index >= ringStart + 6 * radius) {
ringStart += 6 * radius;
radius += 1;
}
const ringLength = 6 * radius;
const ringIndex = index - ringStart;
// Multiplication by a number coprime with the ring length is a permutation,
// not sampling: every slot is eventually visited. A step near half a ring
// alternates opposite sides, preventing a partially filled layer from
// producing the one-sided growth of a clockwise spiral.
let step = Math.max(1, Math.floor(ringLength / 2) - 1);
while (greatestCommonDivisor(step, ringLength) !== 1) step -= 1;
const offsetSeed = stableHash(`ring:${radius}`) % ringLength;
let offset = (offsetSeed + ringIndex * step) % ringLength;
let coordinate = { q: -radius, r: radius };
for (const direction of HEX_DIRECTIONS) {
const steps = Math.min(radius, offset);
coordinate = {
q: coordinate.q + direction.q * steps,
r: coordinate.r + direction.r * steps,
};
offset -= steps;
if (offset === 0) {
break;
}
}
return coordinate;
}
function greatestCommonDivisor(left: number, right: number): number {
let a = left;
let b = right;
while (b !== 0) {
const remainder = a % b;
a = b;
b = remainder;
}
return a;
}
function findBounds(
cells: readonly HexCoordinate[],
): CommunityComputeHexBounds | null {
if (cells.length === 0) {
return null;
}
let minQ = cells[0].q;
let maxQ = cells[0].q;
let minR = cells[0].r;
let maxR = cells[0].r;
for (const cell of cells.slice(1)) {
minQ = Math.min(minQ, cell.q);
maxQ = Math.max(maxQ, cell.q);
minR = Math.min(minR, cell.r);
maxR = Math.max(maxR, cell.r);
}
return { minQ, maxQ, minR, maxR };
}
/** FNV-1a over UTF-16 code units; deterministic on every JS runtime. */
function stableHash(value: string): number {
let hash = 0x811c9dc5;
for (let index = 0; index < value.length; index += 1) {
hash ^= value.charCodeAt(index);
hash = Math.imul(hash, 0x01000193);
}
return hash >>> 0;
}

View File

@@ -0,0 +1,206 @@
import assert from "node:assert/strict";
import test from "node:test";
import {
bucketHexCellCount,
capacityGbToHexCellCount,
deriveCommunityComputeMapModel,
} from "./communityComputeMapModel.ts";
import {
COMMUNITY_COMPUTE_TUTORIAL_FIXTURES,
LARGE_DENSE_COMMUNITY_COMPUTE_FIXTURE,
createLargeDenseSnapshot,
} from "./communityComputeFixtures.ts";
function device(overrides = {}) {
return {
deviceId: "device-1",
label: "Studio",
capacityGb: 32,
models: ["gemma"],
state: "serving",
isSelf: false,
memberPubkey: "member-1",
reportedAt: 1_786_032_000,
modelSizeGb: 18,
...overrides,
};
}
function snapshot(overrides = {}) {
return {
sharingDeviceCount: 1,
contributorMemberCount: 1,
sharedCapacityGb: 32,
allocatedCapacityGb: 18,
models: ["gemma"],
devices: [device()],
includesSelf: false,
memberCount: 4,
reason: null,
...overrides,
};
}
test("cell buckets are exactly 1, 2, 4, and 7", () => {
assert.deepEqual(
[-1, 1, 1.1, 2, 2.1, 4, 4.1, 999, Number.NaN].map(bucketHexCellCount),
[1, 1, 2, 2, 4, 4, 7, 7, 1],
);
assert.deepEqual(
[null, 128, 128.1, 256, 256.1, 512, 512.1, 1000].map(
capacityGbToHexCellCount,
),
[1, 1, 2, 2, 4, 4, 7, 7],
);
});
test("only ready serving models become deployments", () => {
const model = deriveCommunityComputeMapModel(
snapshot({
sharingDeviceCount: 1,
devices: [
device({ deviceId: "a", models: ["gemma", "qwen"] }),
device({ deviceId: "b", state: "loading", models: [] }),
device({ deviceId: "c", state: "standby", models: [] }),
device({ deviceId: "d", state: "consuming", models: [] }),
],
}),
);
assert.equal(model.status, "ready");
assert.deepEqual(
model.deployments.map((deployment) => deployment.modelId),
["gemma", "qwen"],
);
assert.equal(model.kpis.deploymentCount, 2);
assert.equal(model.kpis.contributorMemberCount, 1);
assert.equal(model.health.counts.healthy, 1);
assert.equal(model.health.counts.warming, 1);
assert.equal(model.health.counts.idle, 1);
});
test("one territory is produced per model and per device replica", () => {
const model = deriveCommunityComputeMapModel(
snapshot({
devices: [
device({ deviceId: "a", models: ["qwen", "gemma"] }),
device({ deviceId: "b", memberPubkey: "member-2", models: ["gemma"] }),
],
}),
);
assert.equal(model.deployments.length, 3);
assert.equal(
model.deployments.filter((deployment) => deployment.modelId === "gemma")
.length,
2,
);
assert.equal(new Set(model.deployments.map(({ id }) => id)).size, 3);
});
test("reported model footprint controls area without fixture overrides", () => {
const model = deriveCommunityComputeMapModel(
snapshot({ devices: [device({ capacityGb: 768, modelSizeGb: 96 })] }),
);
assert.equal(model.deployments[0].cellCount, 1);
const large = deriveCommunityComputeMapModel(
snapshot({ devices: [device({ capacityGb: 768, modelSizeGb: 646 })] }),
);
assert.equal(large.deployments[0].cellCount, 7);
});
test("loading, consumer-only, and empty snapshots render no territories", () => {
for (const state of ["loading", "standby", "consuming"]) {
const model = deriveCommunityComputeMapModel(
snapshot({ devices: [device({ state, models: [] })] }),
);
assert.equal(model.status, "empty");
assert.equal(model.deployments.length, 0);
}
assert.equal(deriveCommunityComputeMapModel(null).status, "loading");
assert.equal(
deriveCommunityComputeMapModel(
COMMUNITY_COMPUTE_TUTORIAL_FIXTURES.empty.snapshot,
).status,
"empty",
);
});
test("projection is deterministic and independent of device/model order", () => {
const devices = [
device({ deviceId: "z", label: "Zulu", models: ["qwen", "gemma"] }),
device({ deviceId: "a", label: "Alpha", models: ["mistral"] }),
];
const forward = deriveCommunityComputeMapModel(snapshot({ devices }));
const reverse = deriveCommunityComputeMapModel(
snapshot({
devices: [...devices]
.reverse()
.map((item) => ({ ...item, models: [...item.models].reverse() })),
}),
);
assert.deepEqual(forward, reverse);
});
test("tutorial fixtures use only production fields and production sizing", () => {
assert.deepEqual(Object.keys(COMMUNITY_COMPUTE_TUTORIAL_FIXTURES).sort(), [
"empty",
"large-dense-500",
"single-device",
"small-company",
]);
const allowed = new Set([
"deviceId",
"label",
"capacityGb",
"models",
"state",
"isSelf",
"memberPubkey",
"reportedAt",
"modelSizeGb",
]);
for (const fixture of Object.values(COMMUNITY_COMPUTE_TUTORIAL_FIXTURES)) {
for (const item of fixture.snapshot.devices) {
assert.deepEqual(
Object.keys(item).filter((key) => !allowed.has(key)),
[],
);
}
}
const small = deriveCommunityComputeMapModel(
COMMUNITY_COMPUTE_TUTORIAL_FIXTURES["small-company"].snapshot,
);
assert.equal(small.deployments.length, 12);
assert.equal(
small.deployments.filter(({ deviceLabel }) =>
deviceLabel.startsWith("Team MacBook"),
).length,
10,
);
assert.equal(
small.deployments.filter(({ cellCount }) => cellCount === 1).length,
10,
);
assert.equal(
small.deployments.filter(({ cellCount }) => cellCount === 7).length,
2,
);
});
test("large dense fixture is deterministic and excludes non-serving rows", () => {
const fixture = LARGE_DENSE_COMMUNITY_COMPUTE_FIXTURE.snapshot;
assert.deepEqual(fixture, createLargeDenseSnapshot(500));
assert.equal(fixture.devices.length, 500);
const servingCount = fixture.devices.filter(
(item) => item.state === "serving" && item.models.length > 0,
).length;
const model = deriveCommunityComputeMapModel(fixture);
assert.equal(model.deployments.length, servingCount);
assert.equal(model.kpis.deploymentCount, servingCount);
assert.equal(
new Set(model.deployments.map(({ id }) => id)).size,
servingCount,
);
});

View File

@@ -0,0 +1,365 @@
import type {
MeshDeviceState,
MeshSnapshot,
MeshSnapshotDevice,
} from "@/shared/api/tauriMesh";
/** The only territory sizes rendered by the community compute map. */
export const HEX_CELL_BUCKETS = [1, 2, 4, 7] as const;
export type HexCellCount = (typeof HEX_CELL_BUCKETS)[number];
/**
* The Community view intentionally consumes only fields in the production
* snapshot contract. Tutorial fixtures use this same shape so examples cannot
* quietly grow capabilities that live Compute does not have.
*/
export type CommunityComputeDeviceInput = MeshSnapshotDevice;
/** A readonly, structurally compatible form of the current mesh snapshot. */
export type CommunityComputeSnapshotInput<
TDevice extends MeshSnapshotDevice = CommunityComputeDeviceInput,
> = Omit<MeshSnapshot, "devices"> & {
readonly devices: readonly TDevice[];
};
export type CommunityComputeDeploymentHealth =
| "healthy"
| "warming"
| "idle"
| "degraded"
| "offline"
| "unknown";
export type CommunityComputeMapHealth =
| "healthy"
| "attention"
| "critical"
| "empty"
| "unknown";
export type CommunityComputeDeployment<
TDevice extends MeshSnapshotDevice = CommunityComputeDeviceInput,
> = {
/** Stable map identity. Never derived from the device's array position. */
id: string;
/** Model shown as the territory's primary identity. */
label: string;
modelId: string;
deviceLabel: string;
capacityGb: number | null;
models: readonly string[];
state: MeshDeviceState;
isSelf: boolean;
health: CommunityComputeDeploymentHealth;
healthReason: string | null;
cellCount: HexCellCount;
/** Preserves additive backend data for a future detail projection. */
source: Readonly<TDevice>;
};
export type CommunityComputeKpis = {
memberCount: number;
contributorMemberCount: number;
deploymentCount: number;
activeDeploymentCount: number;
sharedCapacityGb: number | null;
allocatedCapacityGb: number | null;
allocatedPercent: number | null;
modelCount: number;
};
export type CommunityComputeHealthSummary = {
status: CommunityComputeMapHealth;
label: string;
reason: string | null;
counts: Record<CommunityComputeDeploymentHealth, number>;
};
export type CommunityComputeMapModel<
TDevice extends MeshSnapshotDevice = CommunityComputeDeviceInput,
> = {
status: "loading" | "ready" | "empty";
kpis: CommunityComputeKpis;
health: CommunityComputeHealthSummary;
deployments: readonly CommunityComputeDeployment<TDevice>[];
};
/**
* Round a desired territory footprint up to one of the four supported shapes.
* Invalid and non-positive weights still get one cell so a deployment cannot
* disappear from the map.
*/
export function bucketHexCellCount(
weight: number | null | undefined,
): HexCellCount {
if (weight === null || weight === undefined || !Number.isFinite(weight)) {
return 1;
}
const normalized = Math.max(1, Math.ceil(weight));
return HEX_CELL_BUCKETS.find((bucket) => normalized <= bucket) ?? 7;
}
/**
* Turn model memory into a deliberately coarse footprint.
*
* A 128 GB Mac is the common mesh workhorse, so every model that fits on one is
* one cell. Multi-cell territories are reserved for genuinely multi-GPU scale
* deployments; this avoids making ordinary local models look fragmented.
*/
export function capacityGbToHexCellCount(
capacityGb: number | null | undefined,
): HexCellCount {
if (capacityGb === null || capacityGb === undefined || capacityGb <= 128) {
return 1;
}
if (capacityGb <= 256) {
return 2;
}
if (capacityGb <= 512) {
return 4;
}
return 7;
}
const EMPTY_HEALTH_COUNTS: Record<CommunityComputeDeploymentHealth, number> = {
healthy: 0,
warming: 0,
idle: 0,
degraded: 0,
offline: 0,
unknown: 0,
};
/** Project a backend snapshot into the complete, render-agnostic map model. */
export function deriveCommunityComputeMapModel<
TDevice extends MeshSnapshotDevice = CommunityComputeDeviceInput,
>(
snapshot: CommunityComputeSnapshotInput<TDevice> | null,
): CommunityComputeMapModel<TDevice> {
if (snapshot === null) {
return {
status: "loading",
kpis: {
memberCount: 0,
contributorMemberCount: 0,
deploymentCount: 0,
activeDeploymentCount: 0,
sharedCapacityGb: null,
allocatedCapacityGb: null,
allocatedPercent: null,
modelCount: 0,
},
health: {
status: "unknown",
label: "Checking community compute",
reason: null,
counts: { ...EMPTY_HEALTH_COUNTS },
},
deployments: [],
};
}
const deployments = projectDeployments(snapshot.devices);
const healthStates = snapshot.devices
.filter((device) => device.state !== "consuming")
.map((device) => healthFromState(device.state));
const counts = countHealth(healthStates);
const models = new Set(snapshot.models);
for (const deployment of deployments) {
for (const model of deployment.models) {
models.add(model);
}
}
const contributorMemberCount =
snapshot.contributorMemberCount ??
new Set(
deployments
.filter((deployment) => deployment.state === "serving")
.map(
(deployment) =>
deployment.source.memberPubkey?.trim() || deployment.id,
),
).size;
const sharedCapacityGb = finiteNonNegative(snapshot.sharedCapacityGb);
const reportedAllocated = finiteNonNegative(snapshot.allocatedCapacityGb);
const servingDeployments = deployments.filter(
(deployment) => deployment.state === "serving",
);
const inferredAllocations = servingDeployments.map((deployment) =>
finiteNonNegative(deployment.source.modelSizeGb),
);
const allocatedCapacityGb =
reportedAllocated ??
(inferredAllocations.length > 0 &&
inferredAllocations.every((value) => value !== null)
? inferredAllocations.reduce((total, value) => total + (value ?? 0), 0)
: null);
return {
status: deployments.length === 0 ? "empty" : "ready",
kpis: {
memberCount: nonNegativeInteger(snapshot.memberCount),
contributorMemberCount,
deploymentCount: deployments.length,
activeDeploymentCount: counts.healthy + counts.warming,
sharedCapacityGb,
allocatedCapacityGb,
allocatedPercent:
allocatedCapacityGb !== null &&
sharedCapacityGb !== null &&
sharedCapacityGb > 0
? Math.min(100, (allocatedCapacityGb / sharedCapacityGb) * 100)
: null,
modelCount: models.size,
},
health: summarizeHealth(counts, healthStates, snapshot.reason),
deployments,
};
}
function projectDeployments<TDevice extends MeshSnapshotDevice>(
devices: readonly TDevice[],
): CommunityComputeDeployment<TDevice>[] {
const canonical = devices
.filter((device) => device.state === "serving" && device.models.length > 0)
.flatMap((device) =>
[...new Set(device.models)].map((model) => ({
device: { ...device, models: [model] } as TDevice,
identity: deploymentIdentity(device, model),
})),
)
.sort(
(left, right) =>
left.identity.localeCompare(right.identity) ||
deviceFingerprint(left.device).localeCompare(
deviceFingerprint(right.device),
),
);
const occurrences = new Map<string, number>();
return canonical.map(({ device, identity }) => {
const occurrence = occurrences.get(identity) ?? 0;
occurrences.set(identity, occurrence + 1);
const models = [...new Set(device.models)].sort();
return {
id: occurrence === 0 ? identity : `${identity}#${occurrence + 1}`,
label: models[0] ?? device.label,
modelId: models[0] ?? "Model not reported",
deviceLabel: device.label,
capacityGb: finiteNonNegative(device.capacityGb),
models,
state: device.state,
isSelf: device.isSelf,
health: healthFromState(device.state),
healthReason: null,
cellCount: capacityGbToHexCellCount(
device.modelSizeGb ?? device.capacityGb,
),
source: device,
};
});
}
function deploymentIdentity(
device: MeshSnapshotDevice,
modelId: string,
): string {
const deviceId = cleanOptionalText(device.deviceId);
const model = encodeURIComponent(modelId);
return deviceId === null
? `derived:${encodeURIComponent(deviceFingerprint(device))}:${model}`
: `deployment:${encodeURIComponent(deviceId)}:${model}`;
}
function deviceFingerprint(device: MeshSnapshotDevice): string {
return JSON.stringify([
device.label,
device.capacityGb,
[...device.models].sort(),
device.state,
device.isSelf,
]);
}
function healthFromState(
state: MeshDeviceState,
): CommunityComputeDeploymentHealth {
switch (state) {
case "serving":
case "consuming":
return "healthy";
case "loading":
return "warming";
case "standby":
return "idle";
}
}
function countHealth(
states: readonly CommunityComputeDeploymentHealth[],
): Record<CommunityComputeDeploymentHealth, number> {
const counts = { ...EMPTY_HEALTH_COUNTS };
for (const state of states) {
counts[state] += 1;
}
return counts;
}
function summarizeHealth(
counts: Record<CommunityComputeDeploymentHealth, number>,
states: readonly CommunityComputeDeploymentHealth[],
snapshotReason: string | null,
): CommunityComputeHealthSummary {
if (states.length === 0) {
return {
status: "empty",
label: "No deployments",
reason: cleanOptionalText(snapshotReason),
counts,
};
}
const unavailable = counts.offline + counts.degraded;
const reason = null;
if (counts.offline === states.length) {
return { status: "critical", label: "Compute unavailable", reason, counts };
}
if (unavailable > 0) {
return {
status: "attention",
label: `${unavailable} deployment${unavailable === 1 ? "" : "s"} need attention`,
reason,
counts,
};
}
if (counts.unknown === states.length) {
return { status: "unknown", label: "Health unknown", reason: null, counts };
}
return {
status: "healthy",
label: "No reported issues",
reason: null,
counts,
};
}
function finiteNonNegative(value: number | null | undefined): number | null {
return value !== null &&
value !== undefined &&
Number.isFinite(value) &&
value >= 0
? value
: null;
}
function nonNegativeInteger(value: number): number {
return Number.isFinite(value) ? Math.max(0, Math.floor(value)) : 0;
}
function cleanOptionalText(value: string | null | undefined): string | null {
const cleaned = value?.trim();
return cleaned ? cleaned : null;
}

View File

@@ -55,7 +55,11 @@ export function useMeshComputeState() {
// transition, instead of waiting out the 30s poll.
const [snapshotNonce, setSnapshotNonce] = React.useState(0);
const { snapshot, error: snapshotError } = useMeshSnapshot({
const {
snapshot,
error: snapshotError,
refresh: refreshSnapshot,
} = useMeshSnapshot({
refreshKey: snapshotNonce,
});
@@ -243,6 +247,7 @@ export function useMeshComputeState() {
shareSwitchChecked,
modelToShare,
setSharing,
refreshSnapshot,
// A transport failure is worth showing; an empty mesh is not an error and
// is already expressed by the row tone.
error: actionError ?? snapshotError,

View File

@@ -0,0 +1,95 @@
import assert from "node:assert/strict";
import { describe, it } from "node:test";
import React from "react";
import { renderToStaticMarkup } from "react-dom/server";
import {
EMPTY_COMMUNITY_COMPUTE_FIXTURE,
SMALL_COMPANY_COMMUNITY_COMPUTE_FIXTURE,
} from "../communityComputeFixtures.ts";
import { deriveCommunityComputeMapModel } from "../communityComputeMapModel.ts";
import { CommunityComputeHealthScorecard } from "./CommunityComputeHealthScorecard.tsx";
import { CommunityComputeKpiRow } from "./CommunityComputeKpiRow.tsx";
import { CommunityComputeTerritoryMap } from "./CommunityComputeTerritoryMap.tsx";
const smallModel = deriveCommunityComputeMapModel(
SMALL_COMPANY_COMMUNITY_COMPUTE_FIXTURE.snapshot,
);
describe("community compute visual components", () => {
it("renders contract-backed KPI values", () => {
const html = renderToStaticMarkup(
React.createElement(CommunityComputeKpiRow, { kpis: smallModel.kpis }),
);
assert.match(html, /community-compute-kpi-members-sharing/);
assert.match(html, /community-compute-kpi-contributed-vram/);
assert.match(html, /community-compute-kpi-vram-allocated/);
assert.match(html, /24 community members/);
assert.match(html, />2,744 GB</);
});
it("renders only health states production can derive", () => {
const html = renderToStaticMarkup(
React.createElement(CommunityComputeHealthScorecard, {
health: smallModel.health,
}),
);
assert.match(html, /data-status="healthy"/);
assert.match(html, /No reported issues/);
assert.match(html, /data-testid="community-compute-health-healthy"/);
});
it("renders one accessible territory and list item per ready model", () => {
const html = renderToStaticMarkup(
React.createElement(CommunityComputeTerritoryMap, { model: smallModel }),
);
assert.match(html, /data-testid="community-compute-map-svg"/);
assert.equal(
[
...html.matchAll(
/data-testid="community-compute-territory-deployment-/g,
),
].length,
smallModel.deployments.length,
);
assert.equal(
[
...html.matchAll(
/data-testid="community-compute-deployment-deployment-/g,
),
].length,
smallModel.deployments.length,
);
assert.match(html, /tabindex="0"/);
assert.match(html, /Search models or devices/);
assert.match(html, /Model footprint/);
assert.doesNotMatch(html, /Utilization|Region|Split across machines/);
});
it("keeps the production map static and supports explicit tutorial motion", () => {
const html = renderToStaticMarkup(
React.createElement(CommunityComputeTerritoryMap, { model: smallModel }),
);
assert.doesNotMatch(html, /animate-mesh-inference/);
const tutorialHtml = renderToStaticMarkup(
React.createElement(CommunityComputeTerritoryMap, {
model: smallModel,
inferenceDeploymentIds: [smallModel.deployments[0].id],
}),
);
assert.match(tutorialHtml, /animate-mesh-inference/);
assert.doesNotMatch(html, /community-compute-split-boundary/);
});
it("renders a static empty state without a deployment list", () => {
const emptyModel = deriveCommunityComputeMapModel(
EMPTY_COMMUNITY_COMPUTE_FIXTURE.snapshot,
);
const html = renderToStaticMarkup(
React.createElement(CommunityComputeTerritoryMap, { model: emptyModel }),
);
assert.match(html, /data-testid="community-compute-map-empty"/);
assert.doesNotMatch(html, /community-compute-deployment-list/);
});
});

View File

@@ -0,0 +1,154 @@
import {
AlertTriangle,
CheckCircle2,
CircleHelp,
MinusCircle,
XCircle,
} from "lucide-react";
import { cn } from "@/shared/lib/cn";
import type {
CommunityComputeDeploymentHealth,
CommunityComputeHealthSummary,
} from "../communityComputeMapModel";
export type CommunityComputeHealthScorecardProps = {
health: CommunityComputeHealthSummary;
className?: string;
};
const HEALTH_ROWS: readonly {
status: CommunityComputeDeploymentHealth;
label: string;
}[] = [
{ status: "healthy", label: "Healthy" },
{ status: "warming", label: "Warming" },
{ status: "idle", label: "Idle" },
{ status: "degraded", label: "Degraded" },
{ status: "offline", label: "Offline" },
{ status: "unknown", label: "Unknown" },
];
/** Health summary with icon, copy, and count labels that do not rely on color. */
export function CommunityComputeHealthScorecard({
health,
className,
}: CommunityComputeHealthScorecardProps) {
const Icon = statusIcon(health.status);
const total = Object.values(health.counts).reduce(
(sum, count) => sum + count,
0,
);
return (
<section
aria-labelledby="community-compute-health-title"
className={cn(
"rounded-xl border border-border/70 bg-background p-4",
className,
)}
data-status={health.status}
data-testid="community-compute-health-scorecard"
>
<div className="flex items-start gap-3">
<span
aria-hidden="true"
className={cn(
"flex size-9 shrink-0 items-center justify-center rounded-full border bg-muted/30",
health.status === "healthy" && "border-foreground/30",
health.status === "attention" &&
"border-dashed border-foreground/50",
health.status === "critical" && "border-2 border-foreground",
)}
>
<Icon className="size-4" />
</span>
<div className="min-w-0 flex-1">
<p
className="text-sm font-semibold"
data-testid="community-compute-health-label"
id="community-compute-health-title"
>
{health.label}
</p>
<p className="mt-0.5 text-xs leading-snug text-muted-foreground">
{health.reason ?? healthDescription(health.status, total)}
</p>
</div>
<span className="shrink-0 text-xs font-medium tabular-nums text-muted-foreground">
{total} total
</span>
</div>
<dl className="mt-4 grid grid-cols-3 gap-2 sm:grid-cols-6">
{HEALTH_ROWS.map(({ status, label }) => (
<div
className={cn(
"rounded-lg border border-border/60 px-2 py-2 text-center",
health.counts[status] > 0 && healthClass(status),
)}
data-testid={`community-compute-health-${status}`}
key={status}
>
<dt className="truncate text-2xs text-muted-foreground">{label}</dt>
<dd className="mt-0.5 text-sm font-semibold tabular-nums">
{health.counts[status]}
</dd>
</div>
))}
</dl>
</section>
);
}
function statusIcon(status: CommunityComputeHealthSummary["status"]) {
switch (status) {
case "healthy":
return CheckCircle2;
case "attention":
return AlertTriangle;
case "critical":
return XCircle;
case "empty":
return MinusCircle;
case "unknown":
return CircleHelp;
}
}
function healthClass(status: CommunityComputeDeploymentHealth): string {
switch (status) {
case "healthy":
return "border-solid bg-foreground/[0.04]";
case "warming":
return "border-dashed bg-foreground/[0.03]";
case "idle":
return "border-dotted";
case "degraded":
return "border-dashed border-foreground/50";
case "offline":
return "border-foreground/50 bg-muted/50 line-through decoration-muted-foreground/50";
case "unknown":
return "border-dotted bg-muted/20";
}
}
function healthDescription(
status: CommunityComputeHealthSummary["status"],
total: number,
): string {
switch (status) {
case "healthy":
return "No reporting device needs attention; some may still be warming or idle.";
case "attention":
return "Some deployments may have reduced availability.";
case "critical":
return "Shared compute is currently unavailable.";
case "empty":
return "No deployments have joined this community yet.";
case "unknown":
return total === 0
? "Waiting for deployment health reports."
: "Deployment health could not be determined.";
}
}

View File

@@ -0,0 +1,83 @@
import { cn } from "@/shared/lib/cn";
import type { CommunityComputeKpis } from "../communityComputeMapModel";
export type CommunityComputeKpiRowProps = {
kpis: CommunityComputeKpis;
className?: string;
};
/** Compact, responsive headline figures for the community compute pool. */
export function CommunityComputeKpiRow({
kpis,
className,
}: CommunityComputeKpiRowProps) {
const items = [
{
label: "Members sharing",
value: formatCount(kpis.contributorMemberCount),
detail: `${formatCount(kpis.memberCount)} community members`,
},
{
label: "Contributed VRAM",
value: formatCapacity(kpis.sharedCapacityGb),
detail: `${formatCount(kpis.deploymentCount)} deployments`,
},
{
label: "VRAM allocated",
value:
kpis.allocatedPercent === null
? "—"
: `${Math.round(kpis.allocatedPercent)}%`,
detail:
kpis.allocatedCapacityGb === null
? "Not fully reported"
: `${formatCapacity(kpis.allocatedCapacityGb)} hosting models`,
},
];
return (
<dl
className={cn(
"grid grid-cols-1 overflow-hidden rounded-xl border border-border/70 bg-muted/15 sm:grid-cols-3",
className,
)}
data-testid="community-compute-kpis"
>
{items.map((item, index) => (
<div
className={cn(
"min-w-0 px-3 py-2.5",
index > 0 && "border-border/60 border-t sm:border-l sm:border-t-0",
)}
data-testid={`community-compute-kpi-${kpiTestId(item.label)}`}
key={item.label}
>
<dt className="truncate text-2xs font-medium tracking-wide text-muted-foreground uppercase">
{item.label}
</dt>
<dd className="mt-1 truncate text-xl font-semibold tabular-nums">
{item.value}
</dd>
<dd className="mt-0.5 truncate text-2xs text-muted-foreground">
{item.detail}
</dd>
</div>
))}
</dl>
);
}
function formatCount(value: number): string {
return new Intl.NumberFormat(undefined, { maximumFractionDigits: 0 }).format(
value,
);
}
function formatCapacity(value: number | null): string {
if (value === null) return "—";
return `${new Intl.NumberFormat(undefined, { maximumFractionDigits: 1 }).format(value)} GB`;
}
function kpiTestId(label: string): string {
return label.toLowerCase().replaceAll(" ", "-");
}

View File

@@ -0,0 +1,568 @@
import * as React from "react";
import { cn } from "@/shared/lib/cn";
import {
hexTerritoryBoundaryEdges,
layoutCommunityComputeHexTerritories,
type CommunityComputeHexCell,
} from "../communityComputeHexLayout";
import type {
CommunityComputeDeployment,
CommunityComputeDeploymentHealth,
CommunityComputeMapModel,
} from "../communityComputeMapModel";
export type CommunityComputeTerritoryMapProps = {
model: CommunityComputeMapModel;
selectedDeploymentId?: string | null;
onSelectedDeploymentChange?: (deploymentId: string) => void;
className?: string;
/** Tutorial-only simulated activity; live snapshots cannot attribute requests. */
inferenceDeploymentIds?: readonly string[];
};
type Point = { x: number; y: number };
type ViewBox = {
x: number;
y: number;
width: number;
height: number;
};
// Deliberately overlap polygons, then trim their outside with the territory
// edge. This avoids SVG antialias seams inside one model footprint.
const FUSED_TILE_RADIUS = 1.025;
const TILE_EDGE_WIDTH = 0.1;
const SQRT_THREE = Math.sqrt(3);
/**
* Responsive SVG territory map. Each deployment owns one stable, contiguous
* cluster of discrete hexes; health changes never move that cluster.
*/
export function CommunityComputeTerritoryMap({
model,
selectedDeploymentId,
onSelectedDeploymentChange,
className,
inferenceDeploymentIds = [],
}: CommunityComputeTerritoryMapProps) {
const [internalSelection, setInternalSelection] = React.useState<
string | null
>(null);
const deploymentById = React.useMemo(
() =>
new Map(
model.deployments.map((deployment) => [deployment.id, deployment]),
),
[model.deployments],
);
const previousLayoutRef = React.useRef<ReturnType<
typeof layoutCommunityComputeHexTerritories
> | null>(null);
const layout = React.useMemo(
() =>
layoutCommunityComputeHexTerritories(
model.deployments.map(({ id, cellCount }) => ({ id, cellCount })),
{ previous: previousLayoutRef.current },
),
[model.deployments],
);
React.useEffect(() => {
previousLayoutRef.current = layout;
}, [layout]);
const fallbackId = model.deployments[0]?.id ?? null;
const requestedId = selectedDeploymentId ?? internalSelection;
const activeId =
requestedId !== null && deploymentById.has(requestedId)
? requestedId
: fallbackId;
const activeDeployment = activeId
? (deploymentById.get(activeId) ?? null)
: null;
const viewBox = computeViewBox(layout.cells);
const inferenceIds = React.useMemo(
() => new Set(inferenceDeploymentIds),
[inferenceDeploymentIds],
);
const [hoveredId, setHoveredId] = React.useState<string | null>(null);
const [deploymentSearch, setDeploymentSearch] = React.useState("");
const hoveredDeployment = hoveredId
? (deploymentById.get(hoveredId) ?? null)
: null;
function selectDeployment(deploymentId: string) {
if (selectedDeploymentId === undefined) {
setInternalSelection(deploymentId);
}
onSelectedDeploymentChange?.(deploymentId);
}
if (model.status === "loading") {
return (
<section
aria-busy="true"
aria-label="Community compute map"
className={cn(
"rounded-xl border border-border/70 bg-muted/10 p-4",
className,
)}
data-testid="community-compute-map-loading"
>
<div className="h-48 animate-pulse rounded-lg bg-muted/50 motion-reduce:animate-none" />
<p className="mt-3 text-sm text-muted-foreground">
Mapping community deployments…
</p>
</section>
);
}
if (model.status === "empty" || viewBox === null) {
return (
<section
aria-label="Community compute map"
className={cn(
"flex min-h-48 flex-col items-center justify-center rounded-xl border border-dashed border-border px-5 py-8 text-center",
className,
)}
data-testid="community-compute-map-empty"
>
<EmptyHexes />
<p className="mt-3 text-sm font-medium">No compute territories yet</p>
<p className="mt-1 max-w-sm text-xs leading-relaxed text-muted-foreground">
Deployments appear here when members share compute with the community.
</p>
</section>
);
}
return (
<section
aria-label="Community compute map"
className={cn(
"min-w-0 space-y-4 rounded-xl border border-border/70 bg-muted/10 p-3",
className,
)}
data-testid="community-compute-territory-map"
>
<div className="relative flex min-h-72 min-w-0 items-center justify-center overflow-hidden rounded-lg border border-border/50 bg-background/70 p-3 sm:min-h-96">
<svg
aria-label={`${model.deployments.length} community compute deployments. Select a territory for details.`}
className="h-auto max-h-[28rem] w-full overflow-visible"
data-testid="community-compute-map-svg"
preserveAspectRatio="xMidYMid meet"
role="img"
viewBox={`${viewBox.x} ${viewBox.y} ${viewBox.width} ${viewBox.height}`}
>
{layout.territories.map((territory) => {
const deployment = deploymentById.get(territory.deploymentId);
if (!deployment) return null;
const selected = deployment.id === activeId;
const inferenceActive = inferenceIds.has(deployment.id);
return (
// SVG groups have no semantic button equivalent; keyboard selection remains in the adjacent deployment list.
// biome-ignore lint/a11y/useSemanticElements: SVG has no native button element.
<g
aria-label={territoryAccessibleLabel(deployment)}
className="cursor-pointer outline-hidden transition-opacity hover:opacity-90 focus-visible:opacity-80"
data-deployment-id={deployment.id}
data-health={deployment.health}
data-cell-count={deployment.cellCount}
data-inference-active={inferenceActive}
data-selected={selected}
data-testid={`community-compute-territory-${testId(deployment.id)}`}
key={deployment.id}
onClick={() => selectDeployment(deployment.id)}
onKeyDown={(event) => {
if (event.key === "Enter" || event.key === " ") {
event.preventDefault();
selectDeployment(deployment.id);
}
}}
onMouseEnter={() => setHoveredId(deployment.id)}
onMouseLeave={() => setHoveredId(null)}
role="button"
tabIndex={0}
>
<title>{territoryAccessibleLabel(deployment)}</title>
<TerritoryShape
cells={territory.cells}
inferenceActive={inferenceActive}
/>
</g>
);
})}
</svg>
{hoveredDeployment ? (
<div
className="pointer-events-none absolute bottom-3 left-3 max-w-64 rounded-xl border border-border/70 bg-popover/95 px-3 py-2 shadow-lg backdrop-blur-sm"
data-testid="community-compute-hover-details"
>
<p
className="truncate text-xs font-semibold"
title={hoveredDeployment.modelId}
>
{shortModelName(hoveredDeployment.modelId)}
</p>
<p className="mt-0.5 truncate text-2xs text-muted-foreground">
{hoveredDeployment.deviceLabel} ·{" "}
{formatCapacity(hoveredDeployment.capacityGb)}
</p>
<p className="mt-1 text-2xs capitalize text-muted-foreground">
{inferenceIds.has(hoveredDeployment.id)
? "Simulated inference"
: hoveredDeployment.health}{" "}
· {hoveredDeployment.cellCount}{" "}
{hoveredDeployment.cellCount === 1 ? "cell" : "cells"}
</p>
</div>
) : null}
</div>
<div className="grid min-w-0 gap-4 lg:grid-cols-[minmax(0,1fr)_minmax(16rem,0.36fr)]">
<DeploymentList
activeId={activeId}
deployments={model.deployments}
onSearchChange={setDeploymentSearch}
onSelect={selectDeployment}
search={deploymentSearch}
/>
{activeDeployment ? (
<DeploymentDetails deployment={activeDeployment} />
) : null}
</div>
</section>
);
}
function TerritoryShape({
cells,
inferenceActive,
}: {
cells: readonly CommunityComputeHexCell[];
inferenceActive: boolean;
}) {
const boundary = hexTerritoryBoundaryEdges(cells);
const fillClass = "fill-foreground";
const territoryAnimationStyle = inferenceActive
? ({
"--mesh-breath-duration": `${5.8 + (stableVisualHash(cells[0]?.deploymentId ?? "") % 7) * 0.24}s`,
animationDelay: `${-((stableVisualHash(`${cells[0]?.deploymentId}:phase`) % 37) / 10)}s`,
} as React.CSSProperties)
: undefined;
return (
<g>
{cells.map((cell) => {
const center = axialToPoint(cell.q, cell.r);
return (
<polygon
className={cn(
fillClass,
"stroke-transparent",
inferenceActive &&
"animate-mesh-inference motion-reduce:animate-none",
)}
data-testid="community-compute-tile"
key={cell.id}
points={hexPoints(center, FUSED_TILE_RADIUS)}
style={territoryAnimationStyle}
/>
);
})}
<path
className={cn(
"fill-none stroke-background transition-[opacity,stroke-width] duration-200 motion-reduce:transition-none",
fillClass,
)}
d={edgesToPath(boundary)}
data-testid="community-compute-territory-boundary"
strokeLinecap="round"
strokeLinejoin="round"
// A crisp opaque perimeter cuts an empty gutter between territories.
strokeWidth={TILE_EDGE_WIDTH}
/>
</g>
);
}
function edgesToPath(
edges: ReturnType<typeof hexTerritoryBoundaryEdges>,
): string {
return edges
.map(
(edge) =>
`M ${edge.start.x} ${edge.start.y} L ${edge.end.x} ${edge.end.y}`,
)
.join(" ");
}
function DeploymentList({
deployments,
activeId,
onSearchChange,
onSelect,
search,
}: {
deployments: readonly CommunityComputeDeployment[];
activeId: string | null;
onSearchChange: (value: string) => void;
onSelect: (id: string) => void;
search: string;
}) {
const query = search.trim().toLowerCase();
const visibleDeployments = query
? deployments.filter((deployment) =>
[deployment.modelId, deployment.deviceLabel]
.filter(Boolean)
.some((value) => value?.toLowerCase().includes(query)),
)
: deployments;
return (
<div className="min-w-0">
<div className="mb-2 flex items-center justify-between gap-3">
<p className="text-xs font-medium text-muted-foreground">Deployments</p>
<span className="text-2xs tabular-nums text-muted-foreground">
{visibleDeployments.length} of {deployments.length}
</span>
</div>
<input
aria-label="Search deployments"
className="mb-2 h-9 w-full rounded-lg border border-input/60 bg-background px-3 text-xs outline-hidden placeholder:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring"
onChange={(event) => onSearchChange(event.target.value)}
placeholder="Search models or devices"
type="search"
value={search}
/>
<ul
aria-label="Community compute deployments"
className="max-h-72 space-y-1 overflow-y-auto pr-1"
data-testid="community-compute-deployment-list"
>
{visibleDeployments.map((deployment) => {
const selected = deployment.id === activeId;
return (
<li key={deployment.id}>
<button
aria-pressed={selected}
className={cn(
"flex w-full items-center gap-2 rounded-lg border border-transparent px-2.5 py-2 text-left text-xs transition-colors hover:bg-muted/60 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring",
selected && "border-border bg-muted/70 text-foreground",
)}
data-testid={`community-compute-deployment-${testId(deployment.id)}`}
onClick={() => onSelect(deployment.id)}
type="button"
>
<HealthGlyph health={deployment.health} />
<span className="min-w-0 flex-1">
<span className="block truncate font-medium">
{shortModelName(deployment.modelId)}
</span>
<span className="block truncate text-2xs text-muted-foreground">
{deployment.deviceLabel}
</span>
</span>
<span className="shrink-0 text-2xs capitalize text-muted-foreground">
{deployment.health}
</span>
</button>
</li>
);
})}
</ul>
</div>
);
}
function DeploymentDetails({
deployment,
}: {
deployment: CommunityComputeDeployment;
}) {
return (
<article
aria-live="polite"
className="min-w-0 rounded-lg border border-border/60 bg-background/80 p-3"
data-testid="community-compute-deployment-details"
>
<div className="flex items-start gap-2">
<HealthGlyph health={deployment.health} />
<div className="min-w-0 flex-1">
<h3
className="truncate text-sm font-semibold"
title={deployment.modelId}
>
{shortModelName(deployment.modelId)}
</h3>
<p className="mt-0.5 truncate text-xs text-muted-foreground">
{deployment.deviceLabel}
{deployment.isSelf ? " · This machine" : ""}
</p>
<p className="mt-0.5 text-2xs capitalize text-muted-foreground">
{deployment.health} · {deployment.cellCount}{" "}
{deployment.cellCount === 1 ? "cell" : "cells"}
</p>
</div>
</div>
{deployment.healthReason ? (
<p className="mt-2 text-xs leading-relaxed text-muted-foreground">
{deployment.healthReason}
</p>
) : null}
<dl className="mt-3 grid grid-cols-2 gap-x-3 gap-y-2 text-xs">
<Detail
label="Shared memory"
value={formatCapacity(deployment.capacityGb)}
/>
<Detail label="Model" value={deployment.modelId} />
<Detail
label="Reported"
value={formatReportedAt(deployment.source.reportedAt)}
/>
<Detail
label="Model footprint"
value={formatCapacity(deployment.source.modelSizeGb ?? null)}
/>
</dl>
</article>
);
}
function Detail({ label, value }: { label: string; value: string }) {
return (
<div className="min-w-0">
<dt className="text-2xs text-muted-foreground">{label}</dt>
<dd className="mt-0.5 truncate font-medium" title={value}>
{value}
</dd>
</div>
);
}
function HealthGlyph({ health }: { health: CommunityComputeDeploymentHealth }) {
const cue = healthCue(health);
return (
<span
aria-hidden="true"
className={cn(
"flex size-4 shrink-0 items-center justify-center rounded-full border border-foreground/45 text-3xs font-bold leading-none",
health === "warming" &&
"animate-pulse border-dashed motion-reduce:animate-none",
health === "idle" && "border-dotted text-muted-foreground",
health === "degraded" && "border-dashed",
health === "offline" &&
"border-muted-foreground/60 text-muted-foreground",
health === "unknown" && "border-dotted text-muted-foreground",
)}
>
{cue.glyph}
</span>
);
}
function EmptyHexes() {
const centers = [
{ x: 2, y: 1.75 },
{ x: 3.58, y: 2.65 },
{ x: 2, y: 3.55 },
{ x: 0.42, y: 2.65 },
];
return (
<svg aria-hidden="true" className="h-14 w-20" viewBox="-0.7 0.5 5.4 4.3">
{centers.map((center) => (
<polygon
className="fill-muted/40 stroke-muted-foreground/40"
key={`${center.x}:${center.y}`}
points={hexPoints(center, 0.82)}
strokeDasharray="2 2"
strokeWidth="0.08"
/>
))}
</svg>
);
}
function axialToPoint(q: number, r: number): Point {
return { x: SQRT_THREE * (q + r / 2), y: 1.5 * r };
}
function hexPoints(center: Point, radius: number): string {
return Array.from({ length: 6 }, (_, index) => {
const angle = ((60 * index - 30) * Math.PI) / 180;
return `${center.x + radius * Math.cos(angle)},${center.y + radius * Math.sin(angle)}`;
}).join(" ");
}
function computeViewBox(
cells: readonly CommunityComputeHexCell[],
): ViewBox | null {
if (cells.length === 0) return null;
const centers = cells.map((cell) => axialToPoint(cell.q, cell.r));
const minX = Math.min(...centers.map(({ x }) => x)) - 1.4;
const maxX = Math.max(...centers.map(({ x }) => x)) + 1.4;
const minY = Math.min(...centers.map(({ y }) => y)) - 1.4;
const maxY = Math.max(...centers.map(({ y }) => y)) + 1.4;
return {
x: minX,
y: minY,
width: Math.max(2.8, maxX - minX),
height: Math.max(2.8, maxY - minY),
};
}
function healthCue(health: CommunityComputeDeploymentHealth): {
dashArray?: string;
glyph: string;
strokeWidth: number;
} {
switch (health) {
case "healthy":
return { glyph: "✓", strokeWidth: 0.075 };
case "warming":
return { glyph: "↻", dashArray: "0.2 0.12", strokeWidth: 0.085 };
case "idle":
return { glyph: "–", dashArray: "0.04 0.14", strokeWidth: 0.08 };
case "degraded":
return { glyph: "!", dashArray: "0.3 0.12", strokeWidth: 0.11 };
case "offline":
return { glyph: "×", dashArray: "0.08 0.1", strokeWidth: 0.075 };
case "unknown":
return { glyph: "?", dashArray: "0.03 0.12", strokeWidth: 0.075 };
}
}
function stableVisualHash(value: string): number {
let hash = 2166136261;
for (const character of value) {
hash ^= character.codePointAt(0) ?? 0;
hash = Math.imul(hash, 16777619);
}
return hash >>> 0;
}
function shortModelName(modelId: string): string {
const tail = modelId.split("/").at(-1) ?? modelId;
return tail.length > 34 ? `${tail.slice(0, 31)}…` : tail;
}
function territoryAccessibleLabel(
deployment: CommunityComputeDeployment,
): string {
const capacity = formatCapacity(deployment.capacityGb);
return `${deployment.modelId} on ${deployment.deviceLabel}, ${deployment.health}, ${capacity}, ${deployment.cellCount} ${deployment.cellCount === 1 ? "cell" : "cells"}`;
}
function formatCapacity(value: number | null): string {
return value === null
? "Capacity not reported"
: `${Math.round(value)} GB shared`;
}
function formatReportedAt(value: number | null | undefined): string {
if (value === null || value === undefined) return "Not reported";
const milliseconds = value < 10_000_000_000 ? value * 1000 : value;
return new Date(milliseconds).toLocaleString();
}
function testId(value: string): string {
return encodeURIComponent(value).replaceAll("%", "-");
}

View File

@@ -0,0 +1,146 @@
import { ArrowLeft, ArrowRight, FlaskConical, X } from "lucide-react";
import { Button } from "@/shared/ui/button";
import { cn } from "@/shared/lib/cn";
import type { CommunityComputeTutorialFixtureId } from "../communityComputeFixtures";
const STEPS = [
{
title: "Every territory is a model deployment",
body: "Each connected group is one ready model on one contributed device. If one device serves multiple models, each model gets its own territory; another device serving the same model appears separately.",
},
{
title: "Area represents memory",
body: "Models snap to four coarse footprints: 1, 2, 4, or 7 cells. The footprint comes from reported model size, or shared device capacity when model size is unavailable.",
},
{
title: "Motion illustrates inference in flight",
body: "For this tutorial, breathing territories simulate models handling requests. The live community snapshot cannot yet identify the deployment serving a request, so the live map remains static.",
},
{
title: "The headline measures the pool",
body: "Members sharing counts contributors, contributed VRAM is the memory they offered, and VRAM allocated is the reported model footprint—not GPU processing utilization.",
},
{
title: "Health summarizes reported state",
body: "The scorecard counts ready, warming, and idle deployments from current status reports. It does not infer utilization, offline devices, replica resilience, or capacity headroom.",
},
] as const;
export function CommunityComputeTutorialPanel({
fixtureId,
onExit,
onFixtureChange,
onStepChange,
step,
}: {
fixtureId: CommunityComputeTutorialFixtureId;
onExit: () => void;
onFixtureChange: (fixture: CommunityComputeTutorialFixtureId) => void;
onStepChange: (step: number) => void;
step: number;
}) {
const current = STEPS[step] ?? STEPS[0];
const showDeveloperControls =
import.meta.env.DEV || import.meta.env.MODE === "e2e";
return (
<section
aria-labelledby="mesh-tutorial-title"
className="rounded-2xl border border-foreground/20 bg-foreground/[0.035] p-4"
data-testid="community-compute-tutorial-panel"
>
<div className="flex items-start gap-3">
<div className="min-w-0 flex-1">
<p className="text-2xs font-semibold uppercase tracking-wide text-muted-foreground">
Tutorial · {step + 1} of {STEPS.length}
</p>
<h2 className="mt-1 text-base font-semibold" id="mesh-tutorial-title">
{current.title}
</h2>
<p className="mt-1 max-w-3xl text-sm leading-relaxed text-muted-foreground">
{current.body}
</p>
</div>
<Button
aria-label="Exit mesh tutorial"
onClick={onExit}
size="icon-xs"
type="button"
variant="ghost"
>
<X />
</Button>
</div>
<div className="mt-4 flex flex-wrap items-center gap-2">
<Button
disabled={step === 0}
onClick={() => onStepChange(step - 1)}
size="sm"
type="button"
variant="outline"
>
<ArrowLeft /> Back
</Button>
<Button
onClick={() =>
step === STEPS.length - 1 ? onStepChange(0) : onStepChange(step + 1)
}
size="sm"
type="button"
>
{step === STEPS.length - 1 ? "Replay" : "Next"}
<ArrowRight />
</Button>
<fieldset className="ml-1 flex gap-1" aria-label="Tutorial progress">
{STEPS.map((item, index) => (
<button
aria-label={`Go to tutorial step ${index + 1}: ${item.title}`}
className={cn(
"size-2 rounded-full bg-muted-foreground/25 transition-colors",
index === step && "bg-foreground",
)}
key={item.title}
onClick={() => onStepChange(index)}
type="button"
/>
))}
</fieldset>
</div>
{showDeveloperControls ? (
<div
className="mt-4 flex flex-wrap items-center gap-2 border-border/60 border-t pt-3"
data-testid="community-compute-dev-controls"
>
<FlaskConical className="size-3.5 text-muted-foreground" />
<label
className="text-xs font-medium"
htmlFor="mesh-tutorial-scenario"
>
Preview scenario
</label>
<select
className="h-8 rounded-lg border border-input/50 bg-background px-2 text-xs focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"
id="mesh-tutorial-scenario"
onChange={(event) =>
onFixtureChange(
event.target.value as CommunityComputeTutorialFixtureId,
)
}
value={fixtureId}
>
<option value="empty">Empty community</option>
<option value="single-device">Single device</option>
<option value="small-company">Small company</option>
<option value="large-dense-500">500 deployments</option>
</select>
<span className="text-2xs text-muted-foreground">
Development-only · deterministic frontend data
</span>
</div>
) : null}
</section>
);
}

View File

@@ -0,0 +1,122 @@
import { Info, RefreshCw } from "lucide-react";
import { Button } from "@/shared/ui/button";
import type { MeshSnapshot } from "@/shared/api/tauriMesh";
import {
deriveCommunityComputeMapModel,
type CommunityComputeSnapshotInput,
} from "../communityComputeMapModel";
import { CommunityComputeHealthScorecard } from "./CommunityComputeHealthScorecard";
import { CommunityComputeKpiRow } from "./CommunityComputeKpiRow";
import { CommunityComputeTerritoryMap } from "./CommunityComputeTerritoryMap";
export function MeshComputeCommunityView({
communityName,
error,
onRefresh,
simulated,
snapshot,
tutorialInference = false,
}: {
communityName: string;
error: string | null;
onRefresh: () => void;
simulated: boolean;
snapshot: MeshSnapshot | CommunityComputeSnapshotInput | null;
tutorialInference?: boolean;
}) {
const model = deriveCommunityComputeMapModel(snapshot);
const inferenceDeploymentIds = tutorialInference
? model.deployments
.filter(
(deployment, index) =>
deployment.cellCount > 1 || index % 3 === 0 || index % 7 === 2,
)
.map((deployment) => deployment.id)
: [];
const observedAt = (snapshot as MeshSnapshot | null)?.observedAt;
return (
<div className="space-y-5" data-testid="community-compute-view">
{simulated ? (
<div
className="flex items-center gap-2 rounded-xl border border-dashed border-foreground/30 bg-foreground/[0.035] px-3 py-2 text-xs"
data-testid="community-compute-simulated-banner"
>
<Info className="size-3.5" />
<span>
Simulated mesh for learning and development. Live community data is
unchanged.
</span>
</div>
) : null}
{error && !simulated ? (
<div className="flex items-center justify-between gap-3 rounded-xl border border-destructive/40 bg-destructive/5 px-3 py-2 text-xs text-destructive">
<span>
Couldn’t load {communityName} compute: {error}
</span>
<Button onClick={onRefresh} size="xs" type="button" variant="outline">
<RefreshCw /> Try again
</Button>
</div>
) : null}
<CommunityComputeKpiRow kpis={model.kpis} />
<div>
<div className="mb-2 flex items-end justify-between gap-3">
<div>
<h2 className="text-lg font-semibold tracking-tight">Model mesh</h2>
<p className="text-sm text-muted-foreground">
Each territory is one ready model on one device. Area reflects its
reported model-memory tier.
</p>
</div>
{!simulated ? (
<Button
aria-label="Refresh community compute"
onClick={onRefresh}
size="icon-xs"
title="Refresh community compute"
type="button"
variant="ghost"
>
<RefreshCw />
</Button>
) : null}
</div>
<CommunityComputeTerritoryMap
inferenceDeploymentIds={inferenceDeploymentIds}
model={model}
/>
<p className="mt-2 text-2xs text-muted-foreground">
{simulated
? "Deterministic tutorial snapshot"
: observedAt
? `Recently reported · updated ${formatAge(observedAt)}`
: "Recently reported by community members · presence may take up to two minutes to expire"}
</p>
</div>
<div>
<div className="mb-2">
<h2 className="text-lg font-semibold tracking-tight">Mesh health</h2>
<p className="text-sm text-muted-foreground">
Current ready, warming, and idle states from community status
reports.
</p>
</div>
<CommunityComputeHealthScorecard health={model.health} />
</div>
</div>
);
}
function formatAge(timestamp: number): string {
const timestampMs = timestamp < 10_000_000_000 ? timestamp * 1000 : timestamp;
const seconds = Math.max(0, Math.round((Date.now() - timestampMs) / 1000));
if (seconds < 10) return "just now";
if (seconds < 60) return `${seconds}s ago`;
return `${Math.floor(seconds / 60)}m ago`;
}

View File

@@ -0,0 +1,103 @@
import * as React from "react";
import { BookOpen } from "lucide-react";
import { useCommunities } from "@/features/communities/useCommunities";
import { SettingsSectionHeader } from "@/features/settings/ui/SettingsSectionHeader";
import { Button } from "@/shared/ui/button";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/shared/ui/tabs";
import {
COMMUNITY_COMPUTE_TUTORIAL_FIXTURES,
type CommunityComputeTutorialFixtureId,
} from "../communityComputeFixtures";
import { useMeshComputeState } from "../hooks/useMeshComputeState";
import { CommunityComputeTutorialPanel } from "./CommunityComputeTutorialPanel";
import { MeshComputeCommunityView } from "./MeshComputeCommunityView";
import { MeshComputeSettingsCard } from "./MeshComputeSettingsCard";
import { MeshComputeShareBanner } from "./MeshComputeShareBanner";
export function MeshComputePage() {
const { activeCommunity } = useCommunities();
const mesh = useMeshComputeState();
const [tab, setTab] = React.useState("community");
const [tutorialOpen, setTutorialOpen] = React.useState(false);
const [tutorialStep, setTutorialStep] = React.useState(0);
const [fixtureId, setFixtureId] =
React.useState<CommunityComputeTutorialFixtureId>("small-company");
const communityName = activeCommunity?.name ?? "this community";
const tutorialFixture = COMMUNITY_COMPUTE_TUTORIAL_FIXTURES[fixtureId];
function toggleTutorial() {
if (tutorialOpen) {
setTutorialOpen(false);
return;
}
setTab("community");
setTutorialOpen(true);
setTutorialStep(0);
setFixtureId("small-company");
}
return (
<section className="min-w-0" data-testid="settings-mesh-compute-page">
<SettingsSectionHeader
action={
<Button
aria-pressed={tutorialOpen}
data-testid="community-compute-tutorial-button"
onClick={toggleTutorial}
size="sm"
type="button"
variant={tutorialOpen ? "secondary" : "outline"}
>
<BookOpen /> Tutorial
</Button>
}
description={`See what ${communityName} can run and contribute this machine’s spare capacity.`}
title="Compute"
/>
<div className="space-y-5">
{tutorialOpen ? null : (
<MeshComputeShareBanner communityName={communityName} mesh={mesh} />
)}
<Tabs onValueChange={setTab} value={tab}>
<TabsList className="grid w-full grid-cols-2 sm:w-72">
<TabsTrigger data-testid="compute-tab-community" value="community">
Community
</TabsTrigger>
<TabsTrigger data-testid="compute-tab-settings" value="settings">
Settings
</TabsTrigger>
</TabsList>
<TabsContent className="mt-5 space-y-5" value="community">
{tutorialOpen ? (
<CommunityComputeTutorialPanel
fixtureId={fixtureId}
onExit={() => setTutorialOpen(false)}
onFixtureChange={setFixtureId}
onStepChange={setTutorialStep}
step={tutorialStep}
/>
) : null}
<MeshComputeCommunityView
communityName={
tutorialOpen ? tutorialFixture.title : communityName
}
error={mesh.error}
onRefresh={mesh.refreshSnapshot}
simulated={tutorialOpen}
snapshot={tutorialOpen ? tutorialFixture.snapshot : mesh.snapshot}
tutorialInference={tutorialOpen}
/>
</TabsContent>
<TabsContent className="mt-8" value="settings">
<MeshComputeSettingsCard hideHeader />
</TabsContent>
</Tabs>
</div>
</section>
);
}

View File

@@ -68,7 +68,11 @@ const SHARE_COMPUTE_REVEAL_TRANSITION = {
* group. User-facing copy describes the shared-compute behavior without
* exposing implementation protocols or raw mesh controls.
*/
export function MeshComputeSettingsCard() {
export function MeshComputeSettingsCard({
hideHeader = false,
}: {
hideHeader?: boolean;
} = {}) {
const shouldReduceMotion = useReducedMotion();
const { status, error, refresh } = useMeshNodeStatus();
const [installedModels, setInstalledModels] = React.useState<
@@ -203,10 +207,12 @@ export function MeshComputeSettingsCard() {
return (
<section className="min-w-0" data-testid="settings-mesh-share-compute">
<SettingsSectionHeader
title="Share compute"
description="Provide compute to your Buzz community. More capacity can increase intelligence and availability of models for agents."
/>
{hideHeader ? null : (
<SettingsSectionHeader
title="Share compute"
description="Provide compute to your Buzz community. More capacity can increase intelligence and availability of models for agents."
/>
)}
{error ? (
<p className="mb-3 rounded-lg bg-destructive/10 px-3 py-2 text-sm text-destructive">

View File

@@ -0,0 +1,113 @@
import { Cpu, LoaderCircle } from "lucide-react";
import { Switch } from "@/shared/ui/switch";
import { cn } from "@/shared/lib/cn";
import type { useMeshComputeState } from "../hooks/useMeshComputeState";
export function MeshComputeShareBanner({
communityName,
mesh,
}: {
communityName: string;
mesh: ReturnType<typeof useMeshComputeState>;
}) {
const {
error,
modelToShare,
pendingAction,
shareSwitchChecked,
status,
toggle,
setSharing,
} = mesh;
const busy = pendingAction !== null;
const statusCopy = shareStatusCopy({
communityName,
modelToShare,
pendingAction,
statusModel: status?.modelName ?? status?.modelId ?? null,
isConsuming: toggle.isConsuming,
isSharing: toggle.isSharing,
});
return (
<section
className="rounded-2xl border border-border/70 bg-muted/15 px-4 py-3.5"
data-testid="compute-share-banner"
>
<div className="flex min-w-0 items-center gap-3">
<span
aria-hidden="true"
className={cn(
"flex size-9 shrink-0 items-center justify-center rounded-xl border border-border/70 bg-background",
toggle.isSharing && "border-foreground/30",
)}
>
{busy ? (
<LoaderCircle className="size-4 animate-spin motion-reduce:animate-none" />
) : (
<Cpu className="size-4" />
)}
</span>
<div className="min-w-0 flex-1">
<label
className="text-sm font-semibold"
htmlFor="compute-share-banner-toggle"
>
Share this machine
</label>
<p
className="mt-0.5 truncate text-xs text-muted-foreground"
data-testid="compute-share-banner-status"
title={statusCopy}
>
{statusCopy}
</p>
</div>
<Switch
checked={shareSwitchChecked}
data-testid="compute-share-banner-toggle"
disabled={busy || (!toggle.isSharing && !modelToShare)}
id="compute-share-banner-toggle"
onCheckedChange={setSharing}
/>
</div>
{error ? (
<p className="mt-2 text-xs text-destructive" role="alert">
{error}
</p>
) : null}
</section>
);
}
function shareStatusCopy({
communityName,
isConsuming,
isSharing,
modelToShare,
pendingAction,
statusModel,
}: {
communityName: string;
isConsuming: boolean;
isSharing: boolean;
modelToShare: string | null;
pendingAction: "start" | "stop" | null;
statusModel: string | null;
}): string {
if (pendingAction === "start") {
return `Preparing ${statusModel ?? modelToShare ?? "a model"} for ${communityName}…`;
}
if (pendingAction === "stop") return "Stopping shared compute…";
if (isSharing) {
return `${statusModel ?? modelToShare ?? "A model"} is available to ${communityName}`;
}
if (isConsuming) {
return "Using another member’s compute; turn this on to contribute instead";
}
if (modelToShare) {
return `${modelToShare} is ready to contribute to ${communityName}`;
}
return "Choose a model in Settings before sharing";
}

View File

@@ -7,7 +7,6 @@ import { cn } from "@/shared/lib/cn";
import { useMeshComputeState } from "../hooks/useMeshComputeState";
import type { MeshRowPulse, MeshRowTone } from "../meshRowModel";
import { MeshComputePopover } from "./MeshComputePopover";
/**
* The sidebar Shared Compute row.
@@ -97,49 +96,42 @@ export function SidebarMeshComputeRow({
const mesh = useMeshComputeState();
const { row, toggle, pendingAction, shareSwitchChecked, setSharing } = mesh;
// The row offers joining; the popover owns managing. Once this machine is
// sharing there is nothing left to invite, and the popover's labelled switch
// is the place to stop — a bare unlabelled switch is a poor control for an
// action with consequences.
// Clicking the row is navigation: Shared Compute opens the community Compute
// view. The trailing switch remains a separate action and does not navigate.
const showJoinToggle = !toggle.isSharing;
return (
<SidebarMenuItem>
<MeshComputePopover
mesh={mesh}
onOpenComputeSettings={onOpenComputeSettings}
<SidebarMenuButton
className={cn(
"data-[active=true]:font-normal",
// Reserve the trailing slot so the label truncates before it runs
// under the switch, rather than colliding with it.
showJoinToggle && "pr-11 group-data-[collapsible=icon]:!pr-0",
)}
data-mesh-tone={row.tone}
data-testid="sidebar-mesh-compute-row"
onClick={onOpenComputeSettings}
tooltip={row.tooltip}
type="button"
>
<SidebarMenuButton
className={cn(
"data-[active=true]:font-normal",
// Reserve the trailing slot so the label truncates before it runs
// under the switch, rather than colliding with it.
showJoinToggle && "pr-11 group-data-[collapsible=icon]:!pr-0",
)}
data-mesh-tone={row.tone}
data-testid="sidebar-mesh-compute-row"
tooltip={row.tooltip}
type="button"
<span
aria-hidden
className="relative flex h-4 w-4 shrink-0 items-center justify-center"
>
<span
aria-hidden
className="relative flex h-4 w-4 shrink-0 items-center justify-center"
>
<Waypoints className="h-4 w-4 opacity-80" />
{/*
<Waypoints className="h-4 w-4 opacity-80" />
{/*
Icon-collapsed only. The label and the dot beside it are both
clipped in icon mode, so without this the row would lose its status
signal entirely at exactly the width where the tooltip is the only
other affordance.
*/}
<span className="absolute -right-1 -bottom-1 hidden rounded-full bg-sidebar p-px group-data-[collapsible=icon]:block">
<MeshPulseDot pulse={row.pulse} size="small" tone={row.tone} />
</span>
<span className="absolute -right-1 -bottom-1 hidden rounded-full bg-sidebar p-px group-data-[collapsible=icon]:block">
<MeshPulseDot pulse={row.pulse} size="small" tone={row.tone} />
</span>
<SidebarMenuLabel className="opacity-80">
{row.label}
</SidebarMenuLabel>
{/*
</span>
<SidebarMenuLabel className="opacity-80">{row.label}</SidebarMenuLabel>
{/*
Right-aligned, the same position and mechanism a channel row uses for
its unread dot (`UnreadDotBadge className="ml-auto"`). Beside the name
it competed with the label for one optical line; here it reads as this
@@ -148,20 +140,18 @@ export function SidebarMeshComputeRow({
When the join switch is present the button carries `pr-11`, so the dot
lands clear of it rather than underneath.
*/}
<span className="ml-auto group-data-[collapsible=icon]:hidden">
<MeshPulseDot
pulse={row.pulse}
testId="mesh-row-dot"
tone={row.tone}
/>
</span>
</SidebarMenuButton>
</MeshComputePopover>
<span className="ml-auto group-data-[collapsible=icon]:hidden">
<MeshPulseDot
pulse={row.pulse}
testId="mesh-row-dot"
tone={row.tone}
/>
</span>
</SidebarMenuButton>
{/*
A sibling of the button, never a child: `PopoverTrigger asChild` makes the
button itself the trigger, so a switch nested inside would be a button
within a button and every toggle would also open the popover.
A sibling of the navigation button, never a child: nesting this switch
would make toggling sharing navigate away from the current view.
*/}
{showJoinToggle ? (
<div className="absolute top-1/2 right-2 -translate-y-1/2 group-data-[collapsible=icon]:hidden">

View File

@@ -77,7 +77,7 @@ import { ChannelTemplatesSettingsCard } from "./ChannelTemplatesSettingsCard";
import { HarnessesSettingsPanel } from "./HarnessesSettingsPanel";
import { ExperimentalFeaturesCard } from "./ExperimentalFeaturesCard";
import { KeyboardShortcutsCard } from "./KeyboardShortcutsCard";
import { MeshComputeSettingsCard } from "@/features/mesh-compute/ui/MeshComputeSettingsCard";
import { MeshComputePage } from "@/features/mesh-compute/ui/MeshComputePage";
import { MobilePairingCard } from "./MobilePairingCard";
import { ModerationQueueCard } from "./ModerationQueueCard";
import { NotificationSettingsCard } from "./NotificationSettingsCard";
@@ -883,7 +883,7 @@ export function renderSettingsSection(
case "channel-templates":
return <ChannelTemplatesSettingsCard />;
case "compute":
return <MeshComputeSettingsCard />;
return <MeshComputePage />;
case "appearance":
return <ThemeSettingsCard />;
case "shortcuts":

View File

@@ -156,6 +156,10 @@ export type MeshSnapshotDevice = {
models: string[];
state: MeshDeviceState;
isSelf: boolean;
/** Additive Community View fields. Older desktop/runtime pairs omit these. */
memberPubkey?: string | null;
reportedAt?: number | null;
modelSizeGb?: number | null;
};
/**
@@ -167,11 +171,17 @@ export type MeshSnapshotDevice = {
*/
export type MeshSnapshot = {
sharingDeviceCount: number;
/** Unique members with at least one ready serving device, when reported. */
contributorMemberCount?: number;
/** `null` when no sharing device reported a figure — render the count only. */
sharedCapacityGb: number | null;
/** Approximate hosted-model footprint when every contributor reports it. */
allocatedCapacityGb?: number | null;
models: string[];
devices: MeshSnapshotDevice[];
includesSelf: boolean;
observedAt?: number;
freshnessSeconds?: number;
/**
* Members in the community right now (NIP-43 roster size).
*

View File

@@ -1231,6 +1231,8 @@ declare global {
*/
nodeMode?: "serve" | "client" | null;
/** Seed host-side serving usage to exercise the "who's using my compute" indicator. */
snapshotDevices?: MockMeshSnapshotDevice[];
snapshotMemberCount?: number;
servingUsage?: Partial<{
inflight: number;
peakInflight: number;
@@ -3014,6 +3016,18 @@ function resetMockPersonaCatalogEvents(config: E2eConfig | undefined) {
// in a browser. They deliberately do NOT model real admission, real inference,
// or real mesh routing — those are proven by the Rust layer-2 tests and the
// on-hardware layer-1 example. Do not port any of this into production code.
type MockMeshSnapshotDevice = {
deviceId: string | null;
label: string;
capacityGb: number | null;
models: string[];
state: "serving" | "loading" | "standby" | "consuming";
isSelf: boolean;
memberPubkey?: string | null;
reportedAt?: number | null;
modelSizeGb?: number | null;
};
type MockServingUsage = {
inflight: number;
peakInflight: number;
@@ -3046,6 +3060,8 @@ const mockMeshState: {
nodeState: "off" | "running";
nodeMode: "serve" | "client" | null;
servingUsage: MockServingUsage;
snapshotDevices: MockMeshSnapshotDevice[] | null;
snapshotMemberCount: number | null;
} = {
admitted: true,
models: [{ id: "Gemma-4-E4B-it-Q4_K_M", name: "Gemma 4 E4B" }],
@@ -3054,6 +3070,8 @@ const mockMeshState: {
nodeState: "off",
nodeMode: null,
servingUsage: { ...ZERO_SERVING_USAGE },
snapshotDevices: null,
snapshotMemberCount: null,
};
function resetMockMesh() {
@@ -3064,6 +3082,8 @@ function resetMockMesh() {
mockMeshState.nodeState = "off";
mockMeshState.nodeMode = null;
mockMeshState.servingUsage = { ...ZERO_SERVING_USAGE };
mockMeshState.snapshotDevices = null;
mockMeshState.snapshotMemberCount = null;
}
let mockPersonas: RawPersona[] = [];
let mockTeams: RawTeam[] = [];
@@ -10253,6 +10273,10 @@ export function maybeInstallE2eTauriMocks() {
mockMeshState.denyReason = mesh.denyReason;
if (mesh.nodeState !== undefined) mockMeshState.nodeState = mesh.nodeState;
if (mesh.nodeMode !== undefined) mockMeshState.nodeMode = mesh.nodeMode;
if (mesh.snapshotDevices !== undefined)
mockMeshState.snapshotDevices = mesh.snapshotDevices;
if (mesh.snapshotMemberCount !== undefined)
mockMeshState.snapshotMemberCount = mesh.snapshotMemberCount;
if (mesh.servingUsage !== undefined)
mockMeshState.servingUsage = {
...mockMeshState.servingUsage,
@@ -10916,19 +10940,54 @@ export function maybeInstallE2eTauriMocks() {
return meshNodeStatus(mockMeshState.nodeState, mockMeshState.nodeMode);
case "mesh_serving_usage":
return mockMeshState.servingUsage;
case "mesh_snapshot":
case "mesh_snapshot": {
const devices =
mockMeshState.snapshotDevices ??
(mockMeshState.nodeMode === "serve" && mockMeshState.activeModel
? [
{
deviceId: "mock-self",
label: "This machine",
capacityGb: 32,
models: [mockMeshState.activeModel.id],
state: "serving" as const,
isSelf: true,
memberPubkey: MOCK_IDENTITY_PUBKEY,
reportedAt: Math.floor(Date.now() / 1000),
modelSizeGb: 3.5,
},
]
: []);
const serving = devices.filter((device) => device.state === "serving");
return {
sharingDeviceCount: mockMeshState.nodeMode === "serve" ? 1 : 0,
sharedCapacityGb: mockMeshState.nodeMode === "serve" ? 32 : null,
models: mockMeshState.activeModel
? [mockMeshState.activeModel.id]
: [],
devices: [],
includesSelf: mockMeshState.nodeMode === "serve",
memberCount: 1,
reason:
mockMeshState.nodeMode === "serve" ? null : "No one is sharing",
sharingDeviceCount: serving.length,
contributorMemberCount: new Set(
serving.map((device) => device.memberPubkey ?? device.deviceId),
).size,
sharedCapacityGb:
serving.length > 0
? serving.reduce(
(total, device) => total + (device.capacityGb ?? 0),
0,
)
: null,
allocatedCapacityGb:
serving.length > 0 &&
serving.every((device) => device.modelSizeGb != null)
? serving.reduce(
(total, device) => total + (device.modelSizeGb ?? 0),
0,
)
: null,
models: [...new Set(serving.flatMap((device) => device.models))],
devices,
includesSelf: serving.some((device) => device.isSelf),
memberCount: mockMeshState.snapshotMemberCount ?? 1,
observedAt: Math.floor(Date.now() / 1000),
freshnessSeconds: 120,
reason: serving.length > 0 ? null : "No one is sharing",
};
}
case "mesh_live_view":
return {
connected: mockMeshState.nodeState === "running",

View File

@@ -53,10 +53,18 @@ export default {
"0%, 100%": { opacity: "1" },
"50%": { opacity: "0.25" },
},
"mesh-breath": {
"0%, 100%": { fill: "hsl(var(--foreground))" },
"50%": {
fill: "color-mix(in oklab, hsl(var(--foreground)) 25%, hsl(var(--background)))",
},
},
},
animation: {
// Work in flight right now.
"mesh-activity": "mesh-dim 1s cubic-bezier(0.4, 0, 0.6, 1) infinite",
"mesh-inference":
"mesh-breath var(--mesh-breath-duration, 4.8s) ease-in-out infinite",
// A start or stop in flight. Slower: nothing is wrong, and nothing needs
// a decision.
"mesh-progress": "mesh-dim 1.8s cubic-bezier(0.4, 0, 0.6, 1) infinite",

View File

@@ -0,0 +1,36 @@
import { expect, test } from "@playwright/test";
import { installMockBridge } from "../helpers/bridge";
import { openSettings } from "../helpers/settings";
import { waitForAnimations } from "../helpers/animations";
test("captures the Community Compute tutorial", async ({ page }) => {
await installMockBridge(page);
await page.goto("/");
await openSettings(page, "compute");
await page.getByTestId("community-compute-tutorial-button").click();
await expect(
page.getByTestId("community-compute-territory-map"),
).toBeVisible();
await expect(page.getByTestId("compute-share-banner")).toHaveCount(0);
await waitForAnimations(page);
await page.getByTestId("settings-panel-compute").screenshot({
path: "test-results/mesh-compute/community-tutorial.png",
});
await page.getByTestId("community-compute-territory-map").screenshot({
path: "test-results/mesh-compute/community-map.png",
});
await page.getByLabel("Preview scenario").selectOption("large-dense-500");
await expect(
page.getByTestId("community-compute-kpi-members-sharing"),
).toContainText("458");
await expect(page.locator("[data-cell-count]")).toHaveCount(458);
await expect(
page.locator('[data-inference-active="true"]').first(),
).toBeVisible();
await waitForAnimations(page);
await page.getByTestId("settings-panel-compute").screenshot({
path: "test-results/mesh-compute/community-dense.png",
});
});

View File

@@ -12,6 +12,17 @@ type E2eWindow = Window & {
__BUZZ_E2E_SET_MESH__?: (mesh: {
nodeState?: "off" | "running";
nodeMode?: "serve" | "client" | null;
snapshotMemberCount?: number;
snapshotDevices?: Array<{
deviceId: string;
label: string;
capacityGb: number;
models: string[];
state: "serving" | "loading" | "standby" | "consuming";
isSelf: boolean;
memberPubkey?: string;
modelSizeGb?: number;
}>;
}) => void;
};
@@ -20,6 +31,7 @@ test("Share compute chooses a model before sharing", async ({ page }) => {
await installMockBridge(page);
await page.goto("/");
await openSettings(page, "compute");
await page.getByTestId("compute-tab-settings").click();
const card = page.getByTestId("settings-mesh-share-compute");
const toggle = page.getByTestId("mesh-share-compute-toggle");
@@ -115,6 +127,7 @@ test("a consuming client can switch to sharing its saved local model", async ({
});
});
await openSettings(page, "compute");
await page.getByTestId("compute-tab-settings").click();
const card = page.getByTestId("settings-mesh-share-compute");
const toggle = page.getByTestId("mesh-share-compute-toggle");
@@ -147,3 +160,134 @@ test("a consuming client can switch to sharing its saved local model", async ({
},
});
});
test("Shared Compute sidebar row opens the Compute community view", async ({
page,
}) => {
await installMockBridge(page);
await page.goto("/");
await page.getByTestId("sidebar-mesh-compute-row").click();
await expect(page.getByTestId("settings-mesh-compute-page")).toBeVisible();
await expect(page.getByTestId("compute-tab-community")).toHaveAttribute(
"data-state",
"active",
);
await expect(page.getByTestId("community-compute-view")).toBeVisible();
await expect(page.getByTestId("mesh-compute-popover")).toHaveCount(0);
});
test("Community Compute shows live KPIs and the tutorial simulation", async ({
page,
}) => {
await installMockBridge(page);
await page.goto("/");
await page.waitForFunction(
() => typeof (window as E2eWindow).__BUZZ_E2E_SET_MESH__ === "function",
);
await page.evaluate(() => {
(window as E2eWindow).__BUZZ_E2E_SET_MESH__?.({
snapshotMemberCount: 7,
snapshotDevices: [
{
deviceId: "alpha",
label: "Alpha Studio",
capacityGb: 64,
models: ["qwen-32b"],
state: "serving",
isSelf: false,
memberPubkey: "member-alpha",
modelSizeGb: 28,
},
{
deviceId: "beta",
label: "Beta Workstation",
capacityGb: 32,
models: ["gemma-12b"],
state: "serving",
isSelf: false,
memberPubkey: "member-beta",
modelSizeGb: 12,
},
],
});
});
await openSettings(page, "compute");
await expect(page.getByTestId("compute-share-banner")).toBeVisible();
await expect(
page.getByTestId("community-compute-kpi-members-sharing"),
).toContainText("2");
await expect(
page.getByTestId("community-compute-kpi-contributed-vram"),
).toContainText("96 GB");
await expect(
page.getByTestId("community-compute-kpi-vram-allocated"),
).toContainText("42%");
await expect(
page.getByTestId("community-compute-territory-map"),
).toBeVisible();
await expect(
page.getByTestId("community-compute-deployment-list"),
).toContainText("Alpha Studio");
await page.getByLabel("Search deployments").fill("Beta");
await expect(
page.getByTestId("community-compute-deployment-list"),
).toContainText("Beta Workstation");
await expect(
page.getByTestId("community-compute-deployment-list"),
).not.toContainText("Alpha Studio");
await page.getByLabel("Search deployments").fill("");
const tutorialButton = page.getByTestId("community-compute-tutorial-button");
await tutorialButton.click();
await expect(tutorialButton).toHaveAttribute("aria-pressed", "true");
await expect(
page.getByTestId("community-compute-simulated-banner"),
).toBeVisible();
await expect(
page.getByTestId("community-compute-tutorial-panel"),
).toContainText("Every territory is a model deployment");
await expect(page.getByTestId("compute-share-banner")).toHaveCount(0);
const tutorialTile = page
.locator('[data-inference-active="true"]')
.first()
.getByTestId("community-compute-tile")
.first();
await expect(tutorialTile).toBeVisible();
await expect
.poll(() =>
tutorialTile.evaluate(
(element) => getComputedStyle(element).animationName,
),
)
.toBe("mesh-breath");
await page.getByLabel("Preview scenario").selectOption("single-device");
await expect(
page.getByTestId("community-compute-kpi-members-sharing"),
).toContainText("1");
await page.getByRole("button", { name: "Next" }).click();
await expect(
page.getByTestId("community-compute-tutorial-panel"),
).toContainText("Area represents memory");
await page.getByRole("button", { name: "Next" }).click();
await expect(
page.getByTestId("community-compute-tutorial-panel"),
).toContainText("Motion illustrates inference in flight");
const territory = page.locator("[data-cell-count]").first();
await territory.click();
await expect(territory).toHaveAttribute("data-selected", "true");
await territory.hover();
await expect(
page.getByTestId("community-compute-hover-details"),
).toContainText("Simulated inference");
await tutorialButton.click();
await expect(tutorialButton).toHaveAttribute("aria-pressed", "false");
await expect(
page.getByTestId("community-compute-simulated-banner"),
).toHaveCount(0);
await expect(
page.getByTestId("community-compute-kpi-members-sharing"),
).toContainText("2");
});