@@ -5,16 +5,31 @@ const WebSocket = require('ws')
55
66import { DEFAULT_PORT , SECURITY_TOKENS } from '@shared/constants/websocket'
77
8+ const is_version_gte = ( v : string , target : string ) => {
9+ if ( v === 'unknown' ) return false
10+ const vParts = v . split ( '.' ) . map ( Number )
11+ const tParts = target . split ( '.' ) . map ( Number )
12+ for ( let i = 0 ; i < Math . max ( vParts . length , tParts . length ) ; i ++ ) {
13+ const p1 = vParts [ i ] || 0
14+ const p2 = tParts [ i ] || 0
15+ if ( p1 > p2 ) return true
16+ if ( p1 < p2 ) return false
17+ }
18+ return true
19+ }
20+
821interface BrowserClient {
922 ws : WebSocket
1023 version : string
1124 id : number
1225 user_agent : string
26+ is_alive : boolean
1327}
1428
1529interface VSCodeClient {
1630 ws : WebSocket
1731 client_id : number
32+ is_alive : boolean
1833}
1934
2035class WebSocketServer {
@@ -88,7 +103,7 @@ class WebSocketServer {
88103
89104 this . connections . add ( ws )
90105
91- ws . on ( 'message' , ( message : any ) => this . _handle_message ( message ) )
106+ ws . on ( 'message' , ( message : any ) => this . _handle_message ( message , ws ) )
92107 ws . on ( 'close' , ( ) => this . _handle_disconnection ( ws , is_browser_client ) )
93108 }
94109
@@ -99,7 +114,13 @@ class WebSocketServer {
99114 this . browser_client_counter ++
100115 const id = this . browser_client_counter
101116
102- const client : BrowserClient = { ws, version, id, user_agent }
117+ const client : BrowserClient = {
118+ ws,
119+ version,
120+ id,
121+ user_agent,
122+ is_alive : true
123+ }
103124 this . browser_clients . set ( id , client )
104125
105126 this . _notify_vscode_clients ( )
@@ -108,7 +129,7 @@ class WebSocketServer {
108129
109130 private _handle_vscode_connection ( ws : WebSocket ) {
110131 const client_id = this . _generate_client_id ( )
111- this . vscode_clients . set ( client_id , { ws, client_id } )
132+ this . vscode_clients . set ( client_id , { ws, client_id, is_alive : true } )
112133
113134 ws . send (
114135 JSON . stringify ( {
@@ -136,9 +157,30 @@ class WebSocketServer {
136157 }
137158 }
138159
139- private _handle_message ( message : any ) {
160+ private _handle_message ( message : any , ws : any ) {
140161 const msg_string = message . toString ( )
141- const msg_data = JSON . parse ( msg_string )
162+ let msg_data
163+ try {
164+ msg_data = JSON . parse ( msg_string )
165+ } catch {
166+ return
167+ }
168+
169+ if ( msg_data . action === 'pong' ) {
170+ for ( const client of this . browser_clients . values ( ) ) {
171+ if ( client . ws === ws ) {
172+ client . is_alive = true
173+ return
174+ }
175+ }
176+ for ( const client of this . vscode_clients . values ( ) ) {
177+ if ( client . ws === ws ) {
178+ client . is_alive = true
179+ return
180+ }
181+ }
182+ return
183+ }
142184
143185 if ( msg_data . action == 'initialize-chat' ) {
144186 if ( msg_data . target_browser_id ) {
@@ -231,12 +273,26 @@ class WebSocketServer {
231273 const ping_message = JSON . stringify ( { action : 'ping' } )
232274
233275 for ( const client of this . browser_clients . values ( ) ) {
276+ const expects_pong = is_version_gte ( client . version , '2026.7.2' )
277+
278+ if ( expects_pong ) {
279+ if ( ! client . is_alive ) {
280+ ; ( client . ws as any ) . terminate ( )
281+ continue
282+ }
283+ client . is_alive = false
284+ }
234285 if ( client . ws . readyState === WebSocket . OPEN ) {
235286 client . ws . send ( ping_message )
236287 }
237288 }
238289
239290 for ( const client of this . vscode_clients . values ( ) ) {
291+ if ( ! client . is_alive ) {
292+ ; ( client . ws as any ) . terminate ( )
293+ continue
294+ }
295+ client . is_alive = false
240296 if ( client . ws . readyState == WebSocket . OPEN ) {
241297 client . ws . send ( ping_message )
242298 }
0 commit comments