import "./tool-display-DMBmPBI-.js";
import "./paths-WcYpcMAY.js";
import { o as createSubsystemLogger } from "./entry.js";
import "./auth-profiles-CaNK0cUT.js";
import { p as resolveAgentIdFromSessionKey, u as normalizeAgentId } from "./session-key-Fto5gqqw.js";
import "./exec-CmvuUufz.js";
import "./agent-scope-E2aR3Ci_.js";
import "./github-copilot-token-CKOQDjEZ.js";
import "./emitter-BKo8D7Oj.js";
import "./sqlite-CVrhPija.js";
import "./reliability-BnL75OlZ.js";
import "./frontmatter-C3D7gE4Z.js";
import "./skills-UwTwDeDw.js";
import "./manifest-registry-AgGLF4V7.js";
import "./validation-B00oOkJ3.js";
import { o as loadConfig } from "./config-CoCeK5B2.js";
import { Ht as SESSION_LABEL_MAX_LENGTH } from "./client-DtQEs2_8.js";
import { n as callGateway } from "./call-CkgY6Bq7.js";
import { t as INTERNAL_MESSAGE_CHANNEL } from "./message-channel-DKXbq8GH.js";
import "./sessions-CFJLtXRH.js";
import "./tokens-D-4TlWcT.js";
import "./heartbeat-XNOTz34R.js";
import "./accounts-CNwod9BY.js";
import "./accounts-C3i8BBiA.js";
import "./normalize-CRf-uoB2.js";
import "./bindings-B1hNZin3.js";
import "./logging-BiuZwq5D.js";
import { r as normalizeChannelId, t as getChannelPlugin } from "./plugins-DMpYx7kb.js";
import { t as AGENT_LANE_NESTED } from "./lanes-6YZC1uc5.js";
import "./image-ops-D0pBQqKh.js";
import "./pi-embedded-helpers-D-q9ylFX.js";
import "./sandbox-C79rEJ_w.js";
import "./chrome-BTLLz_O2.js";
import "./tailscale-V4nwZFBO.js";
import "./auth-Beo6eR0R.js";
import "./server-context-T5wFkzWi.js";
import "./routes-Ch0tqbTH.js";
import "./redact-2qrQ_uJt.js";
import { n as formatErrorMessage } from "./errors-BlUw40-o.js";
import "./paths-Cb76_eC_.js";
import "./ssrf-BEPhIfOk.js";
import "./store-Bz34pm8z.js";
import "./ports-BsKQWWi9.js";
import "./trash-Cn3CsF86.js";
import "./dock-BvRrtCWj.js";
import "./accounts-CdYdWklO.js";
import "./paths-CDTtU20P.js";
import "./tool-images-B4eVOjD0.js";
import "./thinking-C03RqJxq.js";
import { a as jsonResult, u as readStringParam } from "./common-CxpUJZLb.js";
import { a as stripToolMessages, c as resolveEffectiveSessionToolsVisibility, l as resolveSandboxedSessionToolContext, m as resolveSessionReference, o as createAgentToAgentPolicy, r as extractAssistantText, s as createSessionVisibilityGuard, u as isRequesterSpawnedSessionVisible } from "./sessions-helpers-NrlH9x7w.js";
import "./pi-embedded-utils-BCSBp2bL.js";
import { a as buildAgentToAgentReplyContext, c as resolveAnnounceTargetFromKey, i as buildAgentToAgentMessageContext, l as resolvePingPongTurns, n as runAgentStep, o as isAnnounceSkip, r as buildAgentToAgentAnnounceContext, s as isReplySkip, t as readLatestAssistantReply } from "./agent-step-C-kmrjsm.js";
import crypto from "node:crypto";
import { Type } from "@sinclair/typebox";

//#region src/agents/tools/sessions/sessions-announce-target.ts
async function resolveAnnounceTarget(params) {
	const parsed = resolveAnnounceTargetFromKey(params.sessionKey);
	const parsedDisplay = resolveAnnounceTargetFromKey(params.displayKey);
	const fallback = parsed ?? parsedDisplay ?? null;
	if (fallback) {
		const normalized = normalizeChannelId(fallback.channel);
		if (!(normalized ? getChannelPlugin(normalized) : null)?.meta?.preferSessionLookupForAnnounceTarget) return fallback;
	}
	try {
		const list = await callGateway({
			method: "sessions.list",
			params: {
				includeGlobal: true,
				includeUnknown: true,
				limit: 200
			}
		});
		const sessions = Array.isArray(list?.sessions) ? list.sessions : [];
		const match = sessions.find((entry) => entry?.key === params.sessionKey) ?? sessions.find((entry) => entry?.key === params.displayKey);
		const deliveryContext = match?.deliveryContext && typeof match.deliveryContext === "object" ? match.deliveryContext : void 0;
		const channel = (typeof deliveryContext?.channel === "string" ? deliveryContext.channel : void 0) ?? (typeof match?.lastChannel === "string" ? match.lastChannel : void 0);
		const to = (typeof deliveryContext?.to === "string" ? deliveryContext.to : void 0) ?? (typeof match?.lastTo === "string" ? match.lastTo : void 0);
		const accountId = (typeof deliveryContext?.accountId === "string" ? deliveryContext.accountId : void 0) ?? (typeof match?.lastAccountId === "string" ? match.lastAccountId : void 0);
		if (channel && to) return {
			channel,
			to,
			accountId
		};
	} catch {}
	return fallback;
}

//#endregion
//#region src/agents/tools/sessions/sessions-send-tool.a2a.ts
const log = createSubsystemLogger("agents/sessions-send");
async function runSessionsSendA2AFlow(params) {
	const runContextId = params.waitRunId ?? "unknown";
	try {
		let primaryReply = params.roundOneReply;
		let latestReply = params.roundOneReply;
		if (!primaryReply && params.waitRunId) {
			const waitMs = Math.min(params.announceTimeoutMs, 6e4);
			if ((await callGateway({
				method: "agent.wait",
				params: {
					runId: params.waitRunId,
					timeoutMs: waitMs
				},
				timeoutMs: waitMs + 2e3
			}))?.status === "ok") {
				primaryReply = await readLatestAssistantReply({ sessionKey: params.targetSessionKey });
				latestReply = primaryReply;
			}
		}
		if (!latestReply) return;
		const announceTarget = await resolveAnnounceTarget({
			sessionKey: params.targetSessionKey,
			displayKey: params.displayKey
		});
		const targetChannel = announceTarget?.channel ?? "unknown";
		if (params.maxPingPongTurns > 0 && params.requesterSessionKey && params.requesterSessionKey !== params.targetSessionKey) {
			let currentSessionKey = params.requesterSessionKey;
			let nextSessionKey = params.targetSessionKey;
			let incomingMessage = latestReply;
			for (let turn = 1; turn <= params.maxPingPongTurns; turn += 1) {
				const currentRole = currentSessionKey === params.requesterSessionKey ? "requester" : "target";
				const replyPrompt = buildAgentToAgentReplyContext({
					requesterSessionKey: params.requesterSessionKey,
					requesterChannel: params.requesterChannel,
					targetSessionKey: params.displayKey,
					targetChannel,
					currentRole,
					turn,
					maxTurns: params.maxPingPongTurns
				});
				const replyText = await runAgentStep({
					sessionKey: currentSessionKey,
					message: incomingMessage,
					extraSystemPrompt: replyPrompt,
					timeoutMs: params.announceTimeoutMs,
					lane: AGENT_LANE_NESTED,
					sourceSessionKey: nextSessionKey,
					sourceChannel: nextSessionKey === params.requesterSessionKey ? params.requesterChannel : targetChannel,
					sourceTool: "sessions_send"
				});
				if (!replyText || isReplySkip(replyText)) break;
				latestReply = replyText;
				incomingMessage = replyText;
				const swap = currentSessionKey;
				currentSessionKey = nextSessionKey;
				nextSessionKey = swap;
			}
		}
		const announcePrompt = buildAgentToAgentAnnounceContext({
			requesterSessionKey: params.requesterSessionKey,
			requesterChannel: params.requesterChannel,
			targetSessionKey: params.displayKey,
			targetChannel,
			originalMessage: params.message,
			roundOneReply: primaryReply,
			latestReply
		});
		const announceReply = await runAgentStep({
			sessionKey: params.targetSessionKey,
			message: "Agent-to-agent announce step.",
			extraSystemPrompt: announcePrompt,
			timeoutMs: params.announceTimeoutMs,
			lane: AGENT_LANE_NESTED,
			sourceSessionKey: params.requesterSessionKey,
			sourceChannel: params.requesterChannel,
			sourceTool: "sessions_send"
		});
		if (announceTarget && announceReply && announceReply.trim() && !isAnnounceSkip(announceReply)) try {
			await callGateway({
				method: "send",
				params: {
					to: announceTarget.to,
					message: announceReply.trim(),
					channel: announceTarget.channel,
					accountId: announceTarget.accountId,
					idempotencyKey: `a2a-announce:${runContextId}`
				},
				timeoutMs: 1e4
			});
		} catch (err) {
			log.warn("sessions_send announce delivery failed", {
				runId: runContextId,
				channel: announceTarget.channel,
				to: announceTarget.to,
				error: formatErrorMessage(err)
			});
		}
	} catch (err) {
		log.warn("sessions_send announce flow failed", {
			runId: runContextId,
			error: formatErrorMessage(err)
		});
	}
}

//#endregion
//#region src/agents/tools/sessions/sessions-send-tool.ts
const SessionsSendToolSchema = Type.Object({
	sessionKey: Type.Optional(Type.String()),
	label: Type.Optional(Type.String({
		minLength: 1,
		maxLength: SESSION_LABEL_MAX_LENGTH
	})),
	agentId: Type.Optional(Type.String({
		minLength: 1,
		maxLength: 64
	})),
	message: Type.String(),
	timeoutSeconds: Type.Optional(Type.Number({ minimum: 0 })),
	deliveryMode: Type.Optional(Type.Union([
		Type.Literal("default"),
		Type.Literal("followUp"),
		Type.Literal("steer")
	]))
});
function createSessionsSendTool(opts) {
	return {
		label: "Session Send",
		name: "sessions_send",
		description: "Send a message to another session or agent. To talk to another agent, use agentId (e.g. agentId='carla_bot') — this is the simplest way to reach them. If no active session exists for the target agent, use sessions_spawn with agentId and task instead to start a new conversation with them. You can also use sessionKey or label to target a specific session. Set deliveryMode to 'followUp' to queue work that runs after the target's current task completes, or 'steer' to interrupt the target immediately.",
		parameters: SessionsSendToolSchema,
		execute: async (toolCallId, args) => {
			const params = args;
			const message = readStringParam(params, "message", { required: true });
			const cfg = loadConfig();
			const { mainKey, alias, effectiveRequesterKey, restrictToSpawned } = resolveSandboxedSessionToolContext({
				cfg,
				agentSessionKey: opts?.agentSessionKey,
				sandboxed: opts?.sandboxed
			});
			const a2aPolicy = createAgentToAgentPolicy(cfg);
			const sessionVisibility = resolveEffectiveSessionToolsVisibility({
				cfg,
				sandboxed: opts?.sandboxed === true
			});
			const sessionKeyParam = readStringParam(params, "sessionKey");
			const labelParam = readStringParam(params, "label")?.trim() || void 0;
			const labelAgentIdParam = readStringParam(params, "agentId")?.trim() || void 0;
			if (sessionKeyParam && labelParam) return jsonResult({
				runId: crypto.randomUUID(),
				status: "error",
				error: "Provide either sessionKey or label (not both)."
			});
			let sessionKey = sessionKeyParam;
			if (!sessionKey && labelParam) {
				const requesterAgentId = resolveAgentIdFromSessionKey(effectiveRequesterKey);
				const requestedAgentId = labelAgentIdParam ? normalizeAgentId(labelAgentIdParam) : void 0;
				if (restrictToSpawned && requestedAgentId && requestedAgentId !== requesterAgentId) return jsonResult({
					runId: crypto.randomUUID(),
					status: "forbidden",
					error: "Sandboxed sessions_send label lookup is limited to this agent"
				});
				if (requesterAgentId && requestedAgentId && requestedAgentId !== requesterAgentId) {
					if (!a2aPolicy.enabled) return jsonResult({
						runId: crypto.randomUUID(),
						status: "forbidden",
						error: "Agent-to-agent messaging is disabled. Set tools.agentToAgent.enabled=true to allow cross-agent sends."
					});
					if (!a2aPolicy.isAllowed(requesterAgentId, requestedAgentId)) return jsonResult({
						runId: crypto.randomUUID(),
						status: "forbidden",
						error: "Agent-to-agent messaging denied by tools.agentToAgent.allow."
					});
				}
				const resolveParams = {
					label: labelParam,
					...requestedAgentId ? { agentId: requestedAgentId } : {},
					...restrictToSpawned ? { spawnedBy: effectiveRequesterKey } : {}
				};
				let resolvedKey = "";
				try {
					const resolved = await callGateway({
						method: "sessions.resolve",
						params: resolveParams,
						timeoutMs: 1e4
					});
					resolvedKey = typeof resolved?.key === "string" ? resolved.key.trim() : "";
				} catch (err) {
					const msg = err instanceof Error ? err.message : String(err);
					if (restrictToSpawned) return jsonResult({
						runId: crypto.randomUUID(),
						status: "forbidden",
						error: "Session not visible from this sandboxed agent session."
					});
					return jsonResult({
						runId: crypto.randomUUID(),
						status: "error",
						error: msg || `No session found with label: ${labelParam}`
					});
				}
				if (!resolvedKey) {
					if (restrictToSpawned) return jsonResult({
						runId: crypto.randomUUID(),
						status: "forbidden",
						error: "Session not visible from this sandboxed agent session."
					});
					return jsonResult({
						runId: crypto.randomUUID(),
						status: "error",
						error: `No session found with label: ${labelParam}`
					});
				}
				sessionKey = resolvedKey;
			}
			if (!sessionKey && !labelParam && labelAgentIdParam) {
				const requesterAgentId = resolveAgentIdFromSessionKey(effectiveRequesterKey);
				const requestedAgentId = normalizeAgentId(labelAgentIdParam);
				if (restrictToSpawned && requestedAgentId !== requesterAgentId) return jsonResult({
					runId: crypto.randomUUID(),
					status: "forbidden",
					error: "Sandboxed sessions_send agentId lookup is limited to this agent"
				});
				if (requesterAgentId && requestedAgentId !== requesterAgentId) {
					if (!a2aPolicy.enabled) return jsonResult({
						runId: crypto.randomUUID(),
						status: "forbidden",
						error: "Agent-to-agent messaging is disabled. Set tools.agentToAgent.enabled=true to allow cross-agent sends."
					});
					if (!a2aPolicy.isAllowed(requesterAgentId, requestedAgentId)) return jsonResult({
						runId: crypto.randomUUID(),
						status: "forbidden",
						error: "Agent-to-agent messaging denied by tools.agentToAgent.allow."
					});
				}
				try {
					const resolved = await callGateway({
						method: "sessions.resolve",
						params: { agentId: requestedAgentId },
						timeoutMs: 1e4
					});
					sessionKey = typeof resolved?.key === "string" ? resolved.key.trim() : "";
				} catch {
					sessionKey = `agent:${requestedAgentId}:main`;
				}
				if (!sessionKey) sessionKey = `agent:${requestedAgentId}:main`;
			}
			if (!sessionKey) return jsonResult({
				runId: crypto.randomUUID(),
				status: "error",
				error: "Either sessionKey, label, or agentId is required"
			});
			const resolvedSession = await resolveSessionReference({
				sessionKey,
				alias,
				mainKey,
				requesterInternalKey: effectiveRequesterKey,
				restrictToSpawned
			});
			if (!resolvedSession.ok) return jsonResult({
				runId: crypto.randomUUID(),
				status: resolvedSession.status,
				error: resolvedSession.error
			});
			const resolvedKey = resolvedSession.key;
			const displayKey = resolvedSession.displayKey;
			const resolvedViaSessionId = resolvedSession.resolvedViaSessionId;
			if (restrictToSpawned && !resolvedViaSessionId && resolvedKey !== effectiveRequesterKey) {
				if (!await isRequesterSpawnedSessionVisible({
					requesterSessionKey: effectiveRequesterKey,
					targetSessionKey: resolvedKey
				})) return jsonResult({
					runId: crypto.randomUUID(),
					status: "forbidden",
					error: `Session not visible from this sandboxed agent session: ${sessionKey}`,
					sessionKey: displayKey
				});
			}
			const timeoutSeconds = typeof params.timeoutSeconds === "number" && Number.isFinite(params.timeoutSeconds) ? Math.max(0, Math.floor(params.timeoutSeconds)) : 30;
			const timeoutMs = timeoutSeconds * 1e3;
			const announceTimeoutMs = timeoutSeconds === 0 ? 3e4 : timeoutMs;
			const idempotencyKey = toolCallId && toolCallId.trim() ? toolCallId.trim() : crypto.randomUUID();
			let runId = idempotencyKey;
			const access = (await createSessionVisibilityGuard({
				action: "send",
				requesterSessionKey: effectiveRequesterKey,
				visibility: sessionVisibility,
				a2aPolicy
			})).check(resolvedKey);
			if (!access.allowed) return jsonResult({
				runId: crypto.randomUUID(),
				status: access.status,
				error: access.error,
				sessionKey: displayKey
			});
			const agentMessageContext = buildAgentToAgentMessageContext({
				requesterSessionKey: opts?.agentSessionKey,
				requesterChannel: opts?.agentChannel,
				targetSessionKey: displayKey
			});
			const deliveryMode = typeof params.deliveryMode === "string" ? params.deliveryMode : void 0;
			const streamingBehavior = deliveryMode === "followUp" ? "followUp" : deliveryMode === "steer" ? "steer" : void 0;
			const sendParams = {
				message,
				sessionKey: resolvedKey,
				idempotencyKey,
				deliver: false,
				channel: INTERNAL_MESSAGE_CHANNEL,
				lane: AGENT_LANE_NESTED,
				extraSystemPrompt: agentMessageContext,
				inputProvenance: {
					kind: "inter_session",
					sourceSessionKey: opts?.agentSessionKey,
					sourceChannel: opts?.agentChannel,
					sourceTool: "sessions_send"
				},
				...streamingBehavior ? { streamingBehavior } : {}
			};
			const requesterSessionKey = opts?.agentSessionKey;
			const requesterChannel = opts?.agentChannel;
			const maxPingPongTurns = resolvePingPongTurns(cfg);
			const delivery = {
				status: "pending",
				mode: deliveryMode === "followUp" ? "followUp" : "announce"
			};
			const startA2AFlow = (roundOneReply, waitRunId) => {
				runSessionsSendA2AFlow({
					targetSessionKey: resolvedKey,
					displayKey,
					message,
					announceTimeoutMs,
					maxPingPongTurns,
					requesterSessionKey,
					requesterChannel,
					roundOneReply,
					waitRunId
				});
			};
			if (timeoutSeconds === 0) try {
				const response = await callGateway({
					method: "agent",
					params: sendParams,
					timeoutMs: 1e4
				});
				if (typeof response?.runId === "string" && response.runId) runId = response.runId;
				startA2AFlow(void 0, runId);
				return jsonResult({
					runId,
					status: "accepted",
					sessionKey: displayKey,
					delivery
				});
			} catch (err) {
				const messageText = err instanceof Error ? err.message : typeof err === "string" ? err : "error";
				return jsonResult({
					runId,
					status: "error",
					error: messageText,
					sessionKey: displayKey
				});
			}
			try {
				const response = await callGateway({
					method: "agent",
					params: sendParams,
					timeoutMs: 1e4
				});
				if (typeof response?.runId === "string" && response.runId) runId = response.runId;
			} catch (err) {
				const messageText = err instanceof Error ? err.message : typeof err === "string" ? err : "error";
				return jsonResult({
					runId,
					status: "error",
					error: messageText,
					sessionKey: displayKey
				});
			}
			let waitStatus;
			let waitError;
			try {
				const wait = await callGateway({
					method: "agent.wait",
					params: {
						runId,
						timeoutMs
					},
					timeoutMs: timeoutMs + 2e3
				});
				waitStatus = typeof wait?.status === "string" ? wait.status : void 0;
				waitError = typeof wait?.error === "string" ? wait.error : void 0;
			} catch (err) {
				const messageText = err instanceof Error ? err.message : typeof err === "string" ? err : "error";
				return jsonResult({
					runId,
					status: messageText.includes("gateway timeout") ? "timeout" : "error",
					error: messageText,
					sessionKey: displayKey
				});
			}
			if (waitStatus === "timeout") return jsonResult({
				runId,
				status: "timeout",
				error: waitError,
				sessionKey: displayKey
			});
			if (waitStatus === "error") return jsonResult({
				runId,
				status: "error",
				error: waitError ?? "agent error",
				sessionKey: displayKey
			});
			const history = await callGateway({
				method: "chat.history",
				params: {
					sessionKey: resolvedKey,
					limit: 50
				}
			});
			const filtered = stripToolMessages(Array.isArray(history?.messages) ? history.messages : []);
			const last = filtered.length > 0 ? filtered[filtered.length - 1] : void 0;
			const reply = last ? extractAssistantText(last) : void 0;
			startA2AFlow(reply ?? void 0);
			return jsonResult({
				runId,
				status: "ok",
				reply,
				sessionKey: displayKey,
				delivery
			});
		}
	};
}

//#endregion
export { createSessionsSendTool };