vibemon 1.5.1 → 1.6.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/modules/validators.cjs +3 -3
- package/modules/ws-client.cjs +44 -0
- package/package.json +1 -1
package/modules/validators.cjs
CHANGED
|
@@ -10,9 +10,9 @@ const TOOL_MAX_LENGTH = 50;
|
|
|
10
10
|
const MODEL_MAX_LENGTH = 50;
|
|
11
11
|
const TERMINAL_ID_MAX_LENGTH = 100;
|
|
12
12
|
// Memory is now a number (0-100), not a string
|
|
13
|
-
// iTerm2: w0t0p0:UUID format, Ghostty:
|
|
14
|
-
const ITERM2_SESSION_PATTERN = /^w\d+t\d+p\d+:[0-9A-Fa-f-]{36}$/;
|
|
15
|
-
const GHOSTTY_PID_PATTERN =
|
|
13
|
+
// iTerm2: iterm2:w0t0p0:UUID format, Ghostty: ghostty:PID format
|
|
14
|
+
const ITERM2_SESSION_PATTERN = /^iterm2:w\d+t\d+p\d+:[0-9A-Fa-f-]{36}$/;
|
|
15
|
+
const GHOSTTY_PID_PATTERN = /^ghostty:\d{1,10}$/;
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Validate state value
|
package/modules/ws-client.cjs
CHANGED
|
@@ -12,6 +12,9 @@ const RECONNECT_INITIAL_DELAY = 5000; // 5 seconds
|
|
|
12
12
|
const RECONNECT_MAX_DELAY = 30000; // 30 seconds
|
|
13
13
|
const RECONNECT_MULTIPLIER = 1.5;
|
|
14
14
|
|
|
15
|
+
// Heartbeat configuration
|
|
16
|
+
const PING_INTERVAL = 30000; // Ping every 30 seconds
|
|
17
|
+
|
|
15
18
|
class WsClient {
|
|
16
19
|
constructor() {
|
|
17
20
|
this.ws = null;
|
|
@@ -21,6 +24,8 @@ class WsClient {
|
|
|
21
24
|
this.isConnecting = false;
|
|
22
25
|
this.isConnected = false;
|
|
23
26
|
this.shouldReconnect = true;
|
|
27
|
+
this.pingTimer = null;
|
|
28
|
+
this.pongReceived = true;
|
|
24
29
|
|
|
25
30
|
// Persistent storage for token
|
|
26
31
|
this.store = new Store({
|
|
@@ -158,9 +163,14 @@ class WsClient {
|
|
|
158
163
|
this.isConnecting = false;
|
|
159
164
|
this.isConnected = true;
|
|
160
165
|
this.reconnectDelay = RECONNECT_INITIAL_DELAY;
|
|
166
|
+
this.startHeartbeat();
|
|
161
167
|
this.notifyConnectionChange();
|
|
162
168
|
});
|
|
163
169
|
|
|
170
|
+
this.ws.on('pong', () => {
|
|
171
|
+
this.pongReceived = true;
|
|
172
|
+
});
|
|
173
|
+
|
|
164
174
|
this.ws.on('message', (data) => {
|
|
165
175
|
this.handleMessage(data);
|
|
166
176
|
});
|
|
@@ -236,6 +246,38 @@ class WsClient {
|
|
|
236
246
|
}
|
|
237
247
|
}
|
|
238
248
|
|
|
249
|
+
/**
|
|
250
|
+
* Start heartbeat ping to detect stale connections
|
|
251
|
+
*/
|
|
252
|
+
startHeartbeat() {
|
|
253
|
+
this.stopHeartbeat();
|
|
254
|
+
this.pongReceived = true;
|
|
255
|
+
|
|
256
|
+
this.pingTimer = setInterval(() => {
|
|
257
|
+
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;
|
|
258
|
+
|
|
259
|
+
if (!this.pongReceived) {
|
|
260
|
+
// Server didn't respond to last ping - connection is stale
|
|
261
|
+
console.log('WebSocket heartbeat timeout, reconnecting...');
|
|
262
|
+
this.ws.terminate();
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
this.pongReceived = false;
|
|
267
|
+
this.ws.ping();
|
|
268
|
+
}, PING_INTERVAL);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Stop heartbeat ping
|
|
273
|
+
*/
|
|
274
|
+
stopHeartbeat() {
|
|
275
|
+
if (this.pingTimer) {
|
|
276
|
+
clearInterval(this.pingTimer);
|
|
277
|
+
this.pingTimer = null;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
239
281
|
/**
|
|
240
282
|
* Handle disconnection and schedule reconnect
|
|
241
283
|
*/
|
|
@@ -243,6 +285,7 @@ class WsClient {
|
|
|
243
285
|
this.isConnecting = false;
|
|
244
286
|
this.isConnected = false;
|
|
245
287
|
this.ws = null;
|
|
288
|
+
this.stopHeartbeat();
|
|
246
289
|
this.notifyConnectionChange();
|
|
247
290
|
|
|
248
291
|
if (this.shouldReconnect) {
|
|
@@ -286,6 +329,7 @@ class WsClient {
|
|
|
286
329
|
*/
|
|
287
330
|
disconnect() {
|
|
288
331
|
this.shouldReconnect = false;
|
|
332
|
+
this.stopHeartbeat();
|
|
289
333
|
|
|
290
334
|
if (this.reconnectTimer) {
|
|
291
335
|
clearTimeout(this.reconnectTimer);
|