Back to list

Development Update — July 6

A heavy day on the browser visor and the tooling around it. The wasm-visor stopped re-booting itself every time you opened a tab, learned to narrate its own connection process instead of flashing a scary error during the connection window, and — in its single-file form — was made to run straight from file:// again. The transport graph was wired to source its data over dmsg so the standalone tool works against the dmsg-only deployment, and its GPU view learned to group by country like the flat view. Underneath all of it, a connection leak that had grown the transport-discovery node’s heap to ~4GB was tracked down and fixed, and the hypervisor UI gained a group-chat interface.

Skywire: One Visor per Origin

3398 feat(wasm-hv): one shared wasm-visor per origin (SharedWorker) changes the browser visor from one-per-tab to one-per-origin. Previously every tab booted its own visor; the Web Locks single-instance guard prevented two clients colliding but could not preserve the running one — it reload-handed-off the identity between tabs, paying a full ~10–20s re-boot each time. The worker is now a SharedWorker: the first tab boots the visor once, later tabs attach to the running one over a MessagePort, and it stays alive while any tab is connected — so opening, switching and closing tabs no longer re-boots the dmsg client, router or identity. It stays dual-mode, falling back to a per-tab dedicated worker where SharedWorker is unavailable, and — since no worker can hold an RTCPeerConnection — delegates WebRTC/STUN to exactly one elected agent tab so the only NAT-piercing carrier is preserved rather than dropped. Validated on Chrome 149: a second tab attaches to the same visor PK in ~2s with no re-boot and no “already running” notice.

3397 feat(wasm-hv): connecting-to-the-mesh state + live connection journey replaces a transient error with an honest progress view. Opening a dmsg site issues a fetch immediately; if the visor’s dmsg client hasn’t established a session yet the core returns “not booted”, and the iframe used to render a scary “couldn’t reach this site” error that then self-corrected ~10s later once dmsg came up. The render path now waits for a live dmsg session first, showing a “Connecting to the mesh…” page meanwhile — and that page is a live journey log: it streams the visor’s own connection events as they happen (boot, peer listeners, STUN IP, the autoconnect dial attempts and their WT/WS fallbacks) from the runtime-logs ring. If the attempt ultimately fails, the trail freezes below the error as the whole journey rather than one code — reflecting the design conclusion that a skynet/dmsg connection is an adaptive multi-step process, not a request-and-one-code exchange.

3399 feat(wasm-hv): make the serverless single-file visor (cli hv gen) work from file:// repairs the self-contained hypervisor.html, which runs a full visor from file:// with no server and had regressed to a blank page. Several file:// issues were fixed in one pass: the Angular router threw SecurityError on an opaque origin (now guarded so hash routing proceeds), /api was misrouted because relative URLs resolved against the .html path instead of the app root, an XHR shim broke zone.js (rewritten as a real XMLHttpRequest subclass mapping assets to data: URLs), i18n and icon fonts were switched to loaders that work from file://, and a charset/mojibake bug was fixed by leading the injected head with <meta charset>. The same PR also fixes skywire.dmsg on all wasm-visors, which 404’d while native visors served it.

Skywire: Group Chat in the UI

3407 feat(skychat): group-chat UI in the hvui (native + wasm) puts a face on the skychat federated group backend, which already exposed GroupCreate/Join/Send/Poll/AddMember/Invite over RPC but had no UI driving it — the skychat tab was 1:1 only. It adds a Direct/Groups mode toggle with a rooms sidebar, per-room log and composer, roster add-member and invite links. The transport is split like the DM path: a wasm visor drives the in-process skychatGroup* hooks, while a native visor goes over a new hypervisor HTTP bridge that forwards to the group RPC (its POSTs routed through the CSRF-aware API service), so the same UI works on both. Live wasm↔native federation testing also surfaced and fixed a real backend blocker behind the UI: Join was hard-failing and deleting the membership on a transient owner-feed subscribe timeout — common for a browser wasm visor over WS or during deploy churn — so a perfectly joinable group looked permanently un-joinable; a transient dial timeout is now treated as non-fatal (join optimistically, the reconnect watchdog completes it), while an allowlist rejection stays fatal.

Skywire: The Transport Graph over dmsg

3401 fix(tp-viz): wire the CXO subscriber (+ dmsg HTTP fallback) into standalone cli tp viz fixes an empty graph. Standalone cli tp viz never sourced data over dmsg, so against the current dmsg-only deployment every /api/* endpoint failed with “dmsg URL requested but no dmsg HTTP client set” unless run via --visor or the reward server. It now bootstraps an ephemeral dmsg client and installs both the CXO subscriber (CXO-first) and an HTTP-over-dmsg client as fallback, and builds its config from tpviz.DefaultConfig() so the CXO feed publisher PKs are actually set — without them the subscriber has no publisher and silently falls back to HTTP for every feed. Validated live: transports and uptimes now serve from CXO and the graph renders 1019 visors, matching the reward system and hypervisor UI.

3402 feat(tpviz): country/IP grouping in the WebGL (cosmos) view makes the new GPU view group like the flat one. The WebGL view was a raw force layout that ignored the cluster-country/cluster-IP toggles, so with the default country grouping on it showed one ungrouped hairball while the flat view packed nodes into per-country circles. It now reuses the flat view’s exact packing geometry to compute fixed group positions, renders with the simulation disabled so the clusters stay put while pan/zoom still work, colors nodes by group, and draws the boundary circles and country-flag labels on an overlay that tracks pan/zoom each frame — the WebGL analogue of the flat view’s boundaries.

Skywire: Plugging a 4GB Leak

3403 fix(cxo): close the duplicate transport in initConn (tpd CXO connection leak) tracks down a leak that had grown the transport-discovery CXO node’s heap to ~4GB — ~1000 live connections but ~150k retained dead connection stacks, driving sustained GC-bound CPU (a profile was ~90% runtime GC scan/sweep). The root cause: DMSG.acceptConn calls initConn directly, unlike the TCP/UDP paths that pre-guard duplicates. When a peer reconnects while its previous Conn still lingers in the node maps, the dedup returns the existing conn with no error and the freshly-accepted duplicate — whose read/write loops are already running — is orphaned, since the caller only closes it on error. Every duplicate dmsg accept, constant under fleet churn, leaked a full connection stack. The fix closes the unused duplicate in initConn’s two “existing connection returned” paths, covering all transports uniformly; publishers should be restarted once to shed the already-accumulated heap.

Skywire: Smaller Fixes

A cluster of smaller fixes rounded out the day. 3400 fix(hv-ui): narrow visor-switcher chips + place the switcher on node pages drops the 66-char public key line from each switcher chip (preserved as a hover tooltip) so the chip tracks its label instead of the PK, and renders the switcher directly under the home nav on node detail pages to match the list page. 3406 fix(log): route go-socks5’s logger through logrus in the resolving proxies stops the SOCKS5 library logging outside the visor’s structured logging. 3404 fix(visor): add the CXOFeedString alias (unbreaks pkg/visor test build) restores a missing alias that had red-lined CI on every branch, since a test referenced CXOFeedString while only its inverse had been aliased into the visor package.