Skip to content

Conversation

@EhabY
Copy link
Collaborator

@EhabY EhabY commented Dec 1, 2025

Extract SSH process discovery and network status display into a
dedicated SshProcessMonitor class. Add centralized Remote SSH extension
detection to support Cursor, Windsurf, and other VS Code forks.

Key changes:

  • Extract SSH monitoring logic from remote.ts into sshProcess.ts
  • Add sshExtension.ts to detect installed Remote SSH extension
  • Use createRequire instead of private module._load API to load the Remote SSH extension
  • Fix port detection to find most recent port (handles reconnects)
  • Add Cursor's "Socks port:" log format to port regex

Closes #660

@EhabY EhabY force-pushed the fix-log-file-finding-for-non-ms-vs-code branch 2 times, most recently from 1797956 to 68fa375 Compare December 1, 2025 19:51
@EhabY EhabY changed the title Fix log file finding for non ms vs code Refactor SSH process monitoring to support VS Code forks Dec 2, 2025
@EhabY EhabY requested review from jakehwll and mafredri December 2, 2025 14:24
Comment on lines +31 to +32
// Poll interval for SSH process and file discovery
pollInterval?: number;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this one be exponential? Right now it will keep retrying every second forever if it cannot find the SSH process :/

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If made exponential, do put a ceiling in, like 30s.

Comment on lines +285 to +294
const stats = await fs.stat(networkInfoFile);
const ageMs = Date.now() - stats.mtime.getTime();

if (ageMs > staleThreshold) {
// Prevent tight loop: if we just searched due to stale, wait before searching again
const timeSinceLastSearch = Date.now() - this.lastStaleSearchTime;
if (timeSinceLastSearch < staleThreshold) {
await this.delay(staleThreshold - timeSinceLastSearch);
continue;
}
Copy link
Collaborator Author

@EhabY EhabY Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the reconnection detection logic, the issue here is that we do not get events for disconnecting or connecting and thus we have no way to subscribe to them. So what I did here, was assume a connection is stale if the network stats file (generated by the CLI) does not change in poll * 5 seconds - If a network is stale and we find the same process then nothing would break so it's harmless, just means we have to search again.

EhabY added 3 commits December 2, 2025 20:49
dedicated SshProcessMonitor class. Add centralized Remote SSH extension
detection to better support Cursor, Windsurf, and other VS Code forks.

Key changes:
- Extract SSH monitoring logic from remote.ts into sshProcess.ts
- Add sshExtension.ts to detect installed Remote SSH extension
- Use createRequire instead of private module._load API
- Fix port detection to find most recent port (handles reconnects)
- Add Cursor's "Socks port:" log format to port regex
@EhabY EhabY force-pushed the fix-log-file-finding-for-non-ms-vs-code branch from e20c456 to e7f92b2 Compare December 2, 2025 17:50
Copy link
Member

@mafredri mafredri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No major issues spotted, nice refactor 👍🏻 (albeit a bit much TS for me today 😂)

* When found, starts monitoring.
*/
private async searchForProcess(): Promise<void> {
const { pollInterval, logger, sshHost } = this.options;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sshHost only seems to be used for logging, don't we need to filter anything based on it?

Copy link
Collaborator Author

@EhabY EhabY Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do not no, the port is sufficient (this is based on the old logic that was refactored here). Using the hostname to search was an approach I tested out but it's worse because we can have the same host connected on multiple windows so there's no way to tell them apart...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we remove it from the options to simplify or still valuable as a log? Either way, up to you 👍🏻.

// output_logging folder doesn't exist
}

return undefined;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor concern, if our trys always fail, we'll end up in a polling interval, never informing the user of anything (searchForProcess)?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They would get SSH process search attempt ${attempt} for host: ${sshHost}, do you mean that they won't know it failed at that process exactly? 🤔

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose it's more like a potential danger that we never stop trying even if it's never going to match (maybe some expectation changes in the future, etc). And the user has to realize that even though it keeps logging that, it will never resolve.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll go through the different pollings and try to make sure we have sufficient logging (but not too much). So at least if there's a failure here the users know why it might have happened (in this case, it could be that the Remote - SSH log location was changed or somehow never written)

Comment on lines +31 to +32
// Poll interval for SSH process and file discovery
pollInterval?: number;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If made exponential, do put a ceiling in, like 30s.

Copy link

@jakehwll jakehwll left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy from a Typescript-side of things 🙂 Once @mafredri's comments are resolved LGTM

@EhabY EhabY requested a review from mafredri December 5, 2025 09:37
Copy link
Member

@mafredri mafredri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, thanks!

const lastMatch = allMatches.at(-1)!;
// Each capture group corresponds to a different Remote SSH extension log format:
// [0] full match, [1] and [2] ms-vscode-remote.remote-ssh,
// [3] windsurf/open-remote-ssh/antigravity, [4] anysphere.remote-ssh
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

`;
expect(findPort(log)).toBe(3333);
});
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is awesome, thanks for adding it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Coder: View Logs does not work on non-MS VS Code IDEs

3 participants