Files
Netcatty/components/sftp/sftpSidePanelAutoConnect.ts
T
陈大猫 6fad3f0b76 fix(sftp): reconnect terminal side panel after SSH session loss (#1608) (#1621)
* fix(sftp): reconnect terminal side panel after SSH session loss

When SSH disconnects while the terminal SFTP side panel is browsing a stale
path, auto-connect reused a dead tab and left the pane stuck on loading.
Rebind SFTP when the terminal session changes and skip reuse unless the
backend session is healthy; also stop follow-terminal-cwd retry loops to
missing directories.

Fixes #1608

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(sftp): address review findings for side panel reconnect

Harden auto-connect after bugbot review: skip tab reuse on SSH session
change, move follow-cwd backoff ref into the interactive body, and make
navigateTo return reached/failed/aborted so follow mode only backs off on
real path failures.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-24 14:31:23 +08:00

58 lines
2.1 KiB
TypeScript

import type { SftpPane } from "../../application/state/sftp/types";
export type SftpSidePanelTabHealth = Pick<SftpPane, "connection" | "loading" | "reconnecting">;
/** Whether a remote SFTP tab is safe to reuse without reconnecting. */
export function isRemoteSftpTabHealthy(
tab: SftpSidePanelTabHealth,
hasBackendSession: boolean,
): boolean {
const conn = tab.connection;
if (!conn || conn.isLocal) return true;
if (conn.status !== "connected") return false;
if (tab.loading || tab.reconnecting) return false;
if (!hasBackendSession) return false;
return true;
}
/** Skip auto-connect only when the active tab is already bound to this endpoint and healthy. */
export function shouldSkipSftpSidePanelAutoConnect(
connectionKey: string,
connectedKey: string | null,
activeTab: SftpSidePanelTabHealth | null | undefined,
hasBackendSession: boolean,
): boolean {
if (connectedKey !== connectionKey) return false;
if (!activeTab) return false;
return isRemoteSftpTabHealthy(activeTab, hasBackendSession);
}
export function findReusableSftpSidePanelTab(
tabs: SftpPane[],
hostId: string,
connectionKey: string,
tabConnectionKeyMap: ReadonlyMap<string, string>,
hasBackendSession: (connectionId: string) => boolean,
): SftpPane | null {
const candidate = tabs.find((tab) => {
if (!tab.connection || tab.connection.hostId !== hostId) return false;
if (tab.connection.status === "error" || tab.connection.status === "disconnected") return false;
return tabConnectionKeyMap.get(tab.id) === connectionKey;
});
if (!candidate?.connection) return null;
if (!isRemoteSftpTabHealthy(candidate, hasBackendSession(candidate.connection.id))) {
return null;
}
return candidate;
}
/** True when the linked terminal SSH session changed and SFTP must rebind. */
export function shouldResetSftpSidePanelSourceSession(
previousSessionId: string | null | undefined,
nextSessionId: string | null | undefined,
): boolean {
if (!nextSessionId) return false;
if (!previousSessionId) return false;
return nextSessionId !== previousSessionId;
}