Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/browser/components/ChatInput/CreationControls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ export function CreationControls(props: CreationControlsProps) {
]}
onChange={(newMode) => {
const mode = newMode as RuntimeMode;
// Clear SSH host when switching away from SSH
props.onRuntimeChange(mode, mode === RUNTIME_MODE.SSH ? props.sshHost : "");
// Preserve SSH host across mode switches so it's remembered when returning to SSH
props.onRuntimeChange(mode, props.sshHost);
}}
disabled={props.disabled}
aria-label="Runtime mode"
Expand Down
23 changes: 18 additions & 5 deletions src/browser/hooks/useDraftWorkspaceSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
getModelKey,
getRuntimeKey,
getTrunkBranchKey,
getLastSshHostKey,
getProjectScopeId,
} from "@/common/constants/storage";
import type { UIMode } from "@/common/types/mode";
Expand Down Expand Up @@ -78,8 +79,16 @@ export function useDraftWorkspaceSettings(
{ listener: true }
);

// Parse runtime string into mode and host
const { mode: runtimeMode, host: sshHost } = parseRuntimeModeAndHost(runtimeString);
// Project-scoped SSH host preference (persisted separately from runtime mode)
// This allows the SSH host to be remembered when switching between runtime modes
const [lastSshHost, setLastSshHost] = usePersistedState<string>(
getLastSshHostKey(projectPath),
"",
{ listener: true }
);

// Parse runtime string into mode (host from runtime string is ignored in favor of lastSshHost)
const { mode: runtimeMode } = parseRuntimeModeAndHost(runtimeString);

// Initialize trunk branch from backend recommendation or first branch
useEffect(() => {
Expand All @@ -89,15 +98,19 @@ export function useDraftWorkspaceSettings(
}
}, [branches, recommendedTrunk, trunkBranch, setTrunkBranch]);

// Setter for runtime options (updates persisted runtime string)
// Setter for runtime options (updates persisted runtime mode and SSH host separately)
const setRuntimeOptions = (newMode: RuntimeMode, newHost: string) => {
const newRuntimeString = buildRuntimeString(newMode, newHost);
setRuntimeString(newRuntimeString);
// Always persist the SSH host separately so it's remembered across mode switches
if (newHost) {
setLastSshHost(newHost);
}
};

// Helper to get runtime string for IPC calls
const getRuntimeString = (): string | undefined => {
return buildRuntimeString(runtimeMode, sshHost);
return buildRuntimeString(runtimeMode, lastSshHost);
};

return {
Expand All @@ -106,7 +119,7 @@ export function useDraftWorkspaceSettings(
thinkingLevel,
mode,
runtimeMode,
sshHost,
sshHost: lastSshHost,
trunkBranch,
},
setRuntimeOptions,
Expand Down
10 changes: 10 additions & 0 deletions src/common/constants/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,16 @@ export function getTrunkBranchKey(projectPath: string): string {
return `trunkBranch:${projectPath}`;
}

/**
* Get the localStorage key for last SSH host preference for a project
* Stores the last entered SSH host separately from runtime mode
* so it persists when switching between runtime modes
* Format: "lastSshHost:{projectPath}"
*/
export function getLastSshHostKey(projectPath: string): string {
return `lastSshHost:${projectPath}`;
}

/**
* Get the localStorage key for the preferred compaction model (global)
* Format: "preferredCompactionModel"
Expand Down