import { i as updateManifestTask, n as createManifest, t as completeManifest } from "./orchestration-manifest-BgEay6gU.js";
import * as fs$1 from "node:fs";
import * as path$1 from "node:path";
import crypto from "node:crypto";

//#region src/agents/subagents/orchestration/orchestration-aggregation.ts
/**
* Orchestration aggregation — builds a structured prompt from task results
* and spawns a single aggregation subagent to synthesize them.
*/
/**
* Format task results into a structured prompt section, appending the
* user's aggregation prompt at the end.
*/
function buildAggregationPrompt(results, userPrompt) {
	const parts = [];
	parts.push("## Orchestration Results");
	parts.push("");
	for (const task of results) {
		const statusTag = task.status;
		parts.push(`### Task: ${task.label} (${statusTag})`);
		if (task.resultText) parts.push(task.resultText);
		else if (task.error) parts.push(`Error: ${task.error}`);
		else parts.push("(no output)");
		parts.push("");
		parts.push("---");
		parts.push("");
	}
	parts.push("## Your Task");
	parts.push(userPrompt);
	return parts.join("\n");
}
/**
* Spawn a single aggregation subagent that synthesizes all task results.
* Returns the aggregation result text or null on failure.
*/
async function runAggregation(params) {
	const prompt = buildAggregationPrompt(params.results, params.aggregationPrompt);
	const aggregationDir = path$1.join(params.orchestrationDir, "aggregation");
	fs$1.mkdirSync(aggregationDir, { recursive: true });
	try {
		return (await params.spawnFn({
			label: "aggregation",
			prompt,
			template: params.aggregationTemplate,
			index: -1
		}, aggregationDir)).resultText ?? null;
	} catch {
		return null;
	}
}

//#endregion
//#region src/agents/subagents/orchestration/orchestration-output.ts
/**
* Orchestration output directory management — handles filesystem
* conventions for orchestration output (dirs, status.json, gather).
*/
/**
* Create the root orchestration directory at `{agentWorkspace}/orchestrations/{orchestrationId}/`.
* Creates recursively and returns the absolute path.
*/
function createOrchestrationDir(agentWorkspace, orchestrationId) {
	const dir = path$1.join(agentWorkspace, "orchestrations", orchestrationId);
	fs$1.mkdirSync(dir, { recursive: true });
	return dir;
}
/**
* Create a task subdirectory named `{paddedIndex}_{sanitizedLabel}`.
* Index is zero-padded to 2 digits (01, 02, ...).
*/
function createTaskDir(orchestrationDir, index, label) {
	const dirName = `${String(index).padStart(2, "0")}_${sanitizeLabel(label)}`;
	const dir = path$1.join(orchestrationDir, dirName);
	fs$1.mkdirSync(dir, { recursive: true });
	return dir;
}
/**
* Sanitize a label for use as a directory name:
* - Lowercase
* - Replace non-[a-z0-9-] with hyphen
* - Collapse multiple dashes
* - Truncate to 50 chars
* - Trim leading/trailing dashes
*/
function sanitizeLabel(label) {
	return label.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-{2,}/g, "-").replace(/^-+|-+$/g, "").slice(0, 50).replace(/^-+|-+$/g, "");
}
/**
* Read and parse StatusJson from `{taskDir}/status.json`.
* Returns null if missing or invalid JSON.
*/
function readStatusJson(taskDir) {
	const filePath = path$1.join(taskDir, "status.json");
	try {
		const raw = fs$1.readFileSync(filePath, "utf-8");
		const validation = validateStatusJson(JSON.parse(raw));
		if (validation.valid && validation.statusJson) return validation.statusJson;
		return null;
	} catch {
		return null;
	}
}
/**
* Validate a raw value as a StatusJson shape.
* Returns `{ valid: true, statusJson }` or `{ valid: false, errors }`.
*/
function validateStatusJson(raw) {
	if (raw == null || typeof raw !== "object" || Array.isArray(raw)) return {
		valid: false,
		errors: ["StatusJson must be an object"]
	};
	const obj = raw;
	const errors = [];
	if (obj.status !== "ok" && obj.status !== "error") errors.push("Field 'status' must be 'ok' or 'error'");
	if (typeof obj.summary !== "string") errors.push("Field 'summary' must be a string");
	if (!Array.isArray(obj.outputFiles)) errors.push("Field 'outputFiles' must be an array");
	if (errors.length > 0) return {
		valid: false,
		errors
	};
	return {
		valid: true,
		statusJson: {
			status: obj.status,
			summary: obj.summary,
			outputFiles: obj.outputFiles,
			error: typeof obj.error === "string" ? obj.error : void 0,
			metrics: obj.metrics != null && typeof obj.metrics === "object" && !Array.isArray(obj.metrics) ? obj.metrics : void 0
		}
	};
}
const DEFAULT_MAX_INLINE_BYTES = 10240;
/**
* Read task output for gather: status.json + file listing.
* Files under `maxInlineBytes` are inlined; larger files are listed as paths only.
*/
function readTaskOutputForGather(taskDir, maxInlineBytes) {
	const maxBytes = maxInlineBytes ?? DEFAULT_MAX_INLINE_BYTES;
	const status = readStatusJson(taskDir);
	const files = [];
	try {
		const entries = fs$1.readdirSync(taskDir, { withFileTypes: true });
		for (const entry of entries) {
			if (!entry.isFile() || entry.name === "status.json") continue;
			const filePath = path$1.join(taskDir, entry.name);
			try {
				const stat = fs$1.statSync(filePath);
				const fileEntry = {
					name: entry.name,
					path: filePath,
					size: stat.size
				};
				if (stat.size <= maxBytes) fileEntry.content = fs$1.readFileSync(filePath, "utf-8");
				files.push(fileEntry);
			} catch {}
		}
	} catch {}
	return {
		status,
		files
	};
}

//#endregion
//#region src/agents/subagents/orchestration/orchestration-types.ts
/**
* Orchestration types — defines all type contracts for the multi-agent
* orchestration system (fan-out, pipeline, failure policies, manifests).
*/
const DEFAULT_MAX_CONCURRENCY = 5;
const MAX_TASKS_PER_ORCHESTRATION = 20;
const RATE_LIMIT_PER_MINUTE = 5;

//#endregion
//#region src/agents/subagents/orchestration/orchestration-engine.ts
/**
* Orchestration engine — executes parallel fan-out with concurrency control,
* failure policies (gather-available, fail-all, retry), budget cap, and dry run.
*/
/**
* Execute an orchestration: spawn tasks with concurrency control,
* apply failure policies, track budget, write manifest.
*/
async function executeOrchestration(config, spawnFn, context) {
	const orchestrationId = config.orchestrationId ?? crypto.randomUUID();
	const mode = config.mode;
	const maxConcurrency = config.maxConcurrency ?? DEFAULT_MAX_CONCURRENCY;
	const onFailure = config.onFailure ?? "gather-available";
	const maxRetries = config.maxRetries ?? 1;
	const maxTotalTokens = config.maxTotalTokens;
	if (config.dryRun) return {
		orchestrationId,
		mode,
		status: "completed",
		tasks: [],
		totalDurationMs: 0,
		tokensUsed: 0
	};
	const tasks = config.tasks ?? [];
	if (tasks.length === 0) return {
		orchestrationId,
		mode,
		status: "completed",
		tasks: [],
		totalDurationMs: 0,
		tokensUsed: 0
	};
	const orchestrationDir = createOrchestrationDir(context.agentWorkspace, orchestrationId);
	const manifestTasks = tasks.map((t, i) => ({
		index: i,
		label: t.label,
		template: t.template,
		status: "pending"
	}));
	createManifest(orchestrationDir, {
		orchestrationId,
		mode,
		startedAt: Date.now(),
		taskCount: tasks.length,
		status: "running",
		tasks: manifestTasks
	});
	const startTime = performance.now();
	const results = Array.from({ length: tasks.length });
	let totalTokensUsed = 0;
	let budgetExceeded = false;
	let failureDetected = false;
	const queue = tasks.map((task, i) => ({
		task,
		index: i
	}));
	let queuePos = 0;
	let activeCount = 0;
	await new Promise((resolveAll) => {
		let completedCount = 0;
		function tryStartNext() {
			while (activeCount < maxConcurrency && queuePos < queue.length && !budgetExceeded && !(failureDetected && onFailure === "fail-all")) {
				const item = queue[queuePos];
				queuePos++;
				activeCount++;
				runTask(item.task, item.index);
			}
			if (budgetExceeded || failureDetected && onFailure === "fail-all") {
				for (let i = queuePos; i < queue.length; i++) {
					const item = queue[i];
					if (!results[item.index]) {
						results[item.index] = {
							label: item.task.label,
							index: item.index,
							status: "skipped",
							durationMs: 0
						};
						completedCount++;
						updateManifestTask(orchestrationDir, item.index, { status: "skipped" });
					}
				}
				queuePos = queue.length;
			}
			if (completedCount >= tasks.length) resolveAll();
		}
		async function runTask(task, index) {
			const taskDir = createTaskDir(orchestrationDir, index, task.label);
			updateManifestTask(orchestrationDir, index, {
				status: "running",
				startedAt: Date.now(),
				outputDir: taskDir
			});
			let attempt = 0;
			const maxAttempts = onFailure === "retry" ? maxRetries + 1 : 1;
			let lastResult;
			while (attempt < maxAttempts) {
				attempt++;
				try {
					const result = await spawnFn({
						...task,
						index
					}, taskDir);
					result.index = index;
					lastResult = result;
					if (result.status === "completed") {
						results[index] = result;
						totalTokensUsed += result.tokensUsed ?? 0;
						updateManifestTask(orchestrationDir, index, {
							status: "completed",
							completedAt: Date.now()
						});
						if (maxTotalTokens && totalTokensUsed >= maxTotalTokens) budgetExceeded = true;
						break;
					}
					if (attempt < maxAttempts) {
						const backoffMs = 1e3 * 2 ** (attempt - 1);
						await new Promise((r) => setTimeout(r, backoffMs));
						continue;
					}
					results[index] = result;
					totalTokensUsed += result.tokensUsed ?? 0;
					failureDetected = true;
					updateManifestTask(orchestrationDir, index, {
						status: result.status === "timeout" ? "timeout" : "failed",
						completedAt: Date.now(),
						error: result.error
					});
				} catch (err) {
					const error = err instanceof Error ? err.message : String(err);
					lastResult = {
						label: task.label,
						index,
						status: "failed",
						error,
						durationMs: 0
					};
					if (attempt < maxAttempts) {
						const backoffMs = 1e3 * 2 ** (attempt - 1);
						await new Promise((r) => setTimeout(r, backoffMs));
						continue;
					}
					results[index] = lastResult;
					failureDetected = true;
					updateManifestTask(orchestrationDir, index, {
						status: "failed",
						completedAt: Date.now(),
						error
					});
				}
			}
			if (!results[index] && lastResult) results[index] = lastResult;
			completedCount++;
			activeCount--;
			tryStartNext();
		}
		tryStartNext();
	});
	const totalDurationMs = Math.round(performance.now() - startTime);
	let finalStatus = "completed";
	if (failureDetected) {
		if (onFailure === "fail-all") finalStatus = "failed";
	}
	completeManifest(orchestrationDir, finalStatus);
	return {
		orchestrationId,
		mode,
		status: finalStatus,
		tasks: results.filter(Boolean),
		totalDurationMs,
		tokensUsed: totalTokensUsed
	};
}

//#endregion
//#region src/agents/subagents/orchestration/orchestration-pipeline.ts
/**
* Pipeline mode execution — processes stages sequentially with
* fan-out within each stage and {{previousOutput}} injection.
*/
/**
* Execute a pipeline orchestration: stages run sequentially, tasks within
* each stage run in parallel (fan-out). Output from completed stages is
* injected as `{{previousOutput}}` into next stage task prompts.
*/
async function executePipeline(config, spawnFn, context) {
	const orchestrationId = config.orchestrationId ?? crypto.randomUUID();
	const maxConcurrency = config.maxConcurrency ?? DEFAULT_MAX_CONCURRENCY;
	const stages = config.stages ?? [];
	if (stages.length === 0) return {
		orchestrationId,
		mode: "pipeline",
		status: "completed",
		tasks: [],
		totalDurationMs: 0,
		tokensUsed: 0
	};
	const orchestrationDir = createOrchestrationDir(context.agentWorkspace, orchestrationId);
	const allTasks = [];
	let globalIndex = 0;
	for (let si = 0; si < stages.length; si++) for (const task of stages[si].tasks) {
		allTasks.push({
			task,
			stageIndex: si,
			globalIndex
		});
		globalIndex++;
	}
	const manifestTasks = allTasks.map((entry) => ({
		index: entry.globalIndex,
		label: entry.task.label,
		template: entry.task.template,
		status: "pending"
	}));
	createManifest(orchestrationDir, {
		orchestrationId,
		mode: "pipeline",
		startedAt: Date.now(),
		taskCount: allTasks.length,
		status: "running",
		tasks: manifestTasks
	});
	const startTime = performance.now();
	const allResults = [];
	let totalTokensUsed = 0;
	let previousOutput = "";
	let pipelineStatus = "completed";
	let pipelineFailed = false;
	for (let stageIndex = 0; stageIndex < stages.length; stageIndex++) {
		if (pipelineFailed) {
			const stageTasks = allTasks.filter((e) => e.stageIndex === stageIndex);
			for (const entry of stageTasks) {
				allResults.push({
					label: entry.task.label,
					index: entry.globalIndex,
					status: "skipped",
					durationMs: 0
				});
				updateManifestTask(orchestrationDir, entry.globalIndex, { status: "skipped" });
			}
			continue;
		}
		const stage = stages[stageIndex];
		const stageTasks = allTasks.filter((e) => e.stageIndex === stageIndex);
		const onStageFailure = stage.onStageFailure ?? "stop";
		const stageName = stageTasks[0]?.task.label ?? "stage";
		const stageDir = createStageDir(orchestrationDir, stageIndex, stageName);
		const stageResults = await executeStageParallel(stageTasks.map((entry) => ({
			...entry,
			task: {
				...entry.task,
				prompt: entry.task.prompt.replace(/\{\{previousOutput\}\}/g, previousOutput),
				index: entry.globalIndex
			}
		})).map((e) => ({
			task: e.task,
			globalIndex: e.globalIndex
		})), spawnFn, stageDir, orchestrationDir, maxConcurrency);
		let stageHasFailure = false;
		for (const result of stageResults) {
			allResults.push(result);
			totalTokensUsed += result.tokensUsed ?? 0;
			if (result.status === "failed" || result.status === "timeout") stageHasFailure = true;
		}
		const stageOutputParts = stageResults.filter((r) => r.resultText).map((r) => `### ${r.label}\n${r.resultText}`);
		if (stageOutputParts.length > 0) previousOutput = stageOutputParts.join("\n\n---\n\n");
		if (stageHasFailure) if (onStageFailure === "stop") {
			pipelineFailed = true;
			pipelineStatus = "failed";
			const errorParts = stageResults.filter((r) => r.status === "failed" || r.status === "timeout").map((r) => `### ${r.label} (${r.status})\n${r.error ?? "Unknown error"}`);
			if (errorParts.length > 0) previousOutput += "\n\n---\n\n## Stage Errors\n\n" + errorParts.join("\n\n");
		} else {
			const errorParts = stageResults.filter((r) => r.status === "failed" || r.status === "timeout").map((r) => `### ${r.label} (${r.status})\n${r.error ?? "Unknown error"}`);
			if (errorParts.length > 0) previousOutput += "\n\n---\n\n## Stage Errors\n\n" + errorParts.join("\n\n");
		}
	}
	const totalDurationMs = Math.round(performance.now() - startTime);
	completeManifest(orchestrationDir, pipelineStatus);
	return {
		orchestrationId,
		mode: "pipeline",
		status: pipelineStatus,
		tasks: allResults,
		totalDurationMs,
		tokensUsed: totalTokensUsed
	};
}
async function executeStageParallel(tasks, spawnFn, stageDir, orchestrationDir, maxConcurrency) {
	const results = Array.from({ length: tasks.length });
	let queuePos = 0;
	let activeCount = 0;
	await new Promise((resolveAll) => {
		let completedCount = 0;
		function tryStartNext() {
			while (activeCount < maxConcurrency && queuePos < tasks.length) {
				const item = tasks[queuePos];
				queuePos++;
				activeCount++;
				runStageTask(item, queuePos - 1);
			}
			if (completedCount >= tasks.length) resolveAll();
		}
		async function runStageTask(item, localIndex) {
			const taskLabel = sanitizeLabel(item.task.label);
			const paddedLocal = String(localIndex).padStart(2, "0");
			const taskDir = path$1.join(stageDir, `${paddedLocal}_${taskLabel}`);
			fs$1.mkdirSync(taskDir, { recursive: true });
			updateManifestTask(orchestrationDir, item.globalIndex, {
				status: "running",
				startedAt: Date.now(),
				outputDir: taskDir
			});
			try {
				const result = await spawnFn(item.task, taskDir);
				result.index = item.globalIndex;
				results[localIndex] = result;
				updateManifestTask(orchestrationDir, item.globalIndex, {
					status: result.status === "completed" ? "completed" : result.status,
					completedAt: Date.now(),
					error: result.error
				});
			} catch (err) {
				const error = err instanceof Error ? err.message : String(err);
				results[localIndex] = {
					label: item.task.label,
					index: item.globalIndex,
					status: "failed",
					error,
					durationMs: 0
				};
				updateManifestTask(orchestrationDir, item.globalIndex, {
					status: "failed",
					completedAt: Date.now(),
					error
				});
			}
			completedCount++;
			activeCount--;
			tryStartNext();
		}
		tryStartNext();
	});
	return results;
}
function createStageDir(orchestrationDir, stageIndex, firstTaskLabel) {
	const dirName = `stage_${String(stageIndex + 1).padStart(2, "0")}_${sanitizeLabel(firstTaskLabel)}`;
	const dir = path$1.join(orchestrationDir, dirName);
	fs$1.mkdirSync(dir, { recursive: true });
	return dir;
}

//#endregion
export { readStatusJson as a, RATE_LIMIT_PER_MINUTE as i, executeOrchestration as n, readTaskOutputForGather as o, MAX_TASKS_PER_ORCHESTRATION as r, runAggregation as s, executePipeline as t };