herdr-remote-relay 0.2.18 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
package/src/relay-server.js
CHANGED
|
@@ -27,10 +27,18 @@ const MAX_DIMENSION = 500;
|
|
|
27
27
|
const MIN_SESSION_COLS = 20;
|
|
28
28
|
const MIN_SESSION_ROWS = 6;
|
|
29
29
|
|
|
30
|
+
/** Matches the host's own cap; the relay re-applies it rather than trusting it. */
|
|
31
|
+
const MAX_AGENT_STATUS_ENTRIES = 16;
|
|
32
|
+
|
|
30
33
|
function randomId(prefix) {
|
|
31
34
|
return `${prefix}-${crypto.randomBytes(9).toString('base64url')}`;
|
|
32
35
|
}
|
|
33
36
|
|
|
37
|
+
/** A bounded string, or null. For fields whose contents a pane decided. */
|
|
38
|
+
function text(value, limit) {
|
|
39
|
+
return typeof value === 'string' && value.length > 0 ? value.slice(0, limit) : null;
|
|
40
|
+
}
|
|
41
|
+
|
|
34
42
|
function clampDimension(value, fallback) {
|
|
35
43
|
const numeric = Number(value);
|
|
36
44
|
if (!Number.isInteger(numeric)) return fallback;
|
|
@@ -813,6 +821,12 @@ class RelayServer {
|
|
|
813
821
|
if (this.hosts.get(host.id) === host) this.detachHost(host, { notify: true, reason: 'host_shutdown' });
|
|
814
822
|
return;
|
|
815
823
|
}
|
|
824
|
+
// What the workstation's agents are doing belongs to the workstation, not
|
|
825
|
+
// to one stream: every window watching it gets the same answer.
|
|
826
|
+
if (message.type === 'agent_status') {
|
|
827
|
+
this.broadcastAgentStatus(host, message);
|
|
828
|
+
return;
|
|
829
|
+
}
|
|
816
830
|
// Session events target the single client that owns this stream.
|
|
817
831
|
const streamId = typeof message.clientId === 'string' ? message.clientId : message.streamId;
|
|
818
832
|
const clientId = streamId ? this.streams.get(streamId) : null;
|
|
@@ -1262,6 +1276,46 @@ class RelayServer {
|
|
|
1262
1276
|
}
|
|
1263
1277
|
}
|
|
1264
1278
|
|
|
1279
|
+
/**
|
|
1280
|
+
* Pass on what the workstation's agents are doing.
|
|
1281
|
+
*
|
|
1282
|
+
* Sanitised rather than forwarded: the host is trusted, but this is the one
|
|
1283
|
+
* message whose contents come from terminal titles, and it lands in a status
|
|
1284
|
+
* bar on every attached window. The counts are numbers and the list is
|
|
1285
|
+
* bounded, so a workstation cannot grow a browser's memory by naming things
|
|
1286
|
+
* carefully.
|
|
1287
|
+
*/
|
|
1288
|
+
broadcastAgentStatus(host, message) {
|
|
1289
|
+
const counts = {};
|
|
1290
|
+
if (message.counts && typeof message.counts === 'object') {
|
|
1291
|
+
for (const [status, value] of Object.entries(message.counts)) {
|
|
1292
|
+
if (typeof status === 'string' && Number.isFinite(value)) {
|
|
1293
|
+
counts[status.slice(0, 32)] = Math.max(0, Math.min(9999, Math.trunc(value)));
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
const agents = (Array.isArray(message.agents) ? message.agents : [])
|
|
1298
|
+
.slice(0, MAX_AGENT_STATUS_ENTRIES)
|
|
1299
|
+
.map((agent) => ({
|
|
1300
|
+
paneId: text(agent?.paneId, 64),
|
|
1301
|
+
workspaceId: text(agent?.workspaceId, 64),
|
|
1302
|
+
agent: text(agent?.agent, 32),
|
|
1303
|
+
title: text(agent?.title, 64),
|
|
1304
|
+
status: text(agent?.status, 16),
|
|
1305
|
+
focused: agent?.focused === true,
|
|
1306
|
+
}));
|
|
1307
|
+
const payload = {
|
|
1308
|
+
type: 'agent_status',
|
|
1309
|
+
counts,
|
|
1310
|
+
total: Number.isFinite(message.total) ? Math.max(0, Math.trunc(message.total)) : agents.length,
|
|
1311
|
+
agents,
|
|
1312
|
+
};
|
|
1313
|
+
for (const clientId of host.clients) {
|
|
1314
|
+
const client = this.clients.get(clientId);
|
|
1315
|
+
if (client) jsonSend(client.ws, payload);
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1265
1319
|
/**
|
|
1266
1320
|
* Close every existing session belonging to `deviceId` on `host`.
|
|
1267
1321
|
*
|