import { __esmMin, __exportAll, __require } from "../../../_virtual/_rolldown/runtime.js";
import { createLogger } from "../../utils/logger/index.js";
import { init_logger } from "../../utils/logger.js";
import { join } from "path";
import { existsSync } from "fs";
import { promisify } from "util";
import { exec } from "child_process";
//#region src/agent/skills/installer.ts
/**
* Skill Installer
* 
* Handles installation of skill dependencies via various package managers.
*
*/
var installer_exports = /* @__PURE__ */ __exportAll({
	findInstallSpec: () => findInstallSpec,
	getDefaultInstallerPreferences: () => getDefaultInstallerPreferences,
	hasBinary: () => hasBinary,
	installSkill: () => installSkill,
	resolveBrewExecutable: () => resolveBrewExecutable
});
/**
* Check if a binary exists
*/
function hasBinary(name) {
	try {
		const { which } = __require("which");
		return !!which.sync(name, { nothrow: true });
	} catch {
		try {
			const { execSync } = __require("child_process");
			execSync(`which ${name}`, { stdio: "ignore" });
			return true;
		} catch {
			return false;
		}
	}
}
/**
* Resolve brew executable path
*/
function resolveBrewExecutable() {
	for (const candidate of ["/opt/homebrew/bin/brew", "/usr/local/bin/brew"]) if (existsSync(candidate)) return candidate;
}
/**
* Build install command for Node.js packages
*/
function buildNodeInstallCommand(packageName, manager) {
	switch (manager) {
		case "pnpm": return [
			"pnpm",
			"add",
			"-g",
			"--ignore-scripts",
			packageName
		];
		case "yarn": return [
			"yarn",
			"global",
			"add",
			"--ignore-scripts",
			packageName
		];
		case "bun": return [
			"bun",
			"add",
			"-g",
			"--ignore-scripts",
			packageName
		];
		default: return [
			"npm",
			"install",
			"-g",
			"--ignore-scripts",
			packageName
		];
	}
}
/**
* Build install command from spec
*/
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 "pnpm":
		case "npm":
		case "yarn":
		case "bun":
			if (!spec.package) return {
				argv: null,
				error: "Missing package name"
			};
			return { argv: buildNodeInstallCommand(spec.package, prefs.nodeManager) };
		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:
			spec.kind;
			return {
				argv: null,
				error: `Unsupported installer: ${spec.kind}`
			};
	}
}
/**
* Run command with timeout
*/
async function runCommandWithTimeout(argv, timeoutMs, env) {
	const [cmd, ...args] = argv;
	try {
		const { stdout, stderr } = await execAsync(`${cmd} ${args.join(" ")}`, {
			timeout: timeoutMs,
			env,
			maxBuffer: 10 * 1024 * 1024
		});
		return {
			code: 0,
			stdout: stdout.toString(),
			stderr: stderr.toString()
		};
	} catch (err) {
		if (err instanceof Error) {
			const execError = err;
			return {
				code: execError.code ?? null,
				stdout: execError.stdout?.toString() ?? "",
				stderr: execError.stderr?.toString() ?? ""
			};
		}
		return {
			code: null,
			stdout: "",
			stderr: err instanceof Error ? err.message : String(err)
		};
	}
}
/**
* Ensure uv is installed
*/
async function ensureUvInstalled(timeoutMs) {
	if (hasBinary("uv")) return;
	const brewExe = resolveBrewExecutable();
	if (!brewExe) return {
		ok: false,
		message: "uv not installed — install manually: https://docs.astral.sh/uv/getting-started/installation/",
		stdout: "",
		stderr: "",
		code: null
	};
	const result = await runCommandWithTimeout([
		brewExe,
		"install",
		"uv"
	], timeoutMs);
	if (result.code === 0) return;
	return {
		ok: false,
		message: "Failed to install uv (brew)",
		stdout: result.stdout,
		stderr: result.stderr,
		code: result.code
	};
}
/**
* Ensure Go is installed
*/
async function ensureGoInstalled(timeoutMs) {
	if (hasBinary("go")) return;
	const brewExe = resolveBrewExecutable();
	if (brewExe) {
		const result = await runCommandWithTimeout([
			brewExe,
			"install",
			"go"
		], timeoutMs);
		if (result.code === 0) return;
		return {
			ok: false,
			message: "Failed to install go (brew)",
			stdout: result.stdout,
			stderr: result.stderr,
			code: result.code
		};
	}
	if (hasBinary("apt-get")) {
		const isRoot = process.getuid?.() === 0;
		const aptCmd = isRoot ? [
			"apt-get",
			"install",
			"-y",
			"golang-go"
		] : [
			"sudo",
			"apt-get",
			"install",
			"-y",
			"golang-go"
		];
		if (!isRoot) await runCommandWithTimeout([
			"sudo",
			"apt-get",
			"update",
			"-qq"
		], Math.min(timeoutMs, 3e4));
		const result = await runCommandWithTimeout(aptCmd, timeoutMs);
		if (result.code === 0) return;
		return {
			ok: false,
			message: "go not installed — automatic install via apt failed. Install manually: https://go.dev/doc/install",
			stdout: result.stdout,
			stderr: result.stderr,
			code: result.code
		};
	}
	return {
		ok: false,
		message: "go not installed — install manually: https://go.dev/doc/install",
		stdout: "",
		stderr: "",
		code: null
	};
}
/**
* Create install failure result
*/
function createInstallFailure(params) {
	return {
		ok: false,
		message: params.message,
		stdout: params.stdout?.trim() ?? "",
		stderr: params.stderr?.trim() ?? "",
		code: params.code ?? null
	};
}
/**
* Create install success result
*/
function createInstallSuccess(result) {
	return {
		ok: true,
		message: "Installed",
		stdout: result.stdout.trim(),
		stderr: result.stderr.trim(),
		code: result.code
	};
}
/**
* Find install spec by ID
*/
function findInstallSpec(entry, installId) {
	const specs = entry.metadata.install ?? [];
	for (const [index, spec] of specs.entries()) if ((spec.id ?? `${spec.kind}-${index}`) === installId) return spec;
}
/**
* Install a skill dependency
*/
async function installSkill(ctx) {
	const { installSpec, timeoutMs, preferences } = ctx;
	log.info({
		skill: ctx.skillEntry.skill.name,
		kind: installSpec.kind
	}, "Installing skill dependency");
	if (installSpec.kind === "download") return createInstallFailure({ message: "Download installer not yet implemented" });
	if (installSpec.kind === "uv") {
		const uvFailure = await ensureUvInstalled(timeoutMs);
		if (uvFailure) return uvFailure;
	}
	if (installSpec.kind === "go") {
		const goFailure = await ensureGoInstalled(timeoutMs);
		if (goFailure) return goFailure;
	}
	const command = buildInstallCommand(installSpec, preferences);
	if (command.error) return createInstallFailure({ message: command.error });
	if (!command.argv) return createInstallFailure({ message: "Invalid install command" });
	let argv = [...command.argv];
	if (installSpec.kind === "brew") {
		const brewExe = resolveBrewExecutable();
		if (!brewExe) return createInstallFailure({ message: `brew not installed — ${process.platform === "linux" ? "Homebrew is not installed. Install it from https://brew.sh or use your system package manager." : "Homebrew is not installed. Install it from https://brew.sh"}` });
		argv[0] = brewExe;
	}
	let env;
	if (installSpec.kind === "go") {
		const brewExe = resolveBrewExecutable();
		if (brewExe) try {
			const { stdout } = await execAsync(`${brewExe} --prefix`);
			const prefix = stdout.trim();
			if (prefix) env = {
				...process.env,
				GOBIN: join(prefix, "bin")
			};
		} catch {}
	}
	const result = await runCommandWithTimeout(argv, timeoutMs, env);
	if (result.code === 0) {
		log.info({ skill: ctx.skillEntry.skill.name }, "Skill dependency installed successfully");
		return createInstallSuccess(result);
	}
	log.warn({
		skill: ctx.skillEntry.skill.name,
		stderr: result.stderr
	}, "Skill dependency installation failed");
	return createInstallFailure({
		message: result.stderr || `Installation failed with exit code ${result.code}`,
		stdout: result.stdout,
		stderr: result.stderr,
		code: result.code
	});
}
/**
* Get default installer preferences from config
*/
function getDefaultInstallerPreferences() {
	return {
		preferBrew: true,
		nodeManager: "pnpm"
	};
}
var execAsync, log;
var init_installer = __esmMin((() => {
	init_logger();
	execAsync = promisify(exec);
	log = createLogger("SkillInstaller");
}));
//#endregion
init_installer();
export { findInstallSpec, getDefaultInstallerPreferences, hasBinary, init_installer, installSkill, installer_exports, resolveBrewExecutable };

//# sourceMappingURL=installer.js.map