@principal-ai/control-tower-core 0.3.0 → 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/dist/index.js.map +3 -3
- package/dist/index.mjs +39 -6
- package/dist/index.mjs.map +3 -3
- package/dist/server/BaseServer.d.ts +22 -2
- package/dist/server/BaseServer.d.ts.map +1 -1
- package/dist/server/BaseServer.js +63 -8
- package/package.json +1 -1
|
@@ -43,6 +43,12 @@ export interface ServerConfig {
|
|
|
43
43
|
export interface ConnectedClient {
|
|
44
44
|
id: string;
|
|
45
45
|
userId: string;
|
|
46
|
+
/**
|
|
47
|
+
* Device ID for presence tracking.
|
|
48
|
+
* By default equals clientId, but can be overridden via setClientDeviceId()
|
|
49
|
+
* to support multi-window scenarios where multiple clients share a device.
|
|
50
|
+
*/
|
|
51
|
+
deviceId: string;
|
|
46
52
|
/**
|
|
47
53
|
* Set of room IDs the client is currently in
|
|
48
54
|
*
|
|
@@ -232,11 +238,25 @@ export declare class BaseServer extends TypedEventEmitter<ServerEvents> {
|
|
|
232
238
|
/**
|
|
233
239
|
* Get device ID from client ID
|
|
234
240
|
*
|
|
235
|
-
*
|
|
241
|
+
* By default, deviceId === clientId. Use setClientDeviceId() to override
|
|
242
|
+
* for multi-window scenarios where multiple clients share a device.
|
|
236
243
|
*
|
|
237
244
|
* @param clientId - Client identifier
|
|
238
|
-
* @returns Device ID
|
|
245
|
+
* @returns Device ID for this client
|
|
239
246
|
*/
|
|
240
247
|
getDeviceIdFromClientId(clientId: string): string;
|
|
248
|
+
/**
|
|
249
|
+
* Set the device ID for a client
|
|
250
|
+
*
|
|
251
|
+
* Use this to associate a custom deviceId with a client, e.g., when
|
|
252
|
+
* the deviceId comes from a JWT token and differs from the WebSocket clientId.
|
|
253
|
+
* This is useful for multi-window scenarios where multiple WebSocket clients
|
|
254
|
+
* share the same device/user session.
|
|
255
|
+
*
|
|
256
|
+
* @param clientId - Client identifier
|
|
257
|
+
* @param deviceId - Device identifier to associate with this client
|
|
258
|
+
* @returns true if the client was found and updated, false otherwise
|
|
259
|
+
*/
|
|
260
|
+
setClientDeviceId(clientId: string, deviceId: string): boolean;
|
|
241
261
|
}
|
|
242
262
|
//# sourceMappingURL=BaseServer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseServer.d.ts","sourceRoot":"","sources":["../../src/server/BaseServer.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"BaseServer.d.ts","sourceRoot":"","sources":["../../src/server/BaseServer.ts"],"names":[],"mappings":"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"}
|
|
@@ -254,6 +254,7 @@ class BaseServer extends EventEmitter_js_1.TypedEventEmitter {
|
|
|
254
254
|
const client = {
|
|
255
255
|
id: payload.clientId,
|
|
256
256
|
userId: payload.userId || "",
|
|
257
|
+
deviceId: payload.clientId, // Default to clientId, can be overridden via setClientDeviceId()
|
|
257
258
|
roomIds,
|
|
258
259
|
get roomId() {
|
|
259
260
|
return roomIds.size > 0 ? roomIds.values().next().value || null : null;
|
|
@@ -340,6 +341,7 @@ class BaseServer extends EventEmitter_js_1.TypedEventEmitter {
|
|
|
340
341
|
const client = {
|
|
341
342
|
id: clientId,
|
|
342
343
|
userId: "",
|
|
344
|
+
deviceId: clientId, // Default to clientId, can be overridden via setClientDeviceId()
|
|
343
345
|
roomIds,
|
|
344
346
|
get roomId() {
|
|
345
347
|
return roomIds.size > 0 ? roomIds.values().next().value || null : null;
|
|
@@ -371,10 +373,10 @@ class BaseServer extends EventEmitter_js_1.TypedEventEmitter {
|
|
|
371
373
|
// Unregister from presence manager
|
|
372
374
|
if (this.presenceManager?.isEnabled() && client.userId) {
|
|
373
375
|
try {
|
|
374
|
-
const presence = await this.presenceManager.disconnectDevice(client.userId,
|
|
376
|
+
const presence = await this.presenceManager.disconnectDevice(client.userId, client.deviceId);
|
|
375
377
|
await this.emit("presence_device_disconnected", {
|
|
376
378
|
userId: client.userId,
|
|
377
|
-
deviceId:
|
|
379
|
+
deviceId: client.deviceId,
|
|
378
380
|
timestamp: Date.now(),
|
|
379
381
|
});
|
|
380
382
|
// Broadcast presence update if user went offline or into grace period
|
|
@@ -385,7 +387,7 @@ class BaseServer extends EventEmitter_js_1.TypedEventEmitter {
|
|
|
385
387
|
type: "presence:user_offline",
|
|
386
388
|
payload: {
|
|
387
389
|
userId: client.userId,
|
|
388
|
-
deviceId:
|
|
390
|
+
deviceId: client.deviceId,
|
|
389
391
|
status: presence?.status || "offline",
|
|
390
392
|
gracePeriod: presenceConfig.gracePeriod,
|
|
391
393
|
},
|
|
@@ -399,8 +401,23 @@ class BaseServer extends EventEmitter_js_1.TypedEventEmitter {
|
|
|
399
401
|
});
|
|
400
402
|
}
|
|
401
403
|
}
|
|
402
|
-
// Leave all rooms the client is in
|
|
404
|
+
// Leave all rooms the client is in and broadcast to other room members
|
|
403
405
|
for (const roomId of client.roomIds) {
|
|
406
|
+
// Broadcast member_left to other room members
|
|
407
|
+
try {
|
|
408
|
+
await this.experimental.broadcastWhere((c) => c.roomIds.has(roomId) && c.id !== clientId, {
|
|
409
|
+
type: "member_left",
|
|
410
|
+
payload: {
|
|
411
|
+
roomId,
|
|
412
|
+
userId: client.userId,
|
|
413
|
+
clientId,
|
|
414
|
+
timestamp: Date.now(),
|
|
415
|
+
},
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
catch {
|
|
419
|
+
// Experimental broadcast not enabled, skip silently
|
|
420
|
+
}
|
|
404
421
|
await this.roomManager.leaveRoom(roomId, client.userId);
|
|
405
422
|
await this.emit("client_left_room", { clientId, roomId });
|
|
406
423
|
}
|
|
@@ -422,7 +439,7 @@ class BaseServer extends EventEmitter_js_1.TypedEventEmitter {
|
|
|
422
439
|
if (this.presenceManager?.isEnabled() &&
|
|
423
440
|
client.userId &&
|
|
424
441
|
client.authenticated) {
|
|
425
|
-
await this.updatePresenceActivity(client.userId,
|
|
442
|
+
await this.updatePresenceActivity(client.userId, client.deviceId, "message");
|
|
426
443
|
}
|
|
427
444
|
switch (message.type) {
|
|
428
445
|
case "authenticate":
|
|
@@ -633,6 +650,22 @@ class BaseServer extends EventEmitter_js_1.TypedEventEmitter {
|
|
|
633
650
|
if (!client.roomIds.has(roomId)) {
|
|
634
651
|
continue;
|
|
635
652
|
}
|
|
653
|
+
// Broadcast to other room members BEFORE removing this client
|
|
654
|
+
// Use experimental broadcast if enabled, otherwise silently skip
|
|
655
|
+
try {
|
|
656
|
+
await this.experimental.broadcastWhere((c) => c.roomIds.has(roomId) && c.id !== clientId, {
|
|
657
|
+
type: "member_left",
|
|
658
|
+
payload: {
|
|
659
|
+
roomId,
|
|
660
|
+
userId: client.userId,
|
|
661
|
+
clientId,
|
|
662
|
+
timestamp: Date.now(),
|
|
663
|
+
},
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
catch {
|
|
667
|
+
// Experimental broadcast not enabled, skip silently
|
|
668
|
+
}
|
|
636
669
|
await this.roomManager.leaveRoom(roomId, client.userId);
|
|
637
670
|
client.roomIds.delete(roomId);
|
|
638
671
|
await this.emit("client_left_room", { clientId, roomId });
|
|
@@ -849,13 +882,35 @@ class BaseServer extends EventEmitter_js_1.TypedEventEmitter {
|
|
|
849
882
|
/**
|
|
850
883
|
* Get device ID from client ID
|
|
851
884
|
*
|
|
852
|
-
*
|
|
885
|
+
* By default, deviceId === clientId. Use setClientDeviceId() to override
|
|
886
|
+
* for multi-window scenarios where multiple clients share a device.
|
|
853
887
|
*
|
|
854
888
|
* @param clientId - Client identifier
|
|
855
|
-
* @returns Device ID
|
|
889
|
+
* @returns Device ID for this client
|
|
856
890
|
*/
|
|
857
891
|
getDeviceIdFromClientId(clientId) {
|
|
858
|
-
|
|
892
|
+
const client = this.clients.get(clientId);
|
|
893
|
+
return client?.deviceId ?? clientId;
|
|
894
|
+
}
|
|
895
|
+
/**
|
|
896
|
+
* Set the device ID for a client
|
|
897
|
+
*
|
|
898
|
+
* Use this to associate a custom deviceId with a client, e.g., when
|
|
899
|
+
* the deviceId comes from a JWT token and differs from the WebSocket clientId.
|
|
900
|
+
* This is useful for multi-window scenarios where multiple WebSocket clients
|
|
901
|
+
* share the same device/user session.
|
|
902
|
+
*
|
|
903
|
+
* @param clientId - Client identifier
|
|
904
|
+
* @param deviceId - Device identifier to associate with this client
|
|
905
|
+
* @returns true if the client was found and updated, false otherwise
|
|
906
|
+
*/
|
|
907
|
+
setClientDeviceId(clientId, deviceId) {
|
|
908
|
+
const client = this.clients.get(clientId);
|
|
909
|
+
if (client) {
|
|
910
|
+
client.deviceId = deviceId;
|
|
911
|
+
return true;
|
|
912
|
+
}
|
|
913
|
+
return false;
|
|
859
914
|
}
|
|
860
915
|
}
|
|
861
916
|
exports.BaseServer = BaseServer;
|
package/package.json
CHANGED