fix(worktrees): remove worktrees in the background (#3319)

* refactor(worktrees): fetch source once during creation

* fix(worktrees): remove worktrees in background

* fix(worktrees): show background removal progress

* fix(worktrees): name the worktree in removal toasts
This commit is contained in:
𝖎𝖚𝖑𝖎𝖎𝖆
2026-09-03 15:17:28 +03:00
committed by GitHub
parent 5995802fe3
commit 0d8709a72e
43 changed files with 326 additions and 447 deletions
@@ -20,7 +20,6 @@ import {
} from '@/lib/responseStyle';
import type { DesktopSettings } from '@/lib/desktop';
import { runtimeFetch } from '@/lib/runtime-fetch';
import { useConfigStore } from '@/stores/useConfigStore';
import { noteDeferredRestartFromPayload, recordDeferredOpenCodeRestart } from '@/lib/opencode/deferredRestart';
import { SettingsPageLayout } from '@/components/sections/shared/SettingsPageLayout';
import {
@@ -47,7 +46,6 @@ type ResponseStyleValue = ResponseStylePreset | 'custom';
type BehaviorSettingsState = {
prompt: string;
optimizeSystemPrompt: boolean;
worktreeFetchSource: boolean;
responseStyleEnabled: boolean;
responseStylePreset: ResponseStyleValue;
responseStyleCustomInstructions: string;
@@ -56,7 +54,6 @@ type BehaviorSettingsState = {
const DEFAULT_BEHAVIOR_SETTINGS: BehaviorSettingsState = {
prompt: '',
optimizeSystemPrompt: false,
worktreeFetchSource: true,
responseStyleEnabled: false,
responseStylePreset: 'concise',
responseStyleCustomInstructions: '',
@@ -106,10 +103,8 @@ const saveBehaviorSetting = async (settings: Partial<DesktopSettings>, fallbackE
export const BehaviorPage: React.FC = () => {
const { t } = useI18n();
const isVSCode = useIsVSCodeRuntime();
const setSettingsWorktreeFetchSource = useConfigStore((state) => state.setSettingsWorktreeFetchSource);
const [prompt, setPrompt] = React.useState('');
const [optimizeSystemPrompt, setOptimizeSystemPrompt] = React.useState(false);
const [worktreeFetchSource, setWorktreeFetchSource] = React.useState(DEFAULT_BEHAVIOR_SETTINGS.worktreeFetchSource);
const [responseStyleEnabled, setResponseStyleEnabled] = React.useState(DEFAULT_BEHAVIOR_SETTINGS.responseStyleEnabled);
const [responseStylePreset, setResponseStylePreset] = React.useState<ResponseStyleValue>(DEFAULT_BEHAVIOR_SETTINGS.responseStylePreset);
const [responseStyleCustomInstructions, setResponseStyleCustomInstructions] = React.useState(DEFAULT_BEHAVIOR_SETTINGS.responseStyleCustomInstructions);
@@ -148,16 +143,12 @@ export const BehaviorPage: React.FC = () => {
nextSettings = {
...nextSettings,
optimizeSystemPrompt: data.optimizeSystemPrompt === true,
worktreeFetchSource: data.worktreeFetchSource !== false,
responseStyleEnabled: data.responseStyleEnabled === true,
responseStylePreset: sanitizeResponseStylePreset(data.responseStylePreset),
responseStyleCustomInstructions: typeof data.responseStyleCustomInstructions === 'string'
? data.responseStyleCustomInstructions
: '',
};
if (typeof data.worktreeFetchSource === 'boolean') {
setSettingsWorktreeFetchSource(data.worktreeFetchSource);
}
if (typeof data.globalBehaviorPrompt === 'string') {
nextSettings = { ...nextSettings, prompt: data.globalBehaviorPrompt };
}
@@ -173,7 +164,6 @@ export const BehaviorPage: React.FC = () => {
setPrompt(nextSettings.prompt);
setOptimizeSystemPrompt(nextSettings.optimizeSystemPrompt);
setInitialOptimizeSystemPrompt(nextSettings.optimizeSystemPrompt);
setWorktreeFetchSource(nextSettings.worktreeFetchSource);
setResponseStyleEnabled(nextSettings.responseStyleEnabled);
setResponseStylePreset(nextSettings.responseStylePreset);
setResponseStyleCustomInstructions(nextSettings.responseStyleCustomInstructions);
@@ -194,7 +184,7 @@ export const BehaviorPage: React.FC = () => {
void load();
return () => abort.abort();
}, [setSettingsWorktreeFetchSource]);
}, []);
React.useEffect(() => {
if (isLoading) return;
@@ -275,21 +265,6 @@ export const BehaviorPage: React.FC = () => {
}
};
const handleWorktreeFetchSourceChange = (enabled: boolean) => {
const previous = worktreeFetchSource;
setWorktreeFetchSource(enabled);
setSettingsWorktreeFetchSource(enabled);
void saveBehaviorSetting(
{ worktreeFetchSource: enabled },
t('settings.behavior.page.toast.saveFailed'),
).catch((error) => {
setWorktreeFetchSource(previous);
setSettingsWorktreeFetchSource(previous);
const message = error instanceof Error ? error.message : t('settings.behavior.page.toast.saveFailed');
toast.error(message);
});
};
const handleSavePromptOptimization = async () => {
setIsApplyingPromptOptimization(true);
try {
@@ -343,21 +318,6 @@ export const BehaviorPage: React.FC = () => {
</SettingsSection>
)}
<SettingsSection
title={t('settings.behavior.page.section.worktrees')}
settingsItem="behavior.worktree-fetch-source"
contentClassName="space-y-3"
>
<SettingsCheckboxRow
checked={worktreeFetchSource}
onChange={handleWorktreeFetchSourceChange}
disabled={isLoading}
label={t('settings.behavior.page.worktreeFetchSource.enable')}
ariaLabel={t('settings.behavior.page.worktreeFetchSource.enableAria')}
info={t('settings.behavior.page.worktreeFetchSource.info')}
/>
</SettingsSection>
<SettingsSection
title={t('settings.behavior.page.section.systemPrompt')}
info={(