import "./paths-C9FmTW1x.js";
import { U as theme } from "./agent-paths-BySKyq9I.js";
import { dd as formatCliCommand } from "./agent-scope-CLn_Ws3B.js";
import { d as defaultRuntime } from "./errors-Dx3S3Nrp.js";
import "./github-copilot-token-BA45-q56.js";
import "./chat-envelope-D_wSv26N.js";
import "./pairing-token-BFGorDQo.js";
import "./ip-D_T5zbZS.js";
import "./ws-cvQhrVP3.js";
import "./device-identity-DzUZ06fL.js";
import "./call-s6DNIELo.js";
import { n as runCommandWithRuntime } from "./cli-utils-DJ7Nfw8J.js";
import { t as formatHelpExamples } from "./help-format-H4GNCFCs.js";
import "./progress-CDqdg8f8.js";
import { n as callGatewayFromCli, t as addGatewayClientOptions } from "./gateway-rpc-C9uKnQRG.js";
import { tmpdir } from "node:os";
import { dirname, join } from "node:path";
import { appendFile, mkdir, open, readFile, rm, stat } from "node:fs/promises";
import { setTimeout } from "node:timers/promises";

//#region src/cli/sat-cli.ts
const LAMPORTS_PER_SOL = 1000000000n;
const DEFAULT_MAINTAIN_INTERVAL_SECONDS = 300;
const DEFAULT_MAINTAIN_JITTER_SECONDS = 30;
const DEFAULT_STALE_LOCK_SECONDS = 900;
function runSatCommand(action, label) {
	return runCommandWithRuntime(defaultRuntime, action, (err) => {
		const message = err instanceof Error ? err.message : String(err);
		defaultRuntime.error(label ? `${label}: ${message}` : message);
		defaultRuntime.exit(1);
	});
}
function parseLamportsPair(solRaw, lamportsRaw, labels) {
	const sol = typeof solRaw === "string" ? solRaw.trim() : "";
	const lamports = typeof lamportsRaw === "string" ? lamportsRaw.trim() : "";
	if (sol && lamports) throw new Error(`Use either ${labels.sol} or ${labels.lamports}, not both`);
	if (lamports) {
		if (!/^\d+$/.test(lamports)) throw new Error(`${labels.lamports} must be a non-negative integer string`);
		return lamports;
	}
	if (!sol) return;
	if (!/^\d+(\.\d{0,9})?$/.test(sol)) throw new Error(`${labels.sol} must be a non-negative number with up to 9 decimals`);
	const [wholePart, fractionPart = ""] = sol.split(".");
	return (BigInt(wholePart || "0") * LAMPORTS_PER_SOL + BigInt((fractionPart + "000000000").slice(0, 9) || "0")).toString();
}
function parseNonNegativeInteger(raw, label) {
	const value = typeof raw === "string" ? raw.trim() : "";
	if (!value) return;
	if (!/^\d+$/.test(value)) throw new Error(`${label} must be a non-negative integer string`);
	return value;
}
function parseNonNegativeIntegerNumber(raw, label, fallback) {
	const parsed = parseNonNegativeInteger(raw, label);
	if (parsed === void 0) return fallback;
	const value = Number(parsed);
	if (!Number.isSafeInteger(value)) throw new Error(`${label} must be a safe non-negative integer`);
	return value;
}
function parseOptionalPositiveInteger(raw, label) {
	const parsed = parseNonNegativeInteger(raw, label);
	if (parsed === void 0) return;
	const value = Number(parsed);
	if (!Number.isSafeInteger(value) || value <= 0) throw new Error(`${label} must be a positive safe integer`);
	return value;
}
function renderSatResult(result, opts, successText) {
	if (opts.json || successText === void 0) {
		defaultRuntime.log(JSON.stringify(result, null, 2));
		return;
	}
	defaultRuntime.log(successText);
}
function renderSatMainnetSyncResult(result, opts) {
	if (opts.json) {
		renderSatResult(result, opts);
		return;
	}
	const payload = result && typeof result === "object" && !Array.isArray(result) ? result.payload : void 0;
	const sync = payload && typeof payload === "object" && !Array.isArray(payload) ? payload : null;
	const state = typeof sync?.state === "string" ? sync.state : "unknown";
	const message = typeof sync?.message === "string" ? sync.message : "No sync detail returned.";
	defaultRuntime.log(`SAT mainnet sync: ${state}`);
	defaultRuntime.log(message);
	if (state !== "synced" && state !== "not_live") defaultRuntime.exit(1);
}
function buildMaintenanceParams(opts) {
	const targetBalanceLamports = parseLamportsPair(opts.targetReserveSol, opts.targetReserveLamports, {
		sol: "--target-reserve-sol",
		lamports: "--target-reserve-lamports"
	});
	const minSolLamports = parseLamportsPair(opts.minSol, opts.minSolLamports, {
		sol: "--min-sol",
		lamports: "--min-sol-lamports"
	});
	const minSatRaw = parseNonNegativeInteger(opts.minSatRaw, "--min-sat-raw");
	const cleanupMaxCycles = parseNonNegativeInteger(opts.cleanupMaxCycles, "--cleanup-max-cycles");
	return {
		...targetBalanceLamports ? { targetBalanceLamports } : {},
		...minSolLamports ? { minSolLamports } : {},
		...minSatRaw ? { minSatRaw } : {},
		...cleanupMaxCycles ? { cleanupMaxCycles } : {}
	};
}
async function appendMaintenanceLog(logFile, record) {
	if (!logFile) return;
	await mkdir(dirname(logFile), { recursive: true });
	await appendFile(logFile, `${JSON.stringify(record)}\n`, "utf8");
}
async function acquireMaintenanceLock(lockFile, staleAfterMs) {
	try {
		return await open(lockFile, "wx");
	} catch (error) {
		if (!(error instanceof Error && "code" in error && error.code === "EEXIST")) throw error;
		let detail = "";
		try {
			detail = (await readFile(lockFile, "utf8")).trim();
		} catch {
			detail = "";
		}
		const pid = parseMaintenanceLockPid(detail);
		if (pid !== void 0 && !isProcessAlive(pid)) {
			await rm(lockFile, { force: true });
			return acquireMaintenanceLock(lockFile, staleAfterMs);
		}
		let lockAgeMs = 0;
		try {
			const lockStat = await stat(lockFile);
			lockAgeMs = Date.now() - lockStat.mtimeMs;
		} catch {
			lockAgeMs = staleAfterMs + 1;
		}
		if (staleAfterMs > 0 && lockAgeMs > staleAfterMs) {
			await rm(lockFile, { force: true });
			return acquireMaintenanceLock(lockFile, staleAfterMs);
		}
		throw new Error(`SAT maintenance loop already running; lock file ${lockFile}${detail ? ` (${detail})` : ""}`, { cause: error });
	}
}
function parseMaintenanceLockPid(detail) {
	if (!detail) return;
	try {
		const parsed = JSON.parse(detail);
		if (typeof parsed.pid === "number" && Number.isInteger(parsed.pid) && parsed.pid > 0) return parsed.pid;
	} catch {
		return;
	}
}
function isProcessAlive(pid) {
	try {
		process.kill(pid, 0);
		return true;
	} catch {
		return false;
	}
}
async function withMaintenanceLock(opts, action) {
	const lockFile = opts.lockFile || join(tmpdir(), "fased-sat-maintain.lock");
	await mkdir(dirname(lockFile), { recursive: true });
	const handle = await acquireMaintenanceLock(lockFile, parseNonNegativeIntegerNumber(opts.staleLockSeconds, "--stale-lock-seconds", DEFAULT_STALE_LOCK_SECONDS) * 1e3);
	let released = false;
	const release = async () => {
		if (released) return;
		released = true;
		await handle.close().catch(() => void 0);
		await rm(lockFile, { force: true }).catch(() => void 0);
	};
	const handleSignal = (signal) => {
		release().catch(() => void 0).finally(() => {
			process.exit(signal === "SIGINT" ? 130 : 143);
		});
	};
	try {
		await handle.writeFile(JSON.stringify({
			pid: process.pid,
			startedAt: (/* @__PURE__ */ new Date()).toISOString()
		}), "utf8");
		process.once("SIGINT", handleSignal);
		process.once("SIGTERM", handleSignal);
		return await action();
	} finally {
		process.off("SIGINT", handleSignal);
		process.off("SIGTERM", handleSignal);
		await release();
	}
}
async function callMaintenancePass(opts) {
	return callGatewayFromCli("sat.runProtocolMaintenanceOnce", opts, buildMaintenanceParams(opts));
}
function summarizeMaintenanceResult(result) {
	if (!result || typeof result !== "object") return result;
	const envelope = result;
	if (!envelope.payload || typeof envelope.payload !== "object") return result;
	return {
		ok: envelope.ok,
		submitted: envelope.payload.submitted,
		status: envelope.payload.status ? {
			currentCycleId: envelope.payload.status.currentCycleId,
			running: envelope.payload.status.running,
			nextAction: envelope.payload.status.nextAction,
			updatedAt: envelope.payload.status.updatedAt
		} : void 0
	};
}
function maintenanceDelayMs(intervalSeconds, jitterSeconds) {
	const baseMs = intervalSeconds * 1e3;
	if (jitterSeconds <= 0) return baseMs;
	return baseMs + Math.floor(Math.random() * (jitterSeconds * 1e3 + 1));
}
async function runMaintenanceLoop(opts) {
	const intervalSeconds = parseNonNegativeIntegerNumber(opts.intervalSeconds, "--interval-seconds", DEFAULT_MAINTAIN_INTERVAL_SECONDS);
	const jitterSeconds = parseNonNegativeIntegerNumber(opts.jitterSeconds, "--jitter-seconds", DEFAULT_MAINTAIN_JITTER_SECONDS);
	const maxIterations = parseOptionalPositiveInteger(opts.maxIterations, "--max-iterations");
	const continuous = maxIterations === void 0;
	await withMaintenanceLock(opts, async () => {
		for (let pass = 1; maxIterations === void 0 || pass <= maxIterations; pass += 1) {
			const startedAt = (/* @__PURE__ */ new Date()).toISOString();
			try {
				const summary = summarizeMaintenanceResult(await callMaintenancePass(opts));
				await appendMaintenanceLog(opts.logFile, {
					ts: (/* @__PURE__ */ new Date()).toISOString(),
					event: "sat-maintain",
					pass,
					status: "success",
					result: summary
				});
				if (opts.json) defaultRuntime.log(JSON.stringify({
					pass,
					result: summary
				}, null, 2));
				else defaultRuntime.log(`SAT protocol maintenance pass ${pass} ok`);
			} catch (error) {
				const message = error instanceof Error ? error.message : String(error);
				await appendMaintenanceLog(opts.logFile, {
					ts: (/* @__PURE__ */ new Date()).toISOString(),
					event: "sat-maintain",
					pass,
					status: "failure",
					error: message,
					startedAt
				});
				defaultRuntime.error(`SAT protocol maintenance pass ${pass} failed: ${message}`);
				if (!continuous) throw error;
			}
			if (maxIterations !== void 0 && pass >= maxIterations) break;
			await setTimeout(maintenanceDelayMs(intervalSeconds, jitterSeconds));
		}
	});
}
function registerSatCli(program) {
	const sat = program.command("sat").description("SAT protocol operator tools").addHelpText("after", () => `\n${theme.heading("Examples:")}\n${formatHelpExamples([
		[formatCliCommand("fased sat maintain --target-reserve-sol 1 --json"), "Run one permissionless SAT protocol maintenance pass."],
		[formatCliCommand("fased sat maintain --min-sol 0.01 --min-sat-raw 100000000000"), "Skip tiny pending protocol lanes."],
		[formatCliCommand("fased sat maintain --loop --interval-seconds 300 --jitter-seconds 30 --log-file ~/.fased/sat-maintainer.jsonl"), "Run a local periodic maintainer loop with jitter and JSONL audit records."],
		[formatCliCommand("fased sat sync-mainnet"), "Fetch and verify the official SAT mainnet manifest."]
	])}\n`);
	addGatewayClientOptions(sat.command("sync-mainnet").description("Fetch and verify the official SAT mainnet manifest, then apply verified IDs").option("--manifest-url <url>", "Override the official manifest URL").option("--json", "Output JSON", false)).action(async (opts) => {
		await runSatCommand(async () => {
			renderSatMainnetSyncResult(await callGatewayFromCli("sat.syncMainnet", opts, opts.manifestUrl ? { manifestUrl: opts.manifestUrl.trim() } : void 0, { expectFinal: true }), opts);
		}, "SAT mainnet sync failed");
	});
	addGatewayClientOptions(sat.command("maintain").description("Run one safe SAT protocol maintenance pass: reserve refill, fixed-recipient protocol claims, and staking feed").option("--target-reserve-sol <amount>", "Reserve target in SOL").option("--target-reserve-lamports <amount>", "Reserve target in lamports").option("--min-sol <amount>", "Minimum pending SOL lane to submit").option("--min-sol-lamports <amount>", "Minimum pending SOL lane in lamports").option("--min-sat-raw <amount>", "Minimum pending SAT raw units to submit").option("--loop", "Run continuously with interval, jitter, and a local lock", false).option("--interval-seconds <seconds>", "Loop interval before jitter", `${DEFAULT_MAINTAIN_INTERVAL_SECONDS}`).option("--jitter-seconds <seconds>", "Random extra loop delay", `${DEFAULT_MAINTAIN_JITTER_SECONDS}`).option("--max-iterations <count>", "Stop after N loop passes; useful for tests and smoke runs").option("--cleanup-max-cycles <count>", "Maximum settled cycles to cleanup per maintenance pass").option("--log-file <path>", "Append JSONL audit records").option("--lock-file <path>", "Local lock file for the loop").option("--stale-lock-seconds <seconds>", "Remove a stale loop lock after this age", `${DEFAULT_STALE_LOCK_SECONDS}`).option("--json", "Output JSON", false)).action(async (opts) => {
		await runSatCommand(async () => {
			if (opts.loop) {
				await runMaintenanceLoop(opts);
				return;
			}
			renderSatResult(await callMaintenancePass(opts), opts, "SAT protocol maintenance pass submitted");
		}, "SAT protocol maintenance failed");
	});
}

//#endregion
export { registerSatCli };