Defer OpenCode restarts for config mutations

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
This commit is contained in:
Cursor Agent
2026-08-03 06:40:01 +00:00
co-authored by Serhii Dziupin
parent 824d1fbbf4
commit 775da6e9f4
11 changed files with 272 additions and 323 deletions
@@ -1,4 +1,5 @@
import { createOpencodeClient } from '@opencode-ai/sdk/v2';
import { buildDeferredRestartResponse } from './config-mutation-response.js';
export const registerSkillRoutes = (app, dependencies) => {
const {
@@ -10,9 +11,8 @@ export const registerSkillRoutes = (app, dependencies) => {
readSettingsFromDisk,
sanitizeSkillCatalogs,
isUnsafeSkillRelativePath,
refreshOpenCodeAfterConfigChange,
clientReloadDelayMs,
buildOpenCodeUrl,
getOpenCodeAuthHeaders,
getOpenCodePort,
getSkillSources,
@@ -444,19 +444,18 @@ export const registerSkillRoutes = (app, dependencies) => {
const installed = result.installed || [];
const skipped = result.skipped || [];
const requiresReload = installed.length > 0;
if (requiresReload) {
await refreshOpenCodeAfterConfigChange('skills install');
}
const requiresRestart = installed.length > 0;
return res.json({
ok: true,
installed,
skipped,
requiresReload,
message: requiresReload ? 'Skills installed successfully. Reloading interface…' : 'No skills were installed',
reloadDelayMs: requiresReload ? clientReloadDelayMs : undefined,
...(requiresRestart
? buildDeferredRestartResponse('Skills installed successfully. Restart OpenCode to apply.')
: {
requiresReload: false,
message: 'No skills were installed',
}),
});
}
@@ -495,19 +494,18 @@ export const registerSkillRoutes = (app, dependencies) => {
const installed = result.installed || [];
const skipped = result.skipped || [];
const requiresReload = installed.length > 0;
if (requiresReload) {
await refreshOpenCodeAfterConfigChange('skills install');
}
const requiresRestart = installed.length > 0;
res.json({
ok: true,
installed,
skipped,
requiresReload,
message: requiresReload ? 'Skills installed successfully. Reloading interface…' : 'No skills were installed',
reloadDelayMs: requiresReload ? clientReloadDelayMs : undefined,
...(requiresRestart
? buildDeferredRestartResponse('Skills installed successfully. Restart OpenCode to apply.')
: {
requiresReload: false,
message: 'No skills were installed',
}),
});
} catch (error) {
console.error('Failed to install skills:', error);
@@ -588,14 +586,9 @@ export const registerSkillRoutes = (app, dependencies) => {
console.log('[Server] Scope:', scope, 'Working directory:', directory);
createSkill(skillName, { ...config, source: skillSource }, directory, scope);
await refreshOpenCodeAfterConfigChange('skill creation');
res.json({
success: true,
requiresReload: true,
message: `Skill ${skillName} created successfully. Reloading interface…`,
reloadDelayMs: clientReloadDelayMs,
});
res.json(buildDeferredRestartResponse(
`Skill ${skillName} created successfully. Restart OpenCode to apply.`,
));
} catch (error) {
console.error('Failed to create skill:', error);
res.status(500).json({ error: error.message || 'Failed to create skill' });
@@ -615,14 +608,9 @@ export const registerSkillRoutes = (app, dependencies) => {
console.log('[Server] Working directory:', directory);
updateSkill(skillName, updates, directory, updates?.targetPath);
await refreshOpenCodeAfterConfigChange('skill update');
res.json({
success: true,
requiresReload: true,
message: `Skill ${skillName} updated successfully. Reloading interface…`,
reloadDelayMs: clientReloadDelayMs,
});
res.json(buildDeferredRestartResponse(
`Skill ${skillName} updated successfully. Restart OpenCode to apply.`,
));
} catch (error) {
console.error('[Server] Failed to update skill:', error);
res.status(500).json({ error: error.message || 'Failed to update skill' });
@@ -707,14 +695,9 @@ export const registerSkillRoutes = (app, dependencies) => {
}
deleteSkill(skillName, directory);
await refreshOpenCodeAfterConfigChange('skill deletion');
res.json({
success: true,
requiresReload: true,
message: `Skill ${skillName} deleted successfully. Reloading interface…`,
reloadDelayMs: clientReloadDelayMs,
});
res.json(buildDeferredRestartResponse(
`Skill ${skillName} deleted successfully. Restart OpenCode to apply.`,
));
} catch (error) {
console.error('Failed to delete skill:', error);
res.status(500).json({ error: error.message || 'Failed to delete skill' });