Accumulate OpenCode settings restarts behind Apply & Restart

Defer OpenCode reloads after settings mutations, track pending changes,
and expose a top-right Apply & Restart OpenCode action with a counter so
sessions stay available until the user explicitly applies.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
This commit is contained in:
Cursor Agent
2026-08-03 06:56:38 +00:00
co-authored by Serhii Dziupin
parent 775da6e9f4
commit 57819dd164
31 changed files with 869 additions and 167 deletions
+15 -12
View File
@@ -15,8 +15,9 @@ import type {
import { invalidateSkillsLoadCache, refreshSkillsAfterOpenCodeRestart, useSkillsStore } from '@/stores/useSkillsStore';
import { opencodeClient } from '@/lib/opencode/client';
import { startConfigUpdate, finishConfigUpdate, updateConfigUpdateMessage } from '@/lib/configUpdate';
import { startConfigUpdate } from '@/lib/configUpdate';
import { runtimeFetch } from '@/lib/runtime-fetch';
import { noteDeferredRestartFromPayload } from '@/lib/opencode/deferredRestart';
const FALLBACK_SOURCES: SkillsCatalogSource[] = [
{
@@ -384,9 +385,7 @@ export const useSkillsCatalogStore = create<SkillsCatalogState>()(
},
installSkills: async (request, options) => {
startConfigUpdate('Installing skills…');
set({ isInstalling: true, lastInstallError: null });
let requiresReload = false;
try {
const directoryOverride = typeof options?.directory === 'string' && options.directory.trim().length > 0
? options.directory.trim()
@@ -404,26 +403,34 @@ export const useSkillsCatalogStore = create<SkillsCatalogState>()(
if (!payload) {
const error = { kind: 'unknown', message: 'Failed to install skills' } as SkillsInstallError;
set({ lastInstallError: error });
updateConfigUpdateMessage('Failed to install skills. Please retry.');
return { ok: false, error };
}
if (!response.ok || !payload.ok) {
const error = payload.error || ({ kind: 'unknown', message: 'Failed to install skills' } as SkillsInstallError);
set({ lastInstallError: error });
updateConfigUpdateMessage(error.message || 'Failed to install skills. Please retry.');
return { ok: false, error };
}
invalidateSkillsLoadCache(currentDirectory);
if (payload.requiresManualRestart) {
void get().loadCatalog({ refresh: true });
return payload;
}
if (noteDeferredRestartFromPayload(payload, 'skills')) {
void get().loadCatalog({ refresh: true });
return { ...payload, restartDeferred: true };
}
if (payload.requiresReload) {
requiresReload = true;
startConfigUpdate('Installing skills…');
await refreshSkillsAfterOpenCodeRestart({
message: payload.message,
delayMs: payload.reloadDelayMs,
});
} else {
updateConfigUpdateMessage(payload.message || 'Refreshing skills…');
invalidateSkillsLoadCache(currentDirectory);
void useSkillsStore.getState().loadSkills();
}
@@ -431,13 +438,9 @@ export const useSkillsCatalogStore = create<SkillsCatalogState>()(
} catch (error) {
const err = { kind: 'unknown', message: error instanceof Error ? error.message : String(error) } as SkillsInstallError;
set({ lastInstallError: err });
updateConfigUpdateMessage('Failed to install skills. Please retry.');
return { ok: false, error: err };
} finally {
set({ isInstalling: false });
if (!requiresReload) {
finishConfigUpdate();
}
}
},
}),