// @generated by scripts/build-runtime.mjs; do not edit. // @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader. import { runCancellableOperation, showRemoteSelectionReview } from "./chunk-D3S54OXI.ts"; import { errorMessage, safeTerminalText } from "./chunk-W64NEHXT.ts"; import { loadConfig, syncConfigReviewIdentity } from "./chunk-APZVBSM6.ts"; // src/sync-resolution-ui.ts import { defineMenu, runMenu } from "@narumitw/pi-tui-kit"; async function showSyncResolution(ctx, initialDecision, runRoute, sessionSignal) { let currentDecision = initialDecision; let resolvedDirection; let chainedResult; const menu = defineMenu({ start: "resolve", screens: { resolve: ({ state }) => ({ kind: "actions", title: resolutionTitle(state), lines: resolutionLines(state), items: [ { id: "review", label: "Review differences (recommended)", to: "review" }, ...state.directions.includes("push") ? [ { id: "push", label: pushLabel(state), description: "Review an exact push before replacing the remote version.", action: "push" } ] : [], ...state.directions.includes("pull") ? [ { id: "pull", label: pullLabel(state), description: "Review exact local changes and create a backup before applying.", action: "pull" } ] : [], { id: "back", label: "Back", action: "back" } ], hint: "back" }), review: ({ state }) => ({ kind: "review", title: `Review differences \xB7 ${safeTerminalText(state.setupName)}`, content: state.review, format: { kind: "text" }, viewportSize: "adaptive", hint: "back" }) }, actions: { push: ({ state, signal }) => resolveDirection("push", state, signal), pull: ({ state, signal }) => resolveDirection("pull", state, signal), back: async () => ({ kind: "back" }) } }); async function resolveDirection(direction, decision, actionSignal) { const signal = sessionSignal ? AbortSignal.any([sessionSignal, actionSignal]) : actionSignal; const config = await loadConfig(decision.setupName); if (signal.aborted) return { kind: "close" }; if (syncConfigReviewIdentity(config) !== decision.configIdentity) { throw new Error( `Sync setup \u201C${safeTerminalText(decision.setupName)}\u201D changed while conflict resolution was open; return to the sync manager and retry.` ); } const result2 = await runCancellableOperation( ctx, direction === "push" ? "Preparing local-wins push preview\u2026" : "Preparing remote-wins pull preview\u2026", `${direction} --force`, runRoute, { commitAware: true, cancelledMessage: direction === "push" ? "Push preparation cancelled; no remote files were changed." : "Pull check cancelled; no local files were changed.", target: decision.setupName, signal } ); if (result2.kind === "decision-required") { currentDecision = result2.decision; return { kind: "stay" }; } if (result2.kind === "remote-selection-required") { chainedResult = { result: result2, route: direction }; return { kind: "close" }; } if (result2.kind === "completed") { if (result2.outcome === "cancelled") return { kind: "stay" }; resolvedDirection = direction; return { kind: "close" }; } return result2.kind === "closed" ? { kind: "close" } : { kind: "stay" }; } const result = await runMenu(ctx, menu, { getState: () => currentDecision, signal: sessionSignal, isCurrent: () => !sessionSignal?.aborted, onError: (_menuCtx, error) => ctx.ui.notify(errorMessage(error), "error") }); if (sessionSignal?.aborted || result.kind === "stale") return { kind: "stale" }; if (chainedResult) return { kind: "route-result", ...chainedResult }; if (resolvedDirection) return { kind: "resolved", direction: resolvedDirection }; if (result.kind === "closed") { return result.reason === "back" ? { kind: "back" } : { kind: "closed" }; } return { kind: "closed" }; } function resolutionTitle(decision) { return decision.kind === "remote-empty" ? "Remote is empty" : "Resolve sync conflict"; } function resolutionLines(decision) { return [ `Sync setup: ${safeTerminalText(decision.setupName)}`, ...causeSummary(decision), "No files have been changed by this failed operation." ]; } function causeSummary(decision) { if (decision.kind === "first-sync-settings-diverged") { return ["This machine and the remote have different Pi settings on first sync."]; } if (decision.kind === "first-sync-sessions-diverged") { return ["Pi settings match, but local and remote sessions differ on first sync."]; } if (decision.kind === "remote-empty") return ["The remote storage location has no snapshot."]; return [ ...decision.causes.localChanged ? ["Local content changed since the last sync."] : [], ...decision.causes.remoteChanged ? ["Remote content changed since the last sync."] : [], ...decision.causes.policyChanged ? ["Included content changed since the last sync."] : [] ]; } function pushLabel(decision) { if (decision.kind === "remote-empty") return "Push local content\u2026"; if (decision.kind.startsWith("first-sync-")) return "Use local as initial source\u2026"; return "Keep local content and replace remote\u2026"; } function pullLabel(decision) { return decision.kind.startsWith("first-sync-") ? "Use remote as initial source\u2026" : "Use remote content and replace local\u2026"; } // src/manager-result-dispatcher.ts var MAX_DECISION_TRANSITIONS = 32; async function dispatchManagerResult(ctx, initialResult, origin, runRoute, signal, options = {}) { let result = initialResult; let currentRoute = origin; let resolving = false; for (let transition = 0; transition < MAX_DECISION_TRANSITIONS; transition += 1) { if (signal?.aborted) return { kind: "close" }; if (result.kind === "remote-selection-required") { resolving = true; const resolution = await showRemoteSelectionReview( ctx, result.decision.setupName, signal, void 0, { decision: result.decision, origin: currentRoute, runRoute, cancelLabel: options.cancelLabel, onSelectionResolved: options.onSelectionResolved, withStateAccess: options.withStateAccess } ); if (resolution.kind === "route-result") { result = resolution.result; currentRoute = resolution.route; continue; } return resolution.kind === "closed" || resolution.kind === "stale" ? { kind: "close" } : { kind: "stay" }; } if (result.kind === "decision-required") { resolving = true; const resolution = await showSyncResolution(ctx, result.decision, runRoute, signal); if (resolution.kind === "route-result") { result = resolution.result; currentRoute = resolution.route; continue; } if (resolution.kind === "resolved") { return { kind: "close", appliedRoute: resolution.direction }; } return resolution.kind === "closed" || resolution.kind === "stale" ? { kind: "close" } : { kind: "stay" }; } if (result.kind === "closed") return { kind: "close" }; if (result.kind === "completed") { const appliedRoute = result.outcome === "applied" ? currentRoute : void 0; if (resolving || origin === "pull" && result.outcome === "applied") { return { kind: "close", ...appliedRoute ? { appliedRoute } : {} }; } return { kind: "stay", ...appliedRoute ? { appliedRoute } : {} }; } return { kind: "stay" }; } ctx.ui.notify( "Sync resolution stopped after too many state changes. Start /sync again to review fresh state.", "warning" ); return { kind: "stay" }; } export { dispatchManagerResult }; //# sourceMappingURL=chunk-3GRWMWUZ.ts.map