Files
openchamber/packages/ui/src/lib/opencode/deferredRestart.ts
T
Cursor AgentandSerhii Dziupin 0cde9e9413 Fix deferred restart review findings.
Drop phantom pending records when provider disconnect removes nothing
and when Behavior AGENTS.md payloads are not deferred. Clear the Apply
badge after external OpenCode manual-restart guidance. Align skills and
commands save toasts with deferred restart feedback, and fix French
OpenCode elision.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-08-03 08:56:05 +00:00

82 lines
2.4 KiB
TypeScript

import {
usePendingOpenCodeRestartStore,
type PendingOpenCodeRestartScope,
} from '@/stores/usePendingOpenCodeRestartStore';
export type ConfigMutationPayload = {
requiresReload?: boolean;
requiresRestart?: boolean;
restartDeferred?: boolean;
requiresManualRestart?: boolean;
reloadFailed?: boolean;
message?: string;
warning?: string;
reloadDelayMs?: number;
} | null | undefined;
export function isDeferredRestartPayload(payload: ConfigMutationPayload): boolean {
if (!payload || typeof payload !== 'object') {
return false;
}
if (payload.requiresManualRestart === true) {
return false;
}
return payload.restartDeferred === true || (payload.requiresRestart === true && payload.requiresReload !== true);
}
export function recordDeferredOpenCodeRestart(
scope: PendingOpenCodeRestartScope,
options?: { id?: string; label?: string },
): void {
usePendingOpenCodeRestartStore.getState().recordChange({
scope,
id: options?.id,
label: options?.label,
});
}
/**
* If the mutation response deferred the OpenCode restart, record it and return true.
* Callers should skip immediate refresh overlays when this returns true.
*/
export function noteDeferredRestartFromPayload(
payload: ConfigMutationPayload,
scope: PendingOpenCodeRestartScope,
options?: { id?: string; label?: string },
): boolean {
if (!isDeferredRestartPayload(payload)) {
return false;
}
recordDeferredOpenCodeRestart(scope, options);
return true;
}
export async function applyPendingOpenCodeRestart(options?: {
message?: string;
}): Promise<{ ok: boolean; requiresManualRestart?: boolean }> {
const store = usePendingOpenCodeRestartStore.getState();
if (store.isApplying) {
return { ok: false };
}
store.setApplying(true);
try {
const { reloadOpenCodeConfiguration } = await import('@/stores/useAgentsStore');
await reloadOpenCodeConfiguration({
message: options?.message,
mode: 'projects',
scopes: ['all'],
});
usePendingOpenCodeRestartStore.getState().clear();
return { ok: true };
} catch (error) {
if ((error as Error & { requiresManualRestart?: boolean })?.requiresManualRestart) {
// Changes are already on disk; clear the badge after delivering manual-restart guidance.
usePendingOpenCodeRestartStore.getState().clear();
return { ok: false, requiresManualRestart: true };
}
usePendingOpenCodeRestartStore.getState().setApplying(false);
throw error;
}
}