@geometra/mcp 1.44.0 → 1.45.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/session.js +29 -2
- package/package.json +1 -1
package/dist/session.js
CHANGED
|
@@ -645,19 +645,46 @@ export function connect(url, opts) {
|
|
|
645
645
|
let resolved = false;
|
|
646
646
|
let lastMessageAt = Date.now();
|
|
647
647
|
let heartbeatInterval = null;
|
|
648
|
+
let pendingPongBy = null;
|
|
649
|
+
// Heartbeat: send a real WS-level ping every 15s and only tear the socket
|
|
650
|
+
// down if the peer fails to respond to two consecutive pings (i.e. ~45s of
|
|
651
|
+
// true unresponsiveness). Previous versions used a dumb idle timer that
|
|
652
|
+
// closed the socket after 30s of no inbound frames — which killed sessions
|
|
653
|
+
// during normal form-submission flows where the DOM is legitimately idle
|
|
654
|
+
// for 20-30+ seconds while the backend processes (Greenhouse submit →
|
|
655
|
+
// security-code dialog is the canonical repro). A real ping/pong cycle
|
|
656
|
+
// distinguishes a silent-but-healthy session from a dead one.
|
|
648
657
|
function startHeartbeat() {
|
|
649
658
|
if (heartbeatInterval)
|
|
650
659
|
return;
|
|
651
660
|
heartbeatInterval = setInterval(() => {
|
|
652
|
-
|
|
661
|
+
// If we're waiting on a pong and it's overdue, the peer is dead.
|
|
662
|
+
if (pendingPongBy !== null && Date.now() > pendingPongBy) {
|
|
653
663
|
try {
|
|
654
664
|
ws.close();
|
|
655
665
|
}
|
|
656
666
|
catch { /* ignore */ }
|
|
667
|
+
return;
|
|
668
|
+
}
|
|
669
|
+
// Only send a new ping if we haven't heard anything for a while,
|
|
670
|
+
// to avoid spamming a chatty session.
|
|
671
|
+
if (Date.now() - lastMessageAt > 10_000) {
|
|
672
|
+
try {
|
|
673
|
+
ws.ping();
|
|
674
|
+
// Allow 30s for the pong before declaring the peer dead.
|
|
675
|
+
pendingPongBy = Date.now() + 30_000;
|
|
676
|
+
}
|
|
677
|
+
catch {
|
|
678
|
+
/* if ping throws, the socket is already gone — let 'close' handle */
|
|
679
|
+
}
|
|
657
680
|
}
|
|
658
|
-
},
|
|
681
|
+
}, 15_000);
|
|
659
682
|
heartbeatInterval.unref();
|
|
660
683
|
}
|
|
684
|
+
ws.on('pong', () => {
|
|
685
|
+
lastMessageAt = Date.now();
|
|
686
|
+
pendingPongBy = null;
|
|
687
|
+
});
|
|
661
688
|
const timeout = setTimeout(() => {
|
|
662
689
|
if (!resolved) {
|
|
663
690
|
resolved = true;
|
package/package.json
CHANGED