import { t as CONFIG_PATH, u as resolveGatewayPort } from "./paths-mmi2xb99.js";
import { g as shortenHomePath, m as resolveUserPath } from "./utils-3Lue6wVm.js";
import { c as defaultRuntime } from "./subsystem-_lp1q2Mi.js";
import { a as readConfigFileSnapshot, r as loadConfig, s as writeConfigFile } from "./config-VoJVjSgT.js";
import { ot as ensureAuthProfileStore } from "./model-selection-CMHF17-l.js";
import { t as formatCliCommand } from "./command-format-D8drL8c2.js";
import { n as listChannelPlugins, t as getChannelPlugin } from "./plugins-B3jBOs5H.js";
import { n as withProgress } from "./progress-DIssriZ5.js";
import { a as guardCancel, c as normalizeGatewayTokenInput, d as probeGatewayReachable, f as randomToken, g as waitForGatewayReachable, h as summarizeExistingConfig, i as ensureWorkspaceAndSessions, n as applyWizardMetadata, p as resolveControlUiLinks, t as DEFAULT_WORKSPACE, u as printWizardHeader, v as logConfigUpdated } from "./onboard-helpers-CSsQgmZN.js";
import { i as stylePromptTitle, n as stylePromptHint, r as stylePromptMessage, t as note$1 } from "./note-B0WhCXlw.js";
import { t as WizardCancelledError } from "./prompts-Dg8uUwNx.js";
import { t as createClackPrompter } from "./clack-prompter-CwHL0EGc.js";
import { a as applyModelAllowlist, c as promptDefaultModel, f as applyAuthChoice, l as promptModelAllowlist, m as promptAuthChoiceGrouped, o as applyModelFallbacksFromSelection, r as promptRemoteGatewayConfig, s as applyPrimaryModel, t as setupSkills, u as resolvePreferredProviderForAuthChoice } from "./onboard-skills-CoK0dkQn.js";
import { n as setupChannels, t as noteChannelStatus } from "./onboard-channels-Del21pjv.js";
import { i as healthCommand, t as formatHealthCheckFailure } from "./health-format-C1q5vlEI.js";
import { a as findTailscaleBinary } from "./tailscale-9brshfui.js";
import { t as resolveGatewayService } from "./service-BssQxmRt.js";
import { a as gatewayInstallErrorHint, i as buildGatewayInstallPlan, n as GATEWAY_DAEMON_RUNTIME_OPTIONS, t as DEFAULT_GATEWAY_DAEMON_RUNTIME } from "./daemon-runtime-CEk_30Dc.js";
import { t as ensureSystemdUserLingerInteractive } from "./systemd-linger-B_hlqS-Z.js";
import { confirm, intro, outro, select, text } from "@clack/prompts";

//#region ../../src/commands/configure.shared.ts
const CONFIGURE_WIZARD_SECTIONS = [
	"workspace",
	"model",
	"web",
	"gateway",
	"daemon",
	"channels",
	"skills",
	"health"
];
const CONFIGURE_SECTION_OPTIONS = [
	{
		value: "workspace",
		label: "Workspace",
		hint: "Set workspace + sessions"
	},
	{
		value: "model",
		label: "Model",
		hint: "Pick provider + credentials"
	},
	{
		value: "web",
		label: "Web tools",
		hint: "Configure Brave search + fetch"
	},
	{
		value: "gateway",
		label: "Gateway",
		hint: "Port, bind, auth, tailscale"
	},
	{
		value: "daemon",
		label: "Daemon",
		hint: "Install/manage the background service"
	},
	{
		value: "channels",
		label: "Channels",
		hint: "Link WhatsApp/Telegram/etc and defaults"
	},
	{
		value: "skills",
		label: "Skills",
		hint: "Install/enable workspace skills"
	},
	{
		value: "health",
		label: "Health check",
		hint: "Run gateway + channel checks"
	}
];
const intro$1 = (message) => intro(stylePromptTitle(message) ?? message);
const outro$1 = (message) => outro(stylePromptTitle(message) ?? message);
const text$1 = (params) => text({
	...params,
	message: stylePromptMessage(params.message)
});
const confirm$1 = (params) => confirm({
	...params,
	message: stylePromptMessage(params.message)
});
const select$1 = (params) => select({
	...params,
	message: stylePromptMessage(params.message),
	options: params.options.map((opt) => opt.hint === void 0 ? opt : {
		...opt,
		hint: stylePromptHint(opt.hint)
	})
});

//#endregion
//#region ../../src/commands/configure.channels.ts
async function removeChannelConfigWizard(cfg, runtime) {
	let next = { ...cfg };
	const listConfiguredChannels = () => listChannelPlugins().map((plugin) => plugin.meta).filter((meta) => next.channels?.[meta.id] !== void 0);
	while (true) {
		const configured = listConfiguredChannels();
		if (configured.length === 0) {
			note$1(["No channel config found in edwinpai.json.", `Tip: \`${formatCliCommand("edwinpai channels status")}\` shows what is configured and enabled.`].join("\n"), "Remove channel");
			return next;
		}
		const channel = guardCancel(await select$1({
			message: "Remove which channel config?",
			options: [...configured.map((meta) => ({
				value: meta.id,
				label: meta.label,
				hint: "Deletes tokens + settings from config (credentials stay on disk)"
			})), {
				value: "done",
				label: "Done"
			}]
		}), runtime);
		if (channel === "done") return next;
		const label = getChannelPlugin(channel)?.meta.label ?? channel;
		if (!guardCancel(await confirm$1({
			message: `Delete ${label} configuration from ${shortenHomePath(CONFIG_PATH)}?`,
			initialValue: false
		}), runtime)) continue;
		const nextChannels = { ...next.channels };
		delete nextChannels[channel];
		next = {
			...next,
			channels: Object.keys(nextChannels).length ? nextChannels : void 0
		};
		note$1([`${label} removed from config.`, "Note: credentials/sessions on disk are unchanged."].join("\n"), "Channel removed");
	}
}

//#endregion
//#region ../../src/commands/configure.daemon.ts
async function maybeInstallDaemon(params) {
	const service = resolveGatewayService();
	const loaded = await service.isLoaded({ env: process.env });
	let shouldCheckLinger = false;
	let shouldInstall = true;
	let daemonRuntime = params.daemonRuntime ?? DEFAULT_GATEWAY_DAEMON_RUNTIME;
	if (loaded) {
		const action = guardCancel(await select$1({
			message: "Gateway service already installed",
			options: [
				{
					value: "restart",
					label: "Restart"
				},
				{
					value: "reinstall",
					label: "Reinstall"
				},
				{
					value: "skip",
					label: "Skip"
				}
			]
		}), params.runtime);
		if (action === "restart") {
			await withProgress({
				label: "Gateway service",
				indeterminate: true,
				delayMs: 0
			}, async (progress) => {
				progress.setLabel("Restarting Gateway service…");
				await service.restart({
					env: process.env,
					stdout: process.stdout
				});
				progress.setLabel("Gateway service restarted.");
			});
			shouldCheckLinger = true;
			shouldInstall = false;
		}
		if (action === "skip") return;
		if (action === "reinstall") await withProgress({
			label: "Gateway service",
			indeterminate: true,
			delayMs: 0
		}, async (progress) => {
			progress.setLabel("Uninstalling Gateway service…");
			await service.uninstall({
				env: process.env,
				stdout: process.stdout
			});
			progress.setLabel("Gateway service uninstalled.");
		});
	}
	if (shouldInstall) {
		let installError = null;
		if (!params.daemonRuntime) if (GATEWAY_DAEMON_RUNTIME_OPTIONS.length === 1) daemonRuntime = GATEWAY_DAEMON_RUNTIME_OPTIONS[0]?.value ?? DEFAULT_GATEWAY_DAEMON_RUNTIME;
		else daemonRuntime = guardCancel(await select$1({
			message: "Gateway service runtime",
			options: GATEWAY_DAEMON_RUNTIME_OPTIONS,
			initialValue: DEFAULT_GATEWAY_DAEMON_RUNTIME
		}), params.runtime);
		await withProgress({
			label: "Gateway service",
			indeterminate: true,
			delayMs: 0
		}, async (progress) => {
			progress.setLabel("Preparing Gateway service…");
			const cfg = loadConfig();
			const { programArguments, workingDirectory, environment } = await buildGatewayInstallPlan({
				env: process.env,
				port: params.port,
				token: params.gatewayToken,
				runtime: daemonRuntime,
				warn: (message, title) => note$1(message, title),
				config: cfg
			});
			progress.setLabel("Installing Gateway service…");
			try {
				await service.install({
					env: process.env,
					stdout: process.stdout,
					programArguments,
					workingDirectory,
					environment
				});
				progress.setLabel("Gateway service installed.");
			} catch (err) {
				installError = err instanceof Error ? err.message : String(err);
				progress.setLabel("Gateway service install failed.");
			}
		});
		if (installError) {
			note$1("Gateway service install failed: " + installError, "Gateway");
			note$1(gatewayInstallErrorHint(), "Gateway");
			return;
		}
		shouldCheckLinger = true;
	}
	if (shouldCheckLinger) await ensureSystemdUserLingerInteractive({
		runtime: params.runtime,
		prompter: {
			confirm: async (p) => guardCancel(await confirm$1(p), params.runtime),
			note: note$1
		},
		reason: "Linux installs use a systemd user service. Without lingering, systemd stops the user session on logout/idle and kills the Gateway.",
		requireConfirm: true
	});
}

//#endregion
//#region ../../src/commands/configure.gateway-auth.ts
const ANTHROPIC_OAUTH_MODEL_KEYS = [
	"anthropic/claude-opus-4-5",
	"anthropic/claude-sonnet-4-5",
	"anthropic/claude-haiku-4-5"
];
function buildGatewayAuthConfig(params) {
	const allowTailscale = params.existing?.allowTailscale;
	const base = {};
	if (typeof allowTailscale === "boolean") base.allowTailscale = allowTailscale;
	if (params.mode === "token") return {
		...base,
		mode: "token",
		token: params.token
	};
	return {
		...base,
		mode: "password",
		password: params.password
	};
}
async function promptAuthConfig(cfg, runtime, prompter) {
	const authChoice = await promptAuthChoiceGrouped({
		prompter,
		store: ensureAuthProfileStore(void 0, { allowKeychainPrompt: false }),
		includeSkip: true
	});
	let next = cfg;
	if (authChoice !== "skip") next = (await applyAuthChoice({
		authChoice,
		config: next,
		prompter,
		runtime,
		setDefaultModel: true
	})).config;
	else {
		const modelSelection = await promptDefaultModel({
			config: next,
			prompter,
			allowKeep: true,
			ignoreAllowlist: true,
			preferredProvider: resolvePreferredProviderForAuthChoice(authChoice)
		});
		if (modelSelection.model) next = applyPrimaryModel(next, modelSelection.model);
	}
	const anthropicOAuth = authChoice === "setup-token" || authChoice === "token" || authChoice === "oauth";
	const allowlistSelection = await promptModelAllowlist({
		config: next,
		prompter,
		allowedKeys: anthropicOAuth ? ANTHROPIC_OAUTH_MODEL_KEYS : void 0,
		initialSelections: anthropicOAuth ? ["anthropic/claude-opus-4-5"] : void 0,
		message: anthropicOAuth ? "Anthropic OAuth models" : void 0
	});
	if (allowlistSelection.models) {
		next = applyModelAllowlist(next, allowlistSelection.models);
		next = applyModelFallbacksFromSelection(next, allowlistSelection.models);
	}
	return next;
}

//#endregion
//#region ../../src/commands/configure.gateway.ts
async function promptGatewayConfig(cfg, runtime) {
	const portRaw = guardCancel(await text$1({
		message: "Gateway port",
		initialValue: String(resolveGatewayPort(cfg)),
		validate: (value) => Number.isFinite(Number(value)) ? void 0 : "Invalid port"
	}), runtime);
	const port = Number.parseInt(String(portRaw), 10);
	let bind = guardCancel(await select$1({
		message: "Gateway bind mode",
		options: [
			{
				value: "loopback",
				label: "Loopback (Local only)",
				hint: "Bind to 127.0.0.1 - secure, local-only access"
			},
			{
				value: "tailnet",
				label: "Tailnet (Tailscale IP)",
				hint: "Bind to your Tailscale IP only (100.x.x.x)"
			},
			{
				value: "auto",
				label: "Auto (Loopback → LAN)",
				hint: "Prefer loopback; fall back to all interfaces if unavailable"
			},
			{
				value: "lan",
				label: "LAN (All interfaces)",
				hint: "Bind to 0.0.0.0 - accessible from anywhere on your network"
			},
			{
				value: "custom",
				label: "Custom IP",
				hint: "Specify a specific IP address, with 0.0.0.0 fallback if unavailable"
			}
		]
	}), runtime);
	let customBindHost;
	if (bind === "custom") {
		const input = guardCancel(await text$1({
			message: "Custom IP address",
			placeholder: "192.168.1.100",
			validate: (value) => {
				if (!value) return "IP address is required for custom bind mode";
				const parts = value.trim().split(".");
				if (parts.length !== 4) return "Invalid IPv4 address (e.g., 192.168.1.100)";
				if (parts.every((part) => {
					const n = parseInt(part, 10);
					return !Number.isNaN(n) && n >= 0 && n <= 255 && part === String(n);
				})) return;
				return "Invalid IPv4 address (each octet must be 0-255)";
			}
		}), runtime);
		customBindHost = typeof input === "string" ? input : void 0;
	}
	let authMode = guardCancel(await select$1({
		message: "Gateway auth",
		options: [{
			value: "token",
			label: "Token",
			hint: "Recommended default"
		}, {
			value: "password",
			label: "Password"
		}],
		initialValue: "token"
	}), runtime);
	const tailscaleMode = guardCancel(await select$1({
		message: "Tailscale exposure",
		options: [
			{
				value: "off",
				label: "Off",
				hint: "No Tailscale exposure"
			},
			{
				value: "serve",
				label: "Serve",
				hint: "Private HTTPS for your tailnet (devices on Tailscale)"
			},
			{
				value: "funnel",
				label: "Funnel",
				hint: "Public HTTPS via Tailscale Funnel (internet)"
			}
		]
	}), runtime);
	if (tailscaleMode !== "off") {
		if (!await findTailscaleBinary()) note$1([
			"Tailscale binary not found in PATH or /Applications.",
			"Ensure Tailscale is installed from:",
			"  https://tailscale.com/download/mac",
			"",
			"You can continue setup, but serve/funnel will fail at runtime."
		].join("\n"), "Tailscale Warning");
	}
	let tailscaleResetOnExit = false;
	if (tailscaleMode !== "off") {
		note$1([
			"Docs:",
			"https://docs.edwinpai.com/gateway/tailscale",
			"https://docs.edwinpai.com/web"
		].join("\n"), "Tailscale");
		tailscaleResetOnExit = Boolean(guardCancel(await confirm$1({
			message: "Reset Tailscale serve/funnel on exit?",
			initialValue: false
		}), runtime));
	}
	if (tailscaleMode !== "off" && bind !== "loopback") {
		note$1("Tailscale requires bind=loopback. Adjusting bind to loopback.", "Note");
		bind = "loopback";
	}
	if (tailscaleMode === "funnel" && authMode !== "password") {
		note$1("Tailscale funnel requires password auth.", "Note");
		authMode = "password";
	}
	let gatewayToken;
	let gatewayPassword;
	let next = cfg;
	if (authMode === "token") gatewayToken = normalizeGatewayTokenInput(guardCancel(await text$1({
		message: "Gateway token (blank to generate)",
		initialValue: randomToken()
	}), runtime)) || randomToken();
	if (authMode === "password") {
		const password = guardCancel(await text$1({
			message: "Gateway password",
			validate: (value) => value?.trim() ? void 0 : "Required"
		}), runtime);
		gatewayPassword = String(password).trim();
	}
	const authConfig = buildGatewayAuthConfig({
		existing: next.gateway?.auth,
		mode: authMode,
		token: gatewayToken,
		password: gatewayPassword
	});
	next = {
		...next,
		gateway: {
			...next.gateway,
			mode: "local",
			port,
			bind,
			auth: authConfig,
			...customBindHost && { customBindHost },
			tailscale: {
				...next.gateway?.tailscale,
				mode: tailscaleMode,
				resetOnExit: tailscaleResetOnExit
			}
		}
	};
	return {
		config: next,
		port,
		token: gatewayToken
	};
}

//#endregion
//#region ../../src/commands/configure.wizard.ts
async function promptConfigureSection(runtime, hasSelection) {
	return guardCancel(await select$1({
		message: "Select sections to configure",
		options: [...CONFIGURE_SECTION_OPTIONS, {
			value: "__continue",
			label: "Continue",
			hint: hasSelection ? "Done" : "Skip for now"
		}],
		initialValue: CONFIGURE_SECTION_OPTIONS[0]?.value
	}), runtime);
}
async function promptChannelMode(runtime) {
	return guardCancel(await select$1({
		message: "Channels",
		options: [{
			value: "configure",
			label: "Configure/link",
			hint: "Add/update channels; disable unselected accounts"
		}, {
			value: "remove",
			label: "Remove channel config",
			hint: "Delete channel tokens/settings from edwinpai.json"
		}],
		initialValue: "configure"
	}), runtime);
}
async function promptWebToolsConfig(nextConfig, runtime) {
	const existingSearch = nextConfig.tools?.web?.search;
	const existingFetch = nextConfig.tools?.web?.fetch;
	const hasSearchKey = Boolean(existingSearch?.apiKey);
	note$1([
		"Web search lets your agent look things up online using the `web_search` tool.",
		"It requires a Brave Search API key (you can store it in the config or set BRAVE_API_KEY in the Gateway environment).",
		"Docs: https://docs.edwinpai.com/tools/web"
	].join("\n"), "Web search");
	const enableSearch = guardCancel(await confirm$1({
		message: "Enable web_search (Brave Search)?",
		initialValue: existingSearch?.enabled ?? hasSearchKey
	}), runtime);
	let nextSearch = {
		...existingSearch,
		enabled: enableSearch
	};
	if (enableSearch) {
		const keyInput = guardCancel(await text$1({
			message: hasSearchKey ? "Brave Search API key (leave blank to keep current or use BRAVE_API_KEY)" : "Brave Search API key (paste it here; leave blank to use BRAVE_API_KEY)",
			placeholder: hasSearchKey ? "Leave blank to keep current" : "BSA..."
		}), runtime);
		const key = String(keyInput ?? "").trim();
		if (key) nextSearch = {
			...nextSearch,
			apiKey: key
		};
		else if (!hasSearchKey) note$1([
			"No key stored yet, so web_search will stay unavailable.",
			"Store a key here or set BRAVE_API_KEY in the Gateway environment.",
			"Docs: https://docs.edwinpai.com/tools/web"
		].join("\n"), "Web search");
	}
	const enableFetch = guardCancel(await confirm$1({
		message: "Enable web_fetch (keyless HTTP fetch)?",
		initialValue: existingFetch?.enabled ?? true
	}), runtime);
	const nextFetch = {
		...existingFetch,
		enabled: enableFetch
	};
	return {
		...nextConfig,
		tools: {
			...nextConfig.tools,
			web: {
				...nextConfig.tools?.web,
				search: nextSearch,
				fetch: nextFetch
			}
		}
	};
}
async function runConfigureWizard(opts, runtime = defaultRuntime) {
	try {
		printWizardHeader(runtime);
		intro$1(opts.command === "update" ? "EdwinPAI update wizard" : "EdwinPAI configure");
		const prompter = createClackPrompter();
		const snapshot = await readConfigFileSnapshot();
		const baseConfig = snapshot.valid ? snapshot.config : {};
		if (snapshot.exists) {
			const title = snapshot.valid ? "Existing config detected" : "Invalid config";
			note$1(summarizeExistingConfig(baseConfig), title);
			if (!snapshot.valid && snapshot.issues.length > 0) note$1([
				...snapshot.issues.map((iss) => `- ${iss.path}: ${iss.message}`),
				"",
				"Docs: https://docs.edwinpai.com/gateway/configuration"
			].join("\n"), "Config issues");
			if (!snapshot.valid) {
				outro$1(`Config invalid. Run \`${formatCliCommand("edwinpai doctor")}\` to repair it, then re-run configure.`);
				runtime.exit(1);
				return;
			}
		}
		const localUrl = "ws://127.0.0.1:18789";
		const localProbe = await probeGatewayReachable({
			url: localUrl,
			token: baseConfig.gateway?.auth?.token ?? process.env.EDWINPAI_GATEWAY_TOKEN,
			password: baseConfig.gateway?.auth?.password ?? process.env.EDWINPAI_GATEWAY_PASSWORD
		});
		const remoteUrl = baseConfig.gateway?.remote?.url?.trim() ?? "";
		const remoteProbe = remoteUrl ? await probeGatewayReachable({
			url: remoteUrl,
			token: baseConfig.gateway?.remote?.token
		}) : null;
		const mode = guardCancel(await select$1({
			message: "Where will the Gateway run?",
			options: [{
				value: "local",
				label: "Local (this machine)",
				hint: localProbe.ok ? `Gateway reachable (${localUrl})` : `No gateway detected (${localUrl})`
			}, {
				value: "remote",
				label: "Remote (info-only)",
				hint: !remoteUrl ? "No remote URL configured yet" : remoteProbe?.ok ? `Gateway reachable (${remoteUrl})` : `Configured but unreachable (${remoteUrl})`
			}]
		}), runtime);
		if (mode === "remote") {
			let remoteConfig = await promptRemoteGatewayConfig(baseConfig, prompter);
			remoteConfig = applyWizardMetadata(remoteConfig, {
				command: opts.command,
				mode
			});
			await writeConfigFile(remoteConfig);
			logConfigUpdated(runtime);
			outro$1("Remote gateway configured.");
			return;
		}
		let nextConfig = { ...baseConfig };
		let didSetGatewayMode = false;
		if (nextConfig.gateway?.mode !== "local") {
			nextConfig = {
				...nextConfig,
				gateway: {
					...nextConfig.gateway,
					mode: "local"
				}
			};
			didSetGatewayMode = true;
		}
		let workspaceDir = nextConfig.agents?.defaults?.workspace ?? baseConfig.agents?.defaults?.workspace ?? DEFAULT_WORKSPACE;
		let gatewayPort = resolveGatewayPort(baseConfig);
		let gatewayToken = nextConfig.gateway?.auth?.token ?? baseConfig.gateway?.auth?.token ?? process.env.EDWINPAI_GATEWAY_TOKEN;
		const persistConfig = async () => {
			nextConfig = applyWizardMetadata(nextConfig, {
				command: opts.command,
				mode
			});
			await writeConfigFile(nextConfig);
			logConfigUpdated(runtime);
		};
		if (opts.sections) {
			const selected = opts.sections;
			if (!selected || selected.length === 0) {
				outro$1("No changes selected.");
				return;
			}
			if (selected.includes("workspace")) {
				const workspaceInput = guardCancel(await text$1({
					message: "Workspace directory",
					initialValue: workspaceDir
				}), runtime);
				workspaceDir = resolveUserPath(String(workspaceInput ?? "").trim() || DEFAULT_WORKSPACE);
				nextConfig = {
					...nextConfig,
					agents: {
						...nextConfig.agents,
						defaults: {
							...nextConfig.agents?.defaults,
							workspace: workspaceDir
						}
					}
				};
				await ensureWorkspaceAndSessions(workspaceDir, runtime);
			}
			if (selected.includes("model")) nextConfig = await promptAuthConfig(nextConfig, runtime, prompter);
			if (selected.includes("web")) nextConfig = await promptWebToolsConfig(nextConfig, runtime);
			if (selected.includes("gateway")) {
				const gateway = await promptGatewayConfig(nextConfig, runtime);
				nextConfig = gateway.config;
				gatewayPort = gateway.port;
				gatewayToken = gateway.token;
			}
			if (selected.includes("channels")) {
				await noteChannelStatus({
					cfg: nextConfig,
					prompter
				});
				if (await promptChannelMode(runtime) === "configure") nextConfig = await setupChannels(nextConfig, runtime, prompter, {
					allowDisable: true,
					allowSignalInstall: true,
					skipConfirm: true,
					skipStatusNote: true
				});
				else nextConfig = await removeChannelConfigWizard(nextConfig, runtime);
			}
			if (selected.includes("skills")) {
				const wsDir = resolveUserPath(workspaceDir);
				nextConfig = await setupSkills(nextConfig, wsDir, runtime, prompter);
			}
			await persistConfig();
			if (selected.includes("daemon")) {
				if (!selected.includes("gateway")) {
					const portInput = guardCancel(await text$1({
						message: "Gateway port for service install",
						initialValue: String(gatewayPort),
						validate: (value) => Number.isFinite(Number(value)) ? void 0 : "Invalid port"
					}), runtime);
					gatewayPort = Number.parseInt(String(portInput), 10);
				}
				await maybeInstallDaemon({
					runtime,
					port: gatewayPort,
					gatewayToken
				});
			}
			if (selected.includes("health")) {
				const localLinks = resolveControlUiLinks({
					bind: nextConfig.gateway?.bind ?? "loopback",
					port: gatewayPort,
					customBindHost: nextConfig.gateway?.customBindHost,
					basePath: void 0
				});
				const remoteUrl = nextConfig.gateway?.remote?.url?.trim();
				await waitForGatewayReachable({
					url: nextConfig.gateway?.mode === "remote" && remoteUrl ? remoteUrl : localLinks.wsUrl,
					token: nextConfig.gateway?.auth?.token ?? process.env.EDWINPAI_GATEWAY_TOKEN,
					password: nextConfig.gateway?.auth?.password ?? process.env.EDWINPAI_GATEWAY_PASSWORD,
					deadlineMs: 15e3
				});
				try {
					await healthCommand({
						json: false,
						timeoutMs: 1e4
					}, runtime);
				} catch (err) {
					runtime.error(formatHealthCheckFailure(err));
					note$1([
						"Docs:",
						"https://docs.edwinpai.com/gateway/health",
						"https://docs.edwinpai.com/gateway/troubleshooting"
					].join("\n"), "Health check help");
				}
			}
		} else {
			let ranSection = false;
			let didConfigureGateway = false;
			while (true) {
				const choice = await promptConfigureSection(runtime, ranSection);
				if (choice === "__continue") break;
				ranSection = true;
				if (choice === "workspace") {
					const workspaceInput = guardCancel(await text$1({
						message: "Workspace directory",
						initialValue: workspaceDir
					}), runtime);
					workspaceDir = resolveUserPath(String(workspaceInput ?? "").trim() || DEFAULT_WORKSPACE);
					nextConfig = {
						...nextConfig,
						agents: {
							...nextConfig.agents,
							defaults: {
								...nextConfig.agents?.defaults,
								workspace: workspaceDir
							}
						}
					};
					await ensureWorkspaceAndSessions(workspaceDir, runtime);
					await persistConfig();
				}
				if (choice === "model") {
					nextConfig = await promptAuthConfig(nextConfig, runtime, prompter);
					await persistConfig();
				}
				if (choice === "web") {
					nextConfig = await promptWebToolsConfig(nextConfig, runtime);
					await persistConfig();
				}
				if (choice === "gateway") {
					const gateway = await promptGatewayConfig(nextConfig, runtime);
					nextConfig = gateway.config;
					gatewayPort = gateway.port;
					gatewayToken = gateway.token;
					didConfigureGateway = true;
					await persistConfig();
				}
				if (choice === "channels") {
					await noteChannelStatus({
						cfg: nextConfig,
						prompter
					});
					if (await promptChannelMode(runtime) === "configure") nextConfig = await setupChannels(nextConfig, runtime, prompter, {
						allowDisable: true,
						allowSignalInstall: true,
						skipConfirm: true,
						skipStatusNote: true
					});
					else nextConfig = await removeChannelConfigWizard(nextConfig, runtime);
					await persistConfig();
				}
				if (choice === "skills") {
					const wsDir = resolveUserPath(workspaceDir);
					nextConfig = await setupSkills(nextConfig, wsDir, runtime, prompter);
					await persistConfig();
				}
				if (choice === "daemon") {
					if (!didConfigureGateway) {
						const portInput = guardCancel(await text$1({
							message: "Gateway port for service install",
							initialValue: String(gatewayPort),
							validate: (value) => Number.isFinite(Number(value)) ? void 0 : "Invalid port"
						}), runtime);
						gatewayPort = Number.parseInt(String(portInput), 10);
					}
					await maybeInstallDaemon({
						runtime,
						port: gatewayPort,
						gatewayToken
					});
				}
				if (choice === "health") {
					const localLinks = resolveControlUiLinks({
						bind: nextConfig.gateway?.bind ?? "loopback",
						port: gatewayPort,
						customBindHost: nextConfig.gateway?.customBindHost,
						basePath: void 0
					});
					const remoteUrl = nextConfig.gateway?.remote?.url?.trim();
					await waitForGatewayReachable({
						url: nextConfig.gateway?.mode === "remote" && remoteUrl ? remoteUrl : localLinks.wsUrl,
						token: nextConfig.gateway?.auth?.token ?? process.env.EDWINPAI_GATEWAY_TOKEN,
						password: nextConfig.gateway?.auth?.password ?? process.env.EDWINPAI_GATEWAY_PASSWORD,
						deadlineMs: 15e3
					});
					try {
						await healthCommand({
							json: false,
							timeoutMs: 1e4
						}, runtime);
					} catch (err) {
						runtime.error(formatHealthCheckFailure(err));
						note$1([
							"Docs:",
							"https://docs.edwinpai.com/gateway/health",
							"https://docs.edwinpai.com/gateway/troubleshooting"
						].join("\n"), "Health check help");
					}
				}
			}
			if (!ranSection) {
				if (didSetGatewayMode) {
					await persistConfig();
					outro$1("Gateway mode set to local.");
					return;
				}
				outro$1("No changes selected.");
				return;
			}
		}
		const links = resolveControlUiLinks({
			bind: nextConfig.gateway?.bind ?? "loopback",
			port: gatewayPort,
			customBindHost: nextConfig.gateway?.customBindHost,
			basePath: nextConfig.gateway?.controlUi?.basePath
		});
		const newPassword = nextConfig.gateway?.auth?.password ?? process.env.EDWINPAI_GATEWAY_PASSWORD;
		const oldPassword = baseConfig.gateway?.auth?.password ?? process.env.EDWINPAI_GATEWAY_PASSWORD;
		const token = nextConfig.gateway?.auth?.token ?? process.env.EDWINPAI_GATEWAY_TOKEN;
		let gatewayProbe = await probeGatewayReachable({
			url: links.wsUrl,
			token,
			password: newPassword
		});
		if (!gatewayProbe.ok && newPassword !== oldPassword && oldPassword) gatewayProbe = await probeGatewayReachable({
			url: links.wsUrl,
			token,
			password: oldPassword
		});
		const gatewayStatusLine = gatewayProbe.ok ? "Gateway: reachable" : `Gateway: not detected${gatewayProbe.detail ? ` (${gatewayProbe.detail})` : ""}`;
		note$1([
			"UI: Edwin Desktop app",
			`Gateway WS: ${links.wsUrl}`,
			gatewayStatusLine
		].join("\n"), "Desktop");
		outro$1("Configure complete.");
	} catch (err) {
		if (err instanceof WizardCancelledError) {
			runtime.exit(0);
			return;
		}
		throw err;
	}
}

//#endregion
//#region ../../src/commands/configure.commands.ts
async function configureCommand(runtime = defaultRuntime) {
	await runConfigureWizard({ command: "configure" }, runtime);
}
async function configureCommandWithSections(sections, runtime = defaultRuntime) {
	await runConfigureWizard({
		command: "configure",
		sections
	}, runtime);
}

//#endregion
export { CONFIGURE_WIZARD_SECTIONS as a, buildGatewayAuthConfig as i, configureCommandWithSections as n, runConfigureWizard as r, configureCommand as t };