import { j as json } from './exports-D1quPX8S.js';
import { spawn } from 'node:child_process';
import './utils-BSRjJDrZ.js';

//#region src/routes/api/setup/opencode/ensure/+server.ts
/**
* POST /api/setup/opencode/ensure
*
* Ensures an OpenCode server is running for the setup wizard.
* 1. Checks the configured OP_OPENCODE_URL / OP_ASSISTANT_PORT first.
* 2. If unreachable, starts a dedicated `opencode serve` subprocess via the SDK.
* 3. Returns { ok, url, started } — client updates its OP_OPENCODE_URL accordingly.
*
* No auth required — called during pre-setup wizard initialization.
*/
var _url = null;
var _proc = null;
var _inFlight = null;
function killWizardOpencode() {
	const proc = _proc;
	if (proc && proc.exitCode === null && proc.pid) try {
		proc.kill("SIGTERM");
	} catch {}
	_proc = null;
	_url = null;
}
if (!globalThis.__opWizardOpencodeReaper) {
	globalThis.__opWizardOpencodeReaper = true;
	process.on("SIGTERM", killWizardOpencode);
	process.on("SIGINT", killWizardOpencode);
	process.on("exit", killWizardOpencode);
}
async function checkReachable(url) {
	try {
		return (await fetch(`${url}/provider`, { signal: AbortSignal.timeout(2e3) })).ok;
	} catch {
		return false;
	}
}
async function stopWizardOpencode(proc) {
	if (!proc || proc.exitCode !== null || !proc.pid) return;
	try {
		proc.kill("SIGTERM");
	} catch {
		return;
	}
	await Promise.race([new Promise((resolve) => proc.once("exit", () => resolve())), new Promise((resolve) => setTimeout(resolve, 2e3))]);
}
function spawnOpencodeServer() {
	return new Promise((resolve, reject) => {
		const proc = spawn("opencode", [
			"serve",
			"--hostname=127.0.0.1",
			"--port=0"
		], {
			env: process.env,
			stdio: [
				"ignore",
				"pipe",
				"pipe"
			]
		});
		_proc = proc;
		let resolved = false;
		const timer = setTimeout(() => {
			proc.kill();
			reject(/* @__PURE__ */ new Error("Timed out waiting for OpenCode server to start (15s)"));
		}, 15e3);
		let out = "";
		proc.stdout?.on("data", (chunk) => {
			out += chunk.toString();
			for (const line of out.split("\n")) if (line.includes("server listening")) {
				const m = line.match(/on\s+(https?:\/\/[^\s]+)/);
				if (m) {
					resolved = true;
					clearTimeout(timer);
					resolve(m[1]);
				}
			}
		});
		proc.on("exit", (code) => {
			clearTimeout(timer);
			if (_proc === proc) {
				_proc = null;
				_url = null;
			}
			if (!resolved && code !== 0) reject(/* @__PURE__ */ new Error(`OpenCode exited (code ${code}). Output: ${out.slice(0, 300)}`));
		});
		proc.on("error", (err) => {
			clearTimeout(timer);
			if (_proc === proc) {
				_proc = null;
				_url = null;
			}
			reject(err);
		});
	});
}
var POST = async () => {
	const configuredUrl = process.env.OP_OPENCODE_URL ?? process.env.OP_ASSISTANT_URL ?? `http://127.0.0.1:${process.env.OP_ASSISTANT_PORT ?? "3800"}`;
	if (await checkReachable(configuredUrl)) return json({
		ok: true,
		url: configuredUrl,
		started: false
	});
	if (_url && await checkReachable(_url)) return json({
		ok: true,
		url: _url,
		started: false
	});
	if (_inFlight) try {
		return json({
			ok: true,
			...await _inFlight
		});
	} catch (err) {
		return json({
			ok: false,
			error: err instanceof Error ? err.message : "Failed to start OpenCode"
		});
	}
	try {
		_inFlight = (async () => {
			await stopWizardOpencode(_proc);
			const url = await spawnOpencodeServer();
			_url = url;
			return {
				url,
				started: true
			};
		})();
		const { url, started } = await _inFlight;
		_inFlight = null;
		_url = url;
		return json({
			ok: true,
			url,
			started
		});
	} catch (err) {
		_inFlight = null;
		_proc = null;
		_url = null;
		return json({
			ok: false,
			error: err instanceof Error ? err.message : "Failed to start OpenCode"
		});
	}
};

export { POST };
//# sourceMappingURL=_server.ts-BL9qmwrJ.js.map
