import { d as unregisterActiveProgressLine, l as clearActiveProgressLine, u as registerActiveProgressLine } from "./subsystem-hATE68va.js";
import { r as theme } from "./theme-C5EwWDWE.js";
import process$1 from "node:process";
import { spinner } from "@clack/prompts";

//#region node_modules/.pnpm/osc-progress@0.3.0/node_modules/osc-progress/dist/esm/oscProgress.js
/**
* OSC 9;4 progress prefix (`ESC ] 9 ; 4 ;`).
*
* Typical emitted forms:
* - `ESC ] 9;4;<state>;<percent>;<payload> ST`
* - `ESC ] 9;4;<state>;;<payload> ST` (indeterminate)
*/
const OSC_PROGRESS_PREFIX = "\x1B]9;4;";
/** String Terminator (ST): `ESC \\` */
const OSC_PROGRESS_ST = "\x1B\\";
/** Bell (BEL): `0x07` */
const OSC_PROGRESS_BEL = "\x07";
/** C1 String Terminator (ST): `0x9c` */
const OSC_PROGRESS_C1_ST = "";
const DEFAULT_THROTTLE_INTERVAL_MS = 150;
const DEFAULT_CLEAR_DELAY_MS = 150;
function resolveTerminator(terminator) {
	return terminator === "bel" ? OSC_PROGRESS_BEL : OSC_PROGRESS_ST;
}
/**
* Sanitizes a label/payload so it can't break the surrounding OSC sequence.
* Removes escape chars and common OSC terminators; trims whitespace.
*/
function sanitizeLabel(label) {
	return label.replaceAll(OSC_PROGRESS_ST, "").split("\x1B").join("").replaceAll(OSC_PROGRESS_BEL, "").replaceAll(OSC_PROGRESS_C1_ST, "").replaceAll("]", "").trim();
}
/**
* Best-effort check whether OSC 9;4 progress output is likely to work.
*
* Default heuristics:
* - requires `isTty === true`
* - enables for Ghostty (`TERM_PROGRAM=ghostty*`), WezTerm (`TERM_PROGRAM=wezterm*`), Windows Terminal (`WT_SESSION`)
*
* Override knobs:
* - `options.force` / `options.disabled`
* - `options.forceEnvVar` / `options.disableEnvVar` (expects value `"1"`)
*/
function supportsOscProgress(env = process$1.env, isTty = process$1.stdout.isTTY, options = {}) {
	if (!isTty) return false;
	if (options.disabled) return false;
	if (options.force) return true;
	if (options.disableEnvVar && env[options.disableEnvVar] === "1") return false;
	if (options.forceEnvVar && env[options.forceEnvVar] === "1") return true;
	const termProgram = (env.TERM_PROGRAM ?? "").toLowerCase();
	if (termProgram.includes("ghostty")) return true;
	if (termProgram.includes("wezterm")) return true;
	if (env.WT_SESSION) return true;
	return false;
}
/**
* Creates a small stateful controller for OSC 9;4 progress output.
*
* Useful when you want to drive progress updates yourself (e.g. bytes downloaded / total bytes,
* or seconds processed / total duration) and switch between indeterminate and determinate modes.
*
* Behavior:
* - no-op controller when `supportsOscProgress(...)` is false
* - `setIndeterminate(label)` emits `state=3`
* - `setPercent(label, percent)` emits `state=1` with a clamped integer percent
* - `clear()` emits `state=0` using the last label
*/
function createOscProgressController(options = {}) {
	const { label = "Working…", write = (text) => process$1.stderr.write(text), terminator, stallAfterMs = 0, stalledLabel, clearDelayMs = DEFAULT_CLEAR_DELAY_MS, autoClearOnExit = false } = options;
	if (!supportsOscProgress(options.env, options.isTty, options)) return {
		setIndeterminate: () => {},
		setPercent: () => {},
		setPaused: () => {},
		done: () => {},
		fail: () => {},
		clear: () => {},
		dispose: () => {}
	};
	const end = resolveTerminator(terminator);
	const resolveStalledLabel = (baseLabel) => {
		if (typeof stalledLabel === "function") return stalledLabel(baseLabel);
		if (typeof stalledLabel === "string") return stalledLabel;
		return `${baseLabel} (stalled)`;
	};
	const normalizePercent = (percent) => Math.max(0, Math.min(100, Math.round(percent)));
	let lastEmittedLabel = label;
	let lastEmittedPercent = null;
	let lastEmittedState = null;
	let lastEmitAt = 0;
	let hasEmitted = false;
	let lastSeenLabel = label;
	let lastSeenPercent = 0;
	let lastSeenMode = "indeterminate";
	let stallTimer = null;
	let clearTimer = null;
	let stallEnabled = true;
	const clearStallTimer = () => {
		if (stallTimer !== null) {
			clearTimeout(stallTimer);
			stallTimer = null;
		}
	};
	const clearTimers = () => {
		clearStallTimer();
		if (clearTimer !== null) {
			clearTimeout(clearTimer);
			clearTimer = null;
		}
	};
	const scheduleStall = () => {
		if (!stallAfterMs || stallAfterMs <= 0) return;
		if (stallTimer !== null) clearTimeout(stallTimer);
		stallTimer = setTimeout(() => {
			stallTimer = null;
			if (!stallEnabled) return;
			const labelToUse = resolveStalledLabel(lastSeenLabel);
			send(4, lastSeenMode === "determinate" ? lastSeenPercent : null, labelToUse, true);
		}, stallAfterMs);
		stallTimer.unref?.();
	};
	const scheduleClear = () => {
		if (clearDelayMs <= 0) {
			clear();
			return;
		}
		if (clearTimer !== null) clearTimeout(clearTimer);
		clearTimer = setTimeout(() => {
			clearTimer = null;
			clear();
		}, clearDelayMs);
		clearTimer.unref?.();
	};
	const send = (state, percent, nextLabel, force = false) => {
		const cleanLabel = sanitizeLabel(nextLabel);
		const normalizedPercent = percent == null ? null : normalizePercent(percent);
		const now = Date.now();
		const stateChanged = state !== lastEmittedState;
		const labelChanged = cleanLabel !== lastEmittedLabel;
		const percentChanged = normalizedPercent !== lastEmittedPercent;
		const withinInterval = now - lastEmitAt < DEFAULT_THROTTLE_INTERVAL_MS;
		let shouldEmit = force || !hasEmitted || stateChanged || labelChanged;
		if (!shouldEmit && percentChanged) shouldEmit = !withinInterval;
		if (!shouldEmit) return;
		if (normalizedPercent == null) write(`${OSC_PROGRESS_PREFIX}${state};;${cleanLabel}${end}`);
		else write(`${OSC_PROGRESS_PREFIX}${state};${normalizedPercent};${cleanLabel}${end}`);
		lastEmittedLabel = cleanLabel;
		lastEmittedPercent = normalizedPercent;
		lastEmittedState = state;
		lastEmitAt = now;
		hasEmitted = true;
	};
	const updateSeen = (nextLabel, mode, percent, shouldScheduleStall = true) => {
		lastSeenLabel = nextLabel;
		lastSeenMode = mode;
		lastSeenPercent = percent ?? 0;
		if (shouldScheduleStall) scheduleStall();
	};
	const setIndeterminate = (nextLabel) => {
		stallEnabled = true;
		updateSeen(nextLabel, "indeterminate", null);
		send(3, null, nextLabel);
	};
	const setPercent = (nextLabel, percent) => {
		const normalized = normalizePercent(percent);
		stallEnabled = true;
		updateSeen(nextLabel, "determinate", normalized);
		send(1, normalized, nextLabel);
	};
	const setPaused = (nextLabel) => {
		stallEnabled = false;
		const percent = lastSeenMode === "determinate" ? lastSeenPercent : null;
		updateSeen(nextLabel, lastSeenMode, lastSeenMode === "determinate" ? lastSeenPercent : null, false);
		send(4, percent, nextLabel, true);
	};
	const clear = () => {
		stallEnabled = false;
		clearTimers();
		send(0, 0, lastSeenLabel, true);
	};
	const done = (nextLabel) => {
		const labelToUse = nextLabel ?? lastSeenLabel;
		stallEnabled = false;
		clearStallTimer();
		updateSeen(labelToUse, "determinate", 100, false);
		send(1, 100, labelToUse, true);
		scheduleClear();
	};
	const fail = (nextLabel) => {
		const labelToUse = nextLabel ?? lastSeenLabel;
		const percent = lastSeenMode === "determinate" ? lastSeenPercent : null;
		stallEnabled = false;
		clearStallTimer();
		updateSeen(labelToUse, lastSeenMode, lastSeenMode === "determinate" ? lastSeenPercent : null, false);
		send(2, percent, labelToUse, true);
		scheduleClear();
	};
	const handleExit = () => {
		clear();
	};
	if (autoClearOnExit) process$1.once("exit", handleExit);
	const dispose = () => {
		clearTimers();
		if (autoClearOnExit) process$1.off("exit", handleExit);
	};
	return {
		setIndeterminate,
		setPercent,
		setPaused,
		done,
		fail,
		clear,
		dispose
	};
}

//#endregion
//#region src/cli/progress.ts
const DEFAULT_DELAY_MS = 0;
let activeProgress = 0;
const noopReporter = {
	setLabel: () => {},
	setPercent: () => {},
	tick: () => {},
	done: () => {}
};
function createCliProgress(options) {
	if (options.enabled === false) return noopReporter;
	if (activeProgress > 0) return noopReporter;
	const stream = options.stream ?? process.stderr;
	const isTty = stream.isTTY;
	const allowLog = !isTty && options.fallback === "log";
	if (!isTty && !allowLog) return noopReporter;
	const delayMs = typeof options.delayMs === "number" ? options.delayMs : DEFAULT_DELAY_MS;
	const canOsc = isTty && supportsOscProgress(process.env, isTty);
	const allowSpinner = isTty && (options.fallback === void 0 || options.fallback === "spinner");
	const allowLine = isTty && options.fallback === "line";
	let started = false;
	let label = options.label;
	const total = options.total ?? null;
	let completed = 0;
	let percent = 0;
	let indeterminate = options.indeterminate ?? (options.total === void 0 || options.total === null);
	activeProgress += 1;
	if (isTty) registerActiveProgressLine(stream);
	const controller = canOsc ? createOscProgressController({
		env: process.env,
		isTty: stream.isTTY,
		write: (chunk) => stream.write(chunk)
	}) : null;
	const spin = allowSpinner ? spinner() : null;
	const renderLine = allowLine ? () => {
		if (!started) return;
		const suffix = indeterminate ? "" : ` ${percent}%`;
		clearActiveProgressLine();
		stream.write(`${theme.accent(label)}${suffix}`);
	} : null;
	const renderLog = allowLog ? (() => {
		let lastLine = "";
		let lastAt = 0;
		const throttleMs = 250;
		return () => {
			if (!started) return;
			const suffix = indeterminate ? "" : ` ${percent}%`;
			const nextLine = `${label}${suffix}`;
			const now = Date.now();
			if (nextLine === lastLine && now - lastAt < throttleMs) return;
			lastLine = nextLine;
			lastAt = now;
			stream.write(`${nextLine}\n`);
		};
	})() : null;
	let timer = null;
	const applyState = () => {
		if (!started) return;
		if (controller) if (indeterminate) controller.setIndeterminate(label);
		else controller.setPercent(label, percent);
		if (spin) spin.message(theme.accent(label));
		if (renderLine) renderLine();
		if (renderLog) renderLog();
	};
	const start = () => {
		if (started) return;
		started = true;
		if (spin) spin.start(theme.accent(label));
		applyState();
	};
	if (delayMs === 0) start();
	else timer = setTimeout(start, delayMs);
	const setLabel = (next) => {
		label = next;
		applyState();
	};
	const setPercent = (nextPercent) => {
		percent = Math.max(0, Math.min(100, Math.round(nextPercent)));
		indeterminate = false;
		applyState();
	};
	const tick = (delta = 1) => {
		if (!total) return;
		completed = Math.min(total, completed + delta);
		setPercent(total > 0 ? Math.round(completed / total * 100) : 0);
	};
	const done = () => {
		if (timer) {
			clearTimeout(timer);
			timer = null;
		}
		if (!started) {
			activeProgress = Math.max(0, activeProgress - 1);
			return;
		}
		if (controller) controller.clear();
		if (spin) spin.stop();
		clearActiveProgressLine();
		if (isTty) unregisterActiveProgressLine(stream);
		activeProgress = Math.max(0, activeProgress - 1);
	};
	return {
		setLabel,
		setPercent,
		tick,
		done
	};
}
async function withProgress(options, work) {
	const progress = createCliProgress(options);
	try {
		return await work(progress);
	} finally {
		progress.done();
	}
}
async function withProgressTotals(options, work) {
	return await withProgress(options, async (progress) => {
		const update = ({ completed, total, label }) => {
			if (label) progress.setLabel(label);
			if (!Number.isFinite(total) || total <= 0) return;
			progress.setPercent(completed / total * 100);
		};
		return await work(update, progress);
	});
}

//#endregion
export { withProgress as n, withProgressTotals as r, createCliProgress as t };