import { m as resolveUserPath, o as ensureDir, t as CONFIG_DIR } from "./utils-DLd4fFd2.js";
import { t as resolveBrewExecutable } from "./brew-Ds23pxcL.js";
import { bt as loadModelCatalog } from "./loader-nlcizznp.js";
import { a as resolveAgentModelPrimary, c as resolveDefaultAgentId, r as resolveAgentDir, s as resolveAgentWorkspaceDir, w as resolveDefaultAgentWorkspaceDir } from "./agent-scope-BcV171ci.js";
import { t as runCommandWithTimeout } from "./exec-B_ziy0Fn.js";
import { A as getCustomProviderApiKey, E as SYNTHETIC_DEFAULT_MODEL_REF, P as resolveEnvApiKey, R as CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF, S as VENICE_DEFAULT_MODEL_REF, V as resolveAuthProfileOrder, Z as listProfilesForProvider, a as modelKey, et as upsertAuthProfile, ft as DEFAULT_MODEL, l as resolveConfiguredModelRef, n as buildModelAliasIndex, o as normalizeProviderId, pt as DEFAULT_PROVIDER, st as resolveEdwinPAIAgentDir, t as buildAllowedModelSet, tt as ensureAuthProfileStore } from "./model-selection-ChysOie6.js";
import { t as formatCliCommand } from "./command-format-XQlUKdf6.js";
import { G as fetchWithSsrFGuard } from "./deliver-Ce4muAXi.js";
import { _ as resolveSkillKey, d as hasBinary, i as loadWorkspaceSkillEntries, t as resolveSkillsInstallPreferences } from "./skills-B9WXNmn5.js";
import { l as openUrl, m as resolveNodeManagerOptions, r as detectBinary } from "./onboard-helpers-BArU1Ks-.js";
import { a as enablePluginInConfig } from "./onboard-channels-B_O2u1kZ.js";
import { $ as createVpsAwareOAuthHandlers, A as applyVercelAiGatewayProviderConfig, C as applyOpenrouterConfig, D as applyVeniceConfig, E as applySyntheticProviderConfig, F as MOONSHOT_DEFAULT_MODEL_REF, G as setMoonshotApiKey, H as setGeminiApiKey, I as OPENROUTER_DEFAULT_MODEL_REF, J as setSyntheticApiKey, K as setOpencodeZenApiKey, L as VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF, M as applyXiaomiProviderConfig, N as applyZaiConfig, O as applyVeniceProviderConfig, P as KIMI_CODING_MODEL_REF, Q as setZaiApiKey, R as XIAOMI_DEFAULT_MODEL_REF, S as applyMoonshotProviderConfigCn, T as applySyntheticConfig, U as setKimiCodingApiKey, V as setCloudflareAiGatewayConfig, W as setMinimaxApiKey, X as setVercelAiGatewayApiKey, Y as setVeniceApiKey, Z as setXiaomiApiKey, _ as applyKimiCodeConfig, b as applyMoonshotConfigCn, c as applyOpencodeZenConfig, d as applyMinimaxApiProviderConfig, et as isRemoteEnvironment, f as applyMinimaxConfig, g as applyCloudflareAiGatewayProviderConfig, h as applyCloudflareAiGatewayConfig, j as applyXiaomiConfig, k as applyVercelAiGatewayConfig, l as applyOpencodeZenProviderConfig, m as applyAuthProfileConfig, p as applyMinimaxProviderConfig, q as setOpenrouterApiKey, r as formatTokenK, tt as resolvePluginProviders, u as applyMinimaxApiConfig, v as applyKimiCodeProviderConfig, w as applyOpenrouterProviderConfig, x as applyMoonshotProviderConfig, y as applyMoonshotConfig, z as ZAI_DEFAULT_MODEL_REF } from "./shared-DsNlV7x3.js";
import { t as buildWorkspaceSkillStatus } from "./skills-status-CjdifZyI.js";
import { n as resolveWideAreaDiscoveryDomain } from "./widearea-dns-BvuXu7AL.js";
import fs from "node:fs";
import path from "node:path";
import { pipeline } from "node:stream/promises";
import { Readable } from "node:stream";

//#region ../../src/commands/auth-choice-options.ts
const AUTH_CHOICE_GROUP_DEFS = [
	{
		value: "openai",
		label: "OpenAI",
		hint: "Codex OAuth + API key",
		choices: ["openai-codex", "openai-api-key"]
	},
	{
		value: "anthropic",
		label: "Anthropic",
		hint: "setup-token + API key",
		choices: ["token", "apiKey"]
	},
	{
		value: "minimax",
		label: "MiniMax",
		hint: "M2.1 (recommended)",
		choices: [
			"minimax-portal",
			"minimax-api",
			"minimax-api-lightning"
		]
	},
	{
		value: "moonshot",
		label: "Moonshot AI (Kimi K2.5)",
		hint: "Kimi K2.5 + Kimi Coding",
		choices: [
			"moonshot-api-key",
			"moonshot-api-key-cn",
			"kimi-code-api-key"
		]
	},
	{
		value: "google",
		label: "Google",
		hint: "Gemini API key + OAuth",
		choices: [
			"gemini-api-key",
			"google-antigravity",
			"google-gemini-cli"
		]
	},
	{
		value: "openrouter",
		label: "OpenRouter",
		hint: "API key",
		choices: ["openrouter-api-key"]
	},
	{
		value: "qwen",
		label: "Qwen",
		hint: "OAuth",
		choices: ["qwen-portal"]
	},
	{
		value: "zai",
		label: "Z.AI (GLM 4.7)",
		hint: "API key",
		choices: ["zai-api-key"]
	},
	{
		value: "copilot",
		label: "Copilot",
		hint: "GitHub + local proxy",
		choices: ["github-copilot", "copilot-proxy"]
	},
	{
		value: "ai-gateway",
		label: "Vercel AI Gateway",
		hint: "API key",
		choices: ["ai-gateway-api-key"]
	},
	{
		value: "opencode-zen",
		label: "OpenCode Zen",
		hint: "API key",
		choices: ["opencode-zen"]
	},
	{
		value: "xiaomi",
		label: "Xiaomi",
		hint: "API key",
		choices: ["xiaomi-api-key"]
	},
	{
		value: "synthetic",
		label: "Synthetic",
		hint: "Anthropic-compatible (multi-model)",
		choices: ["synthetic-api-key"]
	},
	{
		value: "venice",
		label: "Venice AI",
		hint: "Privacy-focused (uncensored models)",
		choices: ["venice-api-key"]
	},
	{
		value: "cloudflare-ai-gateway",
		label: "Cloudflare AI Gateway",
		hint: "Account ID + Gateway ID + API key",
		choices: ["cloudflare-ai-gateway-api-key"]
	}
];
function buildAuthChoiceOptions(params) {
	params.store;
	const options = [];
	options.push({
		value: "token",
		label: "Anthropic token (paste setup-token)",
		hint: "run `claude setup-token` elsewhere, then paste the token here"
	});
	options.push({
		value: "openai-codex",
		label: "OpenAI Codex (ChatGPT OAuth)"
	});
	options.push({
		value: "chutes",
		label: "Chutes (OAuth)"
	});
	options.push({
		value: "openai-api-key",
		label: "OpenAI API key"
	});
	options.push({
		value: "openrouter-api-key",
		label: "OpenRouter API key"
	});
	options.push({
		value: "ai-gateway-api-key",
		label: "Vercel AI Gateway API key"
	});
	options.push({
		value: "cloudflare-ai-gateway-api-key",
		label: "Cloudflare AI Gateway",
		hint: "Account ID + Gateway ID + API key"
	});
	options.push({
		value: "moonshot-api-key",
		label: "Kimi API key (.ai)"
	});
	options.push({
		value: "moonshot-api-key-cn",
		label: "Kimi API key (.cn)"
	});
	options.push({
		value: "kimi-code-api-key",
		label: "Kimi Code API key (subscription)"
	});
	options.push({
		value: "synthetic-api-key",
		label: "Synthetic API key"
	});
	options.push({
		value: "venice-api-key",
		label: "Venice AI API key",
		hint: "Privacy-focused inference (uncensored models)"
	});
	options.push({
		value: "github-copilot",
		label: "GitHub Copilot (GitHub device login)",
		hint: "Uses GitHub device flow"
	});
	options.push({
		value: "gemini-api-key",
		label: "Google Gemini API key"
	});
	options.push({
		value: "google-antigravity",
		label: "Google Antigravity OAuth",
		hint: "Uses the bundled Antigravity auth plugin"
	});
	options.push({
		value: "google-gemini-cli",
		label: "Google Gemini CLI OAuth",
		hint: "Uses the bundled Gemini CLI auth plugin"
	});
	options.push({
		value: "zai-api-key",
		label: "Z.AI (GLM 4.7) API key"
	});
	options.push({
		value: "xiaomi-api-key",
		label: "Xiaomi API key"
	});
	options.push({
		value: "minimax-portal",
		label: "MiniMax OAuth",
		hint: "Oauth plugin for MiniMax"
	});
	options.push({
		value: "qwen-portal",
		label: "Qwen OAuth"
	});
	options.push({
		value: "copilot-proxy",
		label: "Copilot Proxy (local)",
		hint: "Local proxy for VS Code Copilot models"
	});
	options.push({
		value: "apiKey",
		label: "Anthropic API key"
	});
	options.push({
		value: "opencode-zen",
		label: "OpenCode Zen (multi-model proxy)",
		hint: "Claude, GPT, Gemini via opencode.ai/zen"
	});
	options.push({
		value: "minimax-api",
		label: "MiniMax M2.1"
	});
	options.push({
		value: "minimax-api-lightning",
		label: "MiniMax M2.1 Lightning",
		hint: "Faster, higher output cost"
	});
	if (params.includeSkip) options.push({
		value: "skip",
		label: "Skip for now"
	});
	return options;
}
function buildAuthChoiceGroups(params) {
	const options = buildAuthChoiceOptions({
		...params,
		includeSkip: false
	});
	const optionByValue = new Map(options.map((opt) => [opt.value, opt]));
	return {
		groups: AUTH_CHOICE_GROUP_DEFS.map((group) => ({
			...group,
			options: group.choices.map((choice) => optionByValue.get(choice)).filter((opt) => Boolean(opt))
		})),
		skipOption: params.includeSkip ? {
			value: "skip",
			label: "Skip for now"
		} : void 0
	};
}

//#endregion
//#region ../../src/commands/auth-choice-prompt.ts
const BACK_VALUE = "__back";
async function promptAuthChoiceGrouped(params) {
	const { groups, skipOption } = buildAuthChoiceGroups(params);
	const availableGroups = groups.filter((group) => group.options.length > 0);
	while (true) {
		const providerOptions = [...availableGroups.map((group) => ({
			value: group.value,
			label: group.label,
			hint: group.hint
		})), ...skipOption ? [skipOption] : []];
		const providerSelection = await params.prompter.select({
			message: "Model/auth provider",
			options: providerOptions
		});
		if (providerSelection === "skip") return "skip";
		const group = availableGroups.find((candidate) => candidate.value === providerSelection);
		if (!group || group.options.length === 0) {
			await params.prompter.note("No auth methods available for that provider.", "Model/auth choice");
			continue;
		}
		const methodSelection = await params.prompter.select({
			message: `${group.label} auth method`,
			options: [...group.options, {
				value: BACK_VALUE,
				label: "Back"
			}]
		});
		if (methodSelection === BACK_VALUE) continue;
		return methodSelection;
	}
}

//#endregion
//#region ../../src/commands/auth-choice.apply.plugin-provider.ts
function resolveProviderMatch(providers, rawProvider) {
	const normalized = normalizeProviderId(rawProvider);
	return providers.find((provider) => normalizeProviderId(provider.id) === normalized) ?? providers.find((provider) => provider.aliases?.some((alias) => normalizeProviderId(alias) === normalized) ?? false) ?? null;
}
function pickAuthMethod(provider, rawMethod) {
	const raw = rawMethod?.trim();
	if (!raw) return null;
	const normalized = raw.toLowerCase();
	return provider.auth.find((method) => method.id.toLowerCase() === normalized) ?? provider.auth.find((method) => method.label.toLowerCase() === normalized) ?? null;
}
function isPlainRecord(value) {
	return Boolean(value && typeof value === "object" && !Array.isArray(value));
}
function mergeConfigPatch(base, patch) {
	if (!isPlainRecord(base) || !isPlainRecord(patch)) return patch;
	const next = { ...base };
	for (const [key, value] of Object.entries(patch)) {
		const existing = next[key];
		if (isPlainRecord(existing) && isPlainRecord(value)) next[key] = mergeConfigPatch(existing, value);
		else next[key] = value;
	}
	return next;
}
function applyDefaultModel(cfg, model) {
	const models = { ...cfg.agents?.defaults?.models };
	models[model] = models[model] ?? {};
	const existingModel = cfg.agents?.defaults?.model;
	return {
		...cfg,
		agents: {
			...cfg.agents,
			defaults: {
				...cfg.agents?.defaults,
				models,
				model: {
					...existingModel && typeof existingModel === "object" && "fallbacks" in existingModel ? { fallbacks: existingModel.fallbacks } : void 0,
					primary: model
				}
			}
		}
	};
}
async function applyAuthChoicePluginProvider(params, options) {
	if (params.authChoice !== options.authChoice) return null;
	const enableResult = enablePluginInConfig(params.config, options.pluginId);
	let nextConfig = enableResult.config;
	if (!enableResult.enabled) {
		await params.prompter.note(`${options.label} plugin is disabled (${enableResult.reason ?? "blocked"}).`, options.label);
		return { config: nextConfig };
	}
	const agentId = params.agentId ?? resolveDefaultAgentId(nextConfig);
	const defaultAgentId = resolveDefaultAgentId(nextConfig);
	const agentDir = params.agentDir ?? (agentId === defaultAgentId ? resolveEdwinPAIAgentDir() : resolveAgentDir(nextConfig, agentId));
	const workspaceDir = resolveAgentWorkspaceDir(nextConfig, agentId) ?? resolveDefaultAgentWorkspaceDir();
	const provider = resolveProviderMatch(resolvePluginProviders({
		config: nextConfig,
		workspaceDir
	}), options.providerId);
	if (!provider) {
		await params.prompter.note(`${options.label} auth plugin is not available. Enable it and re-run the wizard.`, options.label);
		return { config: nextConfig };
	}
	const method = pickAuthMethod(provider, options.methodId) ?? provider.auth[0];
	if (!method) {
		await params.prompter.note(`${options.label} auth method missing.`, options.label);
		return { config: nextConfig };
	}
	const isRemote = isRemoteEnvironment();
	const result = await method.run({
		config: nextConfig,
		agentDir,
		workspaceDir,
		prompter: params.prompter,
		runtime: params.runtime,
		isRemote,
		setDefaultModel: params.setDefaultModel,
		openUrl: async (url) => {
			await openUrl(url);
		},
		oauth: { createVpsAwareHandlers: (opts) => createVpsAwareOAuthHandlers(opts) }
	});
	if (result.configPatch) nextConfig = mergeConfigPatch(nextConfig, result.configPatch);
	for (const profile of result.profiles) {
		upsertAuthProfile({
			profileId: profile.profileId,
			credential: profile.credential,
			agentDir
		});
		nextConfig = applyAuthProfileConfig(nextConfig, {
			profileId: profile.profileId,
			provider: profile.credential.provider,
			mode: profile.credential.type === "token" ? "token" : profile.credential.type,
			..."email" in profile.credential && profile.credential.email ? { email: profile.credential.email } : {}
		});
	}
	let agentModelOverride;
	if (result.defaultModel) {
		if (params.setDefaultModel) {
			nextConfig = applyDefaultModel(nextConfig, result.defaultModel);
			await params.prompter.note(`Default model set to ${result.defaultModel}`, "Model configured");
		} else if (params.agentId) {
			agentModelOverride = result.defaultModel;
			await params.prompter.note(`Default model set to ${result.defaultModel} for agent "${params.agentId}".`, "Model configured");
		}
	}
	if (result.notes && result.notes.length > 0) await params.prompter.note(result.notes.join("\n"), "Provider notes");
	return {
		config: nextConfig,
		agentModelOverride
	};
}

//#endregion
//#region ../../src/commands/auth-choice.apply.anthropic.ts
async function applyAuthChoiceAnthropic(params) {
	if (params.authChoice === "setup-token" || params.authChoice === "oauth" || params.authChoice === "token") return await applyAuthChoicePluginProvider(params, {
		authChoice: params.authChoice,
		pluginId: "provider-auth",
		providerId: "anthropic",
		methodId: "setup-token",
		label: "Anthropic"
	});
	if (params.authChoice === "apiKey" && (!params.opts?.tokenProvider || params.opts.tokenProvider === "anthropic")) return await applyAuthChoicePluginProvider(params, {
		authChoice: "apiKey",
		pluginId: "provider-auth",
		providerId: "anthropic",
		methodId: "api-key",
		label: "Anthropic"
	});
	return null;
}

//#endregion
//#region ../../src/commands/auth-choice.api-key.ts
const DEFAULT_KEY_PREVIEW = {
	head: 4,
	tail: 4
};
function normalizeApiKeyInput(raw) {
	const trimmed = String(raw ?? "").trim();
	if (!trimmed) return "";
	const assignmentMatch = trimmed.match(/^(?:export\s+)?[A-Za-z_][A-Za-z0-9_]*\s*=\s*(.+)$/);
	const valuePart = assignmentMatch ? assignmentMatch[1].trim() : trimmed;
	const unquoted = valuePart.length >= 2 && (valuePart.startsWith("\"") && valuePart.endsWith("\"") || valuePart.startsWith("'") && valuePart.endsWith("'") || valuePart.startsWith("`") && valuePart.endsWith("`")) ? valuePart.slice(1, -1) : valuePart;
	return (unquoted.endsWith(";") ? unquoted.slice(0, -1) : unquoted).trim();
}
const validateApiKeyInput = (value) => normalizeApiKeyInput(value).length > 0 ? void 0 : "Required";
function formatApiKeyPreview(raw, opts = {}) {
	const trimmed = raw.trim();
	if (!trimmed) return "…";
	const head = opts.head ?? DEFAULT_KEY_PREVIEW.head;
	const tail = opts.tail ?? DEFAULT_KEY_PREVIEW.tail;
	if (trimmed.length <= head + tail) {
		const shortHead = Math.min(2, trimmed.length);
		const shortTail = Math.min(2, trimmed.length - shortHead);
		if (shortTail <= 0) return `${trimmed.slice(0, shortHead)}…`;
		return `${trimmed.slice(0, shortHead)}…${trimmed.slice(-shortTail)}`;
	}
	return `${trimmed.slice(0, head)}…${trimmed.slice(-tail)}`;
}

//#endregion
//#region ../../src/commands/auth-choice.default-model.ts
async function applyDefaultModelChoice(params) {
	if (params.setDefaultModel) {
		const next = params.applyDefaultConfig(params.config);
		if (params.noteDefault) await params.prompter.note(`Default model set to ${params.noteDefault}`, "Model configured");
		return { config: next };
	}
	const next = params.applyProviderConfig(params.config);
	await params.noteAgentModel(params.defaultModel);
	return {
		config: next,
		agentModelOverride: params.defaultModel
	};
}

//#endregion
//#region ../../src/commands/google-gemini-model-default.ts
const GOOGLE_GEMINI_DEFAULT_MODEL = "google/gemini-3-pro-preview";
function resolvePrimaryModel(model) {
	if (typeof model === "string") return model;
	if (model && typeof model === "object" && typeof model.primary === "string") return model.primary;
}
function applyGoogleGeminiModelDefault(cfg) {
	if (resolvePrimaryModel(cfg.agents?.defaults?.model)?.trim() === GOOGLE_GEMINI_DEFAULT_MODEL) return {
		next: cfg,
		changed: false
	};
	return {
		next: {
			...cfg,
			agents: {
				...cfg.agents,
				defaults: {
					...cfg.agents?.defaults,
					model: cfg.agents?.defaults?.model && typeof cfg.agents.defaults.model === "object" ? {
						...cfg.agents.defaults.model,
						primary: GOOGLE_GEMINI_DEFAULT_MODEL
					} : { primary: GOOGLE_GEMINI_DEFAULT_MODEL }
				}
			}
		},
		changed: true
	};
}

//#endregion
//#region ../../src/commands/opencode-zen-model-default.ts
const OPENCODE_ZEN_DEFAULT_MODEL = "opencode/claude-opus-4-5";

//#endregion
//#region ../../src/commands/auth-choice.apply.api-providers.ts
async function applyAuthChoiceApiProviders(params) {
	let nextConfig = params.config;
	let agentModelOverride;
	const noteAgentModel = async (model) => {
		if (!params.agentId) return;
		await params.prompter.note(`Default model set to ${model} for agent "${params.agentId}".`, "Model configured");
	};
	let authChoice = params.authChoice;
	if (authChoice === "apiKey" && params.opts?.tokenProvider && params.opts.tokenProvider !== "anthropic" && params.opts.tokenProvider !== "openai") {
		if (params.opts.tokenProvider === "openrouter") authChoice = "openrouter-api-key";
		else if (params.opts.tokenProvider === "vercel-ai-gateway") authChoice = "ai-gateway-api-key";
		else if (params.opts.tokenProvider === "cloudflare-ai-gateway") authChoice = "cloudflare-ai-gateway-api-key";
		else if (params.opts.tokenProvider === "moonshot") authChoice = "moonshot-api-key";
		else if (params.opts.tokenProvider === "kimi-code" || params.opts.tokenProvider === "kimi-coding") authChoice = "kimi-code-api-key";
		else if (params.opts.tokenProvider === "google") authChoice = "gemini-api-key";
		else if (params.opts.tokenProvider === "zai") authChoice = "zai-api-key";
		else if (params.opts.tokenProvider === "xiaomi") authChoice = "xiaomi-api-key";
		else if (params.opts.tokenProvider === "synthetic") authChoice = "synthetic-api-key";
		else if (params.opts.tokenProvider === "venice") authChoice = "venice-api-key";
		else if (params.opts.tokenProvider === "opencode") authChoice = "opencode-zen";
	}
	const delegatedProvider = authChoice === "openrouter-api-key" ? {
		authChoice,
		pluginId: "provider-auth",
		providerId: "openrouter",
		methodId: "api-key",
		label: "OpenRouter"
	} : authChoice === "ai-gateway-api-key" ? {
		authChoice,
		pluginId: "provider-auth",
		providerId: "vercel-ai-gateway",
		methodId: "api-key",
		label: "Vercel AI Gateway"
	} : authChoice === "cloudflare-ai-gateway-api-key" ? {
		authChoice,
		pluginId: "provider-auth",
		providerId: "cloudflare-ai-gateway",
		methodId: "api-key",
		label: "Cloudflare AI Gateway"
	} : authChoice === "moonshot-api-key" ? {
		authChoice,
		pluginId: "provider-auth",
		providerId: "moonshot",
		methodId: "api-key",
		label: "Moonshot AI"
	} : authChoice === "moonshot-api-key-cn" ? {
		authChoice,
		pluginId: "provider-auth",
		providerId: "moonshot",
		methodId: "api-key-cn",
		label: "Moonshot AI"
	} : authChoice === "kimi-code-api-key" ? {
		authChoice,
		pluginId: "provider-auth",
		providerId: "kimi-coding",
		methodId: "api-key",
		label: "Kimi Coding"
	} : authChoice === "gemini-api-key" ? {
		authChoice,
		pluginId: "provider-auth",
		providerId: "google",
		methodId: "api-key",
		label: "Google"
	} : authChoice === "zai-api-key" ? {
		authChoice,
		pluginId: "provider-auth",
		providerId: "zai",
		methodId: "api-key",
		label: "Z.AI"
	} : authChoice === "xiaomi-api-key" ? {
		authChoice,
		pluginId: "provider-auth",
		providerId: "xiaomi",
		methodId: "api-key",
		label: "Xiaomi"
	} : authChoice === "synthetic-api-key" ? {
		authChoice,
		pluginId: "provider-auth",
		providerId: "synthetic",
		methodId: "api-key",
		label: "Synthetic"
	} : authChoice === "venice-api-key" ? {
		authChoice,
		pluginId: "provider-auth",
		providerId: "venice",
		methodId: "api-key",
		label: "Venice AI"
	} : authChoice === "opencode-zen" ? {
		authChoice,
		pluginId: "provider-auth",
		providerId: "opencode",
		methodId: "api-key",
		label: "OpenCode Zen"
	} : null;
	if (delegatedProvider) return await applyAuthChoicePluginProvider(params, delegatedProvider);
	if (authChoice === "openrouter-api-key") {
		const store = ensureAuthProfileStore(params.agentDir, { allowKeychainPrompt: false });
		const existingProfileId = resolveAuthProfileOrder({
			cfg: nextConfig,
			store,
			provider: "openrouter"
		}).find((profileId) => Boolean(store.profiles[profileId]));
		const existingCred = existingProfileId ? store.profiles[existingProfileId] : void 0;
		let profileId = "openrouter:default";
		let mode = "api_key";
		let hasCredential = false;
		if (existingProfileId && existingCred?.type) {
			profileId = existingProfileId;
			mode = existingCred.type === "oauth" ? "oauth" : existingCred.type === "token" ? "token" : "api_key";
			hasCredential = true;
		}
		if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "openrouter") {
			await setOpenrouterApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir);
			hasCredential = true;
		}
		if (!hasCredential) {
			const envKey = resolveEnvApiKey("openrouter");
			if (envKey) {
				if (await params.prompter.confirm({
					message: `Use existing OPENROUTER_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
					initialValue: true
				})) {
					await setOpenrouterApiKey(envKey.apiKey, params.agentDir);
					hasCredential = true;
				}
			}
		}
		if (!hasCredential) {
			const key = await params.prompter.text({
				message: "Enter OpenRouter API key",
				validate: validateApiKeyInput
			});
			await setOpenrouterApiKey(normalizeApiKeyInput(String(key)), params.agentDir);
			hasCredential = true;
		}
		if (hasCredential) nextConfig = applyAuthProfileConfig(nextConfig, {
			profileId,
			provider: "openrouter",
			mode
		});
		{
			const applied = await applyDefaultModelChoice({
				config: nextConfig,
				setDefaultModel: params.setDefaultModel,
				defaultModel: OPENROUTER_DEFAULT_MODEL_REF,
				applyDefaultConfig: applyOpenrouterConfig,
				applyProviderConfig: applyOpenrouterProviderConfig,
				noteDefault: OPENROUTER_DEFAULT_MODEL_REF,
				noteAgentModel,
				prompter: params.prompter
			});
			nextConfig = applied.config;
			agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
		}
		return {
			config: nextConfig,
			agentModelOverride
		};
	}
	if (authChoice === "ai-gateway-api-key") {
		let hasCredential = false;
		if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "vercel-ai-gateway") {
			await setVercelAiGatewayApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir);
			hasCredential = true;
		}
		const envKey = resolveEnvApiKey("vercel-ai-gateway");
		if (envKey) {
			if (await params.prompter.confirm({
				message: `Use existing AI_GATEWAY_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
				initialValue: true
			})) {
				await setVercelAiGatewayApiKey(envKey.apiKey, params.agentDir);
				hasCredential = true;
			}
		}
		if (!hasCredential) {
			const key = await params.prompter.text({
				message: "Enter Vercel AI Gateway API key",
				validate: validateApiKeyInput
			});
			await setVercelAiGatewayApiKey(normalizeApiKeyInput(String(key)), params.agentDir);
		}
		nextConfig = applyAuthProfileConfig(nextConfig, {
			profileId: "vercel-ai-gateway:default",
			provider: "vercel-ai-gateway",
			mode: "api_key"
		});
		{
			const applied = await applyDefaultModelChoice({
				config: nextConfig,
				setDefaultModel: params.setDefaultModel,
				defaultModel: VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF,
				applyDefaultConfig: applyVercelAiGatewayConfig,
				applyProviderConfig: applyVercelAiGatewayProviderConfig,
				noteDefault: VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF,
				noteAgentModel,
				prompter: params.prompter
			});
			nextConfig = applied.config;
			agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
		}
		return {
			config: nextConfig,
			agentModelOverride
		};
	}
	if (authChoice === "cloudflare-ai-gateway-api-key") {
		let hasCredential = false;
		let accountId = params.opts?.cloudflareAiGatewayAccountId?.trim() ?? "";
		let gatewayId = params.opts?.cloudflareAiGatewayGatewayId?.trim() ?? "";
		const ensureAccountGateway = async () => {
			if (!accountId) {
				const value = await params.prompter.text({
					message: "Enter Cloudflare Account ID",
					validate: (val) => String(val).trim() ? void 0 : "Account ID is required"
				});
				accountId = String(value).trim();
			}
			if (!gatewayId) {
				const value = await params.prompter.text({
					message: "Enter Cloudflare AI Gateway ID",
					validate: (val) => String(val).trim() ? void 0 : "Gateway ID is required"
				});
				gatewayId = String(value).trim();
			}
		};
		const optsApiKey = normalizeApiKeyInput(params.opts?.cloudflareAiGatewayApiKey ?? "");
		if (!hasCredential && accountId && gatewayId && optsApiKey) {
			await setCloudflareAiGatewayConfig(accountId, gatewayId, optsApiKey, params.agentDir);
			hasCredential = true;
		}
		const envKey = resolveEnvApiKey("cloudflare-ai-gateway");
		if (!hasCredential && envKey) {
			if (await params.prompter.confirm({
				message: `Use existing CLOUDFLARE_AI_GATEWAY_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
				initialValue: true
			})) {
				await ensureAccountGateway();
				await setCloudflareAiGatewayConfig(accountId, gatewayId, normalizeApiKeyInput(envKey.apiKey), params.agentDir);
				hasCredential = true;
			}
		}
		if (!hasCredential && optsApiKey) {
			await ensureAccountGateway();
			await setCloudflareAiGatewayConfig(accountId, gatewayId, optsApiKey, params.agentDir);
			hasCredential = true;
		}
		if (!hasCredential) {
			await ensureAccountGateway();
			const key = await params.prompter.text({
				message: "Enter Cloudflare AI Gateway API key",
				validate: validateApiKeyInput
			});
			await setCloudflareAiGatewayConfig(accountId, gatewayId, normalizeApiKeyInput(String(key)), params.agentDir);
			hasCredential = true;
		}
		if (hasCredential) nextConfig = applyAuthProfileConfig(nextConfig, {
			profileId: "cloudflare-ai-gateway:default",
			provider: "cloudflare-ai-gateway",
			mode: "api_key"
		});
		{
			const applied = await applyDefaultModelChoice({
				config: nextConfig,
				setDefaultModel: params.setDefaultModel,
				defaultModel: CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF,
				applyDefaultConfig: (cfg) => applyCloudflareAiGatewayConfig(cfg, {
					accountId: accountId || params.opts?.cloudflareAiGatewayAccountId,
					gatewayId: gatewayId || params.opts?.cloudflareAiGatewayGatewayId
				}),
				applyProviderConfig: (cfg) => applyCloudflareAiGatewayProviderConfig(cfg, {
					accountId: accountId || params.opts?.cloudflareAiGatewayAccountId,
					gatewayId: gatewayId || params.opts?.cloudflareAiGatewayGatewayId
				}),
				noteDefault: CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF,
				noteAgentModel,
				prompter: params.prompter
			});
			nextConfig = applied.config;
			agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
		}
		return {
			config: nextConfig,
			agentModelOverride
		};
	}
	if (authChoice === "moonshot-api-key") {
		let hasCredential = false;
		if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "moonshot") {
			await setMoonshotApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir);
			hasCredential = true;
		}
		const envKey = resolveEnvApiKey("moonshot");
		if (envKey) {
			if (await params.prompter.confirm({
				message: `Use existing MOONSHOT_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
				initialValue: true
			})) {
				await setMoonshotApiKey(envKey.apiKey, params.agentDir);
				hasCredential = true;
			}
		}
		if (!hasCredential) {
			const key = await params.prompter.text({
				message: "Enter Moonshot API key",
				validate: validateApiKeyInput
			});
			await setMoonshotApiKey(normalizeApiKeyInput(String(key)), params.agentDir);
		}
		nextConfig = applyAuthProfileConfig(nextConfig, {
			profileId: "moonshot:default",
			provider: "moonshot",
			mode: "api_key"
		});
		{
			const applied = await applyDefaultModelChoice({
				config: nextConfig,
				setDefaultModel: params.setDefaultModel,
				defaultModel: MOONSHOT_DEFAULT_MODEL_REF,
				applyDefaultConfig: applyMoonshotConfig,
				applyProviderConfig: applyMoonshotProviderConfig,
				noteAgentModel,
				prompter: params.prompter
			});
			nextConfig = applied.config;
			agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
		}
		return {
			config: nextConfig,
			agentModelOverride
		};
	}
	if (authChoice === "moonshot-api-key-cn") {
		let hasCredential = false;
		if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "moonshot") {
			await setMoonshotApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir);
			hasCredential = true;
		}
		const envKey = resolveEnvApiKey("moonshot");
		if (envKey) {
			if (await params.prompter.confirm({
				message: `Use existing MOONSHOT_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
				initialValue: true
			})) {
				await setMoonshotApiKey(envKey.apiKey, params.agentDir);
				hasCredential = true;
			}
		}
		if (!hasCredential) {
			const key = await params.prompter.text({
				message: "Enter Moonshot API key (.cn)",
				validate: validateApiKeyInput
			});
			await setMoonshotApiKey(normalizeApiKeyInput(String(key)), params.agentDir);
		}
		nextConfig = applyAuthProfileConfig(nextConfig, {
			profileId: "moonshot:default",
			provider: "moonshot",
			mode: "api_key"
		});
		{
			const applied = await applyDefaultModelChoice({
				config: nextConfig,
				setDefaultModel: params.setDefaultModel,
				defaultModel: MOONSHOT_DEFAULT_MODEL_REF,
				applyDefaultConfig: applyMoonshotConfigCn,
				applyProviderConfig: applyMoonshotProviderConfigCn,
				noteAgentModel,
				prompter: params.prompter
			});
			nextConfig = applied.config;
			agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
		}
		return {
			config: nextConfig,
			agentModelOverride
		};
	}
	if (authChoice === "kimi-code-api-key") {
		let hasCredential = false;
		const tokenProvider = params.opts?.tokenProvider?.trim().toLowerCase();
		if (!hasCredential && params.opts?.token && (tokenProvider === "kimi-code" || tokenProvider === "kimi-coding")) {
			await setKimiCodingApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir);
			hasCredential = true;
		}
		if (!hasCredential) await params.prompter.note(["Kimi Coding uses a dedicated endpoint and API key.", "Get your API key at: https://www.kimi.com/code/en"].join("\n"), "Kimi Coding");
		const envKey = resolveEnvApiKey("kimi-coding");
		if (envKey) {
			if (await params.prompter.confirm({
				message: `Use existing KIMI_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
				initialValue: true
			})) {
				await setKimiCodingApiKey(envKey.apiKey, params.agentDir);
				hasCredential = true;
			}
		}
		if (!hasCredential) {
			const key = await params.prompter.text({
				message: "Enter Kimi Coding API key",
				validate: validateApiKeyInput
			});
			await setKimiCodingApiKey(normalizeApiKeyInput(String(key)), params.agentDir);
		}
		nextConfig = applyAuthProfileConfig(nextConfig, {
			profileId: "kimi-coding:default",
			provider: "kimi-coding",
			mode: "api_key"
		});
		{
			const applied = await applyDefaultModelChoice({
				config: nextConfig,
				setDefaultModel: params.setDefaultModel,
				defaultModel: KIMI_CODING_MODEL_REF,
				applyDefaultConfig: applyKimiCodeConfig,
				applyProviderConfig: applyKimiCodeProviderConfig,
				noteDefault: KIMI_CODING_MODEL_REF,
				noteAgentModel,
				prompter: params.prompter
			});
			nextConfig = applied.config;
			agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
		}
		return {
			config: nextConfig,
			agentModelOverride
		};
	}
	if (authChoice === "gemini-api-key") {
		let hasCredential = false;
		if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "google") {
			await setGeminiApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir);
			hasCredential = true;
		}
		const envKey = resolveEnvApiKey("google");
		if (envKey) {
			if (await params.prompter.confirm({
				message: `Use existing GEMINI_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
				initialValue: true
			})) {
				await setGeminiApiKey(envKey.apiKey, params.agentDir);
				hasCredential = true;
			}
		}
		if (!hasCredential) {
			const key = await params.prompter.text({
				message: "Enter Gemini API key",
				validate: validateApiKeyInput
			});
			await setGeminiApiKey(normalizeApiKeyInput(String(key)), params.agentDir);
		}
		nextConfig = applyAuthProfileConfig(nextConfig, {
			profileId: "google:default",
			provider: "google",
			mode: "api_key"
		});
		if (params.setDefaultModel) {
			const applied = applyGoogleGeminiModelDefault(nextConfig);
			nextConfig = applied.next;
			if (applied.changed) await params.prompter.note(`Default model set to ${GOOGLE_GEMINI_DEFAULT_MODEL}`, "Model configured");
		} else {
			agentModelOverride = GOOGLE_GEMINI_DEFAULT_MODEL;
			await noteAgentModel(GOOGLE_GEMINI_DEFAULT_MODEL);
		}
		return {
			config: nextConfig,
			agentModelOverride
		};
	}
	if (authChoice === "zai-api-key") {
		let hasCredential = false;
		if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "zai") {
			await setZaiApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir);
			hasCredential = true;
		}
		const envKey = resolveEnvApiKey("zai");
		if (envKey) {
			if (await params.prompter.confirm({
				message: `Use existing ZAI_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
				initialValue: true
			})) {
				await setZaiApiKey(envKey.apiKey, params.agentDir);
				hasCredential = true;
			}
		}
		if (!hasCredential) {
			const key = await params.prompter.text({
				message: "Enter Z.AI API key",
				validate: validateApiKeyInput
			});
			await setZaiApiKey(normalizeApiKeyInput(String(key)), params.agentDir);
		}
		nextConfig = applyAuthProfileConfig(nextConfig, {
			profileId: "zai:default",
			provider: "zai",
			mode: "api_key"
		});
		{
			const applied = await applyDefaultModelChoice({
				config: nextConfig,
				setDefaultModel: params.setDefaultModel,
				defaultModel: ZAI_DEFAULT_MODEL_REF,
				applyDefaultConfig: applyZaiConfig,
				applyProviderConfig: (config) => ({
					...config,
					agents: {
						...config.agents,
						defaults: {
							...config.agents?.defaults,
							models: {
								...config.agents?.defaults?.models,
								[ZAI_DEFAULT_MODEL_REF]: {
									...config.agents?.defaults?.models?.[ZAI_DEFAULT_MODEL_REF],
									alias: config.agents?.defaults?.models?.[ZAI_DEFAULT_MODEL_REF]?.alias ?? "GLM"
								}
							}
						}
					}
				}),
				noteDefault: ZAI_DEFAULT_MODEL_REF,
				noteAgentModel,
				prompter: params.prompter
			});
			nextConfig = applied.config;
			agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
		}
		return {
			config: nextConfig,
			agentModelOverride
		};
	}
	if (authChoice === "xiaomi-api-key") {
		let hasCredential = false;
		if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "xiaomi") {
			await setXiaomiApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir);
			hasCredential = true;
		}
		const envKey = resolveEnvApiKey("xiaomi");
		if (envKey) {
			if (await params.prompter.confirm({
				message: `Use existing XIAOMI_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
				initialValue: true
			})) {
				await setXiaomiApiKey(envKey.apiKey, params.agentDir);
				hasCredential = true;
			}
		}
		if (!hasCredential) {
			const key = await params.prompter.text({
				message: "Enter Xiaomi API key",
				validate: validateApiKeyInput
			});
			await setXiaomiApiKey(normalizeApiKeyInput(String(key)), params.agentDir);
		}
		nextConfig = applyAuthProfileConfig(nextConfig, {
			profileId: "xiaomi:default",
			provider: "xiaomi",
			mode: "api_key"
		});
		{
			const applied = await applyDefaultModelChoice({
				config: nextConfig,
				setDefaultModel: params.setDefaultModel,
				defaultModel: XIAOMI_DEFAULT_MODEL_REF,
				applyDefaultConfig: applyXiaomiConfig,
				applyProviderConfig: applyXiaomiProviderConfig,
				noteDefault: XIAOMI_DEFAULT_MODEL_REF,
				noteAgentModel,
				prompter: params.prompter
			});
			nextConfig = applied.config;
			agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
		}
		return {
			config: nextConfig,
			agentModelOverride
		};
	}
	if (authChoice === "synthetic-api-key") {
		if (params.opts?.token && params.opts?.tokenProvider === "synthetic") await setSyntheticApiKey(String(params.opts.token).trim(), params.agentDir);
		else {
			const key = await params.prompter.text({
				message: "Enter Synthetic API key",
				validate: (value) => value?.trim() ? void 0 : "Required"
			});
			await setSyntheticApiKey(String(key).trim(), params.agentDir);
		}
		nextConfig = applyAuthProfileConfig(nextConfig, {
			profileId: "synthetic:default",
			provider: "synthetic",
			mode: "api_key"
		});
		{
			const applied = await applyDefaultModelChoice({
				config: nextConfig,
				setDefaultModel: params.setDefaultModel,
				defaultModel: SYNTHETIC_DEFAULT_MODEL_REF,
				applyDefaultConfig: applySyntheticConfig,
				applyProviderConfig: applySyntheticProviderConfig,
				noteDefault: SYNTHETIC_DEFAULT_MODEL_REF,
				noteAgentModel,
				prompter: params.prompter
			});
			nextConfig = applied.config;
			agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
		}
		return {
			config: nextConfig,
			agentModelOverride
		};
	}
	if (authChoice === "venice-api-key") {
		let hasCredential = false;
		if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "venice") {
			await setVeniceApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir);
			hasCredential = true;
		}
		if (!hasCredential) await params.prompter.note([
			"Venice AI provides privacy-focused inference with uncensored models.",
			"Get your API key at: https://venice.ai/settings/api",
			"Supports 'private' (fully private) and 'anonymized' (proxy) modes."
		].join("\n"), "Venice AI");
		const envKey = resolveEnvApiKey("venice");
		if (envKey) {
			if (await params.prompter.confirm({
				message: `Use existing VENICE_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
				initialValue: true
			})) {
				await setVeniceApiKey(envKey.apiKey, params.agentDir);
				hasCredential = true;
			}
		}
		if (!hasCredential) {
			const key = await params.prompter.text({
				message: "Enter Venice AI API key",
				validate: validateApiKeyInput
			});
			await setVeniceApiKey(normalizeApiKeyInput(String(key)), params.agentDir);
		}
		nextConfig = applyAuthProfileConfig(nextConfig, {
			profileId: "venice:default",
			provider: "venice",
			mode: "api_key"
		});
		{
			const applied = await applyDefaultModelChoice({
				config: nextConfig,
				setDefaultModel: params.setDefaultModel,
				defaultModel: VENICE_DEFAULT_MODEL_REF,
				applyDefaultConfig: applyVeniceConfig,
				applyProviderConfig: applyVeniceProviderConfig,
				noteDefault: VENICE_DEFAULT_MODEL_REF,
				noteAgentModel,
				prompter: params.prompter
			});
			nextConfig = applied.config;
			agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
		}
		return {
			config: nextConfig,
			agentModelOverride
		};
	}
	if (authChoice === "opencode-zen") {
		let hasCredential = false;
		if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "opencode") {
			await setOpencodeZenApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir);
			hasCredential = true;
		}
		if (!hasCredential) await params.prompter.note([
			"OpenCode Zen provides access to Claude, GPT, Gemini, and more models.",
			"Get your API key at: https://opencode.ai/auth",
			"Requires an active OpenCode Zen subscription."
		].join("\n"), "OpenCode Zen");
		const envKey = resolveEnvApiKey("opencode");
		if (envKey) {
			if (await params.prompter.confirm({
				message: `Use existing OPENCODE_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
				initialValue: true
			})) {
				await setOpencodeZenApiKey(envKey.apiKey, params.agentDir);
				hasCredential = true;
			}
		}
		if (!hasCredential) {
			const key = await params.prompter.text({
				message: "Enter OpenCode Zen API key",
				validate: validateApiKeyInput
			});
			await setOpencodeZenApiKey(normalizeApiKeyInput(String(key)), params.agentDir);
		}
		nextConfig = applyAuthProfileConfig(nextConfig, {
			profileId: "opencode:default",
			provider: "opencode",
			mode: "api_key"
		});
		{
			const applied = await applyDefaultModelChoice({
				config: nextConfig,
				setDefaultModel: params.setDefaultModel,
				defaultModel: OPENCODE_ZEN_DEFAULT_MODEL,
				applyDefaultConfig: applyOpencodeZenConfig,
				applyProviderConfig: applyOpencodeZenProviderConfig,
				noteDefault: OPENCODE_ZEN_DEFAULT_MODEL,
				noteAgentModel,
				prompter: params.prompter
			});
			nextConfig = applied.config;
			agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
		}
		return {
			config: nextConfig,
			agentModelOverride
		};
	}
	return null;
}

//#endregion
//#region ../../src/commands/auth-choice.apply.copilot-proxy.ts
async function applyAuthChoiceCopilotProxy(params) {
	return await applyAuthChoicePluginProvider(params, {
		authChoice: "copilot-proxy",
		pluginId: "copilot-proxy",
		providerId: "copilot-proxy",
		methodId: "local",
		label: "Copilot Proxy"
	});
}

//#endregion
//#region ../../src/commands/auth-choice.apply.github-copilot.ts
async function applyAuthChoiceGitHubCopilot(params) {
	if (params.authChoice !== "github-copilot") return null;
	return await applyAuthChoicePluginProvider(params, {
		authChoice: "github-copilot",
		pluginId: "provider-auth",
		providerId: "github-copilot",
		methodId: "device-login",
		label: "GitHub Copilot"
	});
}

//#endregion
//#region ../../src/commands/auth-choice.apply.google-antigravity.ts
async function applyAuthChoiceGoogleAntigravity(params) {
	return await applyAuthChoicePluginProvider(params, {
		authChoice: "google-antigravity",
		pluginId: "google-antigravity-auth",
		providerId: "google-antigravity",
		methodId: "oauth",
		label: "Google Antigravity"
	});
}

//#endregion
//#region ../../src/commands/auth-choice.apply.google-gemini-cli.ts
async function applyAuthChoiceGoogleGeminiCli(params) {
	return await applyAuthChoicePluginProvider(params, {
		authChoice: "google-gemini-cli",
		pluginId: "google-gemini-cli-auth",
		providerId: "google-gemini-cli",
		methodId: "oauth",
		label: "Google Gemini CLI"
	});
}

//#endregion
//#region ../../src/commands/auth-choice.apply.minimax.ts
async function applyAuthChoiceMiniMax(params) {
	let nextConfig = params.config;
	let agentModelOverride;
	const noteAgentModel = async (model) => {
		if (!params.agentId) return;
		await params.prompter.note(`Default model set to ${model} for agent "${params.agentId}".`, "Model configured");
	};
	if (params.authChoice === "minimax-portal") return await applyAuthChoicePluginProvider(params, {
		authChoice: "minimax-portal",
		pluginId: "minimax-portal-auth",
		providerId: "minimax-portal",
		methodId: await params.prompter.select({
			message: "Select MiniMax endpoint",
			options: [{
				value: "oauth",
				label: "Global",
				hint: "OAuth for international users"
			}, {
				value: "oauth-cn",
				label: "CN",
				hint: "OAuth for users in China"
			}]
		}),
		label: "MiniMax"
	});
	if (params.authChoice === "minimax-cloud" || params.authChoice === "minimax-api" || params.authChoice === "minimax-api-lightning") {
		const modelId = params.authChoice === "minimax-api-lightning" ? "MiniMax-M2.1-lightning" : "MiniMax-M2.1";
		let hasCredential = false;
		const envKey = resolveEnvApiKey("minimax");
		if (envKey) {
			if (await params.prompter.confirm({
				message: `Use existing MINIMAX_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
				initialValue: true
			})) {
				await setMinimaxApiKey(envKey.apiKey, params.agentDir);
				hasCredential = true;
			}
		}
		if (!hasCredential) {
			const key = await params.prompter.text({
				message: "Enter MiniMax API key",
				validate: validateApiKeyInput
			});
			await setMinimaxApiKey(normalizeApiKeyInput(String(key)), params.agentDir);
		}
		nextConfig = applyAuthProfileConfig(nextConfig, {
			profileId: "minimax:default",
			provider: "minimax",
			mode: "api_key"
		});
		{
			const modelRef = `minimax/${modelId}`;
			const applied = await applyDefaultModelChoice({
				config: nextConfig,
				setDefaultModel: params.setDefaultModel,
				defaultModel: modelRef,
				applyDefaultConfig: (config) => applyMinimaxApiConfig(config, modelId),
				applyProviderConfig: (config) => applyMinimaxApiProviderConfig(config, modelId),
				noteAgentModel,
				prompter: params.prompter
			});
			nextConfig = applied.config;
			agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
		}
		return {
			config: nextConfig,
			agentModelOverride
		};
	}
	if (params.authChoice === "minimax") {
		const applied = await applyDefaultModelChoice({
			config: nextConfig,
			setDefaultModel: params.setDefaultModel,
			defaultModel: "lmstudio/minimax-m2.1-gs32",
			applyDefaultConfig: applyMinimaxConfig,
			applyProviderConfig: applyMinimaxProviderConfig,
			noteAgentModel,
			prompter: params.prompter
		});
		nextConfig = applied.config;
		agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
		return {
			config: nextConfig,
			agentModelOverride
		};
	}
	return null;
}

//#endregion
//#region ../../src/commands/auth-choice.apply.oauth.ts
async function applyAuthChoiceOAuth(params) {
	if (params.authChoice !== "chutes") return null;
	return await applyAuthChoicePluginProvider(params, {
		authChoice: "chutes",
		pluginId: "provider-auth",
		providerId: "chutes",
		methodId: "oauth",
		label: "Chutes"
	});
}

//#endregion
//#region ../../src/commands/auth-choice.apply.openai.ts
async function applyAuthChoiceOpenAI(params) {
	if (params.authChoice === "openai-codex") return await applyAuthChoicePluginProvider(params, {
		authChoice: "openai-codex",
		pluginId: "provider-auth",
		providerId: "openai-codex",
		methodId: "oauth",
		label: "OpenAI Codex"
	});
	if (params.authChoice === "openai-api-key" || params.authChoice === "apiKey" && params.opts?.tokenProvider === "openai") return await applyAuthChoicePluginProvider(params, {
		authChoice: params.authChoice,
		pluginId: "provider-auth",
		providerId: "openai",
		methodId: "api-key",
		label: "OpenAI"
	});
	return null;
}

//#endregion
//#region ../../src/commands/auth-choice.apply.qwen-portal.ts
async function applyAuthChoiceQwenPortal(params) {
	return await applyAuthChoicePluginProvider(params, {
		authChoice: "qwen-portal",
		pluginId: "qwen-portal-auth",
		providerId: "qwen-portal",
		methodId: "device",
		label: "Qwen"
	});
}

//#endregion
//#region ../../src/commands/auth-choice.apply.ts
async function applyAuthChoice(params) {
	const handlers = [
		applyAuthChoiceAnthropic,
		applyAuthChoiceOpenAI,
		applyAuthChoiceOAuth,
		applyAuthChoiceApiProviders,
		applyAuthChoiceMiniMax,
		applyAuthChoiceGitHubCopilot,
		applyAuthChoiceGoogleAntigravity,
		applyAuthChoiceGoogleGeminiCli,
		applyAuthChoiceCopilotProxy,
		applyAuthChoiceQwenPortal
	];
	for (const handler of handlers) {
		const result = await handler(params);
		if (result) return result;
	}
	return { config: params.config };
}

//#endregion
//#region ../../src/commands/openai-codex-model-default.ts
const OPENAI_CODEX_DEFAULT_MODEL = "openai-codex/gpt-5.5";

//#endregion
//#region ../../src/commands/auth-choice.model-check.ts
async function warnIfModelConfigLooksOff(config, prompter, options) {
	const agentModelOverride = options?.agentId ? resolveAgentModelPrimary(config, options.agentId) : void 0;
	const configWithModel = agentModelOverride && agentModelOverride.length > 0 ? {
		...config,
		agents: {
			...config.agents,
			defaults: {
				...config.agents?.defaults,
				model: {
					...typeof config.agents?.defaults?.model === "object" ? config.agents.defaults.model : void 0,
					primary: agentModelOverride
				}
			}
		}
	} : config;
	const ref = resolveConfiguredModelRef({
		cfg: configWithModel,
		defaultProvider: DEFAULT_PROVIDER,
		defaultModel: DEFAULT_MODEL
	});
	const warnings = [];
	const catalog = await loadModelCatalog({
		config: configWithModel,
		useCache: false
	});
	if (catalog.length > 0) {
		if (!catalog.some((entry) => entry.provider === ref.provider && entry.id === ref.model)) warnings.push(`Model not found: ${ref.provider}/${ref.model}. Update agents.defaults.model or run /models list.`);
	}
	const store = ensureAuthProfileStore(options?.agentDir);
	const hasProfile = listProfilesForProvider(store, ref.provider).length > 0;
	const envKey = resolveEnvApiKey(ref.provider);
	const customKey = getCustomProviderApiKey(config, ref.provider);
	if (!hasProfile && !envKey && !customKey) warnings.push(`No auth configured for provider "${ref.provider}". The agent may fail until credentials are added.`);
	if (ref.provider === "openai") {
		if (listProfilesForProvider(store, "openai-codex").length > 0) warnings.push(`Detected OpenAI Codex OAuth. Consider setting agents.defaults.model to ${OPENAI_CODEX_DEFAULT_MODEL}.`);
	}
	if (warnings.length > 0) await prompter.note(warnings.join("\n"), "Model check");
}

//#endregion
//#region ../../src/commands/auth-choice.preferred-provider.ts
const PREFERRED_PROVIDER_BY_AUTH_CHOICE = {
	oauth: "anthropic",
	"setup-token": "anthropic",
	"claude-cli": "anthropic",
	token: "anthropic",
	apiKey: "anthropic",
	"openai-codex": "openai-codex",
	"codex-cli": "openai-codex",
	chutes: "chutes",
	"openai-api-key": "openai",
	"openrouter-api-key": "openrouter",
	"ai-gateway-api-key": "vercel-ai-gateway",
	"cloudflare-ai-gateway-api-key": "cloudflare-ai-gateway",
	"moonshot-api-key": "moonshot",
	"moonshot-api-key-cn": "moonshot",
	"kimi-code-api-key": "kimi-coding",
	"gemini-api-key": "google",
	"google-antigravity": "google-antigravity",
	"google-gemini-cli": "google-gemini-cli",
	"zai-api-key": "zai",
	"xiaomi-api-key": "xiaomi",
	"synthetic-api-key": "synthetic",
	"venice-api-key": "venice",
	"github-copilot": "github-copilot",
	"copilot-proxy": "copilot-proxy",
	"minimax-cloud": "minimax",
	"minimax-api": "minimax",
	"minimax-api-lightning": "minimax",
	minimax: "lmstudio",
	"opencode-zen": "opencode",
	"qwen-portal": "qwen-portal",
	"minimax-portal": "minimax-portal"
};
function resolvePreferredProviderForAuthChoice(choice) {
	return PREFERRED_PROVIDER_BY_AUTH_CHOICE[choice];
}

//#endregion
//#region ../../src/commands/model-picker.ts
const KEEP_VALUE = "__keep__";
const MANUAL_VALUE = "__manual__";
const PROVIDER_FILTER_THRESHOLD = 30;
const HIDDEN_ROUTER_MODELS = new Set(["openrouter/auto"]);
function hasAuthForProvider(provider, cfg, store) {
	if (listProfilesForProvider(store, provider).length > 0) return true;
	if (resolveEnvApiKey(provider)) return true;
	if (getCustomProviderApiKey(cfg, provider)) return true;
	return false;
}
function resolveConfiguredModelRaw(cfg) {
	const raw = cfg.agents?.defaults?.model;
	if (typeof raw === "string") return raw.trim();
	return raw?.primary?.trim() ?? "";
}
function resolveConfiguredModelKeys(cfg) {
	const models = cfg.agents?.defaults?.models ?? {};
	return Object.keys(models).map((key) => String(key ?? "").trim()).filter((key) => key.length > 0);
}
function normalizeModelKeys(values) {
	const seen = /* @__PURE__ */ new Set();
	const next = [];
	for (const raw of values) {
		const value = String(raw ?? "").trim();
		if (!value || seen.has(value)) continue;
		seen.add(value);
		next.push(value);
	}
	return next;
}
async function promptManualModel(params) {
	const modelInput = await params.prompter.text({
		message: params.allowBlank ? "Default model (blank to keep)" : "Default model",
		initialValue: params.initialValue,
		placeholder: "provider/model",
		validate: params.allowBlank ? void 0 : (value) => value?.trim() ? void 0 : "Required"
	});
	const model = String(modelInput ?? "").trim();
	if (!model) return {};
	return { model };
}
async function promptDefaultModel(params) {
	const cfg = params.config;
	const allowKeep = params.allowKeep ?? true;
	const includeManual = params.includeManual ?? true;
	const ignoreAllowlist = params.ignoreAllowlist ?? false;
	const preferredProviderRaw = params.preferredProvider?.trim();
	const preferredProvider = preferredProviderRaw ? normalizeProviderId(preferredProviderRaw) : void 0;
	const configuredRaw = resolveConfiguredModelRaw(cfg);
	const resolved = resolveConfiguredModelRef({
		cfg,
		defaultProvider: DEFAULT_PROVIDER,
		defaultModel: DEFAULT_MODEL
	});
	const resolvedKey = modelKey(resolved.provider, resolved.model);
	const configuredKey = configuredRaw ? resolvedKey : "";
	const catalog = await loadModelCatalog({
		config: cfg,
		useCache: false
	});
	if (catalog.length === 0) return promptManualModel({
		prompter: params.prompter,
		allowBlank: allowKeep,
		initialValue: configuredRaw || resolvedKey || void 0
	});
	const aliasIndex = buildModelAliasIndex({
		cfg,
		defaultProvider: DEFAULT_PROVIDER
	});
	let models = catalog;
	if (!ignoreAllowlist) {
		const { allowedCatalog } = buildAllowedModelSet({
			cfg,
			catalog,
			defaultProvider: DEFAULT_PROVIDER
		});
		models = allowedCatalog.length > 0 ? allowedCatalog : catalog;
	}
	if (models.length === 0) return promptManualModel({
		prompter: params.prompter,
		allowBlank: allowKeep,
		initialValue: configuredRaw || resolvedKey || void 0
	});
	const providers = Array.from(new Set(models.map((entry) => entry.provider))).toSorted((a, b) => a.localeCompare(b));
	const hasPreferredProvider = preferredProvider ? providers.includes(preferredProvider) : false;
	if (!hasPreferredProvider && providers.length > 1 && models.length > PROVIDER_FILTER_THRESHOLD) {
		const selection = await params.prompter.select({
			message: "Filter models by provider",
			options: [{
				value: "*",
				label: "All providers"
			}, ...providers.map((provider) => {
				const count = models.filter((entry) => entry.provider === provider).length;
				return {
					value: provider,
					label: provider,
					hint: `${count} model${count === 1 ? "" : "s"}`
				};
			})]
		});
		if (selection !== "*") models = models.filter((entry) => entry.provider === selection);
	}
	if (hasPreferredProvider && preferredProvider) models = models.filter((entry) => entry.provider === preferredProvider);
	const authStore = ensureAuthProfileStore(params.agentDir, { allowKeychainPrompt: false });
	const authCache = /* @__PURE__ */ new Map();
	const hasAuth = (provider) => {
		const cached = authCache.get(provider);
		if (cached !== void 0) return cached;
		const value = hasAuthForProvider(provider, cfg, authStore);
		authCache.set(provider, value);
		return value;
	};
	const options = [];
	if (allowKeep) options.push({
		value: KEEP_VALUE,
		label: configuredRaw ? `Keep current (${configuredRaw})` : `Keep current (default: ${resolvedKey})`,
		hint: configuredRaw && configuredRaw !== resolvedKey ? `resolves to ${resolvedKey}` : void 0
	});
	if (includeManual) options.push({
		value: MANUAL_VALUE,
		label: "Enter model manually"
	});
	const seen = /* @__PURE__ */ new Set();
	const addModelOption = (entry) => {
		const key = modelKey(entry.provider, entry.id);
		if (seen.has(key)) return;
		if (HIDDEN_ROUTER_MODELS.has(key)) return;
		const hints = [];
		if (entry.name && entry.name !== entry.id) hints.push(entry.name);
		if (entry.contextWindow) hints.push(`ctx ${formatTokenK(entry.contextWindow)}`);
		if (entry.reasoning) hints.push("reasoning");
		const aliases = aliasIndex.byKey.get(key);
		if (aliases?.length) hints.push(`alias: ${aliases.join(", ")}`);
		if (!hasAuth(entry.provider)) hints.push("auth missing");
		options.push({
			value: key,
			label: key,
			hint: hints.length > 0 ? hints.join(" · ") : void 0
		});
		seen.add(key);
	};
	for (const entry of models) addModelOption(entry);
	if (configuredKey && !seen.has(configuredKey)) options.push({
		value: configuredKey,
		label: configuredKey,
		hint: "current (not in catalog)"
	});
	let initialValue = allowKeep ? KEEP_VALUE : configuredKey || void 0;
	if (allowKeep && hasPreferredProvider && preferredProvider && resolved.provider !== preferredProvider) {
		const firstModel = models[0];
		if (firstModel) initialValue = modelKey(firstModel.provider, firstModel.id);
	}
	const selection = await params.prompter.select({
		message: params.message ?? "Default model",
		options,
		initialValue
	});
	if (selection === KEEP_VALUE) return {};
	if (selection === MANUAL_VALUE) return promptManualModel({
		prompter: params.prompter,
		allowBlank: false,
		initialValue: configuredRaw || resolvedKey || void 0
	});
	return { model: String(selection) };
}
async function promptModelAllowlist(params) {
	const cfg = params.config;
	const existingKeys = resolveConfiguredModelKeys(cfg);
	const allowedKeys = normalizeModelKeys(params.allowedKeys ?? []);
	const allowedKeySet = allowedKeys.length > 0 ? new Set(allowedKeys) : null;
	const resolved = resolveConfiguredModelRef({
		cfg,
		defaultProvider: DEFAULT_PROVIDER,
		defaultModel: DEFAULT_MODEL
	});
	const resolvedKey = modelKey(resolved.provider, resolved.model);
	const initialSeeds = normalizeModelKeys([
		...existingKeys,
		resolvedKey,
		...params.initialSelections ?? []
	]);
	const initialKeys = allowedKeySet ? initialSeeds.filter((key) => allowedKeySet.has(key)) : initialSeeds;
	const catalog = await loadModelCatalog({
		config: cfg,
		useCache: false
	});
	if (catalog.length === 0 && allowedKeys.length === 0) {
		const raw = await params.prompter.text({
			message: params.message ?? "Allowlist models (comma-separated provider/model; blank to keep current)",
			initialValue: existingKeys.join(", "),
			placeholder: "openai-codex/gpt-5.5, anthropic/claude-opus-4-5"
		});
		const parsed = String(raw ?? "").split(",").map((value) => value.trim()).filter((value) => value.length > 0);
		if (parsed.length === 0) return {};
		return { models: normalizeModelKeys(parsed) };
	}
	const aliasIndex = buildModelAliasIndex({
		cfg,
		defaultProvider: DEFAULT_PROVIDER
	});
	const authStore = ensureAuthProfileStore(params.agentDir, { allowKeychainPrompt: false });
	const authCache = /* @__PURE__ */ new Map();
	const hasAuth = (provider) => {
		const cached = authCache.get(provider);
		if (cached !== void 0) return cached;
		const value = hasAuthForProvider(provider, cfg, authStore);
		authCache.set(provider, value);
		return value;
	};
	const options = [];
	const seen = /* @__PURE__ */ new Set();
	const addModelOption = (entry) => {
		const key = modelKey(entry.provider, entry.id);
		if (seen.has(key)) return;
		if (HIDDEN_ROUTER_MODELS.has(key)) return;
		const hints = [];
		if (entry.name && entry.name !== entry.id) hints.push(entry.name);
		if (entry.contextWindow) hints.push(`ctx ${formatTokenK(entry.contextWindow)}`);
		if (entry.reasoning) hints.push("reasoning");
		const aliases = aliasIndex.byKey.get(key);
		if (aliases?.length) hints.push(`alias: ${aliases.join(", ")}`);
		if (!hasAuth(entry.provider)) hints.push("auth missing");
		options.push({
			value: key,
			label: key,
			hint: hints.length > 0 ? hints.join(" · ") : void 0
		});
		seen.add(key);
	};
	const filteredCatalog = allowedKeySet ? catalog.filter((entry) => allowedKeySet.has(modelKey(entry.provider, entry.id))) : catalog;
	for (const entry of filteredCatalog) addModelOption(entry);
	const supplementalKeys = allowedKeySet ? allowedKeys : existingKeys;
	for (const key of supplementalKeys) {
		if (seen.has(key)) continue;
		options.push({
			value: key,
			label: key,
			hint: allowedKeySet ? "allowed (not in catalog)" : "configured (not in catalog)"
		});
		seen.add(key);
	}
	if (options.length === 0) return {};
	const selected = normalizeModelKeys((await params.prompter.multiselect({
		message: params.message ?? "Models in /model picker (multi-select)",
		options,
		initialValues: initialKeys.length > 0 ? initialKeys : void 0
	})).map((value) => String(value)));
	if (selected.length > 0) return { models: selected };
	if (existingKeys.length === 0) return { models: [] };
	if (!await params.prompter.confirm({
		message: "Clear the model allowlist? (shows all models)",
		initialValue: false
	})) return {};
	return { models: [] };
}
function applyPrimaryModel(cfg, model) {
	const defaults = cfg.agents?.defaults;
	const existingModel = defaults?.model;
	const existingModels = defaults?.models;
	const fallbacks = typeof existingModel === "object" && existingModel !== null && "fallbacks" in existingModel ? existingModel.fallbacks : void 0;
	return {
		...cfg,
		agents: {
			...cfg.agents,
			defaults: {
				...defaults,
				model: {
					...fallbacks ? { fallbacks } : void 0,
					primary: model
				},
				models: {
					...existingModels,
					[model]: existingModels?.[model] ?? {}
				}
			}
		}
	};
}
function applyModelAllowlist(cfg, models) {
	const defaults = cfg.agents?.defaults;
	const normalized = normalizeModelKeys(models);
	if (normalized.length === 0) {
		if (!defaults?.models) return cfg;
		const { models: _ignored, ...restDefaults } = defaults;
		return {
			...cfg,
			agents: {
				...cfg.agents,
				defaults: restDefaults
			}
		};
	}
	const existingModels = defaults?.models ?? {};
	const nextModels = {};
	for (const key of normalized) nextModels[key] = existingModels[key] ?? {};
	return {
		...cfg,
		agents: {
			...cfg.agents,
			defaults: {
				...defaults,
				models: nextModels
			}
		}
	};
}
function applyModelFallbacksFromSelection(cfg, selection) {
	const normalized = normalizeModelKeys(selection);
	if (normalized.length <= 1) return cfg;
	const resolved = resolveConfiguredModelRef({
		cfg,
		defaultProvider: DEFAULT_PROVIDER,
		defaultModel: DEFAULT_MODEL
	});
	const resolvedKey = modelKey(resolved.provider, resolved.model);
	if (!normalized.includes(resolvedKey)) return cfg;
	const defaults = cfg.agents?.defaults;
	const existingModel = defaults?.model;
	const existingPrimary = typeof existingModel === "string" ? existingModel : existingModel && typeof existingModel === "object" ? existingModel.primary : void 0;
	const fallbacks = normalized.filter((key) => key !== resolvedKey);
	return {
		...cfg,
		agents: {
			...cfg.agents,
			defaults: {
				...defaults,
				model: {
					...typeof existingModel === "object" ? existingModel : void 0,
					primary: existingPrimary ?? resolvedKey,
					fallbacks
				}
			}
		}
	};
}

//#endregion
//#region ../../src/infra/bonjour-discovery.ts
const DEFAULT_TIMEOUT_MS = 2e3;
const GATEWAY_SERVICE_TYPE = "_edwin-gw._tcp";
function decodeDnsSdEscapes(value) {
	let decoded = false;
	const bytes = [];
	let pending = "";
	const flush = () => {
		if (!pending) return;
		bytes.push(...Buffer.from(pending, "utf8"));
		pending = "";
	};
	for (let i = 0; i < value.length; i += 1) {
		const ch = value[i] ?? "";
		if (ch === "\\" && i + 3 < value.length) {
			const escaped = value.slice(i + 1, i + 4);
			if (/^[0-9]{3}$/.test(escaped)) {
				const byte = Number.parseInt(escaped, 10);
				if (!Number.isFinite(byte) || byte < 0 || byte > 255) {
					pending += ch;
					continue;
				}
				flush();
				bytes.push(byte);
				decoded = true;
				i += 3;
				continue;
			}
		}
		pending += ch;
	}
	if (!decoded) return value;
	flush();
	return Buffer.from(bytes).toString("utf8");
}
function isTailnetIPv4(address) {
	const parts = address.split(".");
	if (parts.length !== 4) return false;
	const octets = parts.map((p) => Number.parseInt(p, 10));
	if (octets.some((n) => !Number.isFinite(n) || n < 0 || n > 255)) return false;
	const [a, b] = octets;
	return a === 100 && b >= 64 && b <= 127;
}
function parseDigShortLines(stdout) {
	return stdout.split("\n").map((l) => l.trim()).filter(Boolean);
}
function parseDigTxt(stdout) {
	const tokens = [];
	for (const raw of stdout.split("\n")) {
		const line = raw.trim();
		if (!line) continue;
		const matches = Array.from(line.matchAll(/"([^"]*)"/g), (m) => m[1] ?? "");
		for (const m of matches) {
			const unescaped = m.replaceAll("\\\\", "\\").replaceAll("\\\"", "\"").replaceAll("\\n", "\n");
			tokens.push(unescaped);
		}
	}
	return tokens;
}
function parseDigSrv(stdout) {
	const line = stdout.split("\n").map((l) => l.trim()).find(Boolean);
	if (!line) return null;
	const parts = line.split(/\s+/).filter(Boolean);
	if (parts.length < 4) return null;
	const port = Number.parseInt(parts[2] ?? "", 10);
	const hostRaw = parts[3] ?? "";
	if (!Number.isFinite(port) || port <= 0) return null;
	const host = hostRaw.replace(/\.$/, "");
	if (!host) return null;
	return {
		host,
		port
	};
}
function parseTailscaleStatusIPv4s(stdout) {
	const parsed = stdout ? JSON.parse(stdout) : {};
	const out = [];
	const addIps = (value) => {
		if (!value || typeof value !== "object") return;
		const ips = value.TailscaleIPs;
		if (!Array.isArray(ips)) return;
		for (const ip of ips) {
			if (typeof ip !== "string") continue;
			const trimmed = ip.trim();
			if (trimmed && isTailnetIPv4(trimmed)) out.push(trimmed);
		}
	};
	addIps(parsed.Self);
	const peerObj = parsed.Peer;
	if (peerObj && typeof peerObj === "object") for (const peer of Object.values(peerObj)) addIps(peer);
	return [...new Set(out)];
}
function parseIntOrNull(value) {
	if (!value) return;
	const parsed = Number.parseInt(value, 10);
	return Number.isFinite(parsed) ? parsed : void 0;
}
function parseTxtTokens(tokens) {
	const txt = {};
	for (const token of tokens) {
		const idx = token.indexOf("=");
		if (idx <= 0) continue;
		const key = token.slice(0, idx).trim();
		const value = decodeDnsSdEscapes(token.slice(idx + 1).trim());
		if (!key) continue;
		txt[key] = value;
	}
	return txt;
}
function parseDnsSdBrowse(stdout) {
	const instances = /* @__PURE__ */ new Set();
	for (const raw of stdout.split("\n")) {
		const line = raw.trim();
		if (!line || !line.includes(GATEWAY_SERVICE_TYPE)) continue;
		if (!line.includes("Add")) continue;
		const match = line.match(/_edwin-gw\._tcp\.?\s+(.+)$/);
		if (match?.[1]) instances.add(decodeDnsSdEscapes(match[1].trim()));
	}
	return Array.from(instances.values());
}
function parseDnsSdResolve(stdout, instanceName) {
	const decodedInstanceName = decodeDnsSdEscapes(instanceName);
	const beacon = { instanceName: decodedInstanceName };
	let txt = {};
	for (const raw of stdout.split("\n")) {
		const line = raw.trim();
		if (!line) continue;
		if (line.includes("can be reached at")) {
			const match = line.match(/can be reached at\s+([^\s:]+):(\d+)/i);
			if (match?.[1]) beacon.host = match[1].replace(/\.$/, "");
			if (match?.[2]) beacon.port = parseIntOrNull(match[2]);
			continue;
		}
		if (line.startsWith("txt") || line.includes("txtvers=")) txt = parseTxtTokens(line.split(/\s+/).filter(Boolean));
	}
	beacon.txt = Object.keys(txt).length ? txt : void 0;
	if (txt.displayName) beacon.displayName = decodeDnsSdEscapes(txt.displayName);
	if (txt.lanHost) beacon.lanHost = txt.lanHost;
	if (txt.tailnetDns) beacon.tailnetDns = txt.tailnetDns;
	if (txt.cliPath) beacon.cliPath = txt.cliPath;
	beacon.gatewayPort = parseIntOrNull(txt.gatewayPort);
	beacon.sshPort = parseIntOrNull(txt.sshPort);
	if (txt.gatewayTls) {
		const raw = txt.gatewayTls.trim().toLowerCase();
		beacon.gatewayTls = raw === "1" || raw === "true" || raw === "yes";
	}
	if (txt.gatewayTlsSha256) beacon.gatewayTlsFingerprintSha256 = txt.gatewayTlsSha256;
	if (txt.role) beacon.role = txt.role;
	if (txt.transport) beacon.transport = txt.transport;
	if (!beacon.displayName) beacon.displayName = decodedInstanceName;
	return beacon;
}
async function discoverViaDnsSd(domain, timeoutMs, run) {
	const instances = parseDnsSdBrowse((await run([
		"dns-sd",
		"-B",
		GATEWAY_SERVICE_TYPE,
		domain
	], { timeoutMs })).stdout);
	const results = [];
	for (const instance of instances) {
		const parsed = parseDnsSdResolve((await run([
			"dns-sd",
			"-L",
			instance,
			GATEWAY_SERVICE_TYPE,
			domain
		], { timeoutMs })).stdout, instance);
		if (parsed) results.push({
			...parsed,
			domain
		});
	}
	return results;
}
async function discoverWideAreaViaTailnetDns(domain, timeoutMs, run) {
	if (!domain || domain === "local.") return [];
	const startedAt = Date.now();
	const remainingMs = () => timeoutMs - (Date.now() - startedAt);
	const tailscaleCandidates = ["tailscale", "/Applications/Tailscale.app/Contents/MacOS/Tailscale"];
	let ips = [];
	for (const candidate of tailscaleCandidates) try {
		ips = parseTailscaleStatusIPv4s((await run([
			candidate,
			"status",
			"--json"
		], { timeoutMs: Math.max(1, Math.min(700, remainingMs())) })).stdout);
		if (ips.length > 0) break;
	} catch {}
	if (ips.length === 0) return [];
	if (remainingMs() <= 0) return [];
	ips = ips.slice(0, 40);
	const probeName = `${GATEWAY_SERVICE_TYPE}.${domain.replace(/\.$/, "")}`;
	const concurrency = 6;
	let nextIndex = 0;
	let nameserver = null;
	let ptrs = [];
	const worker = async () => {
		while (nameserver === null) {
			const budget = remainingMs();
			if (budget <= 0) return;
			const i = nextIndex;
			nextIndex += 1;
			if (i >= ips.length) return;
			const ip = ips[i] ?? "";
			if (!ip) continue;
			try {
				const lines = parseDigShortLines((await run([
					"dig",
					"+short",
					"+time=1",
					"+tries=1",
					`@${ip}`,
					probeName,
					"PTR"
				], { timeoutMs: Math.max(1, Math.min(250, budget)) })).stdout);
				if (lines.length === 0) continue;
				nameserver = ip;
				ptrs = lines;
				return;
			} catch {}
		}
	};
	await Promise.all(Array.from({ length: Math.min(concurrency, ips.length) }, () => worker()));
	if (!nameserver || ptrs.length === 0) return [];
	if (remainingMs() <= 0) return [];
	const nameserverArg = `@${String(nameserver)}`;
	const results = [];
	for (const ptr of ptrs) {
		const budget = remainingMs();
		if (budget <= 0) break;
		const ptrName = ptr.trim().replace(/\.$/, "");
		if (!ptrName) continue;
		const instanceName = ptrName.replace(/\.?_edwin-gw\._tcp\..*$/, "");
		const srv = await run([
			"dig",
			"+short",
			"+time=1",
			"+tries=1",
			nameserverArg,
			ptrName,
			"SRV"
		], { timeoutMs: Math.max(1, Math.min(350, budget)) }).catch(() => null);
		const srvParsed = srv ? parseDigSrv(srv.stdout) : null;
		if (!srvParsed) continue;
		const txtBudget = remainingMs();
		if (txtBudget <= 0) {
			results.push({
				instanceName: instanceName || ptrName,
				displayName: instanceName || ptrName,
				domain,
				host: srvParsed.host,
				port: srvParsed.port
			});
			continue;
		}
		const txt = await run([
			"dig",
			"+short",
			"+time=1",
			"+tries=1",
			nameserverArg,
			ptrName,
			"TXT"
		], { timeoutMs: Math.max(1, Math.min(350, txtBudget)) }).catch(() => null);
		const txtTokens = txt ? parseDigTxt(txt.stdout) : [];
		const txtMap = txtTokens.length > 0 ? parseTxtTokens(txtTokens) : {};
		const beacon = {
			instanceName: instanceName || ptrName,
			displayName: txtMap.displayName || instanceName || ptrName,
			domain,
			host: srvParsed.host,
			port: srvParsed.port,
			txt: Object.keys(txtMap).length ? txtMap : void 0,
			gatewayPort: parseIntOrNull(txtMap.gatewayPort),
			sshPort: parseIntOrNull(txtMap.sshPort),
			tailnetDns: txtMap.tailnetDns || void 0,
			cliPath: txtMap.cliPath || void 0
		};
		if (txtMap.gatewayTls) {
			const raw = txtMap.gatewayTls.trim().toLowerCase();
			beacon.gatewayTls = raw === "1" || raw === "true" || raw === "yes";
		}
		if (txtMap.gatewayTlsSha256) beacon.gatewayTlsFingerprintSha256 = txtMap.gatewayTlsSha256;
		if (txtMap.role) beacon.role = txtMap.role;
		if (txtMap.transport) beacon.transport = txtMap.transport;
		results.push(beacon);
	}
	return results;
}
function parseAvahiBrowse(stdout) {
	const results = [];
	let current = null;
	for (const raw of stdout.split("\n")) {
		const line = raw.trimEnd();
		if (!line) continue;
		if (line.startsWith("=") && line.includes(GATEWAY_SERVICE_TYPE)) {
			if (current) results.push(current);
			const marker = ` ${GATEWAY_SERVICE_TYPE}`;
			const idx = line.indexOf(marker);
			const left = idx >= 0 ? line.slice(0, idx).trim() : line;
			const parts = left.split(/\s+/);
			const instanceName = parts.length > 3 ? parts.slice(3).join(" ") : left;
			current = {
				instanceName,
				displayName: instanceName
			};
			continue;
		}
		if (!current) continue;
		const trimmed = line.trim();
		if (trimmed.startsWith("hostname =")) {
			const match = trimmed.match(/hostname\s*=\s*\[([^\]]+)\]/);
			if (match?.[1]) current.host = match[1];
			continue;
		}
		if (trimmed.startsWith("port =")) {
			const match = trimmed.match(/port\s*=\s*\[(\d+)\]/);
			if (match?.[1]) current.port = parseIntOrNull(match[1]);
			continue;
		}
		if (trimmed.startsWith("txt =")) {
			const txt = parseTxtTokens(Array.from(trimmed.matchAll(/"([^"]*)"/g), (m) => m[1]));
			current.txt = Object.keys(txt).length ? txt : void 0;
			if (txt.displayName) current.displayName = txt.displayName;
			if (txt.lanHost) current.lanHost = txt.lanHost;
			if (txt.tailnetDns) current.tailnetDns = txt.tailnetDns;
			if (txt.cliPath) current.cliPath = txt.cliPath;
			current.gatewayPort = parseIntOrNull(txt.gatewayPort);
			current.sshPort = parseIntOrNull(txt.sshPort);
			if (txt.gatewayTls) {
				const raw = txt.gatewayTls.trim().toLowerCase();
				current.gatewayTls = raw === "1" || raw === "true" || raw === "yes";
			}
			if (txt.gatewayTlsSha256) current.gatewayTlsFingerprintSha256 = txt.gatewayTlsSha256;
			if (txt.role) current.role = txt.role;
			if (txt.transport) current.transport = txt.transport;
		}
	}
	if (current) results.push(current);
	return results;
}
async function discoverViaAvahi(domain, timeoutMs, run) {
	const args = [
		"avahi-browse",
		"-rt",
		GATEWAY_SERVICE_TYPE
	];
	if (domain && domain !== "local.") args.push("-d", domain.replace(/\.$/, ""));
	return parseAvahiBrowse((await run(args, { timeoutMs })).stdout).map((beacon) => ({
		...beacon,
		domain
	}));
}
async function discoverGatewayBeacons(opts = {}) {
	const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
	const platform = opts.platform ?? process.platform;
	const run = opts.run ?? runCommandWithTimeout;
	const wideAreaDomain = resolveWideAreaDiscoveryDomain({ configDomain: opts.wideAreaDomain });
	const domainsRaw = Array.isArray(opts.domains) ? opts.domains : [];
	const defaultDomains = ["local.", ...wideAreaDomain ? [wideAreaDomain] : []];
	const domains = (domainsRaw.length > 0 ? domainsRaw : defaultDomains).map((d) => String(d).trim()).filter(Boolean).map((d) => d.endsWith(".") ? d : `${d}.`);
	try {
		if (platform === "darwin") {
			const discovered = (await Promise.allSettled(domains.map(async (domain) => await discoverViaDnsSd(domain, timeoutMs, run)))).flatMap((r) => r.status === "fulfilled" ? r.value : []);
			const wantsWideArea = wideAreaDomain ? domains.includes(wideAreaDomain) : false;
			const hasWideArea = wideAreaDomain ? discovered.some((b) => b.domain === wideAreaDomain) : false;
			if (wantsWideArea && !hasWideArea && wideAreaDomain) {
				const fallback = await discoverWideAreaViaTailnetDns(wideAreaDomain, timeoutMs, run).catch(() => []);
				return [...discovered, ...fallback];
			}
			return discovered;
		}
		if (platform === "linux") return (await Promise.allSettled(domains.map(async (domain) => await discoverViaAvahi(domain, timeoutMs, run)))).flatMap((r) => r.status === "fulfilled" ? r.value : []);
	} catch {
		return [];
	}
	return [];
}

//#endregion
//#region ../../src/commands/onboard-remote.ts
const DEFAULT_GATEWAY_URL = "ws://127.0.0.1:18789";
function pickHost(beacon) {
	return beacon.tailnetDns || beacon.lanHost || beacon.host;
}
function buildLabel(beacon) {
	const host = pickHost(beacon);
	const port = beacon.gatewayPort ?? beacon.port ?? 18789;
	return `${beacon.displayName ?? beacon.instanceName} (${host ? `${host}:${port}` : "host unknown"})`;
}
function ensureWsUrl(value) {
	const trimmed = value.trim();
	if (!trimmed) return DEFAULT_GATEWAY_URL;
	return trimmed;
}
async function promptRemoteGatewayConfig(cfg, prompter) {
	let selectedBeacon = null;
	let suggestedUrl = cfg.gateway?.remote?.url ?? DEFAULT_GATEWAY_URL;
	const hasBonjourTool = await detectBinary("dns-sd") || await detectBinary("avahi-browse");
	const wantsDiscover = hasBonjourTool ? await prompter.confirm({
		message: "Discover gateway on LAN (Bonjour)?",
		initialValue: true
	}) : false;
	if (!hasBonjourTool) await prompter.note(["Bonjour discovery requires dns-sd (macOS) or avahi-browse (Linux).", "Docs: https://docs.edwinpai.com/gateway/discovery"].join("\n"), "Discovery");
	if (wantsDiscover) {
		const wideAreaDomain = resolveWideAreaDiscoveryDomain({ configDomain: cfg.discovery?.wideArea?.domain });
		const spin = prompter.progress("Searching for gateways…");
		const beacons = await discoverGatewayBeacons({
			timeoutMs: 2e3,
			wideAreaDomain
		});
		spin.stop(beacons.length > 0 ? `Found ${beacons.length} gateway(s)` : "No gateways found");
		if (beacons.length > 0) {
			const selection = await prompter.select({
				message: "Select gateway",
				options: [...beacons.map((beacon, index) => ({
					value: String(index),
					label: buildLabel(beacon)
				})), {
					value: "manual",
					label: "Enter URL manually"
				}]
			});
			if (selection !== "manual") {
				const idx = Number.parseInt(String(selection), 10);
				selectedBeacon = Number.isFinite(idx) ? beacons[idx] ?? null : null;
			}
		}
	}
	if (selectedBeacon) {
		const host = pickHost(selectedBeacon);
		const port = selectedBeacon.gatewayPort ?? 18789;
		if (host) if (await prompter.select({
			message: "Connection method",
			options: [{
				value: "direct",
				label: `Direct gateway WS (${host}:${port})`
			}, {
				value: "ssh",
				label: "SSH tunnel (loopback)"
			}]
		}) === "direct") suggestedUrl = `ws://${host}:${port}`;
		else {
			suggestedUrl = DEFAULT_GATEWAY_URL;
			await prompter.note([
				"Start a tunnel before using the CLI:",
				`ssh -N -L 18789:127.0.0.1:18789 <user>@${host}${selectedBeacon.sshPort ? ` -p ${selectedBeacon.sshPort}` : ""}`,
				"Docs: https://docs.edwinpai.com/gateway/remote"
			].join("\n"), "SSH tunnel");
		}
	}
	const urlInput = await prompter.text({
		message: "Gateway WebSocket URL",
		initialValue: suggestedUrl,
		validate: (value) => String(value).trim().startsWith("ws://") || String(value).trim().startsWith("wss://") ? void 0 : "URL must start with ws:// or wss://"
	});
	const url = ensureWsUrl(String(urlInput));
	const authChoice = await prompter.select({
		message: "Gateway auth",
		options: [{
			value: "token",
			label: "Token (recommended)"
		}, {
			value: "off",
			label: "No auth"
		}]
	});
	let token = cfg.gateway?.remote?.token ?? "";
	if (authChoice === "token") token = String(await prompter.text({
		message: "Gateway token",
		initialValue: token,
		validate: (value) => value?.trim() ? void 0 : "Required"
	})).trim();
	else token = "";
	return {
		...cfg,
		gateway: {
			...cfg.gateway,
			mode: "remote",
			remote: {
				url,
				token: token || void 0
			}
		}
	};
}

//#endregion
//#region ../../src/agents/skills-install.ts
function isNodeReadableStream(value) {
	return Boolean(value && typeof value.pipe === "function");
}
function summarizeInstallOutput(text) {
	const raw = text.trim();
	if (!raw) return;
	const lines = raw.split("\n").map((line) => line.trim()).filter(Boolean);
	if (lines.length === 0) return;
	const preferred = lines.find((line) => /^error\b/i.test(line)) ?? lines.find((line) => /\b(err!|error:|failed)\b/i.test(line)) ?? lines.at(-1);
	if (!preferred) return;
	const normalized = preferred.replace(/\s+/g, " ").trim();
	const maxLen = 200;
	return normalized.length > maxLen ? `${normalized.slice(0, maxLen - 1)}…` : normalized;
}
function formatInstallFailureMessage(result) {
	const code = typeof result.code === "number" ? `exit ${result.code}` : "unknown exit";
	const summary = summarizeInstallOutput(result.stderr) ?? summarizeInstallOutput(result.stdout);
	if (!summary) return `Install failed (${code})`;
	return `Install failed (${code}): ${summary}`;
}
function resolveInstallId(spec, index) {
	return (spec.id ?? `${spec.kind}-${index}`).trim();
}
function findInstallSpec(entry, installId) {
	const specs = entry.metadata?.install ?? [];
	for (const [index, spec] of specs.entries()) if (resolveInstallId(spec, index) === installId) return spec;
}
function buildNodeInstallCommand(packageName, prefs) {
	switch (prefs.nodeManager) {
		case "pnpm": return [
			"pnpm",
			"add",
			"-g",
			packageName
		];
		case "yarn": return [
			"yarn",
			"global",
			"add",
			packageName
		];
		case "bun": return [
			"bun",
			"add",
			"-g",
			packageName
		];
		default: return [
			"npm",
			"install",
			"-g",
			packageName
		];
	}
}
function buildInstallCommand(spec, prefs) {
	switch (spec.kind) {
		case "brew":
			if (!spec.formula) return {
				argv: null,
				error: "missing brew formula"
			};
			return { argv: [
				"brew",
				"install",
				spec.formula
			] };
		case "node":
			if (!spec.package) return {
				argv: null,
				error: "missing node package"
			};
			return { argv: buildNodeInstallCommand(spec.package, prefs) };
		case "go":
			if (!spec.module) return {
				argv: null,
				error: "missing go module"
			};
			return { argv: [
				"go",
				"install",
				spec.module
			] };
		case "uv":
			if (!spec.package) return {
				argv: null,
				error: "missing uv package"
			};
			return { argv: [
				"uv",
				"tool",
				"install",
				spec.package
			] };
		case "download": return {
			argv: null,
			error: "download install handled separately"
		};
		default: return {
			argv: null,
			error: "unsupported installer"
		};
	}
}
function resolveDownloadTargetDir(entry, spec) {
	if (spec.targetDir?.trim()) return resolveUserPath(spec.targetDir);
	const key = resolveSkillKey(entry.skill, entry);
	return path.join(CONFIG_DIR, "tools", key);
}
function resolveArchiveType(spec, filename) {
	const explicit = spec.archive?.trim().toLowerCase();
	if (explicit) return explicit;
	const lower = filename.toLowerCase();
	if (lower.endsWith(".tar.gz") || lower.endsWith(".tgz")) return "tar.gz";
	if (lower.endsWith(".tar.bz2") || lower.endsWith(".tbz2")) return "tar.bz2";
	if (lower.endsWith(".zip")) return "zip";
}
async function downloadFile(url, destPath, timeoutMs) {
	const { response, release } = await fetchWithSsrFGuard({
		url,
		timeoutMs: Math.max(1e3, timeoutMs)
	});
	try {
		if (!response.ok || !response.body) throw new Error(`Download failed (${response.status} ${response.statusText})`);
		await ensureDir(path.dirname(destPath));
		const file = fs.createWriteStream(destPath);
		const body = response.body;
		await pipeline(isNodeReadableStream(body) ? body : Readable.fromWeb(body), file);
		return { bytes: (await fs.promises.stat(destPath)).size };
	} finally {
		await release();
	}
}
async function extractArchive(params) {
	const { archivePath, archiveType, targetDir, stripComponents, timeoutMs } = params;
	if (archiveType === "zip") {
		if (!hasBinary("unzip")) return {
			stdout: "",
			stderr: "unzip not found on PATH",
			code: null
		};
		return await runCommandWithTimeout([
			"unzip",
			"-q",
			archivePath,
			"-d",
			targetDir
		], { timeoutMs });
	}
	if (!hasBinary("tar")) return {
		stdout: "",
		stderr: "tar not found on PATH",
		code: null
	};
	const argv = [
		"tar",
		"xf",
		archivePath,
		"-C",
		targetDir
	];
	if (typeof stripComponents === "number" && Number.isFinite(stripComponents)) argv.push("--strip-components", String(Math.max(0, Math.floor(stripComponents))));
	return await runCommandWithTimeout(argv, { timeoutMs });
}
async function installDownloadSpec(params) {
	const { entry, spec, timeoutMs } = params;
	const url = spec.url?.trim();
	if (!url) return {
		ok: false,
		message: "missing download url",
		stdout: "",
		stderr: "",
		code: null
	};
	let filename = "";
	try {
		const parsed = new URL(url);
		filename = path.basename(parsed.pathname);
	} catch {
		filename = path.basename(url);
	}
	if (!filename) filename = "download";
	const targetDir = resolveDownloadTargetDir(entry, spec);
	await ensureDir(targetDir);
	const archivePath = path.join(targetDir, filename);
	let downloaded = 0;
	try {
		downloaded = (await downloadFile(url, archivePath, timeoutMs)).bytes;
	} catch (err) {
		const message = err instanceof Error ? err.message : String(err);
		return {
			ok: false,
			message,
			stdout: "",
			stderr: message,
			code: null
		};
	}
	const archiveType = resolveArchiveType(spec, filename);
	if (!(spec.extract ?? Boolean(archiveType))) return {
		ok: true,
		message: `Downloaded to ${archivePath}`,
		stdout: `downloaded=${downloaded}`,
		stderr: "",
		code: 0
	};
	if (!archiveType) return {
		ok: false,
		message: "extract requested but archive type could not be detected",
		stdout: "",
		stderr: "",
		code: null
	};
	const extractResult = await extractArchive({
		archivePath,
		archiveType,
		targetDir,
		stripComponents: spec.stripComponents,
		timeoutMs
	});
	const success = extractResult.code === 0;
	return {
		ok: success,
		message: success ? `Downloaded and extracted to ${targetDir}` : formatInstallFailureMessage(extractResult),
		stdout: extractResult.stdout.trim(),
		stderr: extractResult.stderr.trim(),
		code: extractResult.code
	};
}
async function resolveBrewBinDir(timeoutMs, brewExe) {
	const exe = brewExe ?? (hasBinary("brew") ? "brew" : resolveBrewExecutable());
	if (!exe) return;
	const prefixResult = await runCommandWithTimeout([exe, "--prefix"], { timeoutMs: Math.min(timeoutMs, 3e4) });
	if (prefixResult.code === 0) {
		const prefix = prefixResult.stdout.trim();
		if (prefix) return path.join(prefix, "bin");
	}
	const envPrefix = process.env.HOMEBREW_PREFIX?.trim();
	if (envPrefix) return path.join(envPrefix, "bin");
	for (const candidate of ["/opt/homebrew/bin", "/usr/local/bin"]) try {
		if (fs.existsSync(candidate)) return candidate;
	} catch {}
}
async function installSkill(params) {
	const timeoutMs = Math.min(Math.max(params.timeoutMs ?? 3e5, 1e3), 9e5);
	const entry = loadWorkspaceSkillEntries(resolveUserPath(params.workspaceDir)).find((item) => item.skill.name === params.skillName);
	if (!entry) return {
		ok: false,
		message: `Skill not found: ${params.skillName}`,
		stdout: "",
		stderr: "",
		code: null
	};
	const spec = findInstallSpec(entry, params.installId);
	if (!spec) return {
		ok: false,
		message: `Installer not found: ${params.installId}`,
		stdout: "",
		stderr: "",
		code: null
	};
	if (spec.kind === "download") return await installDownloadSpec({
		entry,
		spec,
		timeoutMs
	});
	const command = buildInstallCommand(spec, resolveSkillsInstallPreferences(params.config));
	if (command.error) return {
		ok: false,
		message: command.error,
		stdout: "",
		stderr: "",
		code: null
	};
	const brewExe = hasBinary("brew") ? "brew" : resolveBrewExecutable();
	if (spec.kind === "brew" && !brewExe) return {
		ok: false,
		message: "brew not installed",
		stdout: "",
		stderr: "",
		code: null
	};
	if (spec.kind === "uv" && !hasBinary("uv")) if (brewExe) {
		const brewResult = await runCommandWithTimeout([
			brewExe,
			"install",
			"uv"
		], { timeoutMs });
		if (brewResult.code !== 0) return {
			ok: false,
			message: "Failed to install uv (brew)",
			stdout: brewResult.stdout.trim(),
			stderr: brewResult.stderr.trim(),
			code: brewResult.code
		};
	} else return {
		ok: false,
		message: "uv not installed (install via brew)",
		stdout: "",
		stderr: "",
		code: null
	};
	if (!command.argv || command.argv.length === 0) return {
		ok: false,
		message: "invalid install command",
		stdout: "",
		stderr: "",
		code: null
	};
	if (spec.kind === "brew" && brewExe && command.argv[0] === "brew") command.argv[0] = brewExe;
	if (spec.kind === "go" && !hasBinary("go")) if (brewExe) {
		const brewResult = await runCommandWithTimeout([
			brewExe,
			"install",
			"go"
		], { timeoutMs });
		if (brewResult.code !== 0) return {
			ok: false,
			message: "Failed to install go (brew)",
			stdout: brewResult.stdout.trim(),
			stderr: brewResult.stderr.trim(),
			code: brewResult.code
		};
	} else return {
		ok: false,
		message: "go not installed (install via brew)",
		stdout: "",
		stderr: "",
		code: null
	};
	let env;
	if (spec.kind === "go" && brewExe) {
		const brewBin = await resolveBrewBinDir(timeoutMs, brewExe);
		if (brewBin) env = { GOBIN: brewBin };
	}
	const result = await (async () => {
		const argv = command.argv;
		if (!argv || argv.length === 0) return {
			code: null,
			stdout: "",
			stderr: "invalid install command"
		};
		try {
			return await runCommandWithTimeout(argv, {
				timeoutMs,
				env
			});
		} catch (err) {
			return {
				code: null,
				stdout: "",
				stderr: err instanceof Error ? err.message : String(err)
			};
		}
	})();
	const success = result.code === 0;
	return {
		ok: success,
		message: success ? "Installed" : formatInstallFailureMessage(result),
		stdout: result.stdout.trim(),
		stderr: result.stderr.trim(),
		code: result.code
	};
}

//#endregion
//#region ../../src/commands/onboard-skills.ts
function summarizeInstallFailure(message) {
	const cleaned = message.replace(/^Install failed(?:\s*\([^)]*\))?\s*:?\s*/i, "").trim();
	if (!cleaned) return;
	const maxLen = 140;
	return cleaned.length > maxLen ? `${cleaned.slice(0, maxLen - 1)}…` : cleaned;
}
function formatSkillHint(skill) {
	const desc = skill.description?.trim();
	const installLabel = skill.install[0]?.label?.trim();
	const combined = desc && installLabel ? `${desc} — ${installLabel}` : desc || installLabel;
	if (!combined) return "install";
	const maxLen = 90;
	return combined.length > maxLen ? `${combined.slice(0, maxLen - 1)}…` : combined;
}
function upsertSkillEntry(cfg, skillKey, patch) {
	const entries = { ...cfg.skills?.entries };
	entries[skillKey] = {
		...entries[skillKey] ?? {},
		...patch
	};
	return {
		...cfg,
		skills: {
			...cfg.skills,
			entries
		}
	};
}
async function setupSkills(cfg, workspaceDir, runtime, prompter) {
	const report = buildWorkspaceSkillStatus(workspaceDir, { config: cfg });
	const eligible = report.skills.filter((s) => s.eligible);
	const missing = report.skills.filter((s) => !s.eligible && !s.disabled && !s.blockedByAllowlist);
	const blocked = report.skills.filter((s) => s.blockedByAllowlist);
	const needsBrewPrompt = process.platform !== "win32" && report.skills.some((skill) => skill.install.some((option) => option.kind === "brew")) && !await detectBinary("brew");
	await prompter.note([
		`Eligible: ${eligible.length}`,
		`Missing requirements: ${missing.length}`,
		`Blocked by allowlist: ${blocked.length}`
	].join("\n"), "Skills status");
	if (!await prompter.confirm({
		message: "Configure skills now? (recommended)",
		initialValue: true
	})) return cfg;
	if (needsBrewPrompt) {
		await prompter.note(["Many skill dependencies are shipped via Homebrew.", "Without brew, you'll need to build from source or download releases manually."].join("\n"), "Homebrew recommended");
		if (await prompter.confirm({
			message: "Show Homebrew install command?",
			initialValue: true
		})) await prompter.note(["Run:", "/bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""].join("\n"), "Homebrew install");
	}
	const nodeManager = await prompter.select({
		message: "Preferred node manager for skill installs",
		options: resolveNodeManagerOptions()
	});
	let next = {
		...cfg,
		skills: {
			...cfg.skills,
			install: {
				...cfg.skills?.install,
				nodeManager
			}
		}
	};
	const installable = missing.filter((skill) => skill.install.length > 0 && skill.missing.bins.length > 0);
	if (installable.length > 0) {
		const selected = (await prompter.multiselect({
			message: "Install missing skill dependencies",
			options: [{
				value: "__skip__",
				label: "Skip for now",
				hint: "Continue without installing dependencies"
			}, ...installable.map((skill) => ({
				value: skill.name,
				label: `${skill.emoji ?? "🧩"} ${skill.name}`,
				hint: formatSkillHint(skill)
			}))]
		})).filter((name) => name !== "__skip__");
		for (const name of selected) {
			const target = installable.find((s) => s.name === name);
			if (!target || target.install.length === 0) continue;
			const installId = target.install[0]?.id;
			if (!installId) continue;
			const spin = prompter.progress(`Installing ${name}…`);
			const result = await installSkill({
				workspaceDir,
				skillName: target.name,
				installId,
				config: next
			});
			if (result.ok) spin.stop(`Installed ${name}`);
			else {
				const code = result.code == null ? "" : ` (exit ${result.code})`;
				const detail = summarizeInstallFailure(result.message);
				spin.stop(`Install failed: ${name}${code}${detail ? ` — ${detail}` : ""}`);
				if (result.stderr) runtime.log(result.stderr.trim());
				else if (result.stdout) runtime.log(result.stdout.trim());
				runtime.log(`Tip: run \`${formatCliCommand("edwinpai doctor")}\` to review skills + requirements.`);
				runtime.log("Docs: https://docs.edwinpai.com/skills");
			}
		}
	}
	for (const skill of missing) {
		if (!skill.primaryEnv || skill.missing.env.length === 0) continue;
		if (!await prompter.confirm({
			message: `Set ${skill.primaryEnv} for ${skill.name}?`,
			initialValue: false
		})) continue;
		const apiKey = String(await prompter.text({
			message: `Enter ${skill.primaryEnv}`,
			validate: (value) => value?.trim() ? void 0 : "Required"
		}));
		next = upsertSkillEntry(next, skill.skillKey, { apiKey: apiKey.trim() });
	}
	return next;
}

//#endregion
export { applyModelAllowlist as a, promptDefaultModel as c, warnIfModelConfigLooksOff as d, applyAuthChoice as f, discoverGatewayBeacons as i, promptModelAllowlist as l, promptAuthChoiceGrouped as m, installSkill as n, applyModelFallbacksFromSelection as o, applyGoogleGeminiModelDefault as p, promptRemoteGatewayConfig as r, applyPrimaryModel as s, setupSkills as t, resolvePreferredProviderForAuthChoice as u };