Skip to content

Commit 99bbb39

Browse files
ozgesolidkeyclaude
andcommitted
Fix SSH Connect & Browse — SFTP-only connection mode
The SSH browse modal called liveConnect with no remotePath, causing SshHandler.connect() to crash with TypeError when building the tail -f command (shellEscape(undefined)). - Make remotePath optional in SshHandler.connect(); when absent, skip tail -f and just open an SFTP session (browse-only mode) - Fix null guard on sshUtilHandler.parseSSHConfig() in case ssh2 native module is unavailable Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent d1c69c5 commit 99bbb39

File tree

2 files changed

+40
-27
lines changed

2 files changed

+40
-27
lines changed

src/main/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1670,7 +1670,7 @@ function saveSshProfiles(profiles: SshProfile[]): void {
16701670

16711671
ipcMain.handle(IPC.SSH_PARSE_CONFIG, async () => {
16721672
try {
1673-
const hosts = sshUtilHandler.parseSSHConfig();
1673+
const hosts = sshUtilHandler ? sshUtilHandler.parseSSHConfig() : [];
16741674
return { success: true, hosts };
16751675
} catch (error) {
16761676
return { success: false, error: String(error) };

src/main/sshHandler.ts

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ export class SshHandler extends EventEmitter {
9191
port: number;
9292
username: string;
9393
identityFile?: string;
94-
remotePath: string;
94+
remotePath?: string;
9595
passphrase?: string;
9696
}): Promise<string> {
9797
if (this.client) {
@@ -164,39 +164,52 @@ export class SshHandler extends EventEmitter {
164164
const client = this.client!;
165165

166166
client.on('ready', () => {
167-
// Start tail -f on the remote path
168-
client.exec(`tail -f ${this.shellEscape(config.remotePath)}`, (err, stream) => {
169-
if (err) {
170-
this.cleanup();
171-
reject(err);
172-
return;
173-
}
167+
if (config.remotePath) {
168+
// Start tail -f on the remote path
169+
client.exec(`tail -f ${this.shellEscape(config.remotePath)}`, (err, stream) => {
170+
if (err) {
171+
this.cleanup();
172+
reject(err);
173+
return;
174+
}
174175

175-
this.stream = stream;
176+
this.stream = stream;
176177

177-
stream.on('data', (chunk: Buffer) => {
178-
this.handleData(chunk);
179-
});
178+
stream.on('data', (chunk: Buffer) => {
179+
this.handleData(chunk);
180+
});
180181

181-
stream.stderr.on('data', (chunk: Buffer) => {
182-
const msg = chunk.toString('utf-8').trim();
183-
if (msg) this.emit('error', msg);
184-
});
182+
stream.stderr.on('data', (chunk: Buffer) => {
183+
const msg = chunk.toString('utf-8').trim();
184+
if (msg) this.emit('error', msg);
185+
});
185186

186-
stream.on('close', () => {
187-
this.emit('disconnected');
188-
this.stream = null;
189-
});
187+
stream.on('close', () => {
188+
this.emit('disconnected');
189+
this.stream = null;
190+
});
190191

191-
// Also open SFTP for browsing
192+
// Also open SFTP for browsing
193+
client.sftp((err, sftp) => {
194+
if (!err) {
195+
this.sftp = sftp;
196+
}
197+
});
198+
199+
resolve(this.tempFilePath!);
200+
});
201+
} else {
202+
// SFTP-only connection (no tail) — used by the SSH browse modal
192203
client.sftp((err, sftp) => {
193-
if (!err) {
194-
this.sftp = sftp;
204+
if (err) {
205+
this.cleanup();
206+
reject(err);
207+
return;
195208
}
209+
this.sftp = sftp;
210+
resolve(this.tempFilePath!);
196211
});
197-
198-
resolve(this.tempFilePath!);
199-
});
212+
}
200213
});
201214

202215
client.on('error', (err) => {

0 commit comments

Comments
 (0)