@principal-ai/control-tower-core 0.1.11 → 0.1.13

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,193 @@
1
+ "use strict";
2
+ /**
3
+ * Presence Client Helper
4
+ *
5
+ * Simplifies client-side presence integration for web/Electron applications.
6
+ * Automatically handles connection, authentication, and presence event forwarding.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.PresenceClient = void 0;
10
+ const BaseClient_js_1 = require("./BaseClient.js");
11
+ const EventEmitter_js_1 = require("../abstractions/EventEmitter.js");
12
+ /**
13
+ * High-level presence client for easy integration
14
+ *
15
+ * Example:
16
+ * ```typescript
17
+ * import { PresenceClient } from '@principal-ai/control-tower-core';
18
+ * import { WebSocketClientTransportAdapter } from '@principal-ai/control-tower-core';
19
+ * import { ClientBuilder } from '@principal-ai/control-tower-core';
20
+ *
21
+ * const transport = new WebSocketClientTransportAdapter();
22
+ *
23
+ * const client = new ClientBuilder()
24
+ * .withTransport(transport)
25
+ * .build();
26
+ *
27
+ * const presence = new PresenceClient({
28
+ * clientConfig: client,
29
+ * wsUrl: 'ws://localhost:3000/ws',
30
+ * autoConnect: true,
31
+ * autoReconnect: true
32
+ * });
33
+ *
34
+ * presence.on('userOnline', (data) => {
35
+ * console.log(`${data.userId} came online`);
36
+ * });
37
+ *
38
+ * presence.on('userOffline', (data) => {
39
+ * console.log(`${data.userId} went offline`);
40
+ * });
41
+ * ```
42
+ */
43
+ class PresenceClient extends EventEmitter_js_1.TypedEventEmitter {
44
+ constructor(config) {
45
+ super();
46
+ this.wsUrl = config.wsUrl;
47
+ this.autoReconnectEnabled = config.autoReconnect ?? true;
48
+ this.globalRoomId = config.globalRoomId ?? '__global_presence__';
49
+ // Create base client
50
+ this.client = new BaseClient_js_1.BaseClient(config.clientConfig);
51
+ this.setupEventForwarding();
52
+ if (config.autoConnect) {
53
+ void this.connect();
54
+ }
55
+ }
56
+ /**
57
+ * Connect to the presence system
58
+ */
59
+ async connect() {
60
+ try {
61
+ // Connect base client
62
+ await this.client.connect(this.wsUrl);
63
+ // Join global presence room
64
+ await this.client.joinRoom(this.globalRoomId);
65
+ await this.emit('connected', {});
66
+ }
67
+ catch (error) {
68
+ await this.emit('error', { error: error });
69
+ throw error;
70
+ }
71
+ }
72
+ /**
73
+ * Disconnect from the presence system
74
+ */
75
+ async disconnect() {
76
+ // Disable auto-reconnect
77
+ this.autoReconnectEnabled = false;
78
+ // Clear any pending reconnect
79
+ if (this.reconnectTimeout) {
80
+ clearTimeout(this.reconnectTimeout);
81
+ this.reconnectTimeout = undefined;
82
+ }
83
+ try {
84
+ // Leave global presence room
85
+ await this.client.leaveRoom();
86
+ // Disconnect
87
+ await this.client.disconnect();
88
+ await this.emit('disconnected', {});
89
+ }
90
+ catch (error) {
91
+ await this.emit('error', { error: error });
92
+ }
93
+ }
94
+ /**
95
+ * Get all online users
96
+ *
97
+ * Note: This requires a corresponding API endpoint on your server.
98
+ */
99
+ async getOnlineUsers() {
100
+ // This assumes you have a REST API endpoint for fetching online users
101
+ // You can customize this based on your server implementation
102
+ throw new Error('getOnlineUsers() requires a REST API endpoint. ' +
103
+ 'Implement this method based on your server API.');
104
+ }
105
+ /**
106
+ * Set user status
107
+ *
108
+ * Note: This requires a corresponding API endpoint on your server.
109
+ */
110
+ async setStatus(status, message) {
111
+ // This assumes you have a REST API endpoint for setting status
112
+ // You can customize this based on your server implementation
113
+ throw new Error('setStatus() requires a REST API endpoint. ' +
114
+ 'Implement this method based on your server API.');
115
+ }
116
+ /**
117
+ * Set visibility
118
+ *
119
+ * Note: This requires a corresponding API endpoint on your server.
120
+ */
121
+ async setVisibility(visible) {
122
+ // This assumes you have a REST API endpoint for setting visibility
123
+ // You can customize this based on your server implementation
124
+ throw new Error('setVisibility() requires a REST API endpoint. ' +
125
+ 'Implement this method based on your server API.');
126
+ }
127
+ /**
128
+ * Get the underlying BaseClient
129
+ */
130
+ getClient() {
131
+ return this.client;
132
+ }
133
+ /**
134
+ * Check if connected
135
+ */
136
+ isConnected() {
137
+ // BaseClient doesn't expose getState(), so we check internal state via a workaround
138
+ // In practice, you can track connection state via events
139
+ return this.client.connectionState === 'connected';
140
+ }
141
+ /**
142
+ * Set up event forwarding from BaseClient
143
+ * @private
144
+ */
145
+ setupEventForwarding() {
146
+ // Forward presence events with simplified API
147
+ this.client.on('presence:user_online', (data) => {
148
+ if (data && typeof data === 'object') {
149
+ const payload = data;
150
+ void this.emit('userOnline', {
151
+ userId: payload.userId,
152
+ devices: payload.devices || []
153
+ });
154
+ }
155
+ });
156
+ this.client.on('presence:user_offline', (data) => {
157
+ if (data && typeof data === 'object') {
158
+ const payload = data;
159
+ void this.emit('userOffline', { userId: payload.userId });
160
+ }
161
+ });
162
+ this.client.on('presence:status_changed', (data) => {
163
+ if (data && typeof data === 'object') {
164
+ const payload = data;
165
+ void this.emit('statusChanged', {
166
+ userId: payload.userId,
167
+ status: payload.status,
168
+ statusMessage: payload.statusMessage
169
+ });
170
+ }
171
+ });
172
+ // Handle disconnection
173
+ this.client.on('disconnected', () => {
174
+ void this.emit('disconnected', {});
175
+ // Auto-reconnect if enabled
176
+ if (this.autoReconnectEnabled) {
177
+ this.reconnectTimeout = setTimeout(() => {
178
+ void this.connect().catch((error) => {
179
+ void this.emit('error', { error: error });
180
+ });
181
+ }, 5000);
182
+ }
183
+ });
184
+ // Forward errors
185
+ this.client.on('error', (data) => {
186
+ if (data && typeof data === 'object' && 'error' in data) {
187
+ const payload = data;
188
+ void this.emit('error', { error: payload.error });
189
+ }
190
+ });
191
+ }
192
+ }
193
+ exports.PresenceClient = PresenceClient;
@@ -1,3 +1,4 @@
1
1
  export { BaseClient, type ClientConfig, type ClientEvents } from './BaseClient.js';
2
2
  export { ClientBuilder } from './ClientBuilder.js';
3
+ export { PresenceClient, type PresenceClientConfig, type PresenceClientEvents } from './PresenceClient.js';
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACnF,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACnF,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EACL,cAAc,EACd,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAC"}
@@ -1,8 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ClientBuilder = exports.BaseClient = void 0;
3
+ exports.PresenceClient = exports.ClientBuilder = exports.BaseClient = void 0;
4
4
  // Client-side implementations
5
5
  var BaseClient_js_1 = require("./BaseClient.js");
6
6
  Object.defineProperty(exports, "BaseClient", { enumerable: true, get: function () { return BaseClient_js_1.BaseClient; } });
7
7
  var ClientBuilder_js_1 = require("./ClientBuilder.js");
8
8
  Object.defineProperty(exports, "ClientBuilder", { enumerable: true, get: function () { return ClientBuilder_js_1.ClientBuilder; } });
9
+ var PresenceClient_js_1 = require("./PresenceClient.js");
10
+ Object.defineProperty(exports, "PresenceClient", { enumerable: true, get: function () { return PresenceClient_js_1.PresenceClient; } });
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { EventType, BaseEvent, FileAction, FileChangeEvent, GitStatusEvent, CommitEvent, BranchChangeEvent, CursorPositionEvent, Event, TokenPayload, AuthResult, CredentialType, OAuthProvider, Credentials, JWTConfig, OAuthConfig, AuthProvider, RoomPermission, Room, RoomUser, UserStatus, RoomState, RoomConfig, LockType, LockPriority, Lock, LockRequest, LockQueueItem, LockState, ConnectionState, ConnectionOptions, Message, MessageHandler, ErrorHandler, CloseHandler, ExperimentalFeatureConfig, ClientPredicate, BroadcastResult, BroadcastOptions, ExperimentalUsageEvent, ExperimentalFeatureError, PresenceStatus, DeviceInfo, UserPresence, PresenceConfig, PresenceChangeEvent, ActivityUpdate } from './types/index.js';
2
- export { ITransportAdapter, IStorageAdapter, StorageOperation, IAuthAdapter, TypedEventEmitter, EventListener, UnsubscribeFn, RoomManager, LockManager, DefaultRoomManager, DefaultLockManager, PresenceManager, DefaultPresenceManager } from './abstractions/index.js';
2
+ export { ITransportAdapter, IStorageAdapter, StorageOperation, IAuthAdapter, TypedEventEmitter, EventListener, UnsubscribeFn, RoomManager, LockManager, DefaultRoomManager, DefaultLockManager, PresenceManager, DefaultPresenceManager, PresenceExtension, ExtendedUserPresence } from './abstractions/index.js';
3
3
  export { MockTransportAdapter, MockStorageAdapter, MockAuthAdapter } from './adapters/mock/index.js';
4
4
  export { WebSocketServerTransportAdapter, type WebSocketServerTransportConfig, WebSocketClientTransportAdapter, type WebSocketClientConfig } from './adapters/websocket/index.js';
5
- export { BaseClient, ClientBuilder, type ClientConfig, type ClientEvents } from './client/index.js';
5
+ export { BaseClient, ClientBuilder, type ClientConfig, type ClientEvents, PresenceClient, type PresenceClientConfig, type PresenceClientEvents } from './client/index.js';
6
6
  export { BaseServer, ServerBuilder, ExperimentalAPI, type ServerConfig, type ServerEvents, type ConnectedClient } from './server/index.js';
7
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,SAAS,EACT,SAAS,EACT,UAAU,EACV,eAAe,EACf,cAAc,EACd,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACnB,KAAK,EAEL,YAAY,EACZ,UAAU,EACV,cAAc,EACd,aAAa,EACb,WAAW,EACX,SAAS,EACT,WAAW,EACX,YAAY,EAEZ,cAAc,EACd,IAAI,EACJ,QAAQ,EACR,UAAU,EACV,SAAS,EACT,UAAU,EAEV,QAAQ,EACR,YAAY,EACZ,IAAI,EACJ,WAAW,EACX,aAAa,EACb,SAAS,EAET,eAAe,EACf,iBAAiB,EACjB,OAAO,EACP,cAAc,EACd,YAAY,EACZ,YAAY,EAEZ,yBAAyB,EACzB,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,sBAAsB,EACtB,wBAAwB,EAExB,cAAc,EACd,UAAU,EACV,YAAY,EACZ,cAAc,EACd,mBAAmB,EACnB,cAAc,EACf,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,sBAAsB,EACvB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,eAAe,EAChB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,+BAA+B,EAC/B,KAAK,8BAA8B,EACnC,+BAA+B,EAC/B,KAAK,qBAAqB,EAC3B,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EACL,UAAU,EACV,aAAa,EACb,KAAK,YAAY,EACjB,KAAK,YAAY,EAClB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,UAAU,EACV,aAAa,EACb,eAAe,EACf,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,eAAe,EACrB,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,SAAS,EACT,SAAS,EACT,UAAU,EACV,eAAe,EACf,cAAc,EACd,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACnB,KAAK,EAEL,YAAY,EACZ,UAAU,EACV,cAAc,EACd,aAAa,EACb,WAAW,EACX,SAAS,EACT,WAAW,EACX,YAAY,EAEZ,cAAc,EACd,IAAI,EACJ,QAAQ,EACR,UAAU,EACV,SAAS,EACT,UAAU,EAEV,QAAQ,EACR,YAAY,EACZ,IAAI,EACJ,WAAW,EACX,aAAa,EACb,SAAS,EAET,eAAe,EACf,iBAAiB,EACjB,OAAO,EACP,cAAc,EACd,YAAY,EACZ,YAAY,EAEZ,yBAAyB,EACzB,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,sBAAsB,EACtB,wBAAwB,EAExB,cAAc,EACd,UAAU,EACV,YAAY,EACZ,cAAc,EACd,mBAAmB,EACnB,cAAc,EACf,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACrB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,eAAe,EAChB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,+BAA+B,EAC/B,KAAK,8BAA8B,EACnC,+BAA+B,EAC/B,KAAK,qBAAqB,EAC3B,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EACL,UAAU,EACV,aAAa,EACb,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,cAAc,EACd,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EAC1B,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,UAAU,EACV,aAAa,EACb,eAAe,EACf,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,eAAe,EACrB,MAAM,mBAAmB,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ExperimentalAPI = exports.ServerBuilder = exports.BaseServer = exports.ClientBuilder = exports.BaseClient = exports.WebSocketClientTransportAdapter = exports.WebSocketServerTransportAdapter = exports.MockAuthAdapter = exports.MockStorageAdapter = exports.MockTransportAdapter = exports.DefaultPresenceManager = exports.PresenceManager = exports.DefaultLockManager = exports.DefaultRoomManager = exports.LockManager = exports.RoomManager = exports.TypedEventEmitter = exports.ExperimentalFeatureError = void 0;
3
+ exports.ExperimentalAPI = exports.ServerBuilder = exports.BaseServer = exports.PresenceClient = exports.ClientBuilder = exports.BaseClient = exports.WebSocketClientTransportAdapter = exports.WebSocketServerTransportAdapter = exports.MockAuthAdapter = exports.MockStorageAdapter = exports.MockTransportAdapter = exports.DefaultPresenceManager = exports.PresenceManager = exports.DefaultLockManager = exports.DefaultRoomManager = exports.LockManager = exports.RoomManager = exports.TypedEventEmitter = exports.ExperimentalFeatureError = void 0;
4
4
  // Types
5
5
  var index_js_1 = require("./types/index.js");
6
6
  Object.defineProperty(exports, "ExperimentalFeatureError", { enumerable: true, get: function () { return index_js_1.ExperimentalFeatureError; } });
@@ -25,6 +25,7 @@ Object.defineProperty(exports, "WebSocketClientTransportAdapter", { enumerable:
25
25
  var index_js_5 = require("./client/index.js");
26
26
  Object.defineProperty(exports, "BaseClient", { enumerable: true, get: function () { return index_js_5.BaseClient; } });
27
27
  Object.defineProperty(exports, "ClientBuilder", { enumerable: true, get: function () { return index_js_5.ClientBuilder; } });
28
+ Object.defineProperty(exports, "PresenceClient", { enumerable: true, get: function () { return index_js_5.PresenceClient; } });
28
29
  // Server
29
30
  var index_js_6 = require("./server/index.js");
30
31
  Object.defineProperty(exports, "BaseServer", { enumerable: true, get: function () { return index_js_6.BaseServer; } });