import "./tool-display-B7qTeoCS.js";
import "./paths-D4_LjrY7.js";
import { M as logVerbose } from "./utils-BnlaT0eO.js";
import "./theme-CG-K7m8u.js";
import "./thinking-CKGMvVgd.js";
import { Cn as markSubagentRunTerminated, Dn as getSubagentDepthFromSessionStore, N as clearSessionQueues, Sn as markSubagentRunForSteerRestart, W as abortEmbeddedPiRun, _ as spawnSubagentDirect, _n as clearSubagentRunSteerRestart, _t as resolveSubagentTargetFromRuns, g as truncateLine, gt as resolveSubagentLabel, h as resolveTotalTokens, m as formatTokenUsageDisplay, p as formatDurationCompact, vt as sortSubagentRuns, wn as replaceSubagentRunAfterSteer, xn as listSubagentRunsForRequester, y as getTemplate } from "./reply-DbpXq1MH.js";
import "./subsystem-ocBR131w.js";
import "./runtime-CRvfzclG.js";
import { C as parseAgentSessionKey, S as isSubagentSessionKey } from "./session-key-DIUsVZjU.js";
import "./exec-CZr_EJHt.js";
import { l as resolveAgentWorkspaceDir } from "./agent-scope-CVnlY0oG.js";
import "./model-selection-p6J3l4qF.js";
import "./github-copilot-token-CjSKohyA.js";
import "./emitter-oHo8y9ow.js";
import "./sqlite-wYNyDR1B.js";
import "./reliability-Dl7hbRzF.js";
import "./boolean-DGGu1sGA.js";
import "./env-CvUd308i.js";
import "./validation-p1IK70TM.js";
import { o as loadConfig } from "./config-DJ3A5x_1.js";
import "./manifest-registry-U2EDFVP4.js";
import "./runner-BZrNCxMY.js";
import "./image-tool.helpers-tqRivaKA.js";
import "./models-config-DLUtus3b.js";
import "./pi-model-discovery-4-XyjjxG.js";
import "./pi-embedded-utils-BraP32ED.js";
import "./redact-DcYCKU6u.js";
import "./pi-embedded-helpers-CLkeTWAT.js";
import "./sandbox-C5rKvtrA.js";
import "./chrome-BQkAVfz8.js";
import "./tailscale-CcUMoDkd.js";
import "./auth-BxKMeEw-.js";
import "./server-context-s_zNpSdX.js";
import "./frontmatter-VFr0KMAQ.js";
import "./skills-CHYyY1lO.js";
import "./routes-CT0DmotX.js";
import "./errors-DbYSuCgv.js";
import "./paths-Ct4sqLyX.js";
import "./ssrf-tneKFjA6.js";
import "./image-ops-C0D77XHD.js";
import "./store-Cdm3Z5cQ.js";
import "./ports-DvLDsgl0.js";
import "./trash-BRBQoy9m.js";
import { a as loadSessionStore, u as updateSessionStore } from "./sessions-Ct2d_bGl.js";
import { t as INTERNAL_MESSAGE_CHANNEL } from "./message-channel-DSU96OKy.js";
import "./dock-DY0TWaYa.js";
import "./normalize-DgwtBdm-.js";
import "./accounts-BZv5WxME.js";
import "./accounts-DFaskvEN.js";
import "./accounts-T7o73ZSN.js";
import "./bindings-BbaWTQJM.js";
import "./logging-wfRfbMvt.js";
import "./client-36a9DTBg.js";
import "./plugins-DYgcd4QJ.js";
import "./targets-qjNLO5UC.js";
import { c as resolveStorePath } from "./paths-DRyRQF9o.js";
import "./tool-images-CRPqucMe.js";
import "./image-Dx_UDO2W.js";
import "./fetch-guard-C12KgXTM.js";
import "./api-key-rotation-Bl9Larnz.js";
import "./fetch-Dy3Y7lWo.js";
import "./session-files-DroWN-X3.js";
import "./model-catalog-DyP7lvDH.js";
import "./tokens-DuLZdp8u.js";
import "./heartbeat-BJ0mtjXV.js";
import "./helpers-DAXsRcXO.js";
import "./targets-D3Hd_LiZ.js";
import "./with-timeout-BeRjsuGt.js";
import "./diagnostic-Ct9JySKv.js";
import "./diagnostic-session-state-CjvcsE8F.js";
import { n as AGENT_LANE_SUBAGENT } from "./lanes-s-MZ35vD.js";
import "./reply-payloads-Idpqh_HL.js";
import "./route-reply-C3GnJgPP.js";
import "./tts-pLGM3rbp.js";
import "./audio-Cf4_M2_g.js";
import "./model-p-v6-khS.js";
import "./chat-trace-DE0u11RV.js";
import "./response-prefix-template-ZNVQwQzJ.js";
import "./tool-tracking-BeyzFfAx.js";
import "./memory-cli-D_iCajsu.js";
import "./manager-Be4wtySp.js";
import "./retry-BR_e19Qc.js";
import "./hybrid-oFciuzzr.js";
import { a as jsonResult, o as readNumberParam, u as readStringParam } from "./common-oaZdjdal.js";
import "./send-BFMLircB.js";
import "./chunk-CF0Wb8FK.js";
import "./markdown-tables-BkkSACKz.js";
import "./media-Ce9mjBUa.js";
import "./ir-DDJn3mJR.js";
import "./render-Cz3PVxTW.js";
import "./commands-registry-CvAV0O7w.js";
import "./client-DNPnFy4E.js";
import { n as callGateway } from "./call-C206Z-zx.js";
import { f as resolveInternalSessionKey, p as resolveMainSessionAlias } from "./sessions-helpers-DYJnJN3U.js";
import "./external-content-CNcZgk3W.js";
import "./send-BQth8hb0.js";
import "./channel-activity-C8K3u-iy.js";
import "./fetch-CdBeMr8t.js";
import "./tables-GfMspQYU.js";
import "./server-startup-users-Bb0MWaNU.js";
import "./resolve-route-D-YVS8mL.js";
import "./pairing-store-Z_SXyT9W.js";
import "./replies-AgkcH9tU.js";
import "./reply-prefix-DB7HiPpn.js";
import "./workspace-dirs-C1v5ssUA.js";
import "./skill-commands-vM7RDRiG.js";
import "./pi-tools.policy-C7_kjOAN.js";
import "./send-BKH82oGz.js";
import "./onboard-helpers-B0CkVZ2U.js";
import "./prompt-style-D4OL61iD.js";
import "./onboard-helpers-BvqKOAqv.js";
import "./outbound-attachment-DzzKBoks.js";
import "./targets-B17-mYQK.js";
import "./pairing-labels-BoIZlK5l.js";
import "./send-C5tjqyuP.js";
import "./session-cost-usage-UDBgjJvw.js";
import "./send-XU_khFvN.js";
import "./proxy-CjhP7CG1.js";
import "./links-G4gKCCcI.js";
import "./cli-utils-Cps3tWFt.js";
import "./help-format-DukcHIxz.js";
import "./progress-WmzCxxhb.js";
import "./active-listener-CEwpUvTV.js";
import "./exec-approvals-C7AUcy3J.js";
import "./gateway-DKSm1BrZ.js";
import "./nodes-utils-yMGpHJYN.js";
import "./model-fallback-BPqOLk8z.js";
import "./typed-schema-4lv655ii.js";
import "./knowledge-graph-D4-b38d_.js";
import { r as optionalStringEnum } from "./typebox-BNGTpPE2.js";
import { a as readStatusJson, i as RATE_LIMIT_PER_MINUTE, n as executeOrchestration, o as readTaskOutputForGather, r as MAX_TASKS_PER_ORCHESTRATION, s as runAggregation, t as executePipeline } from "./orchestration-pipeline-DVVSD1Ve.js";
import { r as readManifest } from "./orchestration-manifest-BgEay6gU.js";
import * as fs$1 from "node:fs";
import * as path$1 from "node:path";
import crypto from "node:crypto";
import { Type } from "@sinclair/typebox";

//#region src/agents/subagents/orchestration/orchestration-gather.ts
/**
* Orchestration gather — collects task results by orchestrationId,
* reads status.json and output files, supports filtering and cleanup.
*/
/**
* Gather results for an orchestration by reading the manifest and task output
* directories. Pure disk reads (no state mutation except cleanup).
*/
function gatherOrchestrationResults(params) {
	const manifest = readManifest(params.orchestrationDir);
	if (!manifest) return {
		orchestrationId: params.orchestrationId,
		status: "pending",
		taskCount: 0,
		tasks: []
	};
	let filteredTasks = manifest.tasks;
	if (params.template) filteredTasks = filteredTasks.filter((t) => t.template === params.template);
	if (params.label) filteredTasks = filteredTasks.filter((t) => t.label === params.label);
	if (!params.includeRunning) filteredTasks = filteredTasks.filter((t) => t.status !== "running" && t.status !== "pending");
	const gatherTasks = [];
	for (const manifestTask of filteredTasks) {
		const taskResult = buildGatherTaskResult(manifestTask, params);
		gatherTasks.push(taskResult);
	}
	const isInterrupted = manifest.status === "interrupted";
	const completedCount = manifest.tasks.filter((t) => t.status === "completed" || t.status === "failed").length;
	const incompleteCount = manifest.tasks.filter((t) => t.status === "pending" || t.status === "running" || t.status === "skipped").length;
	const result = {
		orchestrationId: params.orchestrationId,
		status: manifest.status,
		mode: manifest.mode,
		startedAt: manifest.startedAt,
		completedAt: manifest.completedAt,
		taskCount: manifest.taskCount,
		tasks: gatherTasks,
		...isInterrupted ? {
			interrupted: true,
			completedTasks: completedCount,
			incompleteTasks: incompleteCount,
			canResume: true
		} : {}
	};
	if (params.cleanup) try {
		fs$1.rmSync(params.orchestrationDir, {
			recursive: true,
			force: true
		});
	} catch {}
	return result;
}
function buildGatherTaskResult(manifestTask, params) {
	if (manifestTask.status === "running" || manifestTask.status === "pending") return {
		index: manifestTask.index,
		label: manifestTask.label,
		template: manifestTask.template,
		status: manifestTask.status,
		statusJson: null,
		files: []
	};
	if (manifestTask.outputDir) {
		const output = readTaskOutputForGather(manifestTask.outputDir, params.maxInlineBytes);
		const run = params.runs.find((r) => r.orchestrationId === params.orchestrationId && r.label === manifestTask.label);
		return {
			index: manifestTask.index,
			label: manifestTask.label,
			template: manifestTask.template,
			status: manifestTask.status,
			statusJson: output.status,
			files: output.files,
			resultText: run?.resultText ?? output.status?.summary,
			error: manifestTask.error
		};
	}
	return {
		index: manifestTask.index,
		label: manifestTask.label,
		template: manifestTask.template,
		status: manifestTask.status,
		statusJson: null,
		files: [],
		error: manifestTask.error
	};
}

//#endregion
//#region src/agents/tools/sessions/subagents-tool.ts
const SUBAGENT_ACTIONS = [
	"list",
	"kill",
	"steer",
	"orchestrate",
	"gather",
	"orchestrations"
];
const DEFAULT_RECENT_MINUTES = 30;
const MAX_RECENT_MINUTES = 1440;
const MAX_STEER_MESSAGE_CHARS = 4e3;
const STEER_RATE_LIMIT_MS = 2e3;
const STEER_ABORT_SETTLE_TIMEOUT_MS = 5e3;
const steerRateLimit = /* @__PURE__ */ new Map();
const orchestrateRateWindow = [];
const SubagentsToolSchema = Type.Object({
	action: optionalStringEnum(SUBAGENT_ACTIONS),
	target: Type.Optional(Type.String()),
	message: Type.Optional(Type.String()),
	recentMinutes: Type.Optional(Type.Number({ minimum: 1 })),
	mode: Type.Optional(Type.String()),
	tasks: Type.Optional(Type.Array(Type.Object({
		label: Type.String(),
		prompt: Type.String(),
		template: Type.Optional(Type.String()),
		model: Type.Optional(Type.String()),
		timeoutSeconds: Type.Optional(Type.Number())
	}))),
	stages: Type.Optional(Type.Array(Type.Object({
		tasks: Type.Array(Type.Object({
			label: Type.String(),
			prompt: Type.String(),
			template: Type.Optional(Type.String()),
			model: Type.Optional(Type.String()),
			timeoutSeconds: Type.Optional(Type.Number())
		})),
		onStageFailure: Type.Optional(Type.String())
	}))),
	maxConcurrency: Type.Optional(Type.Number()),
	onFailure: Type.Optional(Type.String()),
	maxRetries: Type.Optional(Type.Number()),
	maxTotalTokens: Type.Optional(Type.Number()),
	aggregationPrompt: Type.Optional(Type.String()),
	aggregationTemplate: Type.Optional(Type.String()),
	dryRun: Type.Optional(Type.Boolean()),
	orchestrationId: Type.Optional(Type.String()),
	template: Type.Optional(Type.String()),
	label: Type.Optional(Type.String()),
	includeRunning: Type.Optional(Type.Boolean()),
	cleanup: Type.Optional(Type.Boolean()),
	resumeOrchestrationId: Type.Optional(Type.String()),
	status: Type.Optional(Type.String()),
	since: Type.Optional(Type.Number()),
	until: Type.Optional(Type.Number())
});
function resolveRunStatus(entry) {
	if (!entry.endedAt) return "running";
	const status = entry.outcome?.status ?? "done";
	if (status === "ok") return "done";
	if (status === "error") return "failed";
	return status;
}
function resolveModelRef(entry) {
	const model = typeof entry?.model === "string" ? entry.model.trim() : "";
	const provider = typeof entry?.modelProvider === "string" ? entry.modelProvider.trim() : "";
	if (model.includes("/")) return model;
	if (model && provider) return `${provider}/${model}`;
	if (model) return model;
	if (provider) return provider;
	const overrideModel = typeof entry?.modelOverride === "string" ? entry.modelOverride.trim() : "";
	const overrideProvider = typeof entry?.providerOverride === "string" ? entry.providerOverride.trim() : "";
	if (overrideModel.includes("/")) return overrideModel;
	if (overrideModel && overrideProvider) return `${overrideProvider}/${overrideModel}`;
	if (overrideModel) return overrideModel;
	return overrideProvider || void 0;
}
function resolveModelDisplay(entry, fallbackModel) {
	const modelRef = resolveModelRef(entry) || fallbackModel || void 0;
	if (!modelRef) return "model n/a";
	const slash = modelRef.lastIndexOf("/");
	if (slash >= 0 && slash < modelRef.length - 1) return modelRef.slice(slash + 1);
	return modelRef;
}
function resolveSubagentTarget(runs, token, options) {
	return resolveSubagentTargetFromRuns({
		runs,
		token,
		recentWindowMinutes: options?.recentMinutes ?? DEFAULT_RECENT_MINUTES,
		label: (entry) => resolveSubagentLabel(entry),
		errors: {
			missingTarget: "Missing subagent target.",
			invalidIndex: (value) => `Invalid subagent index: ${value}`,
			unknownSession: (value) => `Unknown subagent session: ${value}`,
			ambiguousLabel: (value) => `Ambiguous subagent label: ${value}`,
			ambiguousLabelPrefix: (value) => `Ambiguous subagent label prefix: ${value}`,
			ambiguousRunIdPrefix: (value) => `Ambiguous subagent run id prefix: ${value}`,
			unknownTarget: (value) => `Unknown subagent target: ${value}`
		}
	});
}
function resolveStorePathForKey(cfg, key, parsed) {
	return resolveStorePath(cfg.session?.store, { agentId: parsed?.agentId });
}
function resolveSessionEntryForKey(params) {
	const parsed = parseAgentSessionKey(params.key);
	const storePath = resolveStorePathForKey(params.cfg, params.key, parsed);
	let store = params.cache.get(storePath);
	if (!store) {
		store = loadSessionStore(storePath);
		params.cache.set(storePath, store);
	}
	return {
		storePath,
		entry: store[params.key]
	};
}
function resolveRequesterKey(params) {
	const { mainKey, alias } = resolveMainSessionAlias(params.cfg);
	const callerSessionKey = resolveInternalSessionKey({
		key: params.agentSessionKey?.trim() || alias,
		alias,
		mainKey
	});
	if (!isSubagentSessionKey(callerSessionKey)) return {
		requesterSessionKey: callerSessionKey,
		callerSessionKey,
		callerIsSubagent: false
	};
	if (getSubagentDepthFromSessionStore(callerSessionKey, { cfg: params.cfg }) < (params.cfg.agents?.defaults?.subagents?.maxSpawnDepth ?? 2)) return {
		requesterSessionKey: callerSessionKey,
		callerSessionKey,
		callerIsSubagent: true
	};
	const cache = /* @__PURE__ */ new Map();
	const callerEntry = resolveSessionEntryForKey({
		cfg: params.cfg,
		key: callerSessionKey,
		cache
	}).entry;
	return {
		requesterSessionKey: (typeof callerEntry?.spawnedBy === "string" ? callerEntry.spawnedBy.trim() : "") || callerSessionKey,
		callerSessionKey,
		callerIsSubagent: true
	};
}
async function killSubagentRun(params) {
	if (params.entry.endedAt) return { killed: false };
	const childSessionKey = params.entry.childSessionKey;
	const resolved = resolveSessionEntryForKey({
		cfg: params.cfg,
		key: childSessionKey,
		cache: params.cache
	});
	const sessionId = resolved.entry?.sessionId;
	const aborted = sessionId ? abortEmbeddedPiRun(sessionId) : false;
	const cleared = clearSessionQueues([childSessionKey, sessionId]);
	if (cleared.followupCleared > 0 || cleared.laneCleared > 0) logVerbose(`subagents tool kill: cleared followups=${cleared.followupCleared} lane=${cleared.laneCleared} keys=${cleared.keys.join(",")}`);
	if (resolved.entry) await updateSessionStore(resolved.storePath, (store) => {
		const current = store[childSessionKey];
		if (!current) return;
		current.abortedLastRun = true;
		current.updatedAt = Date.now();
		store[childSessionKey] = current;
	});
	return {
		killed: markSubagentRunTerminated({
			runId: params.entry.runId,
			childSessionKey,
			reason: "killed"
		}) > 0 || aborted || cleared.followupCleared > 0 || cleared.laneCleared > 0,
		sessionId
	};
}
/**
* Recursively kill all descendant subagent runs spawned by a given parent session key.
* This ensures that when a subagent is killed, all of its children (and their children) are also killed.
*/
async function cascadeKillChildren(params) {
	const childRuns = listSubagentRunsForRequester(params.parentChildSessionKey);
	const seenChildSessionKeys = params.seenChildSessionKeys ?? /* @__PURE__ */ new Set();
	let killed = 0;
	const labels = [];
	for (const run of childRuns) {
		const childKey = run.childSessionKey?.trim();
		if (!childKey || seenChildSessionKeys.has(childKey)) continue;
		seenChildSessionKeys.add(childKey);
		if (!run.endedAt) {
			if ((await killSubagentRun({
				cfg: params.cfg,
				entry: run,
				cache: params.cache
			})).killed) {
				killed += 1;
				labels.push(resolveSubagentLabel(run));
			}
		}
		const cascade = await cascadeKillChildren({
			cfg: params.cfg,
			parentChildSessionKey: childKey,
			cache: params.cache,
			seenChildSessionKeys
		});
		killed += cascade.killed;
		labels.push(...cascade.labels);
	}
	return {
		killed,
		labels
	};
}
function buildListText(params) {
	const lines = [];
	lines.push("active subagents:");
	if (params.active.length === 0) lines.push("(none)");
	else lines.push(...params.active.map((entry) => entry.line));
	lines.push("");
	lines.push(`recent (last ${params.recentMinutes}m):`);
	if (params.recent.length === 0) lines.push("(none)");
	else lines.push(...params.recent.map((entry) => entry.line));
	return lines.join("\n");
}
function createSubagentsTool(opts) {
	return {
		label: "Subagents",
		name: "subagents",
		description: "Manage sub-agents: list, kill, steer, orchestrate (fan-out/pipeline), gather results, or list orchestrations.",
		parameters: SubagentsToolSchema,
		execute: async (_toolCallId, args) => {
			const params = args;
			const action = readStringParam(params, "action") ?? "list";
			const cfg = loadConfig();
			const requester = resolveRequesterKey({
				cfg,
				agentSessionKey: opts?.agentSessionKey
			});
			const runs = sortSubagentRuns(listSubagentRunsForRequester(requester.requesterSessionKey));
			const recentMinutesRaw = readNumberParam(params, "recentMinutes");
			const recentMinutes = recentMinutesRaw ? Math.max(1, Math.min(MAX_RECENT_MINUTES, Math.floor(recentMinutesRaw))) : DEFAULT_RECENT_MINUTES;
			if (action === "list") {
				const now = Date.now();
				const recentCutoff = now - recentMinutes * 6e4;
				const cache = /* @__PURE__ */ new Map();
				let index = 1;
				const buildListEntry = (entry, runtimeMs) => {
					const sessionEntry = resolveSessionEntryForKey({
						cfg,
						key: entry.childSessionKey,
						cache
					}).entry;
					const totalTokens = resolveTotalTokens(sessionEntry);
					const usageText = formatTokenUsageDisplay(sessionEntry);
					const status = resolveRunStatus(entry);
					const runtime = formatDurationCompact(runtimeMs);
					const label = truncateLine(resolveSubagentLabel(entry), 48);
					const task = truncateLine(entry.task.trim(), 72);
					const line = `${index}. ${label} (${resolveModelDisplay(sessionEntry, entry.model)}, ${runtime}${usageText ? `, ${usageText}` : ""}) ${status}${task.toLowerCase() !== label.toLowerCase() ? ` - ${task}` : ""}`;
					const baseView = {
						index,
						runId: entry.runId,
						sessionKey: entry.childSessionKey,
						label,
						task,
						status,
						runtime,
						runtimeMs,
						model: resolveModelRef(sessionEntry) || entry.model,
						totalTokens,
						startedAt: entry.startedAt
					};
					index += 1;
					return {
						line,
						view: entry.endedAt ? {
							...baseView,
							endedAt: entry.endedAt
						} : baseView
					};
				};
				const active = runs.filter((entry) => !entry.endedAt).map((entry) => buildListEntry(entry, now - (entry.startedAt ?? entry.createdAt)));
				const recent = runs.filter((entry) => !!entry.endedAt && (entry.endedAt ?? 0) >= recentCutoff).map((entry) => buildListEntry(entry, (entry.endedAt ?? now) - (entry.startedAt ?? entry.createdAt)));
				const text = buildListText({
					active,
					recent,
					recentMinutes
				});
				return jsonResult({
					status: "ok",
					action: "list",
					requesterSessionKey: requester.requesterSessionKey,
					callerSessionKey: requester.callerSessionKey,
					callerIsSubagent: requester.callerIsSubagent,
					total: runs.length,
					active: active.map((entry) => entry.view),
					recent: recent.map((entry) => entry.view),
					text
				});
			}
			if (action === "kill") {
				const target = readStringParam(params, "target", { required: true });
				if (target === "all" || target === "*") {
					const cache = /* @__PURE__ */ new Map();
					const seenChildSessionKeys = /* @__PURE__ */ new Set();
					const killedLabels = [];
					let killed = 0;
					for (const entry of runs) {
						const childKey = entry.childSessionKey?.trim();
						if (!childKey || seenChildSessionKeys.has(childKey)) continue;
						seenChildSessionKeys.add(childKey);
						if (!entry.endedAt) {
							if ((await killSubagentRun({
								cfg,
								entry,
								cache
							})).killed) {
								killed += 1;
								killedLabels.push(resolveSubagentLabel(entry));
							}
						}
						const cascade = await cascadeKillChildren({
							cfg,
							parentChildSessionKey: childKey,
							cache,
							seenChildSessionKeys
						});
						killed += cascade.killed;
						killedLabels.push(...cascade.labels);
					}
					return jsonResult({
						status: "ok",
						action: "kill",
						target: "all",
						killed,
						labels: killedLabels,
						text: killed > 0 ? `killed ${killed} subagent${killed === 1 ? "" : "s"}.` : "no running subagents to kill."
					});
				}
				const resolved = resolveSubagentTarget(runs, target, { recentMinutes });
				if (!resolved.entry) return jsonResult({
					status: "error",
					action: "kill",
					target,
					error: resolved.error ?? "Unknown subagent target."
				});
				const killCache = /* @__PURE__ */ new Map();
				const stopResult = await killSubagentRun({
					cfg,
					entry: resolved.entry,
					cache: killCache
				});
				const seenChildSessionKeys = /* @__PURE__ */ new Set();
				const targetChildKey = resolved.entry.childSessionKey?.trim();
				if (targetChildKey) seenChildSessionKeys.add(targetChildKey);
				const cascade = await cascadeKillChildren({
					cfg,
					parentChildSessionKey: resolved.entry.childSessionKey,
					cache: killCache,
					seenChildSessionKeys
				});
				if (!stopResult.killed && cascade.killed === 0) return jsonResult({
					status: "done",
					action: "kill",
					target,
					runId: resolved.entry.runId,
					sessionKey: resolved.entry.childSessionKey,
					text: `${resolveSubagentLabel(resolved.entry)} is already finished.`
				});
				const cascadeText = cascade.killed > 0 ? ` (+ ${cascade.killed} descendant${cascade.killed === 1 ? "" : "s"})` : "";
				return jsonResult({
					status: "ok",
					action: "kill",
					target,
					runId: resolved.entry.runId,
					sessionKey: resolved.entry.childSessionKey,
					label: resolveSubagentLabel(resolved.entry),
					cascadeKilled: cascade.killed,
					cascadeLabels: cascade.killed > 0 ? cascade.labels : void 0,
					text: stopResult.killed ? `killed ${resolveSubagentLabel(resolved.entry)}${cascadeText}.` : `killed ${cascade.killed} descendant${cascade.killed === 1 ? "" : "s"} of ${resolveSubagentLabel(resolved.entry)}.`
				});
			}
			if (action === "steer") {
				const target = readStringParam(params, "target", { required: true });
				const message = readStringParam(params, "message", { required: true });
				if (message.length > MAX_STEER_MESSAGE_CHARS) return jsonResult({
					status: "error",
					action: "steer",
					target,
					error: `Message too long (${message.length} chars, max ${MAX_STEER_MESSAGE_CHARS}).`
				});
				const resolved = resolveSubagentTarget(runs, target, { recentMinutes });
				if (!resolved.entry) return jsonResult({
					status: "error",
					action: "steer",
					target,
					error: resolved.error ?? "Unknown subagent target."
				});
				if (resolved.entry.endedAt) return jsonResult({
					status: "done",
					action: "steer",
					target,
					runId: resolved.entry.runId,
					sessionKey: resolved.entry.childSessionKey,
					text: `${resolveSubagentLabel(resolved.entry)} is already finished.`
				});
				if (requester.callerIsSubagent && requester.callerSessionKey === resolved.entry.childSessionKey) return jsonResult({
					status: "forbidden",
					action: "steer",
					target,
					runId: resolved.entry.runId,
					sessionKey: resolved.entry.childSessionKey,
					error: "Subagents cannot steer themselves."
				});
				const rateKey = `${requester.callerSessionKey}:${resolved.entry.childSessionKey}`;
				const now = Date.now();
				if (now - (steerRateLimit.get(rateKey) ?? 0) < STEER_RATE_LIMIT_MS) return jsonResult({
					status: "rate_limited",
					action: "steer",
					target,
					runId: resolved.entry.runId,
					sessionKey: resolved.entry.childSessionKey,
					error: "Steer rate limit exceeded. Wait a moment before sending another steer."
				});
				steerRateLimit.set(rateKey, now);
				markSubagentRunForSteerRestart(resolved.entry.runId);
				const targetSession = resolveSessionEntryForKey({
					cfg,
					key: resolved.entry.childSessionKey,
					cache: /* @__PURE__ */ new Map()
				});
				const sessionId = typeof targetSession.entry?.sessionId === "string" && targetSession.entry.sessionId.trim() ? targetSession.entry.sessionId.trim() : void 0;
				if (sessionId) abortEmbeddedPiRun(sessionId);
				const cleared = clearSessionQueues([resolved.entry.childSessionKey, sessionId]);
				if (cleared.followupCleared > 0 || cleared.laneCleared > 0) logVerbose(`subagents tool steer: cleared followups=${cleared.followupCleared} lane=${cleared.laneCleared} keys=${cleared.keys.join(",")}`);
				try {
					await callGateway({
						method: "agent.wait",
						params: {
							runId: resolved.entry.runId,
							timeoutMs: STEER_ABORT_SETTLE_TIMEOUT_MS
						},
						timeoutMs: STEER_ABORT_SETTLE_TIMEOUT_MS + 2e3
					});
				} catch {}
				const idempotencyKey = crypto.randomUUID();
				let runId = idempotencyKey;
				try {
					const response = await callGateway({
						method: "agent",
						params: {
							message,
							sessionKey: resolved.entry.childSessionKey,
							sessionId,
							idempotencyKey,
							deliver: false,
							channel: INTERNAL_MESSAGE_CHANNEL,
							lane: AGENT_LANE_SUBAGENT,
							timeout: 0
						},
						timeoutMs: 1e4
					});
					if (typeof response?.runId === "string" && response.runId) runId = response.runId;
				} catch (err) {
					clearSubagentRunSteerRestart(resolved.entry.runId);
					const error = err instanceof Error ? err.message : String(err);
					return jsonResult({
						status: "error",
						action: "steer",
						target,
						runId,
						sessionKey: resolved.entry.childSessionKey,
						sessionId,
						error
					});
				}
				replaceSubagentRunAfterSteer({
					previousRunId: resolved.entry.runId,
					nextRunId: runId,
					fallback: resolved.entry,
					runTimeoutSeconds: resolved.entry.runTimeoutSeconds ?? 0
				});
				return jsonResult({
					status: "accepted",
					action: "steer",
					target,
					runId,
					sessionKey: resolved.entry.childSessionKey,
					sessionId,
					mode: "restart",
					label: resolveSubagentLabel(resolved.entry),
					text: `steered ${resolveSubagentLabel(resolved.entry)}.`
				});
			}
			if (action === "orchestrate") {
				const mode = readStringParam(params, "mode");
				if (mode !== "parallel" && mode !== "pipeline") return jsonResult({
					status: "error",
					action: "orchestrate",
					error: "mode is required and must be 'parallel' or 'pipeline'."
				});
				const tasksRaw = params.tasks;
				const stagesRaw = params.stages;
				if (mode === "parallel" && (!tasksRaw || tasksRaw.length === 0)) return jsonResult({
					status: "error",
					action: "orchestrate",
					error: "tasks array is required for parallel mode."
				});
				if (mode === "pipeline" && (!stagesRaw || stagesRaw.length === 0)) return jsonResult({
					status: "error",
					action: "orchestrate",
					error: "stages array is required for pipeline mode."
				});
				let totalTaskCount = 0;
				const allTasksList = [];
				if (mode === "parallel" && tasksRaw) {
					totalTaskCount = tasksRaw.length;
					allTasksList.push(...tasksRaw);
				} else if (mode === "pipeline" && stagesRaw) for (const stage of stagesRaw) {
					totalTaskCount += stage.tasks.length;
					allTasksList.push(...stage.tasks);
				}
				if (totalTaskCount > MAX_TASKS_PER_ORCHESTRATION) return jsonResult({
					status: "error",
					action: "orchestrate",
					error: `Too many tasks (${totalTaskCount}). Maximum is ${MAX_TASKS_PER_ORCHESTRATION} per orchestrate call.`
				});
				const now = Date.now();
				const windowStart = now - 6e4;
				while (orchestrateRateWindow.length > 0 && orchestrateRateWindow[0] < windowStart) orchestrateRateWindow.shift();
				if (orchestrateRateWindow.length >= RATE_LIMIT_PER_MINUTE) return jsonResult({
					status: "rate_limited",
					action: "orchestrate",
					error: `Orchestrate rate limit exceeded (max ${RATE_LIMIT_PER_MINUTE}/minute). Wait before starting another orchestration.`
				});
				orchestrateRateWindow.push(now);
				const callerDepth = getSubagentDepthFromSessionStore(requester.callerSessionKey, { cfg });
				const maxSpawnDepth = cfg.agents?.defaults?.subagents?.maxSpawnDepth ?? 2;
				if (callerDepth + 1 >= maxSpawnDepth) return jsonResult({
					status: "forbidden",
					action: "orchestrate",
					error: `Insufficient spawn depth for orchestration (current: ${callerDepth}, max: ${maxSpawnDepth}). Workers need at least 1 level.`
				});
				for (const task of allTasksList) if (task.template) {
					if (!getTemplate(task.template)) return jsonResult({
						status: "error",
						action: "orchestrate",
						error: `Template "${task.template}" not found for task "${task.label}".`
					});
				}
				const agentId = parseAgentSessionKey(requester.callerSessionKey)?.agentId ?? "main";
				const agentWorkspace = resolveAgentWorkspaceDir(cfg, agentId);
				const spawnCtx = { agentSessionKey: opts?.agentSessionKey };
				const spawnFn = async (task, outputDir) => {
					const startMs = performance.now();
					try {
						const result = await spawnSubagentDirect({
							task: task.prompt,
							label: task.label,
							template: task.template,
							model: task.model,
							runTimeoutSeconds: task.timeoutSeconds,
							cleanup: "keep"
						}, spawnCtx);
						if (result.status === "error" || result.status === "forbidden") return {
							label: task.label,
							index: task.index ?? 0,
							status: "failed",
							error: result.error ?? "Spawn failed",
							durationMs: Math.round(performance.now() - startMs),
							childSessionKey: result.childSessionKey,
							runId: result.runId,
							template: task.template
						};
						const waitTimeoutMs = (task.timeoutSeconds ?? 300) * 1e3;
						try {
							const waitResult = await callGateway({
								method: "agent.wait",
								params: {
									runId: result.runId,
									timeoutMs: waitTimeoutMs
								},
								timeoutMs: waitTimeoutMs + 1e4
							});
							const durationMs = Math.round(performance.now() - startMs);
							const statusJson = readStatusJson(outputDir);
							if (waitResult?.status === "error") return {
								label: task.label,
								index: task.index ?? 0,
								status: "failed",
								error: waitResult.error ?? "Subagent failed",
								durationMs,
								childSessionKey: result.childSessionKey,
								runId: result.runId,
								template: task.template
							};
							if (waitResult?.status === "timeout") return {
								label: task.label,
								index: task.index ?? 0,
								status: "timeout",
								error: "Subagent timed out",
								durationMs,
								childSessionKey: result.childSessionKey,
								runId: result.runId,
								template: task.template
							};
							return {
								label: task.label,
								index: task.index ?? 0,
								status: "completed",
								resultText: statusJson?.summary ?? "Completed",
								durationMs,
								childSessionKey: result.childSessionKey,
								runId: result.runId,
								template: task.template
							};
						} catch {
							return {
								label: task.label,
								index: task.index ?? 0,
								status: "timeout",
								error: "Subagent wait timed out",
								durationMs: Math.round(performance.now() - startMs),
								childSessionKey: result.childSessionKey,
								runId: result.runId,
								template: task.template
							};
						}
					} catch (err) {
						return {
							label: task.label,
							index: task.index ?? 0,
							status: "failed",
							error: err instanceof Error ? err.message : String(err),
							durationMs: Math.round(performance.now() - startMs),
							template: task.template
						};
					}
				};
				const orchestrationContext = {
					agentWorkspace,
					agentId,
					requesterSessionKey: requester.requesterSessionKey
				};
				const orchestrationConfig = {
					mode,
					tasks: mode === "parallel" ? tasksRaw : void 0,
					stages: mode === "pipeline" ? stagesRaw : void 0,
					maxConcurrency: readNumberParam(params, "maxConcurrency") ?? void 0,
					onFailure: readStringParam(params, "onFailure"),
					maxRetries: readNumberParam(params, "maxRetries") ?? void 0,
					maxTotalTokens: readNumberParam(params, "maxTotalTokens") ?? void 0,
					aggregationPrompt: readStringParam(params, "aggregationPrompt") ?? void 0,
					aggregationTemplate: readStringParam(params, "aggregationTemplate") ?? void 0,
					dryRun: params.dryRun === true,
					orchestrationId: readStringParam(params, "orchestrationId") ?? void 0
				};
				let orchestrationResult;
				if (mode === "parallel") orchestrationResult = await executeOrchestration(orchestrationConfig, spawnFn, orchestrationContext);
				else orchestrationResult = await executePipeline(orchestrationConfig, spawnFn, orchestrationContext);
				if (orchestrationConfig.aggregationPrompt && orchestrationResult.tasks.length > 0) {
					const orchDir = path$1.join(agentWorkspace, "orchestrations", orchestrationResult.orchestrationId);
					const aggregationText = await runAggregation({
						aggregationPrompt: orchestrationConfig.aggregationPrompt,
						results: orchestrationResult.tasks,
						orchestrationDir: orchDir,
						spawnFn,
						aggregationTemplate: orchestrationConfig.aggregationTemplate
					});
					if (aggregationText) orchestrationResult.aggregationResult = aggregationText;
				}
				return jsonResult({
					status: "ok",
					action: "orchestrate",
					orchestrationId: orchestrationResult.orchestrationId,
					mode: orchestrationResult.mode,
					orchestrationStatus: orchestrationResult.status,
					taskCount: orchestrationResult.tasks.length,
					completedCount: orchestrationResult.tasks.filter((t) => t.status === "completed").length,
					failedCount: orchestrationResult.tasks.filter((t) => t.status === "failed" || t.status === "timeout").length,
					totalDurationMs: orchestrationResult.totalDurationMs,
					tokensUsed: orchestrationResult.tokensUsed,
					aggregationResult: orchestrationResult.aggregationResult ?? void 0,
					tasks: orchestrationResult.tasks.map((t) => ({
						label: t.label,
						status: t.status,
						resultText: t.resultText,
						error: t.error,
						durationMs: t.durationMs,
						template: t.template
					}))
				});
			}
			if (action === "gather") {
				const orchestrationId = readStringParam(params, "orchestrationId");
				if (!orchestrationId) return jsonResult({
					status: "error",
					action: "gather",
					error: "orchestrationId is required for gather action."
				});
				const agentWorkspace = resolveAgentWorkspaceDir(cfg, parseAgentSessionKey(requester.callerSessionKey)?.agentId ?? "main");
				const orchestrationDir = path$1.join(agentWorkspace, "orchestrations", orchestrationId);
				if (!readManifest(orchestrationDir)) return jsonResult({
					status: "error",
					action: "gather",
					orchestrationId,
					error: `Orchestration "${orchestrationId}" not found.`
				});
				const gatherResult = gatherOrchestrationResults({
					orchestrationDir,
					orchestrationId,
					template: readStringParam(params, "template") ?? void 0,
					label: readStringParam(params, "label") ?? void 0,
					includeRunning: params.includeRunning === true,
					cleanup: params.cleanup === true,
					runs
				});
				return jsonResult({
					status: "ok",
					action: "gather",
					orchestrationId: gatherResult.orchestrationId,
					orchestrationStatus: gatherResult.status,
					mode: gatherResult.mode,
					startedAt: gatherResult.startedAt,
					completedAt: gatherResult.completedAt,
					taskCount: gatherResult.taskCount,
					tasks: gatherResult.tasks,
					interrupted: gatherResult.interrupted,
					completedTasks: gatherResult.completedTasks,
					incompleteTasks: gatherResult.incompleteTasks,
					canResume: gatherResult.canResume
				});
			}
			if (action === "orchestrations") {
				const agentWorkspace = resolveAgentWorkspaceDir(cfg, parseAgentSessionKey(requester.callerSessionKey)?.agentId ?? "main");
				const orchestrationsDir = path$1.join(agentWorkspace, "orchestrations");
				if (!fs$1.existsSync(orchestrationsDir)) return jsonResult({
					status: "ok",
					action: "orchestrations",
					orchestrations: [],
					total: 0
				});
				const statusFilter = readStringParam(params, "status") ?? void 0;
				const sinceFilter = readNumberParam(params, "since") ?? void 0;
				const untilFilter = readNumberParam(params, "until") ?? void 0;
				const entries = fs$1.readdirSync(orchestrationsDir, { withFileTypes: true });
				const orchestrations = [];
				for (const entry of entries) {
					if (!entry.isDirectory()) continue;
					const manifest = readManifest(path$1.join(orchestrationsDir, entry.name));
					if (!manifest) continue;
					if (statusFilter && manifest.status !== statusFilter) continue;
					if (sinceFilter && manifest.startedAt < sinceFilter) continue;
					if (untilFilter && manifest.startedAt > untilFilter) continue;
					orchestrations.push({
						orchestrationId: manifest.orchestrationId,
						status: manifest.status,
						mode: manifest.mode,
						taskCount: manifest.taskCount,
						startedAt: manifest.startedAt,
						completedAt: manifest.completedAt
					});
				}
				orchestrations.sort((a, b) => b.startedAt - a.startedAt);
				return jsonResult({
					status: "ok",
					action: "orchestrations",
					orchestrations,
					total: orchestrations.length
				});
			}
			return jsonResult({
				status: "error",
				error: "Unsupported action."
			});
		}
	};
}

//#endregion
export { createSubagentsTool };