fix: SSH keepalive + auto-reconnect for SFTP and terminal

- Add transport.set_keepalive(30) to all SSH connections
- Add SFTPSession.reconnect() method
- Auto-reconnect in _refresh_remote with retry on failure
- Auto-reconnect before upload/download operations
- Guard all remote navigation methods with connection checks
- ShellSession.connected wrapped in try/except
- Terminal: reset reconnect counter on send failure, increase max to 5
- Terminal: trigger reconnect on send to dead session

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
chrome-storm-c442
2026-02-24 02:25:40 -05:00
parent 3e9aeababe
commit 85a8c3ffc6
4 changed files with 85 additions and 34 deletions

View File

@@ -45,6 +45,9 @@ def _connect_client(server: dict, key_path: str, timeout: int = 15) -> paramiko.
try:
kwargs["key_filename"] = key_path
client.connect(**kwargs)
transport = client.get_transport()
if transport is not None:
transport.set_keepalive(30)
return client
except paramiko.AuthenticationException:
log.debug(f"Key auth failed for {server.get('alias', '?')}, trying password")
@@ -68,6 +71,9 @@ def _connect_client(server: dict, key_path: str, timeout: int = 15) -> paramiko.
kwargs["look_for_keys"] = False
kwargs["allow_agent"] = False
client.connect(**kwargs)
transport = client.get_transport()
if transport is not None:
transport.set_keepalive(30)
return client
raise Exception(f"No auth method for {server.get('alias', 'unknown')}")
@@ -92,11 +98,14 @@ class ShellSession:
@property
def connected(self) -> bool:
return (
self._channel is not None
and self._channel.get_transport() is not None
and self._channel.get_transport().is_active()
)
try:
return (
self._channel is not None
and self._channel.get_transport() is not None
and self._channel.get_transport().is_active()
)
except Exception:
return False
def connect(self):
self._client = _connect_client(self.server, self.key_path)
@@ -334,6 +343,12 @@ class SFTPSession:
self._client = _connect_client(self.server, self.key_path)
self._sftp = self._client.open_sftp()
def reconnect(self):
"""Disconnect and re-establish SFTP session."""
self.disconnect()
time.sleep(0.2)
self.connect()
def disconnect(self):
if self._sftp:
try: