mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
fix(mesh): state what is shared plainly, and scope the memory meter
Drops two captions that hedged or mislabeled facts we have. "Join to see live detail" was wrong twice over: in that state the only thing to join is sharing, and the field already shows what the community has published. "Last reported by the community" annotated a real fact with doubt -- the notes are current within 120s, and what we know is shared should be shown as shared. The live-vs-relay difference is already carried by the geometry: relay nodes get no synthetic RTT, and the centre is hollow with no spokes because adjacency is what we cannot assert. A caption repeating that was noise. The only surviving caption states something the drawing cannot: alone on the mesh. The memory meter is per-node and now says so -- "This computer · model uses 10 GB of 40 GB". It sits directly beneath a radar field showing the whole community, so an unqualified figure read as mesh-wide utilization: a number nobody has, since members publish their own capacity but nothing about each other's live allocation. A test pins the scoping rather than the wording. Signed-off-by: Michael Neale <michael.neale@gmail.com>
This commit is contained in:
@@ -84,7 +84,14 @@ test("relay nodes carry no RTT and claim no membership", () => {
|
||||
// A hollow centre and no spokes depend on this staying false.
|
||||
assert.equal(field.selfParticipating, false);
|
||||
assert.equal(field.selfCapacityGb, null);
|
||||
assert.match(field.caption, /Last reported/);
|
||||
});
|
||||
|
||||
test("the relay view is not hedged with a caption", () => {
|
||||
// What we know is shared gets shown as shared. Annotating it with "last
|
||||
// reported" hedged a fact we actually have, and the old "join to see live
|
||||
// detail" mislabeled sharing as joining.
|
||||
const field = deriveMeshFieldModel({ view: null, snapshot: snapshot() });
|
||||
assert.equal(field.caption, null);
|
||||
});
|
||||
|
||||
test("our own note is excluded so we are never drawn twice", () => {
|
||||
@@ -132,5 +139,5 @@ test("a solo sharer is told it is waiting, not that it is alone in error", () =>
|
||||
snapshot: null,
|
||||
});
|
||||
assert.equal(field.source, "live");
|
||||
assert.match(field.caption, /waiting for another device/);
|
||||
assert.equal(field.caption, "Waiting for another device");
|
||||
});
|
||||
|
||||
@@ -13,14 +13,16 @@ import type { MeshFieldNode } from "./ui/MeshRadarField";
|
||||
* renders either way, and the earlier "turn on sharing to see who's on the
|
||||
* mesh" was simply wrong.
|
||||
*
|
||||
* The two are not equivalent, and the difference is not cosmetic:
|
||||
* The two are not equivalent, and the difference is expressed in the geometry
|
||||
* rather than in a hedging caption — what we know is shared gets shown either
|
||||
* way, and the drawing simply does not assert more than it can:
|
||||
*
|
||||
* - **live**: reachable now, RTT known, adjacency to us is real
|
||||
* - **relay**: last known within 120s, no RTT, adjacency unknown
|
||||
* - **relay**: published within the last 120s, no RTT, adjacency unknown
|
||||
*
|
||||
* So relay nodes get no RTT (they land mid-band rather than faking proximity),
|
||||
* the caller draws no spokes when we have not joined, and the caption names
|
||||
* which view is on screen. Never dress last-known state as live.
|
||||
* and the caller draws no spokes and a hollow centre when we have not joined,
|
||||
* because a spoke would assert a connection we do not have.
|
||||
*/
|
||||
|
||||
export type MeshFieldSource = "live" | "relay" | "none";
|
||||
@@ -38,7 +40,13 @@ export type MeshFieldModel = {
|
||||
* so ghosts never contribute capacity — they are the invitation, not a total.
|
||||
*/
|
||||
ghostCount: number;
|
||||
/** Caption naming the source, or null when there is nothing to qualify. */
|
||||
/**
|
||||
* Short caption, or null.
|
||||
*
|
||||
* Only ever states a fact the field cannot draw — currently just "alone on
|
||||
* the mesh". Never used to hedge the relay view: what we know is shared is
|
||||
* shown as shared, not annotated with doubt.
|
||||
*/
|
||||
caption: string | null;
|
||||
};
|
||||
|
||||
@@ -68,10 +76,7 @@ export function deriveMeshFieldModel({
|
||||
selfParticipating: true,
|
||||
selfCapacityGb: view.selfCapacityGb,
|
||||
ghostCount,
|
||||
caption:
|
||||
view.peers.length === 0
|
||||
? "Connected · waiting for another device"
|
||||
: null,
|
||||
caption: view.peers.length === 0 ? "Waiting for another device" : null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -103,6 +108,6 @@ export function deriveMeshFieldModel({
|
||||
selfParticipating: false,
|
||||
selfCapacityGb: null,
|
||||
ghostCount,
|
||||
caption: "Last reported by the community · join to see live detail",
|
||||
caption: null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ test("prefers the runtime's reported model footprint", () => {
|
||||
catalog,
|
||||
modelRef: "gemma",
|
||||
});
|
||||
assert.equal(model.label, "10 GB of 40 GB AI memory used by model");
|
||||
assert.equal(model.label, "This computer · model uses 10 GB of 40 GB");
|
||||
assert.equal(model.usedSegments, 3);
|
||||
});
|
||||
|
||||
@@ -43,7 +43,7 @@ test("falls back to the selected catalog model before runtime status arrives", (
|
||||
catalog,
|
||||
modelRef: "gemma",
|
||||
});
|
||||
assert.equal(model.label, "8 GB of 32 GB AI memory used by model");
|
||||
assert.equal(model.label, "This computer · model uses 8 GB of 32 GB");
|
||||
assert.equal(model.usedSegments, 3);
|
||||
});
|
||||
|
||||
@@ -53,6 +53,32 @@ test("unknown model size shows available memory without inventing use", () => {
|
||||
catalog,
|
||||
modelRef: "custom/model",
|
||||
});
|
||||
assert.equal(model.label, "32 GB AI memory available");
|
||||
assert.equal(model.label, "This computer · 32 GB AI memory");
|
||||
assert.equal(model.usedSegments, 0);
|
||||
});
|
||||
|
||||
test("every label names this computer, never the mesh", () => {
|
||||
// The meter sits directly under a radar field showing the whole community.
|
||||
// An unqualified "10 of 40 GB" would read as mesh-wide utilization, which is
|
||||
// a number nobody has: members publish their own capacity, not each other's
|
||||
// live allocation.
|
||||
const cases = [
|
||||
{
|
||||
view: {
|
||||
connected: true,
|
||||
selfCapacityGb: 40,
|
||||
selfModelSizeGb: 10,
|
||||
peers: [],
|
||||
},
|
||||
catalog,
|
||||
modelRef: "gemma",
|
||||
},
|
||||
{ view: null, catalog, modelRef: "gemma" },
|
||||
{ view: null, catalog, modelRef: "custom/model" },
|
||||
{ view: null, catalog: null, modelRef: null },
|
||||
];
|
||||
for (const input of cases) {
|
||||
const model = deriveMeshMemoryModel(input);
|
||||
assert.match(model.label, /this computer/i, model.label);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -11,9 +11,16 @@ export type MeshMemoryModel = {
|
||||
};
|
||||
|
||||
/**
|
||||
* Approximate model footprint against this machine's shareable AI memory.
|
||||
* MeshLLM reports model package size, not live OS GPU allocation, so the UI
|
||||
* deliberately says "model uses" rather than claiming real-time utilization.
|
||||
* Approximate model footprint against **this machine's** shareable AI memory.
|
||||
*
|
||||
* Scoped to this node on purpose, and the label says so. It sits directly under
|
||||
* a radar field showing the whole community, so an unqualified "36 of 115 GB"
|
||||
* would read as mesh-wide utilization — a number we do not have and could not
|
||||
* compute, since members publish their own capacity but nothing about each
|
||||
* other's live allocation.
|
||||
*
|
||||
* MeshLLM reports model package size, not live OS GPU allocation, so the label
|
||||
* says the model "uses" rather than claiming real-time utilization.
|
||||
*/
|
||||
export function deriveMeshMemoryModel({
|
||||
view,
|
||||
@@ -47,12 +54,14 @@ export function deriveMeshMemoryModel({
|
||||
usedGb,
|
||||
usedSegments,
|
||||
totalSegments: MEMORY_SEGMENTS,
|
||||
// "This computer" leads, because the meter sits under a community-wide
|
||||
// radar field and must not be read as mesh utilization.
|
||||
label:
|
||||
usedGb != null && totalGb != null
|
||||
? `${formatGb(usedGb)} of ${formatGb(totalGb)} AI memory used by model`
|
||||
? `This computer · model uses ${formatGb(usedGb)} of ${formatGb(totalGb)}`
|
||||
: totalGb != null
|
||||
? `${formatGb(totalGb)} AI memory available`
|
||||
: "Checking available AI memory…",
|
||||
? `This computer · ${formatGb(totalGb)} AI memory`
|
||||
: "Checking this computer's AI memory…",
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user