@principal-ai/control-tower-core 0.1.2 → 0.1.4
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/abstractions/TransportAdapter.d.ts +0 -5
- package/dist/abstractions/TransportAdapter.d.ts.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -2
- package/dist/index.js.map +5 -20
- package/dist/index.mjs +1402 -0
- package/dist/index.mjs.map +21 -0
- package/dist/server/BaseServer.d.ts +1 -12
- package/dist/server/BaseServer.d.ts.map +1 -1
- package/dist/server/BaseServer.js +0 -55
- package/dist/server/ServerBuilder.d.ts +0 -9
- package/dist/server/ServerBuilder.d.ts.map +1 -1
- package/dist/server/ServerBuilder.js +1 -16
- package/package.json +2 -5
- package/dist/adapters/websocket/WebSocketTransportAdapter.d.ts +0 -40
- package/dist/adapters/websocket/WebSocketTransportAdapter.d.ts.map +0 -1
- package/dist/adapters/websocket/WebSocketTransportAdapter.js +0 -204
- package/dist/adapters/websocket/index.d.ts +0 -2
- package/dist/adapters/websocket/index.d.ts.map +0 -1
- package/dist/adapters/websocket/index.js +0 -1
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
import { WebSocketServer, WebSocket } from 'ws';
|
|
2
|
-
export class WebSocketTransportAdapter {
|
|
3
|
-
constructor() {
|
|
4
|
-
this.state = 'disconnected';
|
|
5
|
-
this.messageHandlers = new Set();
|
|
6
|
-
this.errorHandlers = new Set();
|
|
7
|
-
this.closeHandlers = new Set();
|
|
8
|
-
// Client management
|
|
9
|
-
this.clients = new Map();
|
|
10
|
-
this.mode = 'standalone';
|
|
11
|
-
}
|
|
12
|
-
// Standalone mode implementation
|
|
13
|
-
async connect(url, _options) {
|
|
14
|
-
if (this.state === 'connected' || this.state === 'connecting') {
|
|
15
|
-
throw new Error('Already connected or connecting');
|
|
16
|
-
}
|
|
17
|
-
this.state = 'connecting';
|
|
18
|
-
this.serverUrl = url;
|
|
19
|
-
this.mode = 'standalone';
|
|
20
|
-
try {
|
|
21
|
-
// Extract port from URL
|
|
22
|
-
const urlObj = new URL(url);
|
|
23
|
-
const port = parseInt(urlObj.port) || (urlObj.protocol === 'wss:' ? 443 : 80);
|
|
24
|
-
// Create WebSocket server
|
|
25
|
-
this.wss = new WebSocketServer({ port });
|
|
26
|
-
this.wss.on('connection', (ws, req) => {
|
|
27
|
-
this.handleConnection(ws, req);
|
|
28
|
-
});
|
|
29
|
-
this.wss.on('error', (error) => {
|
|
30
|
-
this.errorHandlers.forEach(handler => handler(error));
|
|
31
|
-
});
|
|
32
|
-
this.wss.on('close', () => {
|
|
33
|
-
this.state = 'disconnected';
|
|
34
|
-
this.closeHandlers.forEach(handler => handler(1000, 'Server closed'));
|
|
35
|
-
});
|
|
36
|
-
this.state = 'connected';
|
|
37
|
-
}
|
|
38
|
-
catch (error) {
|
|
39
|
-
this.state = 'disconnected';
|
|
40
|
-
throw error;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
// Integration mode implementation
|
|
44
|
-
async attach(server, path = '/ws') {
|
|
45
|
-
if (this.state === 'connected' || this.state === 'connecting') {
|
|
46
|
-
throw new Error('Already connected or connecting');
|
|
47
|
-
}
|
|
48
|
-
this.state = 'connecting';
|
|
49
|
-
this.attachedServer = server;
|
|
50
|
-
this.webSocketPath = path;
|
|
51
|
-
this.mode = 'integration';
|
|
52
|
-
try {
|
|
53
|
-
// Create WebSocket server attached to the existing HTTP server
|
|
54
|
-
this.wss = new WebSocketServer({
|
|
55
|
-
server,
|
|
56
|
-
path,
|
|
57
|
-
perMessageDeflate: false
|
|
58
|
-
});
|
|
59
|
-
this.wss.on('connection', (ws, req) => {
|
|
60
|
-
this.handleConnection(ws, req);
|
|
61
|
-
});
|
|
62
|
-
this.wss.on('error', (error) => {
|
|
63
|
-
this.errorHandlers.forEach(handler => handler(error));
|
|
64
|
-
});
|
|
65
|
-
this.state = 'connected';
|
|
66
|
-
}
|
|
67
|
-
catch (error) {
|
|
68
|
-
this.state = 'disconnected';
|
|
69
|
-
throw error;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
async attachToWebSocketServer(wss) {
|
|
73
|
-
if (this.state === 'connected' || this.state === 'connecting') {
|
|
74
|
-
throw new Error('Already connected or connecting');
|
|
75
|
-
}
|
|
76
|
-
this.state = 'connecting';
|
|
77
|
-
this.attachedWss = wss;
|
|
78
|
-
this.mode = 'integration';
|
|
79
|
-
try {
|
|
80
|
-
this.wss = wss;
|
|
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
|
-
handleConnection(ws, req) {
|
|
95
|
-
const clientId = this.generateId();
|
|
96
|
-
const client = {
|
|
97
|
-
id: clientId,
|
|
98
|
-
ws,
|
|
99
|
-
userId: typeof req.headers['x-user-id'] === 'string' ? req.headers['x-user-id'] : undefined
|
|
100
|
-
};
|
|
101
|
-
this.clients.set(clientId, client);
|
|
102
|
-
ws.on('message', (data) => {
|
|
103
|
-
try {
|
|
104
|
-
const message = JSON.parse(data.toString());
|
|
105
|
-
// Add clientId to message payload for routing
|
|
106
|
-
const enrichedMessage = {
|
|
107
|
-
...message,
|
|
108
|
-
payload: {
|
|
109
|
-
...message.payload,
|
|
110
|
-
clientId
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
|
-
this.messageHandlers.forEach(handler => handler(enrichedMessage));
|
|
114
|
-
}
|
|
115
|
-
catch (error) {
|
|
116
|
-
this.errorHandlers.forEach(handler => handler(error));
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
ws.on('error', (error) => {
|
|
120
|
-
this.errorHandlers.forEach(handler => handler(error));
|
|
121
|
-
});
|
|
122
|
-
ws.on('close', (_code, _reason) => {
|
|
123
|
-
this.clients.delete(clientId);
|
|
124
|
-
// Don't emit close for individual clients, only for server shutdown
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
async disconnect() {
|
|
128
|
-
if (this.state === 'disconnected') {
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
this.state = 'disconnecting';
|
|
132
|
-
// Close all client connections
|
|
133
|
-
for (const [_clientId, client] of this.clients) {
|
|
134
|
-
try {
|
|
135
|
-
client.ws.close(1000, 'Server shutting down');
|
|
136
|
-
}
|
|
137
|
-
catch {
|
|
138
|
-
// Ignore errors when closing individual connections
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
this.clients.clear();
|
|
142
|
-
// Close the WebSocket server (only if we created it)
|
|
143
|
-
if (this.wss && this.mode === 'standalone') {
|
|
144
|
-
await new Promise((resolve) => {
|
|
145
|
-
this.wss.close(() => resolve());
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
this.state = 'disconnected';
|
|
149
|
-
this.wss = undefined;
|
|
150
|
-
this.attachedServer = undefined;
|
|
151
|
-
this.attachedWss = undefined;
|
|
152
|
-
}
|
|
153
|
-
async send(message) {
|
|
154
|
-
if (this.state !== 'connected') {
|
|
155
|
-
throw new Error('Not connected');
|
|
156
|
-
}
|
|
157
|
-
// Extract clientId from message payload for routing
|
|
158
|
-
const payload = message.payload;
|
|
159
|
-
const { clientId, ...clientMessage } = payload;
|
|
160
|
-
if (!clientId) {
|
|
161
|
-
throw new Error('Message must contain clientId in payload for routing');
|
|
162
|
-
}
|
|
163
|
-
const client = this.clients.get(clientId);
|
|
164
|
-
if (!client) {
|
|
165
|
-
throw new Error(`Client ${clientId} not found`);
|
|
166
|
-
}
|
|
167
|
-
if (client.ws.readyState !== WebSocket.OPEN) {
|
|
168
|
-
throw new Error(`Client ${clientId} connection is not open`);
|
|
169
|
-
}
|
|
170
|
-
const messageToSend = {
|
|
171
|
-
...message,
|
|
172
|
-
payload: clientMessage
|
|
173
|
-
};
|
|
174
|
-
client.ws.send(JSON.stringify(messageToSend));
|
|
175
|
-
}
|
|
176
|
-
onMessage(handler) {
|
|
177
|
-
this.messageHandlers.add(handler);
|
|
178
|
-
}
|
|
179
|
-
onError(handler) {
|
|
180
|
-
this.errorHandlers.add(handler);
|
|
181
|
-
}
|
|
182
|
-
onClose(handler) {
|
|
183
|
-
this.closeHandlers.add(handler);
|
|
184
|
-
}
|
|
185
|
-
getState() {
|
|
186
|
-
return this.state;
|
|
187
|
-
}
|
|
188
|
-
isConnected() {
|
|
189
|
-
return this.state === 'connected';
|
|
190
|
-
}
|
|
191
|
-
// Utility methods
|
|
192
|
-
getConnectedClients() {
|
|
193
|
-
return Array.from(this.clients.values());
|
|
194
|
-
}
|
|
195
|
-
getClientCount() {
|
|
196
|
-
return this.clients.size;
|
|
197
|
-
}
|
|
198
|
-
getMode() {
|
|
199
|
-
return this.mode;
|
|
200
|
-
}
|
|
201
|
-
generateId() {
|
|
202
|
-
return Math.random().toString(36).substring(2) + Date.now().toString(36);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/websocket/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { WebSocketTransportAdapter } from './WebSocketTransportAdapter';
|