import { t as formatDocsLink } from "./links-BszRQhGa.js";
import { n as isRich, r as theme, t as colorize } from "./theme-B128avno.js";
import { n as inheritOptionFromParent } from "./command-options-DR-PifHH.js";
import { t as addGatewayServiceCommands } from "./register-service-commands-BljH7dc2.js";
import { n as defaultRuntime } from "./runtime-CIJX7ulQ.js";
import { i as GATEWAY_CLIENT_NAMES, r as GATEWAY_CLIENT_MODES } from "./client-info-BhnDRj_s.js";
import { r as callGateway } from "./call-Bqi4Gvgx.js";
import { a as selectDiagnosticStabilitySnapshot, r as normalizeDiagnosticStabilityQuery } from "./diagnostic-stability-YQRzuYmi.js";
import { n as parseTimeoutMsWithFallback } from "./parse-timeout-D-0pvgUZ.js";
import { n as withProgress } from "./progress-DEutg9EU.js";
import { n as runCommandWithRuntime } from "./cli-utils-CQ5U8Klu.js";
import { t as formatHelpExamples } from "./help-format-CmO6sKiH.js";
import { n as buildGatewayDiscoveryTarget } from "./gateway-discovery-targets-DNTiD_3Z.js";
import { n as addGatewayRunCommand } from "./run-C8gG0pKN.js";
//#region src/cli/gateway-cli/call.ts
const gatewayCallOpts = (cmd) => cmd.option("--url <url>", "网关 WebSocket URL（已配置时默认为 gateway.remote.url）").option("--token <token>", "网关令牌（如需要）").option("--password <password>", "网关密码（password 认证）").option("--timeout <ms>", "超时（毫秒）", "10000").option("--expect-final", "等待最终响应（代理）", false).option("--json", "输出 JSON", false);
const callGatewayCli = async (method, opts, params) => withProgress({
	label: `Gateway ${method}`,
	indeterminate: true,
	enabled: opts.json !== true
}, async () => await callGateway({
	config: opts.config,
	url: opts.url,
	token: opts.token,
	password: opts.password,
	method,
	params,
	expectFinal: Boolean(opts.expectFinal),
	timeoutMs: Number(opts.timeout ?? 1e4),
	clientName: GATEWAY_CLIENT_NAMES.CLI,
	mode: GATEWAY_CLIENT_MODES.CLI
}));
//#endregion
//#region src/cli/gateway-cli/discover.ts
function parseDiscoverTimeoutMs(raw, fallbackMs) {
	return parseTimeoutMsWithFallback(raw, fallbackMs, { invalidType: "error" });
}
function pickBeaconHost(beacon) {
	return buildGatewayDiscoveryTarget(beacon).endpoint?.host ?? null;
}
function pickGatewayPort(beacon) {
	return buildGatewayDiscoveryTarget(beacon).endpoint?.port ?? null;
}
function dedupeBeacons(beacons) {
	const out = [];
	const seen = /* @__PURE__ */ new Set();
	for (const b of beacons) {
		const host = pickBeaconHost(b) ?? "";
		const key = [
			b.domain ?? "",
			b.instanceName ?? "",
			b.displayName ?? "",
			host,
			String(b.port ?? ""),
			String(b.gatewayPort ?? "")
		].join("|");
		if (seen.has(key)) continue;
		seen.add(key);
		out.push(b);
	}
	return out;
}
function renderBeaconLines(beacon, rich) {
	const target = buildGatewayDiscoveryTarget(beacon);
	const lines = [`- ${colorize(rich, theme.accentBright, target.title)} ${colorize(rich, theme.muted, target.domain)}`];
	if (beacon.tailnetDns) lines.push(`  ${colorize(rich, theme.info, "tailnet")}: ${beacon.tailnetDns}`);
	if (beacon.lanHost) lines.push(`  ${colorize(rich, theme.info, "lan")}: ${beacon.lanHost}`);
	if (beacon.host) lines.push(`  ${colorize(rich, theme.info, "host")}: ${beacon.host}`);
	if (target.wsUrl) lines.push(`  ${colorize(rich, theme.muted, "ws")}: ${colorize(rich, theme.command, target.wsUrl)}`);
	if (beacon.role) lines.push(`  ${colorize(rich, theme.muted, "role")}: ${beacon.role}`);
	if (beacon.transport) lines.push(`  ${colorize(rich, theme.muted, "transport")}: ${beacon.transport}`);
	if (beacon.gatewayTls) {
		const fingerprint = beacon.gatewayTlsFingerprintSha256 ? `sha256 ${beacon.gatewayTlsFingerprintSha256}` : "enabled";
		lines.push(`  ${colorize(rich, theme.muted, "tls")}: ${fingerprint}`);
	}
	if (target.endpoint && target.sshPort) {
		const ssh = `ssh -N -L 18789:127.0.0.1:18789 <user>@${target.endpoint.host} -p ${target.sshPort}`;
		lines.push(`  ${colorize(rich, theme.muted, "ssh")}: ${colorize(rich, theme.command, ssh)}`);
	}
	return lines;
}
//#endregion
//#region src/cli/gateway-cli/register.ts
let configModulePromise;
let gatewayStatusModulePromise;
let gatewayHealthModulePromise;
let bonjourDiscoveryModulePromise;
let wideAreaDnsModulePromise;
let healthStyleModulePromise;
let usageFormatModulePromise;
let stabilityBundleModulePromise;
let supportExportModulePromise;
let daemonStatusGatherModulePromise;
function loadConfigModule() {
	configModulePromise ??= import("./read-best-effort-config.runtime-D2z2IMs9.js");
	return configModulePromise;
}
function loadGatewayStatusModule() {
	gatewayStatusModulePromise ??= import("./gateway-status-B22HWyOG.js");
	return gatewayStatusModulePromise;
}
function loadGatewayHealthModule() {
	gatewayHealthModulePromise ??= import("./health-DQ64DqY4.js");
	return gatewayHealthModulePromise;
}
function loadBonjourDiscoveryModule() {
	bonjourDiscoveryModulePromise ??= import("./bonjour-discovery-jVbA75UG.js");
	return bonjourDiscoveryModulePromise;
}
function loadWideAreaDnsModule() {
	wideAreaDnsModulePromise ??= import("./widearea-dns-BQehhM4l.js");
	return wideAreaDnsModulePromise;
}
function loadHealthStyleModule() {
	healthStyleModulePromise ??= import("./health-style-B90i-lCU.js");
	return healthStyleModulePromise;
}
function loadUsageFormatModule() {
	usageFormatModulePromise ??= import("./usage-format-dXyWClYd.js");
	return usageFormatModulePromise;
}
function loadStabilityBundleModule() {
	stabilityBundleModulePromise ??= import("./diagnostic-stability-bundle-CiBSNgus.js");
	return stabilityBundleModulePromise;
}
function loadSupportExportModule() {
	supportExportModulePromise ??= import("./diagnostic-support-export-Da2zeT9Z.js");
	return supportExportModulePromise;
}
function loadDaemonStatusGatherModule() {
	daemonStatusGatherModulePromise ??= import("./status.gather-sO_aFDET.js");
	return daemonStatusGatherModulePromise;
}
function runGatewayCommand(action, label) {
	return runCommandWithRuntime(defaultRuntime, action, (err) => {
		const message = String(err);
		defaultRuntime.error(label ? `${label}: ${message}` : message);
		defaultRuntime.exit(1);
	});
}
function parseDaysOption(raw, fallback = 30) {
	if (typeof raw === "number" && Number.isFinite(raw)) return Math.max(1, Math.floor(raw));
	if (typeof raw === "string" && raw.trim() !== "") {
		const parsed = Number(raw);
		if (Number.isFinite(parsed)) return Math.max(1, Math.floor(parsed));
	}
	return fallback;
}
function resolveGatewayRpcOptions(opts, command) {
	const parentToken = inheritOptionFromParent(command, "token");
	const parentPassword = inheritOptionFromParent(command, "password");
	return {
		...opts,
		token: opts.token ?? parentToken,
		password: opts.password ?? parentPassword
	};
}
async function renderCostUsageSummaryAsync(summary, days, rich) {
	const { formatTokenCount, formatUsd } = await loadUsageFormatModule();
	const totalCost = formatUsd(summary.totals.totalCost) ?? "$0.00";
	const totalTokens = formatTokenCount(summary.totals.totalTokens) ?? "0";
	const lines = [colorize(rich, theme.heading, `Usage cost (${days} days)`), `${colorize(rich, theme.muted, "Total:")} ${totalCost} · ${totalTokens} tokens`];
	if (summary.totals.missingCostEntries > 0) lines.push(`${colorize(rich, theme.muted, "Missing entries:")} ${summary.totals.missingCostEntries}`);
	const latest = summary.daily.at(-1);
	if (latest) {
		const latestCost = formatUsd(latest.totalCost) ?? "$0.00";
		const latestTokens = formatTokenCount(latest.totalTokens) ?? "0";
		lines.push(`${colorize(rich, theme.muted, "Latest day:")} ${latest.date} · ${latestCost} · ${latestTokens} tokens`);
	}
	return lines;
}
function formatBytes(value) {
	if (value === void 0) return "n/a";
	const units = [
		"B",
		"KiB",
		"MiB",
		"GiB"
	];
	let amount = value;
	let unitIndex = 0;
	while (amount >= 1024 && unitIndex < units.length - 1) {
		amount /= 1024;
		unitIndex += 1;
	}
	const digits = unitIndex === 0 || amount >= 100 ? 0 : 1;
	return `${amount.toFixed(digits)} ${units[unitIndex]}`;
}
function formatStabilityEvent(record) {
	return [
		new Date(record.ts).toISOString(),
		`#${record.seq}`,
		record.type,
		record.level ? `level=${record.level}` : "",
		record.action ? `action=${record.action}` : "",
		record.outcome ? `outcome=${record.outcome}` : "",
		record.surface ? `surface=${record.surface}` : "",
		record.channel ? `channel=${record.channel}` : "",
		record.pluginId ? `plugin=${record.pluginId}` : "",
		record.reason ? `reason=${record.reason}` : "",
		record.bytes !== void 0 ? `bytes=${formatBytes(record.bytes)}` : "",
		record.limitBytes !== void 0 ? `limit=${formatBytes(record.limitBytes)}` : "",
		record.queueDepth !== void 0 ? `queueDepth=${record.queueDepth}` : "",
		record.queued !== void 0 ? `queued=${record.queued}` : "",
		record.memory ? `rss=${formatBytes(record.memory.rssBytes)}` : "",
		record.memory ? `heap=${formatBytes(record.memory.heapUsedBytes)}` : ""
	].filter(Boolean).join(" ");
}
function renderStabilitySummary(snapshot, rich) {
	const lines = [colorize(rich, theme.heading, "网关稳定性"), `${colorize(rich, theme.muted, "事件：")} ${snapshot.count}/${snapshot.capacity}${snapshot.dropped > 0 ? ` · dropped=${snapshot.dropped}` : ""}`];
	const topTypes = Object.entries(snapshot.summary.byType).toSorted((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).slice(0, 8).map(([type, count]) => `${type}=${count}`).join(", ");
	if (topTypes) lines.push(`${colorize(rich, theme.muted, "类型：")} ${topTypes}`);
	const memory = snapshot.summary.memory;
	if (memory) lines.push(`${colorize(rich, theme.muted, "内存：")} rss=${formatBytes(memory.latest?.rssBytes)} heap=${formatBytes(memory.latest?.heapUsedBytes)} maxRss=${formatBytes(memory.maxRssBytes)} pressure=${memory.pressureCount}`);
	const payloadLarge = snapshot.summary.payloadLarge;
	if (payloadLarge) {
		const surfaces = Object.entries(payloadLarge.bySurface).toSorted((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).map(([surface, count]) => `${surface}=${count}`).join(", ");
		lines.push(`${colorize(rich, theme.muted, "大载荷：")} total=${payloadLarge.count} rejected=${payloadLarge.rejected} truncated=${payloadLarge.truncated} chunked=${payloadLarge.chunked}${surfaces ? ` · ${surfaces}` : ""}`);
	}
	if (snapshot.events.length > 0) {
		lines.push(colorize(rich, theme.muted, "最近："));
		for (const event of snapshot.events) lines.push(`  ${formatStabilityEvent(event)}`);
	}
	return lines;
}
function normalizeStabilityBundleTarget(raw) {
	if (raw === void 0 || raw === false) return null;
	if (raw === true) return "latest";
	if (typeof raw !== "string") return "latest";
	const value = raw.trim();
	return value === "" ? "latest" : value;
}
function formatBundleError(result) {
	if (result.status === "missing") return `在 ${result.dir} 中未找到稳定性包`;
	if (result.status === "failed") return result.error instanceof Error ? result.error.message : String(result.error);
	return "读取稳定性包时出现意外结果";
}
async function readStabilityBundleTarget(bundleTarget) {
	const { readDiagnosticStabilityBundleFileSync, readLatestDiagnosticStabilityBundleSync } = await loadStabilityBundleModule();
	return bundleTarget === "latest" ? readLatestDiagnosticStabilityBundleSync() : readDiagnosticStabilityBundleFileSync(bundleTarget);
}
function renderStabilityBundleSummary(params) {
	const { bundle, path, rich, snapshot } = params;
	const processDetails = [
		`pid=${bundle.process.pid}`,
		`node=${bundle.process.node}`,
		`${bundle.process.platform}/${bundle.process.arch}`,
		`uptime=${Math.round(bundle.process.uptimeMs / 1e3)}s`
	].join(" ");
	const lines = [
		colorize(rich, theme.heading, "稳定性包"),
		`${colorize(rich, theme.muted, "路径：")} ${path}`,
		`${colorize(rich, theme.muted, "生成时间：")} ${bundle.generatedAt}`,
		`${colorize(rich, theme.muted, "原因：")} ${bundle.reason}`,
		`${colorize(rich, theme.muted, "进程：")} ${processDetails}`,
		`${colorize(rich, theme.muted, "主机：")} ${bundle.host.hostname}`
	];
	if (bundle.error) {
		const errorParts = [bundle.error.name ? `name=${bundle.error.name}` : "", bundle.error.code ? `code=${bundle.error.code}` : ""].filter(Boolean);
		if (errorParts.length > 0) lines.push(`${colorize(rich, theme.muted, "错误：")} ${errorParts.join(" ")}`);
	}
	lines.push("", ...renderStabilitySummary(snapshot, rich));
	return lines;
}
function renderSupportExportResult(result, rich) {
	return [
		colorize(rich, theme.heading, "诊断导出"),
		`${colorize(rich, theme.muted, "路径：")} ${result.path}`,
		`${colorize(rich, theme.muted, "大小：")} ${formatBytes(result.bytes)}`,
		`${colorize(rich, theme.muted, "文件：")} ${result.manifest.contents.length}`,
		`${colorize(rich, theme.muted, "隐私：")} 不含载荷的稳定性数据，已脱敏的日志/状态/健康/配置`
	];
}
function resolveSupportExportRpcOptions(rpc) {
	return {
		url: rpc?.url,
		token: rpc?.token,
		password: rpc?.password,
		timeout: rpc?.timeout ?? "3000",
		json: true
	};
}
async function writeSupportExportFromCli(opts) {
	const { writeDiagnosticSupportExport } = await loadSupportExportModule();
	const rpc = resolveSupportExportRpcOptions(opts.rpc);
	const result = await writeDiagnosticSupportExport({
		outputPath: opts.output,
		logLimit: opts.logLines ? Number(opts.logLines) : void 0,
		logMaxBytes: opts.logBytes ? Number(opts.logBytes) : void 0,
		stabilityBundle: opts.stabilityBundle,
		readStatusSnapshot: async () => {
			const { gatherDaemonStatus } = await loadDaemonStatusGatherModule();
			return await gatherDaemonStatus({
				rpc,
				probe: true,
				requireRpc: false,
				deep: false
			});
		},
		readHealthSnapshot: async () => await callGatewayCli("health", rpc)
	});
	if (opts.json) {
		defaultRuntime.writeJson(result);
		return;
	}
	const rich = isRich();
	for (const line of renderSupportExportResult(result, rich)) defaultRuntime.log(line);
}
function registerGatewayCli(program) {
	const gateway = addGatewayRunCommand(program.command("gateway").description("运行、检查和查询 WebSocket 网关").addHelpText("after", () => `\n${theme.heading("示例：")}\n${formatHelpExamples([
		["openclaw gateway run", "在前台运行网关。"],
		["openclaw gateway status", "显示服务状态以及连通性/能力。"],
		["openclaw gateway discover", "查找本地和广域网关信标。"],
		["openclaw gateway stability", "显示最近的稳定性诊断。"],
		["openclaw gateway call health", "直接调用网关 RPC 方法。"]
	])}\n\n${theme.muted("文档：")} ${formatDocsLink("/cli/gateway", "docs.openclaw.ai/cli/gateway")}\n`));
	addGatewayRunCommand(gateway.command("run").description("在前台运行 WebSocket 网关"));
	addGatewayServiceCommands(gateway, { statusDescription: "显示网关服务状态并探测连通性/能力" });
	gatewayCallOpts(gateway.command("call").description("调用网关方法").argument("<method>", "方法名（health/status/system-presence/cron.*）").option("--params <json>", "参数的 JSON 对象字符串", "{}").action(async (method, opts, command) => {
		await runGatewayCommand(async () => {
			const rpcOpts = resolveGatewayRpcOptions(opts, command);
			const result = await callGatewayCli(method, rpcOpts, JSON.parse(String(opts.params ?? "{}")));
			if (rpcOpts.json) {
				defaultRuntime.writeJson(result);
				return;
			}
			const rich = isRich();
			defaultRuntime.log(`${colorize(rich, theme.heading, "Gateway call")}: ${colorize(rich, theme.muted, String(method))}`);
			defaultRuntime.writeJson(result);
		}, "Gateway call failed");
	}));
	gatewayCallOpts(gateway.command("usage-cost").description("从会话日志中获取用量成本摘要").option("--days <days>", "包含的天数", "30").action(async (opts, command) => {
		await runGatewayCommand(async () => {
			const rpcOpts = resolveGatewayRpcOptions(opts, command);
			const days = parseDaysOption(opts.days);
			const result = await callGatewayCli("usage.cost", rpcOpts, { days });
			if (rpcOpts.json) {
				defaultRuntime.writeJson(result);
				return;
			}
			const rich = isRich();
			const summary = result;
			for (const line of await renderCostUsageSummaryAsync(summary, days, rich)) defaultRuntime.log(line);
		}, "Gateway usage cost failed");
	}));
	gatewayCallOpts(gateway.command("health").description("获取网关健康状态").action(async (opts, command) => {
		await runGatewayCommand(async () => {
			const rpcOpts = resolveGatewayRpcOptions(opts, command);
			const [{ formatHealthChannelLines }, { styleHealthChannelLine }] = await Promise.all([loadGatewayHealthModule(), loadHealthStyleModule()]);
			const result = await callGatewayCli("health", rpcOpts);
			if (rpcOpts.json) {
				defaultRuntime.writeJson(result);
				return;
			}
			const rich = isRich();
			const obj = result && typeof result === "object" ? result : {};
			const durationMs = typeof obj.durationMs === "number" ? obj.durationMs : null;
			defaultRuntime.log(colorize(rich, theme.heading, "Gateway Health"));
			defaultRuntime.log(`${colorize(rich, theme.success, "OK")}${durationMs != null ? ` (${durationMs}ms)` : ""}`);
			if (obj.channels && typeof obj.channels === "object") for (const line of formatHealthChannelLines(obj)) defaultRuntime.log(styleHealthChannelLine(line, rich));
		});
	}));
	gatewayCallOpts(gateway.command("stability").description("获取不含载荷的网关稳定性诊断").option("--limit <limit>", "最近事件的最大数量", "25").option("--type <type>", "按诊断事件类型过滤").option("--since-seq <seq>", "仅包含此序列号之后的事件").option("--bundle [path]", "读取已持久化的稳定性包而非调用网关；传 \"latest\" 获取最新").option("--export", "写入可共享的诊断导出文件", false).option("--output <path>", "诊断导出的 .zip 路径").action(async (opts, command) => {
		await runGatewayCommand(async () => {
			const rpcOpts = resolveGatewayRpcOptions(opts, command);
			const query = normalizeDiagnosticStabilityQuery({
				limit: opts.limit,
				sinceSeq: opts.sinceSeq,
				type: opts.type
			}, { defaultLimit: 25 });
			const bundleTarget = normalizeStabilityBundleTarget(opts.bundle);
			if (opts.export) {
				await writeSupportExportFromCli({
					json: rpcOpts.json,
					output: opts.output,
					stabilityBundle: bundleTarget ?? "latest",
					rpc: rpcOpts
				});
				return;
			}
			if (bundleTarget) {
				const result = await readStabilityBundleTarget(bundleTarget);
				if (result.status !== "found") throw new Error(formatBundleError(result));
				const snapshot = selectDiagnosticStabilitySnapshot(result.bundle.snapshot, query);
				if (rpcOpts.json) {
					defaultRuntime.writeJson({
						path: result.path,
						mtimeMs: result.mtimeMs,
						bundle: {
							...result.bundle,
							snapshot
						}
					});
					return;
				}
				const rich = isRich();
				for (const line of renderStabilityBundleSummary({
					bundle: result.bundle,
					path: result.path,
					rich,
					snapshot
				})) defaultRuntime.log(line);
				return;
			}
			const result = await callGatewayCli("diagnostics.stability", rpcOpts, {
				limit: query.limit,
				...query.type ? { type: query.type } : {},
				...query.sinceSeq !== void 0 ? { sinceSeq: query.sinceSeq } : {}
			});
			if (rpcOpts.json) {
				defaultRuntime.writeJson(result);
				return;
			}
			const rich = isRich();
			for (const line of renderStabilitySummary(result, rich)) defaultRuntime.log(line);
		}, "Gateway stability failed");
	}));
	gateway.command("diagnostics").description("Export local support diagnostics").command("export").description("Write a shareable, payload-free diagnostics .zip").option("--output <path>", "Output .zip path").option("--log-lines <count>", "Maximum sanitized log lines to include", "5000").option("--log-bytes <bytes>", "Maximum log bytes to inspect", "1000000").option("--url <url>", "Gateway WebSocket URL for health snapshot").option("--token <token>", "Gateway token for health snapshot").option("--password <password>", "Gateway password for health snapshot").option("--timeout <ms>", "Status/health snapshot timeout in ms", "3000").option("--no-stability-bundle", "Skip persisted stability bundle lookup").option("--json", "Output JSON", false).action(async (opts, command) => {
		await runGatewayCommand(async () => {
			const rpcOpts = resolveGatewayRpcOptions(opts, command);
			await writeSupportExportFromCli({
				json: opts.json,
				output: opts.output,
				logLines: opts.logLines,
				logBytes: opts.logBytes,
				stabilityBundle: opts.stabilityBundle === false ? false : "latest",
				rpc: rpcOpts
			});
		}, "Gateway diagnostics export failed");
	});
	gateway.command("probe").description("显示网关可达性、认证能力和读探测摘要（本地 + 远程）").option("--url <url>", "显式网关 WebSocket URL（仍会探测 localhost）").option("--ssh <target>", "远程网关隧道的 SSH 目标（user@host 或 user@host:port）").option("--ssh-identity <path>", "SSH 身份文件路径").option("--ssh-auto", "尝试从 Bonjour 发现中推导 SSH 目标", false).option("--token <token>", "网关令牌（适用于所有探测）").option("--password <password>", "网关密码（适用于所有探测）").option("--timeout <ms>", "整体探测预算（毫秒）", "3000").option("--json", "Output JSON", false).action(async (opts, command) => {
		await runGatewayCommand(async () => {
			const rpcOpts = resolveGatewayRpcOptions(opts, command);
			const { gatewayStatusCommand } = await loadGatewayStatusModule();
			await gatewayStatusCommand(rpcOpts, defaultRuntime);
		});
	});
	gateway.command("discover").description("通过 Bonjour 发现网关（本地 + 已配置时的广域）").option("--timeout <ms>", "每个命令的超时（毫秒）", "2000").option("--json", "Output JSON", false).action(async (opts) => {
		await runGatewayCommand(async () => {
			const [{ readSourceConfigBestEffort }, { discoverGatewayBeacons }, { resolveWideAreaDiscoveryDomain }] = await Promise.all([
				loadConfigModule(),
				loadBonjourDiscoveryModule(),
				loadWideAreaDnsModule()
			]);
			const wideAreaDomain = resolveWideAreaDiscoveryDomain({ configDomain: (await readSourceConfigBestEffort()).discovery?.wideArea?.domain });
			const timeoutMs = parseDiscoverTimeoutMs(opts.timeout, 2e3);
			const domains = ["local.", ...wideAreaDomain ? [wideAreaDomain] : []];
			const deduped = dedupeBeacons(await withProgress({
				label: "Scanning for gateways…",
				indeterminate: true,
				enabled: opts.json !== true,
				delayMs: 0
			}, async () => await discoverGatewayBeacons({
				timeoutMs,
				wideAreaDomain
			}))).toSorted((a, b) => (a.displayName || a.instanceName).localeCompare(b.displayName || b.instanceName));
			if (opts.json) {
				const enriched = deduped.map((b) => {
					const host = pickBeaconHost(b);
					const port = pickGatewayPort(b);
					return {
						...b,
						wsUrl: host ? `ws://${host}:${port}` : null
					};
				});
				defaultRuntime.writeJson({
					timeoutMs,
					domains,
					count: enriched.length,
					beacons: enriched
				});
				return;
			}
			const rich = isRich();
			defaultRuntime.log(colorize(rich, theme.heading, "Gateway Discovery"));
			defaultRuntime.log(colorize(rich, theme.muted, `Found ${deduped.length} gateway(s) · domains: ${domains.join(", ")}`));
			if (deduped.length === 0) return;
			for (const beacon of deduped) for (const line of renderBeaconLines(beacon, rich)) defaultRuntime.log(line);
		}, "gateway discover failed");
	});
}
//#endregion
export { registerGatewayCli };
