Spaces:
Running on Zero
Running on Zero
GitHub Actions
feat: WebLLM browser agent with PeerJS mesh, HybridRAG, news signals, and easter-egg ticker
78cc96f | // src/mesh/browsermesh.js | |
| // Over-the-internet browser mesh using PeerJS (WebRTC). JavaScript only. | |
| // | |
| // Design (BitTorrent/rendezvous style, no custom server): | |
| // - DISCOVERY: a well-known "anchor" peer id is derived from the room name. | |
| // The first browser in a room claims that id and becomes the anchor. The | |
| // anchor only gossips a roster of member ids β it is a rendezvous point. | |
| // - DATA: every browser also runs its own random-id "self" peer. Members use | |
| // the roster to open direct WebRTC data channels to each other => full mesh. | |
| // - FAILOVER: if the anchor leaves, its id frees up and remaining members | |
| // periodically try to re-claim it, so the mesh self-heals. | |
| // | |
| // Requires global `Peer` from https://unpkg.com/peerjs (loaded in index.html). | |
| function slug(s) { | |
| return String(s || "default").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, ""); | |
| } | |
| export function createMesh({ room = "hearthnet", name = "anon", onStatus, onPeers, onMessage } = {}) { | |
| const Peer = globalThis.Peer; | |
| if (!Peer) throw new Error("PeerJS not loaded (expected global `Peer`)."); | |
| const anchorId = `hn-anchor-${slug(room)}`; | |
| const peers = new Map(); // selfId -> { conn, name } | |
| let self = null; // my mesh identity (random id) | |
| let selfId = null; | |
| let anchor = null; // Peer bound to anchorId if I'm the anchor | |
| let anchorConn = null; // my connection to the anchor (if I'm a member) | |
| let isAnchor = false; | |
| let reclaimTimer = null; | |
| let alive = false; | |
| const status = (extra = {}) => | |
| onStatus?.({ room, anchorId, selfId, isAnchor, peers: [...peers.keys()], ...extra }); | |
| const roster = () => [selfId, ...peers.keys()].filter(Boolean); | |
| // ββ data mesh (self <-> self direct channels) ββββββββββββββββββββββββββββββ | |
| function wireDataConn(conn) { | |
| conn.on("open", () => { | |
| peers.set(conn.peer, { conn, name: conn.metadata?.name || conn.peer.slice(0, 6) }); | |
| conn.send({ type: "presence", payload: { name } }); | |
| onPeers?.(listPeers()); | |
| status(); | |
| }); | |
| conn.on("data", (msg) => { | |
| if (!msg || typeof msg !== "object") return; | |
| if (msg.type === "presence" && peers.has(conn.peer)) { | |
| peers.get(conn.peer).name = msg.payload?.name || peers.get(conn.peer).name; | |
| onPeers?.(listPeers()); | |
| } | |
| onMessage?.({ from: conn.peer, fromName: peers.get(conn.peer)?.name, type: msg.type, payload: msg.payload }); | |
| }); | |
| const drop = () => { | |
| if (peers.delete(conn.peer)) { | |
| onPeers?.(listPeers()); | |
| status(); | |
| } | |
| }; | |
| conn.on("close", drop); | |
| conn.on("error", drop); | |
| } | |
| function connectTo(peerId) { | |
| if (!peerId || peerId === selfId || peers.has(peerId)) return; | |
| const conn = self.connect(peerId, { reliable: true, metadata: { name } }); | |
| wireDataConn(conn); | |
| } | |
| function applyRoster(ids) { | |
| for (const id of ids) connectTo(id); | |
| } | |
| // ββ anchor role: gossip the roster to all anchor clients βββββββββββββββββββ | |
| function becomeAnchor() { | |
| isAnchor = true; | |
| const known = new Set([selfId]); | |
| const clients = new Set(); | |
| const broadcast = () => { | |
| const members = [...known]; | |
| for (const c of clients) { | |
| try { | |
| c.send({ type: "roster", payload: { members } }); | |
| } catch { /* client gone */ } | |
| } | |
| }; | |
| anchor.on("connection", (c) => { | |
| c.on("open", () => { | |
| clients.add(c); | |
| c.on("data", (m) => { | |
| if (m?.type === "hello" && m.payload?.selfId) { | |
| known.add(m.payload.selfId); | |
| broadcast(); | |
| } | |
| }); | |
| // tell the newcomer the current roster (incl. the anchor's own self id) | |
| c.send({ type: "roster", payload: { members: [...known] } }); | |
| broadcast(); | |
| }); | |
| const gone = () => { | |
| clients.delete(c); | |
| }; | |
| c.on("close", gone); | |
| c.on("error", gone); | |
| }); | |
| status({ note: "became anchor" }); | |
| } | |
| // ββ member role: connect to the anchor, learn the roster βββββββββββββββββββ | |
| function joinViaAnchor() { | |
| anchorConn = self.connect(anchorId, { reliable: true, metadata: { name } }); | |
| anchorConn.on("open", () => { | |
| anchorConn.send({ type: "hello", payload: { selfId } }); | |
| clearReclaim(); | |
| }); | |
| anchorConn.on("data", (m) => { | |
| if (m?.type === "roster") applyRoster(m.payload?.members || []); | |
| }); | |
| const lost = () => { | |
| anchorConn = null; | |
| scheduleReclaim(); // anchor may have left β try to take over discovery | |
| }; | |
| anchorConn.on("close", lost); | |
| anchorConn.on("error", lost); | |
| } | |
| function tryClaimAnchor() { | |
| if (!alive || isAnchor) return; | |
| const a = new Peer(anchorId); | |
| a.on("open", () => { | |
| anchor = a; | |
| becomeAnchor(); | |
| }); | |
| a.on("error", (err) => { | |
| a.destroy?.(); | |
| if (err?.type === "unavailable-id") { | |
| // someone else is the anchor β connect to it | |
| if (!anchorConn) joinViaAnchor(); | |
| } | |
| }); | |
| } | |
| function scheduleReclaim() { | |
| clearReclaim(); | |
| reclaimTimer = setInterval(tryClaimAnchor, 4000 + Math.random() * 3000); | |
| } | |
| function clearReclaim() { | |
| if (reclaimTimer) clearInterval(reclaimTimer); | |
| reclaimTimer = null; | |
| } | |
| function listPeers() { | |
| return [...peers.entries()].map(([id, v]) => ({ id, name: v.name })); | |
| } | |
| // ββ public API βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| function join() { | |
| if (alive) return; | |
| alive = true; | |
| self = new Peer(); // random id | |
| self.on("open", (id) => { | |
| selfId = id; | |
| status({ note: "self online" }); | |
| self.on("connection", (conn) => wireDataConn(conn)); // accept inbound mesh links | |
| tryClaimAnchor(); | |
| scheduleReclaim(); | |
| }); | |
| self.on("error", (err) => status({ error: err?.type || String(err) })); | |
| } | |
| function leave() { | |
| alive = false; | |
| clearReclaim(); | |
| for (const { conn } of peers.values()) conn.close?.(); | |
| peers.clear(); | |
| anchorConn?.close?.(); | |
| anchor?.destroy?.(); | |
| self?.destroy?.(); | |
| self = anchor = anchorConn = null; | |
| selfId = null; | |
| isAnchor = false; | |
| onPeers?.([]); | |
| status({ note: "left" }); | |
| } | |
| function broadcast(type, payload) { | |
| for (const { conn } of peers.values()) { | |
| try { | |
| conn.send({ type, payload }); | |
| } catch { /* peer gone */ } | |
| } | |
| } | |
| function send(peerId, type, payload) { | |
| peers.get(peerId)?.conn?.send({ type, payload }); | |
| } | |
| return { | |
| join, | |
| leave, | |
| broadcast, | |
| send, | |
| get id() { return selfId; }, | |
| get peers() { return listPeers(); }, | |
| get isAnchor() { return isAnchor; }, | |
| get room() { return room; }, | |
| }; | |
| } | |