@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.
@@ -0,0 +1,60 @@
1
+ import type { ITransportAdapter } from '../../abstractions/TransportAdapter.js';
2
+ import type { IAuthAdapter } from '../../abstractions/AuthAdapter.js';
3
+ import type { ConnectionState, ConnectionOptions, Message, MessageHandler, ErrorHandler, CloseHandler } from '../../types/index.js';
4
+ import type { Server as HttpServer } from 'http';
5
+ import type { Server as HttpsServer } from 'https';
6
+ import { WebSocketServer, WebSocket } from 'ws';
7
+ interface ClientConnection {
8
+ id: string;
9
+ ws: WebSocket;
10
+ userId?: string;
11
+ authenticated: boolean;
12
+ metadata?: Record<string, unknown>;
13
+ authTimeout?: NodeJS.Timeout;
14
+ connectedAt: number;
15
+ }
16
+ export interface WebSocketTransportConfig {
17
+ authTimeout?: number;
18
+ closeOnAuthFailure?: boolean;
19
+ requireAuth?: boolean;
20
+ }
21
+ export declare class WebSocketTransportAdapter implements ITransportAdapter {
22
+ private state;
23
+ private messageHandlers;
24
+ private errorHandlers;
25
+ private closeHandlers;
26
+ private wss?;
27
+ private serverUrl?;
28
+ private attachedServer?;
29
+ private attachedWss?;
30
+ private webSocketPath?;
31
+ private clients;
32
+ private mode;
33
+ private authAdapter?;
34
+ private config;
35
+ constructor(config?: WebSocketTransportConfig);
36
+ setAuthAdapter(auth: IAuthAdapter): void;
37
+ connect(url: string, _options?: ConnectionOptions): Promise<void>;
38
+ attach(server: HttpServer | HttpsServer, path?: string): Promise<void>;
39
+ attachToWebSocketServer(wss: WebSocketServer): Promise<void>;
40
+ private handleConnection;
41
+ private handleClientMessage;
42
+ private handleAuthMessage;
43
+ private extractBearerToken;
44
+ private sendToClient;
45
+ disconnect(): Promise<void>;
46
+ send(message: Message): Promise<void>;
47
+ onMessage(handler: MessageHandler): void;
48
+ onError(handler: ErrorHandler): void;
49
+ onClose(handler: CloseHandler): void;
50
+ getState(): ConnectionState;
51
+ isConnected(): boolean;
52
+ getConnectedClients(): ClientConnection[];
53
+ getAuthenticatedClients(): ClientConnection[];
54
+ getClientCount(): number;
55
+ getMode(): 'standalone' | 'integration';
56
+ isAuthRequired(): boolean;
57
+ private generateId;
58
+ }
59
+ export {};
60
+ //# sourceMappingURL=WebSocketTransportAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebSocketTransportAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/websocket/WebSocketTransportAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAChF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EACjB,OAAO,EACP,cAAc,EACd,YAAY,EACZ,YAAY,EAGb,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,IAAI,WAAW,EAAE,MAAM,OAAO,CAAC;AAEnD,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAEhD,UAAU,gBAAgB;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,SAAS,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,wBAAwB;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,qBAAa,yBAA0B,YAAW,iBAAiB;IACjE,OAAO,CAAC,KAAK,CAAmC;IAChD,OAAO,CAAC,eAAe,CAAkC;IACzD,OAAO,CAAC,aAAa,CAAgC;IACrD,OAAO,CAAC,aAAa,CAAgC;IAGrD,OAAO,CAAC,GAAG,CAAC,CAAkB;IAC9B,OAAO,CAAC,SAAS,CAAC,CAAS;IAG3B,OAAO,CAAC,cAAc,CAAC,CAA2B;IAClD,OAAO,CAAC,WAAW,CAAC,CAAkB;IACtC,OAAO,CAAC,aAAa,CAAC,CAAS;IAG/B,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,IAAI,CAA8C;IAG1D,OAAO,CAAC,WAAW,CAAC,CAAe;IACnC,OAAO,CAAC,MAAM,CAA2B;gBAE7B,MAAM,CAAC,EAAE,wBAAwB;IAU7C,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAclC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAsCjE,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,WAAW,EAAE,IAAI,GAAE,MAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAiC7E,uBAAuB,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;YA2BpD,gBAAgB;YA6EhB,mBAAmB;YAuCnB,iBAAiB;IA4E/B,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,YAAY;IAMd,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAiC3B,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IA8B3C,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAIxC,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAIpC,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAIpC,QAAQ,IAAI,eAAe;IAI3B,WAAW,IAAI,OAAO;IAKtB,mBAAmB,IAAI,gBAAgB,EAAE;IAIzC,uBAAuB,IAAI,gBAAgB,EAAE;IAI7C,cAAc,IAAI,MAAM;IAIxB,OAAO,IAAI,YAAY,GAAG,aAAa;IAIvC,cAAc,IAAI,OAAO;IAIzB,OAAO,CAAC,UAAU;CAGnB"}
@@ -0,0 +1,386 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WebSocketTransportAdapter = void 0;
4
+ const ws_1 = require("ws");
5
+ class WebSocketTransportAdapter {
6
+ constructor(config) {
7
+ this.state = 'disconnected';
8
+ this.messageHandlers = new Set();
9
+ this.errorHandlers = new Set();
10
+ this.closeHandlers = new Set();
11
+ // Client management
12
+ this.clients = new Map();
13
+ this.mode = 'standalone';
14
+ this.config = {
15
+ authTimeout: config?.authTimeout ?? 5000,
16
+ closeOnAuthFailure: config?.closeOnAuthFailure ?? false,
17
+ requireAuth: config?.requireAuth ?? false,
18
+ ...config
19
+ };
20
+ }
21
+ // Set the auth adapter
22
+ setAuthAdapter(auth) {
23
+ this.authAdapter = auth;
24
+ // Use auth adapter's preference only if requireAuth is not already true
25
+ // This allows explicit requireAuth: true in config to take precedence
26
+ if (auth.isAuthRequired && !this.config.requireAuth) {
27
+ this.config.requireAuth = auth.isAuthRequired();
28
+ }
29
+ // For authTimeout, use adapter's value if not explicitly set (not matching default)
30
+ if (auth.getAuthTimeout && this.config.authTimeout === 5000) {
31
+ this.config.authTimeout = auth.getAuthTimeout();
32
+ }
33
+ }
34
+ // Standalone mode implementation
35
+ async connect(url, _options) {
36
+ if (this.state === 'connected' || this.state === 'connecting') {
37
+ throw new Error('Already connected or connecting');
38
+ }
39
+ this.state = 'connecting';
40
+ this.serverUrl = url;
41
+ this.mode = 'standalone';
42
+ try {
43
+ // Extract port from URL
44
+ const urlObj = new URL(url);
45
+ const port = parseInt(urlObj.port) || (urlObj.protocol === 'wss:' ? 443 : 80);
46
+ // Create WebSocket server
47
+ this.wss = new ws_1.WebSocketServer({ port });
48
+ this.wss.on('connection', (ws, req) => {
49
+ this.handleConnection(ws, req);
50
+ });
51
+ this.wss.on('error', (error) => {
52
+ this.errorHandlers.forEach(handler => handler(error));
53
+ });
54
+ this.wss.on('close', () => {
55
+ this.state = 'disconnected';
56
+ this.closeHandlers.forEach(handler => handler(1000, 'Server closed'));
57
+ });
58
+ this.state = 'connected';
59
+ }
60
+ catch (error) {
61
+ this.state = 'disconnected';
62
+ throw error;
63
+ }
64
+ }
65
+ // Integration mode implementation
66
+ async attach(server, path = '/ws') {
67
+ if (this.state === 'connected' || this.state === 'connecting') {
68
+ throw new Error('Already connected or connecting');
69
+ }
70
+ this.state = 'connecting';
71
+ this.attachedServer = server;
72
+ this.webSocketPath = path;
73
+ this.mode = 'integration';
74
+ try {
75
+ // Create WebSocket server attached to the existing HTTP server
76
+ this.wss = new ws_1.WebSocketServer({
77
+ server,
78
+ path,
79
+ perMessageDeflate: false
80
+ });
81
+ this.wss.on('connection', (ws, req) => {
82
+ this.handleConnection(ws, req);
83
+ });
84
+ this.wss.on('error', (error) => {
85
+ this.errorHandlers.forEach(handler => handler(error));
86
+ });
87
+ this.state = 'connected';
88
+ }
89
+ catch (error) {
90
+ this.state = 'disconnected';
91
+ throw error;
92
+ }
93
+ }
94
+ async attachToWebSocketServer(wss) {
95
+ if (this.state === 'connected' || this.state === 'connecting') {
96
+ throw new Error('Already connected or connecting');
97
+ }
98
+ this.state = 'connecting';
99
+ this.attachedWss = wss;
100
+ this.mode = 'integration';
101
+ try {
102
+ this.wss = wss;
103
+ this.wss.on('connection', (ws, req) => {
104
+ this.handleConnection(ws, req);
105
+ });
106
+ this.wss.on('error', (error) => {
107
+ this.errorHandlers.forEach(handler => handler(error));
108
+ });
109
+ this.state = 'connected';
110
+ }
111
+ catch (error) {
112
+ this.state = 'disconnected';
113
+ throw error;
114
+ }
115
+ }
116
+ async handleConnection(ws, req) {
117
+ const clientId = this.generateId();
118
+ // Step 1: Try header authentication if auth adapter is available
119
+ let authenticated = false;
120
+ let authResult = null;
121
+ if (this.authAdapter && req.headers.authorization) {
122
+ const token = this.extractBearerToken(req.headers.authorization);
123
+ if (token) {
124
+ try {
125
+ authResult = await this.authAdapter.authenticate({
126
+ type: 'bearer',
127
+ token: token
128
+ });
129
+ authenticated = authResult.success;
130
+ }
131
+ catch {
132
+ // Header auth failed but don't reject connection
133
+ }
134
+ }
135
+ }
136
+ // Step 2: Create client with auth state
137
+ const client = {
138
+ id: clientId,
139
+ ws,
140
+ authenticated,
141
+ userId: authResult?.userId || (authResult?.user?.userId),
142
+ metadata: authResult?.metadata || authResult?.user?.metadata,
143
+ connectedAt: Date.now()
144
+ };
145
+ this.clients.set(clientId, client);
146
+ // Step 3: Set up message handling
147
+ ws.on('message', (data) => {
148
+ this.handleClientMessage(clientId, data);
149
+ });
150
+ ws.on('error', (error) => {
151
+ this.errorHandlers.forEach(handler => handler(error));
152
+ });
153
+ ws.on('close', (_code, _reason) => {
154
+ // Clear auth timeout if exists
155
+ if (client.authTimeout) {
156
+ clearTimeout(client.authTimeout);
157
+ }
158
+ this.clients.delete(clientId);
159
+ });
160
+ // Step 4: Set auth timeout if not authenticated and auth is required
161
+ if (!authenticated && this.config.requireAuth && this.authAdapter) {
162
+ client.authTimeout = setTimeout(() => {
163
+ if (!client.authenticated) {
164
+ ws.close(1008, 'Authentication timeout');
165
+ this.clients.delete(clientId);
166
+ }
167
+ }, this.config.authTimeout);
168
+ }
169
+ // Step 5: Notify about connection (with auth status)
170
+ const connectionMessage = {
171
+ id: this.generateId(),
172
+ type: 'connection',
173
+ payload: {
174
+ clientId,
175
+ authenticated,
176
+ userId: client.userId,
177
+ metadata: client.metadata
178
+ },
179
+ timestamp: Date.now()
180
+ };
181
+ this.messageHandlers.forEach(handler => handler(connectionMessage));
182
+ }
183
+ async handleClientMessage(clientId, data) {
184
+ const client = this.clients.get(clientId);
185
+ if (!client)
186
+ return;
187
+ try {
188
+ const message = JSON.parse(data.toString());
189
+ // Special handling for authentication messages
190
+ if (message.type === 'authenticate' && !client.authenticated && this.authAdapter) {
191
+ await this.handleAuthMessage(client, message);
192
+ return;
193
+ }
194
+ // Reject messages from unauthenticated clients if auth is required
195
+ if (this.config.requireAuth && !client.authenticated) {
196
+ this.sendToClient(client, {
197
+ id: this.generateId(),
198
+ type: 'error',
199
+ payload: { error: 'Authentication required' },
200
+ timestamp: Date.now()
201
+ });
202
+ return;
203
+ }
204
+ // Add clientId to message payload for routing
205
+ const enrichedMessage = {
206
+ ...message,
207
+ payload: {
208
+ ...message.payload,
209
+ clientId
210
+ }
211
+ };
212
+ this.messageHandlers.forEach(handler => handler(enrichedMessage));
213
+ }
214
+ catch (error) {
215
+ this.errorHandlers.forEach(handler => handler(error));
216
+ }
217
+ }
218
+ async handleAuthMessage(client, message) {
219
+ if (!this.authAdapter) {
220
+ this.sendToClient(client, {
221
+ id: this.generateId(),
222
+ type: 'auth_error',
223
+ payload: { error: 'No auth adapter configured' },
224
+ timestamp: Date.now()
225
+ });
226
+ return;
227
+ }
228
+ try {
229
+ const credentials = message.payload;
230
+ const result = await this.authAdapter.authenticate(credentials);
231
+ if (result.success) {
232
+ // Clear auth timeout
233
+ if (client.authTimeout) {
234
+ clearTimeout(client.authTimeout);
235
+ client.authTimeout = undefined;
236
+ }
237
+ // Update client state
238
+ client.authenticated = true;
239
+ client.userId = result.userId || result.user?.userId;
240
+ client.metadata = result.metadata || result.user?.metadata;
241
+ // Send success response
242
+ this.sendToClient(client, {
243
+ id: this.generateId(),
244
+ type: 'auth_success',
245
+ payload: {
246
+ userId: client.userId,
247
+ metadata: client.metadata
248
+ },
249
+ timestamp: Date.now()
250
+ });
251
+ // Notify handlers about authentication
252
+ const authMessage = {
253
+ id: this.generateId(),
254
+ type: 'client_authenticated',
255
+ payload: {
256
+ clientId: client.id,
257
+ userId: client.userId,
258
+ metadata: client.metadata
259
+ },
260
+ timestamp: Date.now()
261
+ };
262
+ this.messageHandlers.forEach(handler => handler(authMessage));
263
+ }
264
+ else {
265
+ // Send error response
266
+ this.sendToClient(client, {
267
+ id: this.generateId(),
268
+ type: 'auth_error',
269
+ payload: { error: result.error || 'Authentication failed' },
270
+ timestamp: Date.now()
271
+ });
272
+ // Optionally close connection
273
+ if (this.config.closeOnAuthFailure) {
274
+ client.ws.close(1008, 'Authentication failed');
275
+ this.clients.delete(client.id);
276
+ }
277
+ }
278
+ }
279
+ catch (error) {
280
+ this.sendToClient(client, {
281
+ id: this.generateId(),
282
+ type: 'auth_error',
283
+ payload: { error: error.message },
284
+ timestamp: Date.now()
285
+ });
286
+ }
287
+ }
288
+ extractBearerToken(authHeader) {
289
+ if (authHeader.startsWith('Bearer ')) {
290
+ return authHeader.substring(7);
291
+ }
292
+ return null;
293
+ }
294
+ sendToClient(client, message) {
295
+ if (client.ws.readyState === ws_1.WebSocket.OPEN) {
296
+ client.ws.send(JSON.stringify(message));
297
+ }
298
+ }
299
+ async disconnect() {
300
+ if (this.state === 'disconnected') {
301
+ return;
302
+ }
303
+ this.state = 'disconnecting';
304
+ // Close all client connections
305
+ for (const [_clientId, client] of this.clients) {
306
+ try {
307
+ if (client.authTimeout) {
308
+ clearTimeout(client.authTimeout);
309
+ }
310
+ client.ws.close(1000, 'Server shutting down');
311
+ }
312
+ catch {
313
+ // Ignore errors when closing individual connections
314
+ }
315
+ }
316
+ this.clients.clear();
317
+ // Close the WebSocket server (only if we created it)
318
+ if (this.wss && this.mode === 'standalone') {
319
+ await new Promise((resolve) => {
320
+ this.wss.close(() => resolve());
321
+ });
322
+ }
323
+ this.state = 'disconnected';
324
+ this.wss = undefined;
325
+ this.attachedServer = undefined;
326
+ this.attachedWss = undefined;
327
+ }
328
+ async send(message) {
329
+ if (this.state !== 'connected') {
330
+ throw new Error('Not connected');
331
+ }
332
+ // Extract clientId from message payload for routing
333
+ const payload = message.payload;
334
+ const { clientId, ...clientMessage } = payload;
335
+ if (!clientId) {
336
+ throw new Error('Message must contain clientId in payload for routing');
337
+ }
338
+ const client = this.clients.get(clientId);
339
+ if (!client) {
340
+ throw new Error(`Client ${clientId} not found`);
341
+ }
342
+ if (client.ws.readyState !== ws_1.WebSocket.OPEN) {
343
+ throw new Error(`Client ${clientId} connection is not open`);
344
+ }
345
+ const messageToSend = {
346
+ ...message,
347
+ payload: clientMessage
348
+ };
349
+ client.ws.send(JSON.stringify(messageToSend));
350
+ }
351
+ onMessage(handler) {
352
+ this.messageHandlers.add(handler);
353
+ }
354
+ onError(handler) {
355
+ this.errorHandlers.add(handler);
356
+ }
357
+ onClose(handler) {
358
+ this.closeHandlers.add(handler);
359
+ }
360
+ getState() {
361
+ return this.state;
362
+ }
363
+ isConnected() {
364
+ return this.state === 'connected';
365
+ }
366
+ // Utility methods
367
+ getConnectedClients() {
368
+ return Array.from(this.clients.values());
369
+ }
370
+ getAuthenticatedClients() {
371
+ return Array.from(this.clients.values()).filter(c => c.authenticated);
372
+ }
373
+ getClientCount() {
374
+ return this.clients.size;
375
+ }
376
+ getMode() {
377
+ return this.mode;
378
+ }
379
+ isAuthRequired() {
380
+ return this.config.requireAuth ?? false;
381
+ }
382
+ generateId() {
383
+ return Math.random().toString(36).substring(2) + Date.now().toString(36);
384
+ }
385
+ }
386
+ exports.WebSocketTransportAdapter = WebSocketTransportAdapter;
@@ -78,6 +78,7 @@ export declare class BaseClient extends TypedEventEmitter<ClientEvents> {
78
78
  private reconnectTimer;
79
79
  private lastConnectionUrl;
80
80
  private lastToken;
81
+ private pendingRequests;
81
82
  constructor(config: ClientConfig);
82
83
  /**
83
84
  * Connect to the server with an optional authentication token.
@@ -105,6 +106,28 @@ export declare class BaseClient extends TypedEventEmitter<ClientEvents> {
105
106
  broadcast(event: Event): Promise<void>;
106
107
  requestLock(request: LockRequest): Promise<void>;
107
108
  releaseLock(lockId: string): Promise<void>;
109
+ /**
110
+ * Send a request message and wait for a response.
111
+ *
112
+ * This enables request/response patterns over WebSocket by correlating
113
+ * the response message with the request via the message ID.
114
+ *
115
+ * @param type The message type to send
116
+ * @param payload The message payload
117
+ * @param timeoutMs Timeout in milliseconds (default: 5000)
118
+ * @returns Promise that resolves with the response payload
119
+ * @throws Error if the request times out or the client is not connected
120
+ *
121
+ * @example
122
+ * ```typescript
123
+ * const response = await client.request<PresenceGetUsersResponse>(
124
+ * 'presence:get_users',
125
+ * {}
126
+ * );
127
+ * console.log(response.users);
128
+ * ```
129
+ */
130
+ request<T>(type: string, payload: unknown, timeoutMs?: number): Promise<T>;
108
131
  getConnectionState(): ConnectionState;
109
132
  getRoomState(): RoomState | null;
110
133
  getPresence(): RoomUser[];
@@ -1 +1 @@
1
- {"version":3,"file":"BaseClient.d.ts","sourceRoot":"","sources":["../../src/client/BaseClient.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"BaseClient.d.ts","sourceRoot":"","sources":["../../src/client/BaseClient.ts"],"names":[],"mappings":"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"}
@@ -16,6 +16,8 @@ class BaseClient extends EventEmitter_js_1.TypedEventEmitter {
16
16
  this.reconnectTimer = null;
17
17
  this.lastConnectionUrl = null;
18
18
  this.lastToken = null;
19
+ // Request/response tracking for request() method
20
+ this.pendingRequests = new Map();
19
21
  this.config = config;
20
22
  this.transport = config.transport;
21
23
  this.auth = config.auth;
@@ -222,6 +224,56 @@ class BaseClient extends EventEmitter_js_1.TypedEventEmitter {
222
224
  };
223
225
  await this.transport.send(message);
224
226
  }
227
+ // Request/Response Pattern
228
+ /**
229
+ * Send a request message and wait for a response.
230
+ *
231
+ * This enables request/response patterns over WebSocket by correlating
232
+ * the response message with the request via the message ID.
233
+ *
234
+ * @param type The message type to send
235
+ * @param payload The message payload
236
+ * @param timeoutMs Timeout in milliseconds (default: 5000)
237
+ * @returns Promise that resolves with the response payload
238
+ * @throws Error if the request times out or the client is not connected
239
+ *
240
+ * @example
241
+ * ```typescript
242
+ * const response = await client.request<PresenceGetUsersResponse>(
243
+ * 'presence:get_users',
244
+ * {}
245
+ * );
246
+ * console.log(response.users);
247
+ * ```
248
+ */
249
+ async request(type, payload, timeoutMs = 5000) {
250
+ if (this.connectionState !== "connected") {
251
+ throw new Error("Client must be connected to send requests");
252
+ }
253
+ const id = this.generateId();
254
+ const message = {
255
+ id,
256
+ type,
257
+ payload,
258
+ timestamp: Date.now(),
259
+ };
260
+ return new Promise((resolve, reject) => {
261
+ const timeout = setTimeout(() => {
262
+ this.pendingRequests.delete(id);
263
+ reject(new Error(`Request '${type}' timed out after ${timeoutMs}ms`));
264
+ }, timeoutMs);
265
+ this.pendingRequests.set(id, {
266
+ resolve: resolve,
267
+ reject,
268
+ timeout,
269
+ });
270
+ this.transport.send(message).catch((error) => {
271
+ this.pendingRequests.delete(id);
272
+ clearTimeout(timeout);
273
+ reject(error);
274
+ });
275
+ });
276
+ }
225
277
  // State Getters
226
278
  getConnectionState() {
227
279
  return this.connectionState;
@@ -242,6 +294,14 @@ class BaseClient extends EventEmitter_js_1.TypedEventEmitter {
242
294
  }
243
295
  // Private Methods
244
296
  async handleMessage(message) {
297
+ // Check for pending request response (matched by message id)
298
+ if (message.id && this.pendingRequests.has(message.id)) {
299
+ const pending = this.pendingRequests.get(message.id);
300
+ clearTimeout(pending.timeout);
301
+ this.pendingRequests.delete(message.id);
302
+ pending.resolve(message.payload);
303
+ return;
304
+ }
245
305
  try {
246
306
  switch (message.type) {
247
307
  case "auth_result":
@@ -5,7 +5,7 @@
5
5
  * Automatically handles connection, authentication, and presence event forwarding.
6
6
  */
7
7
  import { TypedEventEmitter } from "../abstractions/EventEmitter.js";
8
- import type { UserPresence } from "../types/presence.js";
8
+ import type { SerializableUserPresence } from "../types/presence.js";
9
9
  import { BaseClient, type ClientConfig } from "./BaseClient.js";
10
10
  export interface PresenceClientConfig {
11
11
  /**
@@ -118,23 +118,58 @@ export declare class PresenceClient extends TypedEventEmitter<PresenceClientEven
118
118
  */
119
119
  disconnect(): Promise<void>;
120
120
  /**
121
- * Get all online users
121
+ * Get all online users with their presence data
122
122
  *
123
- * Note: This requires a corresponding API endpoint on your server.
123
+ * @returns Array of user presence objects
124
124
  */
125
- getOnlineUsers(): Promise<UserPresence[]>;
125
+ getOnlineUsers(): Promise<SerializableUserPresence[]>;
126
+ /**
127
+ * Get presence information for a specific user
128
+ *
129
+ * @param userId The user ID to look up
130
+ * @returns User presence or null if not found
131
+ */
132
+ getUserPresence(userId: string): Promise<SerializableUserPresence | null>;
133
+ /**
134
+ * Get all users in a specific repository
135
+ *
136
+ * @param owner Repository owner
137
+ * @param repo Repository name
138
+ * @returns Array of user presence objects
139
+ */
140
+ getRepoUsers(owner: string, repo: string): Promise<SerializableUserPresence[]>;
126
141
  /**
127
142
  * Set user status
128
143
  *
129
- * Note: This requires a corresponding API endpoint on your server.
144
+ * @param status The status to set ('online' or 'away')
145
+ * @param statusMessage Optional status message
130
146
  */
131
- setStatus(status: "online" | "away", message?: string): Promise<void>;
147
+ setStatus(status: "online" | "away", statusMessage?: string): Promise<void>;
132
148
  /**
133
- * Set visibility
149
+ * Set visibility (invisible/lurker mode)
134
150
  *
135
- * Note: This requires a corresponding API endpoint on your server.
151
+ * @param visible Whether the user should be visible to others
136
152
  */
137
153
  setVisibility(visible: boolean): Promise<void>;
154
+ /**
155
+ * Report that a repository was opened
156
+ *
157
+ * @param repoId Repository ID (format: "owner/repo")
158
+ * @param branch Branch name
159
+ */
160
+ reportRepoOpened(repoId: string, branch: string): Promise<void>;
161
+ /**
162
+ * Report that a repository was closed
163
+ *
164
+ * @param repoId Repository ID (format: "owner/repo")
165
+ */
166
+ reportRepoClosed(repoId: string): Promise<void>;
167
+ /**
168
+ * Report that a repository is now focused/active
169
+ *
170
+ * @param repoId Repository ID (format: "owner/repo")
171
+ */
172
+ reportRepoFocused(repoId: string): Promise<void>;
138
173
  /**
139
174
  * Get the underlying BaseClient
140
175
  */
@@ -1 +1 @@
1
- {"version":3,"file":"PresenceClient.d.ts","sourceRoot":"","sources":["../../src/client/PresenceClient.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEhE,MAAM,WAAW,oBAAoB;IACpC;;;OAGG;IACH,YAAY,EAAE,YAAY,CAAC;IAE3B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACpC;;OAEG;IACH,UAAU,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,EAAE,CAAA;KAAE,CAAC;IAEnD;;OAEG;IACH,WAAW,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAEhC;;OAEG;IACH,aAAa,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAE1E;;OAEG;IACH,SAAS,EAAE,EAAE,CAAC;IAEd;;OAEG;IACH,YAAY,EAAE,EAAE,CAAC;IAEjB;;OAEG;IACH,KAAK,EAAE;QAAE,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC;IAExB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,cAAe,SAAQ,iBAAiB,CAAC,oBAAoB,CAAC;IAC1E,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,oBAAoB,CAAU;IACtC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,gBAAgB,CAAC,CAAiB;gBAE9B,MAAM,EAAE,oBAAoB;IAiBxC;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAe9B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAuBjC;;;;OAIG;IACG,cAAc,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IAS/C;;;;OAIG;IACG,SAAS,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS3E;;;;OAIG;IACG,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IASpD;;OAEG;IACH,SAAS,IAAI,UAAU;IAIvB;;OAEG;IACH,WAAW,IAAI,OAAO;IAMtB;;;OAGG;IACH,OAAO,CAAC,oBAAoB;CAwD5B"}
1
+ {"version":3,"file":"PresenceClient.d.ts","sourceRoot":"","sources":["../../src/client/PresenceClient.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,KAAK,EAKX,wBAAwB,EACxB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEhE,MAAM,WAAW,oBAAoB;IACpC;;;OAGG;IACH,YAAY,EAAE,YAAY,CAAC;IAE3B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACpC;;OAEG;IACH,UAAU,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,EAAE,CAAA;KAAE,CAAC;IAEnD;;OAEG;IACH,WAAW,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAEhC;;OAEG;IACH,aAAa,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAE1E;;OAEG;IACH,SAAS,EAAE,EAAE,CAAC;IAEd;;OAEG;IACH,YAAY,EAAE,EAAE,CAAC;IAEjB;;OAEG;IACH,KAAK,EAAE;QAAE,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC;IAExB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,cAAe,SAAQ,iBAAiB,CAAC,oBAAoB,CAAC;IAC1E,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,oBAAoB,CAAU;IACtC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,gBAAgB,CAAC,CAAiB;gBAE9B,MAAM,EAAE,oBAAoB;IAiBxC;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAe9B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAuBjC;;;;OAIG;IACG,cAAc,IAAI,OAAO,CAAC,wBAAwB,EAAE,CAAC;IAQ3D;;;;;OAKG;IACG,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,GAAG,IAAI,CAAC;IAQ/E;;;;;;OAMG;IACG,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,EAAE,CAAC;IAQpF;;;;;OAKG;IACG,SAAS,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUjF;;;;OAIG;IACG,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAUpD;;;;;OAKG;IACG,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUrE;;;;OAIG;IACG,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUrD;;;;OAIG;IACG,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUtD;;OAEG;IACH,SAAS,IAAI,UAAU;IAIvB;;OAEG;IACH,WAAW,IAAI,OAAO;IAMtB;;;OAGG;IACH,OAAO,CAAC,oBAAoB;CAwD5B"}