Client Code -
const viewer = new WebViewer({
containerId: divId,
endpointUri,
model: model?.modelName,
rendererType: renererType,
});
Server Code -
export function spawnViewer(project: string, model: string, res: any): void {
const modelDir = ${modelDirectory}/${project}
;
const spawnId = uuidv4();
const wsPort = allocateWsPort();
const args = [
“–id”,
spawnId,
“–sc-port”,
wsPort.toString(),
“–liveliness-endpoint”,
http://${host}:${port}/liveliness
,
“–model-search-directories”,
modelDir,
“–license”,
license,
“–initial-use-duration”,
“0”,
];
console.log(host, port, wsPort, modelDir, license);
const options = { env: { DISPLAY: “:0” } };
let process: ChildProcess;
if (renderType === “ssr”) {
args.push(“–ssr”, “true”);
}
try {
process = spawn(executablePath, args, options);
} catch (err) {
const message = err instanceof Error ? err.message : String(err);
console.error([ERROR] Failed to spawn viewer: ${message}
);
res.status(500).json({ error: “Failed to start viewer” });
return;
}
const spawnInfo: SpawnInfo = {
spawnId,
wsPort,
rendererType: renderType === “csr” ? “csr” : “ssr”,
response: res,
startTime: new Date(),
process,
modelDir,
modelName: model,
};
spawnArray.push(spawnInfo);
setupProcessListeners(spawnInfo);
}
// Handles liveliness updates (ready, disconnect, ping) from a viewer process.
export function handleLiveliness(
spawnId: string,
updateType: string,
res: any,
wsHost: string,
): void {
const spawnInfo = spawnArray.find((e) => e.spawnId === spawnId);
if (!spawnInfo) {
res.status(404).json({ error: No active spawn with ID ${spawnId}
});
return;
}
switch (updateType) {
case “ready”:
console.log(“ready”);
spawnInfo.response?.status(201).json({
endpoint: ws://${wsHost}:${spawnInfo.wsPort}
,
wsPort: spawnInfo.wsPort,
rendererType: spawnInfo.rendererType,
spawnId,
modelName: spawnInfo.modelName,
});
spawnInfo.response = null;
break;
case “disconnect”:
console.log(“disconnect”);
cleanupSpawn(spawnId, spawnInfo.wsPort);
res.status(200).end();
break;
case “ping”:
console.log(“ping”);
res.status(200).json({ message: Ping received for ${spawnId}
});
break;
default:
console.log(“default”);
cleanupSpawn(spawnId, spawnInfo.wsPort);
res.status(400).json({ error: “Invalid liveliness value” });
}
}
This is the current implementation of the Client Viewer WebSocket connection, which is set up to load only a single model at a time. How can I modify this to support multi-model loading, as demonstrated in the Model Loading and Aggregation section of your example code?