//#region src/gateway/worker-environments/session-placement-lifecycle.ts
var SessionWorkerPlacementMutationError = class extends Error {
	constructor(state, action, key) {
		super(`Session ${key} cannot ${action} while cloud worker placement is ${state}.`);
	}
};
function isFailedWorkerPlacementEnvironmentGone(params) {
	if (params.placement.environmentId === null) return true;
	if (!params.environmentService) return false;
	try {
		const environment = params.environmentService.get(params.placement.environmentId);
		return environment === void 0 || environment.state === "destroyed" || environment.state === "failed" && environment.leaseId === null;
	} catch {
		return false;
	}
}
function isWorkerPlacementSafeForMutation(context, placement) {
	if (placement.state === "failed") return isFailedWorkerPlacementEnvironmentGone({
		environmentService: context.workerEnvironmentService,
		placement
	});
	return placement.state === "local" || placement.state === "reclaimed";
}
function resolveWorkerPlacementArchiveRestoreError(params) {
	if (!params.placement || isWorkerPlacementSafeForMutation(params.context, params.placement)) return;
	return `Session ${params.key} cannot change archive state while cloud worker placement is ${params.placement.state}.`;
}
function retirementGuard(placement) {
	return {
		status: "retirement-required",
		sessionId: placement.sessionId,
		expectedState: placement.state,
		expectedGeneration: placement.generation
	};
}
function resolveSessionWorkerPlacementMutationGuard(params) {
	const placement = readSessionWorkerPlacement(params);
	if (!placement) return { status: "allowed" };
	if (isWorkerPlacementSafeForMutation(params.context, placement)) {
		if (params.action === "reset") return retirementGuard(placement);
		if (placement.state === "local" || params.action === "fork") return { status: "allowed" };
	}
	return {
		status: "blocked",
		error: new SessionWorkerPlacementMutationError(placement.state, params.action, params.key)
	};
}
function retireSessionWorkerPlacementBeforeMutation(params) {
	const guard = resolveSessionWorkerPlacementMutationGuard(params);
	if (guard.status !== "retirement-required") return guard.status === "blocked" ? guard.error : void 0;
	const retirementService = params.context.workerSessionPlacementService;
	if (!retirementService?.retireSessionPlacement) throw new Error("Worker session placement retirement service is unavailable");
	retirementService.retireSessionPlacement(guard);
}
function resolveSessionWorkerPlacementMutationError(params) {
	const guard = resolveSessionWorkerPlacementMutationGuard(params);
	return guard.status === "blocked" ? guard.error : void 0;
}
function readSessionWorkerPlacement(params) {
	return params.sessionId ? params.context.workerSessionPlacementService?.getMany([params.sessionId]).get(params.sessionId) : void 0;
}
function samePlacementOwner(expected, current) {
	return current?.sessionId === expected?.sessionId && current?.sessionKey === expected?.sessionKey && current?.agentId === expected?.agentId && current?.state === expected?.state && current?.generation === expected?.generation && current?.environmentId === expected?.environmentId && current?.activeOwnerEpoch === expected?.activeOwnerEpoch && current?.executionMode === expected?.executionMode;
}
/** Retain the exact stopped placement across fallible workspace or session mutations. */
function prepareSessionWorkerPlacementMutationCheck(params, operation = "mutation") {
	const expected = readSessionWorkerPlacement(params);
	const assertCurrent = () => {
		const current = readSessionWorkerPlacement(params);
		if (!samePlacementOwner(expected, current) || current?.turnClaim || current && !isWorkerPlacementSafeForMutation(params.context, current)) throw new Error(`Worker session placement ${params.sessionId} changed before ${operation}`);
	};
	assertCurrent();
	return assertCurrent;
}
/** Capture retirement without erasing cloud affinity before fallible session cleanup. */
function prepareSessionWorkerPlacementRetirement(params) {
	const expected = readSessionWorkerPlacement(params);
	const assertCurrent = prepareSessionWorkerPlacementMutationCheck(params, "retirement");
	const retire = params.context.workerSessionPlacementService?.retireSessionPlacement;
	if (expected && !retire) throw new Error("Worker session placement retirement service is unavailable");
	return {
		assertCurrent,
		retire: () => {
			if (!readSessionWorkerPlacement(params)) return;
			assertCurrent();
			if (expected && retire && isWorkerPlacementSafeForMutation(params.context, expected)) retire({
				sessionId: expected.sessionId,
				expectedState: expected.state,
				expectedGeneration: expected.generation
			});
		}
	};
}
/** Validate before cancellation; the returned stop remains bound to this placement across drains. */
function prepareSessionWorkerPlacementStop(params) {
	const { agentId, context, sessionId, sessionKey } = params;
	const expected = readSessionWorkerPlacement(params);
	const matches = (candidate) => candidate.sessionId === sessionId && candidate.sessionKey === sessionKey && candidate.agentId === agentId;
	if (expected && !matches(expected)) throw new Error(`Session ${sessionKey} cloud worker placement identity changed.`);
	if (expected && !isWorkerPlacementSafeForMutation(context, expected) && expected.state !== "active") throw new Error(`Session ${sessionKey} cannot ${params.action} while cloud worker placement is ${expected.state}.`);
	const beforeDrain = () => {
		params.authorize?.();
		const current = readSessionWorkerPlacement(params);
		if (!samePlacementOwner(expected, current) || current && current.state !== "active" && !isWorkerPlacementSafeForMutation(context, current)) throw new Error(`Session ${sessionKey} cloud worker placement identity changed.`);
	};
	return async () => {
		beforeDrain();
		if (!expected || expected.state !== "active" || !sessionId) return;
		if (!context.workerPlacementDispatchService?.reclaim) throw new Error(`Session ${sessionKey} cloud worker reclaim is unavailable.`);
		const reclaimed = await context.workerPlacementDispatchService.reclaim({
			agentId,
			sessionId,
			sessionKey
		}, params.authorize, beforeDrain);
		params.authorize?.();
		const settled = readSessionWorkerPlacement(params);
		if (reclaimed.state !== "reclaimed" || !matches(reclaimed) || !samePlacementOwner(reclaimed, settled)) throw new Error(`Session ${sessionKey} cloud worker reclaim identity changed.`);
	};
}
//#endregion
export { resolveSessionWorkerPlacementMutationError as a, prepareSessionWorkerPlacementStop as i, prepareSessionWorkerPlacementMutationCheck as n, resolveWorkerPlacementArchiveRestoreError as o, prepareSessionWorkerPlacementRetirement as r, retireSessionWorkerPlacementBeforeMutation as s, isFailedWorkerPlacementEnvironmentGone as t };
