import { s as defaultRuntime } from "./subsystem-hATE68va.js";
import { d as resolveIsNixMode } from "./paths-VdmjGGyc.js";
import { n as isRich, r as theme, t as colorize } from "./theme-C5EwWDWE.js";
import "./ansi-By7x1TI7.js";
import "./utils-D019Z2NU.js";
import "./logger-BKidfKRU.js";
import "./exec-BBWSxSu-.js";
import "./koi-scope-BeICsBhH.js";
import "./model-selection-DvQd6xjM.js";
import "./dist-Czg7dzzf.js";
import "./dist-cjs-CtVce_lP.js";
import { t as formatCliCommand } from "./command-format-DOYW_19_.js";
import "./boolean-D-3joTkO.js";
import "./env-ChCKTuXK.js";
import "./github-copilot-token-BqhLBQWA.js";
import "./config-BOTdzMIB.js";
import "./manifest-registry-D7MfBQxU.js";
import "./lib-C-WEldjv.js";
import "./src-CiVOi-Ma.js";
import "./core-DrwlWTgS.js";
import "./chrome-CTicuLaA.js";
import "./routes-C952rvWJ.js";
import "./server-context-Cs8Yx5qf.js";
import "./image-ops-B6MN1Uli.js";
import "./message-channel-B-LM-U45.js";
import "./logging-Dn5qdhsZ.js";
import "./dispatcher-Da_eDTB8.js";
import "./device-identity-CBC9Fa-4.js";
import "./client-CnWPlz1L.js";
import { t as formatDocsLink } from "./links-DlFnXfJ_.js";
import { t as isWSL } from "./wsl-BuljpQTZ.js";
import "./control-service-CamrxDfq.js";
import { c as formatNodeServiceDescription, g as resolveNodeWindowsTaskName, h as resolveNodeSystemdServiceName, m as resolveNodeLaunchAgentLabel } from "./constants-CRHmdXpV.js";
import "./path-env-B9AK_97y.js";
import { d as renderSystemNodeWarning, f as resolvePreferredNodePath, h as resolveNodeProgramArguments, o as resolveGatewayDevMode, p as resolveSystemNodeInfo, r as isGatewayDaemonRuntime, s as buildNodeServiceEnvironment, t as DEFAULT_GATEWAY_DAEMON_RUNTIME } from "./daemon-runtime-EHtDn8NC.js";
import { o as resolveGatewayLogPaths } from "./service-C6lyBW0F.js";
import { r as isSystemdUserServiceAvailable } from "./systemd-C7TaOB0r.js";
import { t as resolveNodeService } from "./node-service-CtGQ_WCB.js";
import { n as renderSystemdUnavailableHints } from "./systemd-hints-Mjx4VQ0S.js";
import { d as createNullWriter, f as emitDaemonActionJson, i as parsePort, n as formatRuntimeStatus, u as buildDaemonServiceSnapshot } from "./shared-C_VbBG7x.js";
import { n as loadNodeHostConfig, t as runNodeHost } from "./runner-B1NLg5jU.js";

//#region src/commands/node-daemon-install-helpers.ts
async function buildNodeInstallPlan(params) {
	const devMode = params.devMode ?? resolveGatewayDevMode();
	const nodePath = params.nodePath ?? await resolvePreferredNodePath({
		env: params.env,
		runtime: params.runtime
	});
	const { programArguments, workingDirectory } = await resolveNodeProgramArguments({
		host: params.host,
		port: params.port,
		tls: params.tls,
		tlsFingerprint: params.tlsFingerprint,
		nodeId: params.nodeId,
		displayName: params.displayName,
		dev: devMode,
		runtime: params.runtime,
		nodePath
	});
	if (params.runtime === "node") {
		const warning = renderSystemNodeWarning(await resolveSystemNodeInfo({ env: params.env }), programArguments[0]);
		if (warning) params.warn?.(warning, "Node daemon runtime");
	}
	const environment = buildNodeServiceEnvironment({ env: params.env });
	return {
		programArguments,
		workingDirectory,
		environment,
		description: formatNodeServiceDescription({ version: environment.SKYKOI_SERVICE_VERSION })
	};
}

//#endregion
//#region src/commands/node-daemon-runtime.ts
const DEFAULT_NODE_DAEMON_RUNTIME = DEFAULT_GATEWAY_DAEMON_RUNTIME;
function isNodeDaemonRuntime(value) {
	return isGatewayDaemonRuntime(value);
}

//#endregion
//#region src/cli/node-cli/daemon.ts
function renderNodeServiceStartHints() {
	const base = [formatCliCommand("skykoi node install"), formatCliCommand("skykoi node start")];
	switch (process.platform) {
		case "darwin": return [...base, `launchctl bootstrap gui/$UID ~/Library/LaunchAgents/${resolveNodeLaunchAgentLabel()}.plist`];
		case "linux": return [...base, `systemctl --user start ${resolveNodeSystemdServiceName()}.service`];
		case "win32": return [...base, `schtasks /Run /TN "${resolveNodeWindowsTaskName()}"`];
		default: return base;
	}
}
function buildNodeRuntimeHints(env = process.env) {
	if (process.platform === "darwin") {
		const logs = resolveGatewayLogPaths(env);
		return [`Launchd stdout (if installed): ${logs.stdoutPath}`, `Launchd stderr (if installed): ${logs.stderrPath}`];
	}
	if (process.platform === "linux") return [`Logs: journalctl --user -u ${resolveNodeSystemdServiceName()}.service -n 200 --no-pager`];
	if (process.platform === "win32") return [`Logs: schtasks /Query /TN "${resolveNodeWindowsTaskName()}" /V /FO LIST`];
	return [];
}
function resolveNodeDefaults(opts, config) {
	const host = opts.host?.trim() || config?.gateway?.host || "127.0.0.1";
	const portOverride = parsePort(opts.port);
	if (opts.port !== void 0 && portOverride === null) return {
		host,
		port: null
	};
	return {
		host,
		port: portOverride ?? config?.gateway?.port ?? 18789
	};
}
async function runNodeDaemonInstall(opts) {
	const json = Boolean(opts.json);
	const warnings = [];
	const stdout = json ? createNullWriter() : process.stdout;
	const emit = (payload) => {
		if (!json) return;
		emitDaemonActionJson({
			action: "install",
			...payload
		});
	};
	const fail = (message, hints) => {
		if (json) emit({
			ok: false,
			error: message,
			hints,
			warnings: warnings.length ? warnings : void 0
		});
		else {
			defaultRuntime.error(message);
			if (hints?.length) for (const hint of hints) defaultRuntime.log(`Tip: ${hint}`);
		}
		defaultRuntime.exit(1);
	};
	if (resolveIsNixMode(process.env)) {
		fail("Nix mode detected; service install is disabled.");
		return;
	}
	const config = await loadNodeHostConfig();
	const { host, port } = resolveNodeDefaults(opts, config);
	if (!Number.isFinite(port ?? NaN) || (port ?? 0) <= 0) {
		fail("Invalid port");
		return;
	}
	const runtimeRaw = opts.runtime ? String(opts.runtime) : DEFAULT_NODE_DAEMON_RUNTIME;
	if (!isNodeDaemonRuntime(runtimeRaw)) {
		fail("Invalid --runtime (use \"node\" or \"bun\")");
		return;
	}
	const service = resolveNodeService();
	let loaded = false;
	try {
		loaded = await service.isLoaded({ env: process.env });
	} catch (err) {
		fail(`Node service check failed: ${String(err)}`);
		return;
	}
	if (loaded && !opts.force) {
		emit({
			ok: true,
			result: "already-installed",
			message: `Node service already ${service.loadedText}.`,
			service: buildDaemonServiceSnapshot(service, loaded),
			warnings: warnings.length ? warnings : void 0
		});
		if (!json) {
			defaultRuntime.log(`Node service already ${service.loadedText}.`);
			defaultRuntime.log(`Reinstall with: ${formatCliCommand("skykoi node install --force")}`);
		}
		return;
	}
	const tlsFingerprint = opts.tlsFingerprint?.trim() || config?.gateway?.tlsFingerprint;
	const tls = Boolean(opts.tls) || Boolean(tlsFingerprint) || Boolean(config?.gateway?.tls);
	const { programArguments, workingDirectory, environment, description } = await buildNodeInstallPlan({
		env: process.env,
		host,
		port: port ?? 18789,
		tls,
		tlsFingerprint: tlsFingerprint || void 0,
		nodeId: opts.nodeId,
		displayName: opts.displayName,
		runtime: runtimeRaw,
		warn: (message) => {
			if (json) warnings.push(message);
			else defaultRuntime.log(message);
		}
	});
	try {
		await service.install({
			env: process.env,
			stdout,
			programArguments,
			workingDirectory,
			environment,
			description
		});
	} catch (err) {
		fail(`Node install failed: ${String(err)}`);
		return;
	}
	let installed = true;
	try {
		installed = await service.isLoaded({ env: process.env });
	} catch {
		installed = true;
	}
	emit({
		ok: true,
		result: "installed",
		service: buildDaemonServiceSnapshot(service, installed),
		warnings: warnings.length ? warnings : void 0
	});
}
async function runNodeDaemonUninstall(opts = {}) {
	const json = Boolean(opts.json);
	const stdout = json ? createNullWriter() : process.stdout;
	const emit = (payload) => {
		if (!json) return;
		emitDaemonActionJson({
			action: "uninstall",
			...payload
		});
	};
	const fail = (message) => {
		if (json) emit({
			ok: false,
			error: message
		});
		else defaultRuntime.error(message);
		defaultRuntime.exit(1);
	};
	if (resolveIsNixMode(process.env)) {
		fail("Nix mode detected; service uninstall is disabled.");
		return;
	}
	const service = resolveNodeService();
	try {
		await service.uninstall({
			env: process.env,
			stdout
		});
	} catch (err) {
		fail(`Node uninstall failed: ${String(err)}`);
		return;
	}
	let loaded = false;
	try {
		loaded = await service.isLoaded({ env: process.env });
	} catch {
		loaded = false;
	}
	emit({
		ok: true,
		result: "uninstalled",
		service: buildDaemonServiceSnapshot(service, loaded)
	});
}
async function runNodeDaemonRestart(opts = {}) {
	const json = Boolean(opts.json);
	const stdout = json ? createNullWriter() : process.stdout;
	const emit = (payload) => {
		if (!json) return;
		emitDaemonActionJson({
			action: "restart",
			...payload
		});
	};
	const fail = (message, hints) => {
		if (json) emit({
			ok: false,
			error: message,
			hints
		});
		else defaultRuntime.error(message);
		defaultRuntime.exit(1);
	};
	const service = resolveNodeService();
	let loaded = false;
	try {
		loaded = await service.isLoaded({ env: process.env });
	} catch (err) {
		fail(`Node service check failed: ${String(err)}`);
		return;
	}
	if (!loaded) {
		let hints = renderNodeServiceStartHints();
		if (process.platform === "linux") {
			if (!await isSystemdUserServiceAvailable().catch(() => false)) hints = [...hints, ...renderSystemdUnavailableHints({ wsl: await isWSL() })];
		}
		emit({
			ok: true,
			result: "not-loaded",
			message: `Node service ${service.notLoadedText}.`,
			hints,
			service: buildDaemonServiceSnapshot(service, loaded)
		});
		if (!json) {
			defaultRuntime.log(`Node service ${service.notLoadedText}.`);
			for (const hint of hints) defaultRuntime.log(`Start with: ${hint}`);
		}
		return;
	}
	try {
		await service.restart({
			env: process.env,
			stdout
		});
	} catch (err) {
		const hints = renderNodeServiceStartHints();
		fail(`Node restart failed: ${String(err)}`, hints);
		return;
	}
	let restarted = true;
	try {
		restarted = await service.isLoaded({ env: process.env });
	} catch {
		restarted = true;
	}
	emit({
		ok: true,
		result: "restarted",
		service: buildDaemonServiceSnapshot(service, restarted)
	});
}
async function runNodeDaemonStop(opts = {}) {
	const json = Boolean(opts.json);
	const stdout = json ? createNullWriter() : process.stdout;
	const emit = (payload) => {
		if (!json) return;
		emitDaemonActionJson({
			action: "stop",
			...payload
		});
	};
	const fail = (message) => {
		if (json) emit({
			ok: false,
			error: message
		});
		else defaultRuntime.error(message);
		defaultRuntime.exit(1);
	};
	const service = resolveNodeService();
	let loaded = false;
	try {
		loaded = await service.isLoaded({ env: process.env });
	} catch (err) {
		fail(`Node service check failed: ${String(err)}`);
		return;
	}
	if (!loaded) {
		emit({
			ok: true,
			result: "not-loaded",
			message: `Node service ${service.notLoadedText}.`,
			service: buildDaemonServiceSnapshot(service, loaded)
		});
		if (!json) defaultRuntime.log(`Node service ${service.notLoadedText}.`);
		return;
	}
	try {
		await service.stop({
			env: process.env,
			stdout
		});
	} catch (err) {
		fail(`Node stop failed: ${String(err)}`);
		return;
	}
	let stopped = false;
	try {
		stopped = await service.isLoaded({ env: process.env });
	} catch {
		stopped = false;
	}
	emit({
		ok: true,
		result: "stopped",
		service: buildDaemonServiceSnapshot(service, stopped)
	});
}
async function runNodeDaemonStatus(opts = {}) {
	const json = Boolean(opts.json);
	const service = resolveNodeService();
	const [loaded, command, runtime] = await Promise.all([
		service.isLoaded({ env: process.env }).catch(() => false),
		service.readCommand(process.env).catch(() => null),
		service.readRuntime(process.env).catch((err) => ({
			status: "unknown",
			detail: String(err)
		}))
	]);
	const payload = { service: {
		...buildDaemonServiceSnapshot(service, loaded),
		command,
		runtime
	} };
	if (json) {
		defaultRuntime.log(JSON.stringify(payload, null, 2));
		return;
	}
	const rich = isRich();
	const label = (value) => colorize(rich, theme.muted, value);
	const accent = (value) => colorize(rich, theme.accent, value);
	const infoText = (value) => colorize(rich, theme.info, value);
	const okText = (value) => colorize(rich, theme.success, value);
	const warnText = (value) => colorize(rich, theme.warn, value);
	const errorText = (value) => colorize(rich, theme.error, value);
	const serviceStatus = loaded ? okText(service.loadedText) : warnText(service.notLoadedText);
	defaultRuntime.log(`${label("Service:")} ${accent(service.label)} (${serviceStatus})`);
	if (command?.programArguments?.length) defaultRuntime.log(`${label("Command:")} ${infoText(command.programArguments.join(" "))}`);
	if (command?.sourcePath) defaultRuntime.log(`${label("Service file:")} ${infoText(command.sourcePath)}`);
	if (command?.workingDirectory) defaultRuntime.log(`${label("Working dir:")} ${infoText(command.workingDirectory)}`);
	const runtimeLine = formatRuntimeStatus(runtime);
	if (runtimeLine) {
		const runtimeStatus = runtime?.status ?? "unknown";
		const runtimeColor = runtimeStatus === "running" ? theme.success : runtimeStatus === "stopped" ? theme.error : runtimeStatus === "unknown" ? theme.muted : theme.warn;
		defaultRuntime.log(`${label("Runtime:")} ${colorize(rich, runtimeColor, runtimeLine)}`);
	}
	if (!loaded) {
		defaultRuntime.log("");
		for (const hint of renderNodeServiceStartHints()) defaultRuntime.log(`${warnText("Start with:")} ${infoText(hint)}`);
		return;
	}
	const baseEnv = {
		...process.env,
		...command?.environment ?? void 0
	};
	const hintEnv = {
		...baseEnv,
		SKYKOI_LOG_PREFIX: baseEnv.SKYKOI_LOG_PREFIX ?? "node"
	};
	if (runtime?.missingUnit) {
		defaultRuntime.error(errorText("Service unit not found."));
		for (const hint of buildNodeRuntimeHints(hintEnv)) defaultRuntime.error(errorText(hint));
		return;
	}
	if (runtime?.status === "stopped") {
		defaultRuntime.error(errorText("Service is loaded but not running."));
		for (const hint of buildNodeRuntimeHints(hintEnv)) defaultRuntime.error(errorText(hint));
	}
}

//#endregion
//#region src/cli/node-cli/register.ts
function parsePortWithFallback(value, fallback) {
	return parsePort(value) ?? fallback;
}
function registerNodeCli(program) {
	const node = program.command("node").description("Run a headless node host (system.run/system.which)").addHelpText("after", () => `\n${theme.muted("Docs:")} ${formatDocsLink("/cli/node", "docs.skykoi.com/cli/node")}\n`);
	node.command("run").description("Run the headless node host (foreground)").option("--host <host>", "Gateway host").option("--port <port>", "Gateway port").option("--tls", "Use TLS for the gateway connection", false).option("--tls-fingerprint <sha256>", "Expected TLS certificate fingerprint (sha256)").option("--node-id <id>", "Override node id (clears pairing token)").option("--display-name <name>", "Override node display name").action(async (opts) => {
		const existing = await loadNodeHostConfig();
		await runNodeHost({
			gatewayHost: opts.host?.trim() || existing?.gateway?.host || "127.0.0.1",
			gatewayPort: parsePortWithFallback(opts.port, existing?.gateway?.port ?? 18789),
			gatewayTls: Boolean(opts.tls) || Boolean(opts.tlsFingerprint),
			gatewayTlsFingerprint: opts.tlsFingerprint,
			nodeId: opts.nodeId,
			displayName: opts.displayName
		});
	});
	node.command("status").description("Show node host status").option("--json", "Output JSON", false).action(async (opts) => {
		await runNodeDaemonStatus(opts);
	});
	node.command("install").description("Install the node host service (launchd/systemd/schtasks)").option("--host <host>", "Gateway host").option("--port <port>", "Gateway port").option("--tls", "Use TLS for the gateway connection", false).option("--tls-fingerprint <sha256>", "Expected TLS certificate fingerprint (sha256)").option("--node-id <id>", "Override node id (clears pairing token)").option("--display-name <name>", "Override node display name").option("--runtime <runtime>", "Service runtime (node|bun). Default: node").option("--force", "Reinstall/overwrite if already installed", false).option("--json", "Output JSON", false).action(async (opts) => {
		await runNodeDaemonInstall(opts);
	});
	node.command("uninstall").description("Uninstall the node host service (launchd/systemd/schtasks)").option("--json", "Output JSON", false).action(async (opts) => {
		await runNodeDaemonUninstall(opts);
	});
	node.command("stop").description("Stop the node host service (launchd/systemd/schtasks)").option("--json", "Output JSON", false).action(async (opts) => {
		await runNodeDaemonStop(opts);
	});
	node.command("restart").description("Restart the node host service (launchd/systemd/schtasks)").option("--json", "Output JSON", false).action(async (opts) => {
		await runNodeDaemonRestart(opts);
	});
}

//#endregion
export { registerNodeCli };