@@ -28,8 +28,10 @@ export interface SshProcessMonitorOptions {
2828 networkInfoPath : string ;
2929 proxyLogDir ?: string ;
3030 logger : Logger ;
31- // Poll interval for SSH process and file discovery
32- pollInterval ?: number ;
31+ // Initial poll interval for SSH process and file discovery (ms)
32+ discoveryPollIntervalMs ?: number ;
33+ // Maximum backoff interval for process and file discovery (ms)
34+ maxDiscoveryBackoffMs ?: number ;
3335 // Poll interval for network info updates
3436 networkPollInterval ?: number ;
3537 // For port-based SSH process discovery
@@ -72,7 +74,8 @@ export class SshProcessMonitor implements vscode.Disposable {
7274 this . options = {
7375 ...options ,
7476 proxyLogDir : options . proxyLogDir ,
75- pollInterval : options . pollInterval ?? 1000 ,
77+ discoveryPollIntervalMs : options . discoveryPollIntervalMs ?? 1000 ,
78+ maxDiscoveryBackoffMs : options . maxDiscoveryBackoffMs ?? 30_000 ,
7679 // Matches the SSH update interval
7780 networkPollInterval : options . networkPollInterval ?? 3000 ,
7881 } ;
@@ -138,8 +141,10 @@ export class SshProcessMonitor implements vscode.Disposable {
138141 * Starts monitoring when it finds the process through the port.
139142 */
140143 private async searchForProcess ( ) : Promise < void > {
141- const { pollInterval, logger, sshHost } = this . options ;
144+ const { discoveryPollIntervalMs, maxDiscoveryBackoffMs, logger, sshHost } =
145+ this . options ;
142146 let attempt = 0 ;
147+ let currentBackoff = discoveryPollIntervalMs ;
143148
144149 while ( ! this . disposed ) {
145150 attempt ++ ;
@@ -157,7 +162,8 @@ export class SshProcessMonitor implements vscode.Disposable {
157162 return ;
158163 }
159164
160- await this . delay ( pollInterval ) ;
165+ await this . delay ( currentBackoff ) ;
166+ currentBackoff = Math . min ( currentBackoff * 2 , maxDiscoveryBackoffMs ) ;
161167 }
162168 }
163169
@@ -172,13 +178,14 @@ export class SshProcessMonitor implements vscode.Disposable {
172178 const logPath = await findRemoteSshLogPath (
173179 codeLogDir ,
174180 remoteSshExtensionId ,
181+ logger ,
175182 ) ;
176183 if ( ! logPath ) {
177184 return undefined ;
178185 }
179186
180187 const logContent = await fs . readFile ( logPath , "utf8" ) ;
181- this . options . logger . debug ( `Read Remote SSH log file: ${ logPath } ` ) ;
188+ this . options . logger . debug ( `Read Remote SSH log file:` , logPath ) ;
182189
183190 const port = findPort ( logContent ) ;
184191 if ( ! port ) {
@@ -234,11 +241,18 @@ export class SshProcessMonitor implements vscode.Disposable {
234241 * Polls until found or PID changes.
235242 */
236243 private async searchForLogFile ( ) : Promise < void > {
237- const { proxyLogDir : logDir , logger, pollInterval } = this . options ;
244+ const {
245+ proxyLogDir : logDir ,
246+ logger,
247+ discoveryPollIntervalMs,
248+ maxDiscoveryBackoffMs,
249+ } = this . options ;
238250 if ( ! logDir ) {
239251 return ;
240252 }
241253
254+ let currentBackoff = discoveryPollIntervalMs ;
255+
242256 const targetPid = this . currentPid ;
243257 while ( ! this . disposed && this . currentPid === targetPid ) {
244258 try {
@@ -262,7 +276,8 @@ export class SshProcessMonitor implements vscode.Disposable {
262276 logger . debug ( `Could not read log directory: ${ logDir } ` ) ;
263277 }
264278
265- await this . delay ( pollInterval ) ;
279+ await this . delay ( currentBackoff ) ;
280+ currentBackoff = Math . min ( currentBackoff * 2 , maxDiscoveryBackoffMs ) ;
266281 }
267282 }
268283
@@ -376,10 +391,13 @@ export class SshProcessMonitor implements vscode.Disposable {
376391
377392/**
378393 * Finds the Remote SSH extension's log file path.
394+ * Tries extension-specific folder first (Cursor, Windsurf, Antigravity),
395+ * then output_logging_ fallback (MS VS Code).
379396 */
380397async function findRemoteSshLogPath (
381398 codeLogDir : string ,
382399 extensionId : string ,
400+ logger : Logger ,
383401) : Promise < string | undefined > {
384402 const logsParentDir = path . dirname ( codeLogDir ) ;
385403
@@ -394,8 +412,12 @@ async function findRemoteSshLogPath(
394412 if ( remoteSsh ) {
395413 return path . join ( extensionLogDir , remoteSsh ) ;
396414 }
415+ // Folder exists but no Remote SSH log yet
416+ logger . debug (
417+ `Extension log folder exists but no Remote SSH log found: ${ extensionLogDir } ` ,
418+ ) ;
397419 } catch {
398- // Extension-specific folder doesn't exist, try fallback
420+ // Extension-specific folder doesn't exist - expected for MS VS Code , try fallback
399421 }
400422
401423 try {
@@ -411,9 +433,14 @@ async function findRemoteSshLogPath(
411433 if ( remoteSSHLog ) {
412434 return path . join ( outputPath , remoteSSHLog ) ;
413435 }
436+ logger . debug (
437+ `Output logging folder exists but no Remote SSH log found: ${ outputPath } ` ,
438+ ) ;
439+ } else {
440+ logger . debug ( `No output_logging_ folders found in: ${ logsParentDir } ` ) ;
414441 }
415442 } catch {
416- // output_logging folder doesn't exist
443+ logger . debug ( `Could not read logs parent directory: ${ logsParentDir } ` ) ;
417444 }
418445
419446 return undefined ;
0 commit comments