@principal-ai/control-tower-core 0.2.2 → 0.3.0

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.mjs CHANGED
@@ -5485,6 +5485,7 @@ class BaseClient extends TypedEventEmitter {
5485
5485
  reconnectTimer = null;
5486
5486
  lastConnectionUrl = null;
5487
5487
  lastToken = null;
5488
+ pendingRequests = new Map;
5488
5489
  constructor(config) {
5489
5490
  super();
5490
5491
  this.config = config;
@@ -5656,6 +5657,34 @@ class BaseClient extends TypedEventEmitter {
5656
5657
  };
5657
5658
  await this.transport.send(message);
5658
5659
  }
5660
+ async request(type, payload, timeoutMs = 5000) {
5661
+ if (this.connectionState !== "connected") {
5662
+ throw new Error("Client must be connected to send requests");
5663
+ }
5664
+ const id = this.generateId();
5665
+ const message = {
5666
+ id,
5667
+ type,
5668
+ payload,
5669
+ timestamp: Date.now()
5670
+ };
5671
+ return new Promise((resolve, reject) => {
5672
+ const timeout = setTimeout(() => {
5673
+ this.pendingRequests.delete(id);
5674
+ reject(new Error(`Request '${type}' timed out after ${timeoutMs}ms`));
5675
+ }, timeoutMs);
5676
+ this.pendingRequests.set(id, {
5677
+ resolve,
5678
+ reject,
5679
+ timeout
5680
+ });
5681
+ this.transport.send(message).catch((error) => {
5682
+ this.pendingRequests.delete(id);
5683
+ clearTimeout(timeout);
5684
+ reject(error);
5685
+ });
5686
+ });
5687
+ }
5659
5688
  getConnectionState() {
5660
5689
  return this.connectionState;
5661
5690
  }
@@ -5672,6 +5701,13 @@ class BaseClient extends TypedEventEmitter {
5672
5701
  return this.userId;
5673
5702
  }
5674
5703
  async handleMessage(message) {
5704
+ if (message.id && this.pendingRequests.has(message.id)) {
5705
+ const pending = this.pendingRequests.get(message.id);
5706
+ clearTimeout(pending.timeout);
5707
+ this.pendingRequests.delete(message.id);
5708
+ pending.resolve(message.payload);
5709
+ return;
5710
+ }
5675
5711
  try {
5676
5712
  switch (message.type) {
5677
5713
  case "auth_result":
@@ -5874,13 +5910,46 @@ class PresenceClient extends TypedEventEmitter {
5874
5910
  }
5875
5911
  }
5876
5912
  async getOnlineUsers() {
5877
- throw new Error("getOnlineUsers() requires a REST API endpoint. " + "Implement this method based on your server API.");
5913
+ const response = await this.client.request("presence:get_users", {});
5914
+ return response.users;
5915
+ }
5916
+ async getUserPresence(userId) {
5917
+ const response = await this.client.request("presence:get_user", { userId });
5918
+ return response.user;
5919
+ }
5920
+ async getRepoUsers(owner, repo) {
5921
+ const response = await this.client.request("presence:get_repo_users", { owner, repo });
5922
+ return response.users;
5878
5923
  }
5879
- async setStatus(status, message) {
5880
- throw new Error("setStatus() requires a REST API endpoint. " + "Implement this method based on your server API.");
5924
+ async setStatus(status, statusMessage) {
5925
+ const response = await this.client.request("presence:set_status", { status, statusMessage });
5926
+ if (!response.success) {
5927
+ throw new Error(response.error || "Failed to set status");
5928
+ }
5881
5929
  }
5882
5930
  async setVisibility(visible) {
5883
- throw new Error("setVisibility() requires a REST API endpoint. " + "Implement this method based on your server API.");
5931
+ const response = await this.client.request("presence:set_visibility", { visible });
5932
+ if (!response.success) {
5933
+ throw new Error(response.error || "Failed to set visibility");
5934
+ }
5935
+ }
5936
+ async reportRepoOpened(repoId, branch) {
5937
+ const response = await this.client.request("presence:repo_open", { repoId, branch });
5938
+ if (!response.success) {
5939
+ throw new Error(response.error || "Failed to report repo opened");
5940
+ }
5941
+ }
5942
+ async reportRepoClosed(repoId) {
5943
+ const response = await this.client.request("presence:repo_close", { repoId });
5944
+ if (!response.success) {
5945
+ throw new Error(response.error || "Failed to report repo closed");
5946
+ }
5947
+ }
5948
+ async reportRepoFocused(repoId) {
5949
+ const response = await this.client.request("presence:repo_focus", { repoId });
5950
+ if (!response.success) {
5951
+ throw new Error(response.error || "Failed to report repo focused");
5952
+ }
5884
5953
  }
5885
5954
  getClient() {
5886
5955
  return this.client;
@@ -6309,7 +6378,6 @@ class BaseServer extends TypedEventEmitter {
6309
6378
  const client = {
6310
6379
  id: payload.clientId,
6311
6380
  userId: payload.userId || "",
6312
- deviceId: payload.clientId,
6313
6381
  roomIds,
6314
6382
  get roomId() {
6315
6383
  return roomIds.size > 0 ? roomIds.values().next().value || null : null;
@@ -6389,7 +6457,6 @@ class BaseServer extends TypedEventEmitter {
6389
6457
  const client = {
6390
6458
  id: clientId,
6391
6459
  userId: "",
6392
- deviceId: clientId,
6393
6460
  roomIds,
6394
6461
  get roomId() {
6395
6462
  return roomIds.size > 0 ? roomIds.values().next().value || null : null;
@@ -6418,10 +6485,10 @@ class BaseServer extends TypedEventEmitter {
6418
6485
  }
6419
6486
  if (this.presenceManager?.isEnabled() && client.userId) {
6420
6487
  try {
6421
- const presence = await this.presenceManager.disconnectDevice(client.userId, client.deviceId);
6488
+ const presence = await this.presenceManager.disconnectDevice(client.userId, clientId);
6422
6489
  await this.emit("presence_device_disconnected", {
6423
6490
  userId: client.userId,
6424
- deviceId: client.deviceId,
6491
+ deviceId: clientId,
6425
6492
  timestamp: Date.now()
6426
6493
  });
6427
6494
  const presenceConfig = this.presenceManager.getConfig();
@@ -6430,7 +6497,7 @@ class BaseServer extends TypedEventEmitter {
6430
6497
  type: "presence:user_offline",
6431
6498
  payload: {
6432
6499
  userId: client.userId,
6433
- deviceId: client.deviceId,
6500
+ deviceId: clientId,
6434
6501
  status: presence?.status || "offline",
6435
6502
  gracePeriod: presenceConfig.gracePeriod
6436
6503
  }
@@ -6444,17 +6511,6 @@ class BaseServer extends TypedEventEmitter {
6444
6511
  }
6445
6512
  }
6446
6513
  for (const roomId of client.roomIds) {
6447
- try {
6448
- await this.experimental.broadcastWhere((c) => c.roomIds.has(roomId) && c.id !== clientId, {
6449
- type: "member_left",
6450
- payload: {
6451
- roomId,
6452
- userId: client.userId,
6453
- clientId,
6454
- timestamp: Date.now()
6455
- }
6456
- });
6457
- } catch {}
6458
6514
  await this.roomManager.leaveRoom(roomId, client.userId);
6459
6515
  await this.emit("client_left_room", { clientId, roomId });
6460
6516
  }
@@ -6471,7 +6527,7 @@ class BaseServer extends TypedEventEmitter {
6471
6527
  return;
6472
6528
  }
6473
6529
  if (this.presenceManager?.isEnabled() && client.userId && client.authenticated) {
6474
- await this.updatePresenceActivity(client.userId, client.deviceId, "message");
6530
+ await this.updatePresenceActivity(client.userId, clientId, "message");
6475
6531
  }
6476
6532
  switch (message.type) {
6477
6533
  case "authenticate":
@@ -6504,11 +6560,23 @@ class BaseServer extends TypedEventEmitter {
6504
6560
  timestamp: Date.now()
6505
6561
  });
6506
6562
  break;
6507
- default:
6563
+ default: {
6564
+ if (this.config.customMessageHandler) {
6565
+ const sendResponse = async (response) => {
6566
+ await this.sendToClient(clientId, {
6567
+ id: message.id,
6568
+ ...response
6569
+ });
6570
+ };
6571
+ const handled = await this.config.customMessageHandler(clientId, message, sendResponse);
6572
+ if (handled)
6573
+ break;
6574
+ }
6508
6575
  await this.sendToClient(clientId, {
6509
6576
  type: "error",
6510
6577
  error: `Unknown message type: ${message.type}`
6511
6578
  });
6579
+ }
6512
6580
  }
6513
6581
  } catch (error) {
6514
6582
  await this.sendToClient(clientId, {
@@ -6648,17 +6716,6 @@ class BaseServer extends TypedEventEmitter {
6648
6716
  if (!client.roomIds.has(roomId)) {
6649
6717
  continue;
6650
6718
  }
6651
- try {
6652
- await this.experimental.broadcastWhere((c) => c.roomIds.has(roomId) && c.id !== clientId, {
6653
- type: "member_left",
6654
- payload: {
6655
- roomId,
6656
- userId: client.userId,
6657
- clientId,
6658
- timestamp: Date.now()
6659
- }
6660
- });
6661
- } catch {}
6662
6719
  await this.roomManager.leaveRoom(roomId, client.userId);
6663
6720
  client.roomIds.delete(roomId);
6664
6721
  await this.emit("client_left_room", { clientId, roomId });
@@ -6831,16 +6888,7 @@ class BaseServer extends TypedEventEmitter {
6831
6888
  });
6832
6889
  }
6833
6890
  getDeviceIdFromClientId(clientId) {
6834
- const client = this.clients.get(clientId);
6835
- return client?.deviceId ?? clientId;
6836
- }
6837
- setClientDeviceId(clientId, deviceId) {
6838
- const client = this.clients.get(clientId);
6839
- if (client) {
6840
- client.deviceId = deviceId;
6841
- return true;
6842
- }
6843
- return false;
6891
+ return clientId;
6844
6892
  }
6845
6893
  }
6846
6894
  // src/server/ServerBuilder.ts
@@ -6856,6 +6904,7 @@ class ServerBuilder {
6856
6904
  webSocketPath;
6857
6905
  webSocketServer;
6858
6906
  experimentalFeatures;
6907
+ customMessageHandler;
6859
6908
  withTransport(transport) {
6860
6909
  this.transport = transport;
6861
6910
  return this;
@@ -6900,6 +6949,10 @@ class ServerBuilder {
6900
6949
  this.experimentalFeatures = features;
6901
6950
  return this;
6902
6951
  }
6952
+ withCustomMessageHandler(handler) {
6953
+ this.customMessageHandler = handler;
6954
+ return this;
6955
+ }
6903
6956
  build() {
6904
6957
  if (!this.transport) {
6905
6958
  throw new Error("Transport adapter is required");
@@ -6929,7 +6982,8 @@ class ServerBuilder {
6929
6982
  enableBroadcast: false,
6930
6983
  warnOnExperimentalUse: true,
6931
6984
  trackUsageMetrics: false
6932
- }
6985
+ },
6986
+ customMessageHandler: this.customMessageHandler
6933
6987
  };
6934
6988
  const server = new BaseServer(config);
6935
6989
  if (this.roomManager.constructor.name === "DefaultRoomManager") {
@@ -7003,4 +7057,4 @@ export {
7003
7057
  BaseClient
7004
7058
  };
7005
7059
 
7006
- //# debugId=A5E31B6ED779287364756E2164756E21
7060
+ //# debugId=A1A2F55B1633C22A64756E2164756E21