diff --git a/frontend/src/components/world/WorldCanvas.tsx b/frontend/src/components/world/WorldCanvas.tsx index 725abe0..fb69764 100644 --- a/frontend/src/components/world/WorldCanvas.tsx +++ b/frontend/src/components/world/WorldCanvas.tsx @@ -181,6 +181,7 @@ export function WorldCanvas({ roots, selectedId, onSelect, expanded, onToggleExp live.on("agent.status", (d) => e.onStatus(d)), live.on("world.touch", (d) => e.onTouch(d)), live.on("node.activity", (d) => e.onNodeActivity(d)), + live.on("agent.reasoning.delta", (d) => e.onReasoning(d.agentId)), ]; return () => offs.forEach((off) => off()); }, [live, mode]); @@ -434,15 +435,15 @@ export function WorldCanvas({ roots, selectedId, onSelect, expanded, onToggleExp const renderBrain = (dt: number) => { // Neurons = agents (bright, drive firing) + structure nodes (org/company/ // team) as a dim support mesh, so even a near-idle brain has body. - type Neuron = { id: string; color: string; agent: boolean; boost: number }; + type Neuron = { id: string; color: string; fire: string; agent: boolean; boost: number }; const neurons: Neuron[] = []; for (const p of engine.pawns.values()) { const recent = p.idle < 2.5 ? 1 : 0; // a recent touch lights the neuron - neurons.push({ id: p.id, color: p.color, agent: true, boost: (p.status === "working" ? 0.9 : 0) + recent }); + neurons.push({ id: p.id, color: p.color, fire: p.fireColor ?? p.color, agent: true, boost: (p.status === "working" ? 0.9 : 0) + recent }); } for (const n of engine.nodes.values()) { if (n.tier === "org" || n.tier === "company" || n.tier === "team") - neurons.push({ id: n.id, color: n.color, agent: false, boost: n.heat }); + neurons.push({ id: n.id, color: n.color, fire: n.color, agent: false, boost: n.heat }); } const ids = neurons.map((n) => n.id); const seen = new Set(ids); @@ -480,7 +481,7 @@ export function WorldCanvas({ roots, selectedId, onSelect, expanded, onToggleExp const dz = tp.z - pos.z; const len = Math.hypot(dx, dy, dz) || 1; const speed = 150; - spawn(pos.x, pos.y, pos.z, ne.color, (dx / len) * speed, (dy / len) * speed, (dz / len) * speed, speed / len + 0.25); + spawn(pos.x, pos.y, pos.z, ne.fire, (dx / len) * speed, (dy / len) * speed, (dz / len) * speed, speed / len + 0.25); neuronAct.set(tid, Math.min(1, (neuronAct.get(tid) ?? 0.05) + 0.14)); } } @@ -928,6 +929,16 @@ export function WorldCanvas({ roots, selectedId, onSelect, expanded, onToggleExp ) : null} + {formation === "hierarchy" ? ( +
+ {([["#c98af0", "think"], ["#5ec8d8", "tool"], ["#ff6f61", "file"], ["#5fd08a", "run"]] as const).map(([c, l]) => ( + + + {l} + + ))} +
+ ) : null} {/* WorldClock — live ⇄ replay (Gource-style playback of run history) */}
= 0.9 ? "#ff6f61" : "#5ec8d8"; + else if (e.nodeId.startsWith("run:")) p.fireColor = "#5fd08a"; + } + + /** A reasoning token from an agent — marks it active and tints its signals. */ + onReasoning(agentId: string) { + const p = this.ensurePawn(agentId); + p.fireColor = "#c98af0"; // think = purple + p.idle = 0; } onNodeActivity(e: TaxonomyEvents["node.activity"]) { const node = this.ensureNode(e.nodeId, e.kind === "event" ? "event" : "service", e.label ?? e.nodeId, ROOT, 1);