import { o as normalizeLowercaseStringOrEmpty } from "./string-coerce-CIXf7egm.js";
import { t as formatCliCommand } from "./command-format-HwSAdvXB.js";
import { r as defaultRuntime } from "./runtime-LRpY2Icg.js";
import { r as theme } from "./theme-vjDs9tao.js";
import { r as formatDurationPrecise } from "./format-duration-CfGzOxKC.js";
import { spinner } from "@clack/prompts";
//#region src/cli/update-cli/progress.ts
const STEP_LABELS = {
	"clean check": "Working directory is clean",
	"upstream check": "Upstream branch exists",
	"git fetch": "Fetching latest changes",
	"git rebase": "Rebasing onto target commit",
	"git rev-parse @{upstream}": "Resolving upstream commit",
	"git rev-list": "Enumerating candidate commits",
	"git clone": "Cloning git checkout",
	"preflight worktree": "Preparing preflight worktree",
	"preflight cleanup": "Cleaning preflight worktree",
	"deps install": "Installing dependencies",
	build: "Building",
	"ui:build": "Building UI assets",
	"ui:build (post-doctor repair)": "Restoring missing UI assets",
	"ui assets verify": "Validating UI assets",
	"openclaw doctor entry": "Checking doctor entrypoint",
	"openclaw doctor": "Running doctor checks",
	"git rev-parse HEAD (after)": "Verifying update",
	"global update": "Updating via package manager",
	"global update (omit optional)": "Retrying update without optional deps",
	"global install stage": "Preparing staged package install",
	"global install verify": "Verifying global package",
	"global install swap": "Activating global package",
	"global install": "Installing global package"
};
function getStepLabel(step) {
	return STEP_LABELS[step.name] ?? step.name;
}
function isAdvisoryStep(step) {
	return step.advisory !== void 0;
}
/** Convert updater failure reasons and stderr tails into operator-facing recovery hints. */
function inferUpdateFailureHints(result) {
	if (result.status !== "error") return [];
	if (result.reason === "preflight-insufficient-space") return ["Free space on the preflight staging and package-manager store filesystems, then rerun the update.", "Preflight stopped because storage was exhausted; trying another commit would not repair it."];
	if (result.reason === "pnpm-corepack-missing") return ["This pnpm checkout could not auto-enable pnpm because corepack is missing.", "Install pnpm manually or install Node with corepack available, then rerun the update command."];
	if (result.reason === "pnpm-corepack-enable-failed") return ["This pnpm checkout could not auto-enable pnpm via corepack.", "Run `corepack enable` manually or install pnpm manually, then rerun the update command."];
	if (result.reason === "pnpm-npm-bootstrap-failed") return ["This pnpm checkout could not bootstrap pnpm from npm automatically.", "Install pnpm manually, then rerun the update command."];
	if (result.reason === "preferred-manager-unavailable") return ["This checkout requires its declared package manager and the updater could not find it.", "Install the missing package manager manually, then rerun the update command."];
	if (result.mode !== "npm") return [];
	const failedStep = [...result.steps].toReversed().find((step) => step.exitCode !== 0);
	if (!failedStep) return [];
	const stderr = normalizeLowercaseStringOrEmpty(failedStep.stderrTail);
	const hints = [];
	if ((failedStep.name.startsWith("global update") || failedStep.name.startsWith("global install")) && stderr.includes("eacces")) {
		hints.push("Detected permission failure (EACCES). Re-run with a writable global prefix or sudo (for system-managed Node installs).");
		hints.push("If you recover with sudo/manual package install on a managed Gateway, stop the Gateway first so it does not load files while the package tree is being replaced.");
		hints.push("Example: npm config set prefix ~/.local && npm i -g openclaw@latest");
		hints.push("System install outline: openclaw gateway stop -> sudo <system-npm> i -g openclaw@latest -> openclaw gateway install --force -> openclaw gateway restart.");
	}
	if (failedStep.name.startsWith("global update") && (stderr.includes("node-gyp") || stderr.includes("prebuild"))) {
		hints.push("Detected native optional dependency build failure. The updater retries with --omit=optional automatically.");
		hints.push("If it still fails: npm i -g openclaw@latest --omit=optional");
	}
	return hints;
}
/** Create a progress adapter for the updater runner without coupling runner code to terminal UI. */
function createUpdateProgress(enabled) {
	if (!enabled) return {
		progress: {},
		stop: () => {}
	};
	let currentSpinner = null;
	return {
		progress: {
			onStepStart: (step) => {
				currentSpinner = spinner();
				currentSpinner.start(theme.accent(getStepLabel(step)));
			},
			onStepComplete: (step) => {
				if (!currentSpinner) return;
				const label = getStepLabel(step);
				const duration = theme.muted(`(${formatDurationPrecise(step.durationMs)})`);
				const icon = formatStepStatus(step);
				currentSpinner.stop(`${icon} ${label} ${duration}`);
				currentSpinner = null;
				if (isAdvisoryStep(step) && step.stderrTail) {
					const lines = step.stderrTail.split("\n").slice(-10);
					for (const line of lines) if (line.trim()) defaultRuntime.log(`    ${theme.warn(line)}`);
				} else if (step.exitCode !== 0 && step.stderrTail) {
					const lines = step.stderrTail.split("\n").slice(-10);
					for (const line of lines) if (line.trim()) defaultRuntime.log(`    ${theme.error(line)}`);
				}
			}
		},
		stop: () => {
			if (currentSpinner) {
				currentSpinner.stop();
				currentSpinner = null;
			}
		}
	};
}
function formatStepStatus(step) {
	if (isAdvisoryStep(step)) return theme.warn("!");
	if (step.exitCode === 0) return theme.success("✓");
	if (step.exitCode === null) return theme.warn("?");
	return theme.error("✗");
}
/** Render a completed updater run as JSON or terminal output. */
function printResult(result, opts) {
	if (opts.json) {
		defaultRuntime.writeJson(result);
		return;
	}
	const statusColor = result.status === "ok" ? theme.success : result.status === "skipped" ? theme.warn : theme.error;
	defaultRuntime.log("");
	defaultRuntime.log(`${theme.heading("Update Result:")} ${statusColor(result.status.toUpperCase())}`);
	if (result.root) defaultRuntime.log(`  Root: ${theme.muted(result.root)}`);
	if (result.reason) defaultRuntime.log(`  Reason: ${theme.muted(result.reason)}`);
	if (result.before?.version || result.before?.sha) {
		const before = result.before.version ?? result.before.sha?.slice(0, 8) ?? "";
		defaultRuntime.log(`  Before: ${theme.muted(before)}`);
	}
	if (result.after?.version || result.after?.sha) {
		const after = result.after.version ?? result.after.sha?.slice(0, 8) ?? "";
		defaultRuntime.log(`  After: ${theme.muted(after)}`);
	}
	if (!opts.hideSteps && result.steps.length > 0) {
		defaultRuntime.log("");
		defaultRuntime.log(theme.heading("Steps:"));
		for (const step of result.steps) {
			const status = formatStepStatus(step);
			const duration = theme.muted(`(${formatDurationPrecise(step.durationMs)})`);
			defaultRuntime.log(`  ${status} ${step.name} ${duration}`);
			if (isAdvisoryStep(step) && step.stderrTail) {
				const lines = step.stderrTail.split("\n").slice(0, 5);
				for (const line of lines) if (line.trim()) defaultRuntime.log(`      ${theme.warn(line)}`);
			} else if (step.exitCode !== 0 && step.stderrTail) {
				const lines = step.stderrTail.split("\n").slice(0, 5);
				for (const line of lines) if (line.trim()) defaultRuntime.log(`      ${theme.error(line)}`);
			}
		}
	}
	const hints = inferUpdateFailureHints(result);
	if (hints.length > 0) {
		defaultRuntime.log("");
		defaultRuntime.log(theme.heading("Recovery hints:"));
		for (const hint of hints) defaultRuntime.log(`  - ${theme.warn(hint)}`);
	}
	defaultRuntime.log("");
	defaultRuntime.log(`Total time: ${theme.muted(formatDurationPrecise(result.durationMs))}`);
}
//#endregion
//#region src/cli/update-cli/update-recovery-guidance.ts
function resolveUnsafeUpdateRecoveryGuidance(reason) {
	const updateCommand = formatCliCommand("openclaw update");
	if (reason === "rollback-checkout-dirty") return `From the update root shown above, run \`git status --short\`, resolve the reported changes, then rerun \`${updateCommand}\`.`;
	return `Review the failed recovery step above, repair the checkout or installation, then rerun \`${updateCommand}\`.`;
}
//#endregion
export { createUpdateProgress as n, printResult as r, resolveUnsafeUpdateRecoveryGuidance as t };
