To build a clean, non-blocking bridge for these asynchronous payloads, we can
treat the WebSocket server as a network-level extension of a classic IPC
mailbox. Just as local VM syscalls yield and resume based on memory handles,
this bridge routes JSON payloads based on connection identities (Player vs.
Bot) and room subscriptions.
Here is a robust structure for the SignalingBridge in Node.js using the
standard ws package.
The Signaling Bridge (bridge.js)
This module acts as the central router. It catches inbound RPCs from your
bots, emits the mutation events to your core FSO engine, and pushes
environment broadcasts down to specific rooms.
import { WebSocketServer } from 'ws';
import EventEmitter from 'events';
export class SignalingBridge extends EventEmitter {
constructor(port = 8080) {
super();
this.wss = new WebSocketServer({ port });
// Map to track connection state: ws -> { id, type: 'BOT'|'PLAYER',
room: 'room_cove' }
this.clients = new Map();
this.wss.on('connection', (ws) => {
this.clients.set(ws, { id: null, type: null, room: null });
ws.on('message', (data) => this.handleMessage(ws, data));
ws.on('close', () => this.clients.delete(ws));
});
console.log(`[BRIDGE] Signaling active on port ${port}`);
}
handleMessage(ws, rawData) {
try {
const payload = JSON.parse(rawData);
// 1. Connection Handshake
if (payload.intent === 'AUTH') {
const meta = this.clients.get(ws);
meta.id = payload.id;
meta.type = payload.type; // 'BOT' or 'PLAYER'
meta.room = payload.initial_room;
return;
}
// 2. Autonomous Bot RPCs
if (payload.protocol === 'FSO_RPC_V1') {
// Fire the mutation to the FSO Engine to safely process
if (payload.mutation) {
this.emit('mutation_request', payload.mutation);
}
// Push the narrative text to players in the room
if (payload.broadcast) {
this.broadcastToRoom(payload.broadcast.target_room,
payload.broadcast.message);
}
return;
}
// 3. Player Terminal Input
if (payload.intent === 'CMD') {
this.emit('player_input', { ws, id: this.clients.get(ws).id,
command: payload.command });
}
} catch (err) {
ws.send(JSON.stringify({ error: "Malformed payload" }));
}
}
// Helper for the FSO Engine to update a player's physical location
updatePlayerRoom(ws, newRoomId) {
const meta = this.clients.get(ws);
if (meta) meta.room = newRoomId;
}
// Target a specific room (like sending a localized ENV EVENT)
broadcastToRoom(roomId, message) {
const outbound = JSON.stringify({ type: 'ENV_EVENT', text: message });
for (const [clientWs, meta] of this.clients.entries()) {
if (meta.room === roomId && clientWs.readyState === 1 /* OPEN */)
{
clientWs.send(outbound);
}
}
}
}
Hooking It Into the FSO Engine
In your main cli.js (or engine.js), you instantiate this bridge and wire it
directly into your deterministic parser. The engine listens for the events,
processes the opcodes, and then uses the bridge to write back out.
import { SignalingBridge } from './bridge.js';
/ ... FSO Engine imports
const bridge = new SignalingBridge(8080);
/ Catch live FSO mutations from autonomous bots
bridge.on('mutation_request', (mutation) => {
// 1. Verify mutation payload
// 2. Perform atomic ARRAY_PUSH or EXIT string replacement
// 3. Log telemetry
console.log(`[VM] Hot-patched memory for ${mutation.anchor?.room_id ||
'Global'}`);
});
/ Catch standard player commands
bridge.on('player_input', ({ ws, id, command }) => {
// Pass command to the FSO VM
const result = fsoEngine.execute(id, command);
// Update tracking if they moved
if (result.new_room) {
bridge.updatePlayerRoom(ws, result.new_room);
}
});
Network Deployment
Because this is a standard WebSocket server, it plays perfectly with secure
mesh networking architectures. If you deploy this behind a cloudflared tunnel,
you can easily route traffic through omega-mesh.fi so your external LLM agent
microservices can securely authenticate and push their JSON RPCs into the
local VM without exposing the core server's ports directly to the open web.