import { t as isFastTestRuntimeEnv } from "./test-runtime-env-DQDRzsLt.js";
import "./env-DDC-EStD.js";
import { Y as selectDeliverableSessionsReply } from "./openclaw-state-db-Cb4e1jdd.js";
import { i as isSilentReplyPayloadText } from "./tokens-DbQz-n_m.js";
import { u as stripHeartbeatToken } from "./heartbeat-yX5WzsUn.js";
import { p as listDescendantRunsForRequester } from "./subagent-registry-read-U1BV359x.js";
import { t as resolveSubagentCompletionResultText } from "./subagent-completion-result-D6rx9E4J.js";
import { r as readLatestAssistantReply, s as waitForAgentRunsToDrain } from "./run-wait-KKS4R_W9.js";
import { n as isLikelyInterimCronMessage } from "./subagent-followup-hints-CdPqyvGp.js";
//#region src/cron/isolated-agent/subagent-followup.ts
/** Reads or waits for descendant subagent summaries after isolated cron orchestration. */
function resolveCronSubagentTimings() {
	const fastTestMode = isFastTestRuntimeEnv();
	return {
		waitMinMs: fastTestMode ? 10 : 3e4,
		finalReplyGraceMs: fastTestMode ? 50 : 5e3,
		gracePollMs: fastTestMode ? 8 : 200
	};
}
/** Reads completed descendant subagent replies when the orchestrator only emitted interim text. */
async function readDescendantSubagentFallbackReply(params) {
	const descendants = listDescendantRunsForRequester(params.sessionKey).filter((entry) => typeof entry.execution.endedAt === "number" && entry.execution.endedAt >= params.runStartedAt && entry.childSessionKey.trim().length > 0).toSorted((a, b) => (a.execution.endedAt ?? 0) - (b.execution.endedAt ?? 0));
	if (descendants.length === 0) return;
	const latestByChild = /* @__PURE__ */ new Map();
	for (const entry of descendants) {
		const childKey = entry.childSessionKey.trim();
		if (!childKey) continue;
		const current = latestByChild.get(childKey);
		if (!current || (entry.execution.endedAt ?? 0) >= (current.execution.endedAt ?? 0)) latestByChild.set(childKey, entry);
	}
	const replies = [];
	const latestRuns = [...latestByChild.values()].toSorted((a, b) => (a.execution.endedAt ?? 0) - (b.execution.endedAt ?? 0)).slice(-4);
	for (const entry of latestRuns) {
		const completionReply = resolveSubagentCompletionResultText(entry);
		const reply = entry.completion?.terminalReply === void 0 && entry.execution.transcriptTarget === void 0 ? selectDeliverableSessionsReply(await readLatestAssistantReply({ sessionKey: entry.childSessionKey }), completionReply) : completionReply;
		if (!reply || reply.toUpperCase() === "NO_REPLY".toUpperCase()) continue;
		replies.push(reply);
	}
	if (replies.length === 0) return;
	if (replies.length === 1) return replies[0];
	return replies.join("\n\n");
}
/**
* Waits for descendant subagents to complete using a push-based approach:
* each active descendant run is awaited via `agent.wait` (gateway RPC) instead
* of a busy-poll loop.  After all active runs settle, a short grace period
* polls the cron agent's session for a post-orchestration synthesis message.
*/
async function waitForDescendantSubagentSummary(params) {
	const timings = resolveCronSubagentTimings();
	const initialReply = params.initialReply?.trim();
	const deadline = Date.now() + Math.max(timings.waitMinMs, Math.floor(params.timeoutMs));
	const getActiveRuns = () => listDescendantRunsForRequester(params.sessionKey).filter((entry) => typeof entry.execution.endedAt !== "number");
	const initialActiveRuns = getActiveRuns();
	if (!(params.observedActiveDescendants === true || initialActiveRuns.length > 0)) return initialReply;
	await waitForAgentRunsToDrain({
		deadlineAtMs: deadline,
		initialPendingRunIds: initialActiveRuns.map((entry) => entry.runId),
		getPendingRunIds: () => getActiveRuns().map((entry) => entry.runId)
	});
	const gracePeriodDeadline = Math.min(Date.now() + timings.finalReplyGraceMs, deadline);
	const resolveUsableLatestReply = async () => {
		const latest = (await readLatestAssistantReply({ sessionKey: params.sessionKey }))?.trim();
		if (latest && latest.toUpperCase() !== "NO_REPLY".toUpperCase() && !stripHeartbeatToken(latest, {
			mode: "heartbeat",
			maxAckChars: 0
		}).shouldSkip && !isSilentReplyPayloadText(latest, "HEARTBEAT_OK") && (latest !== initialReply || !isLikelyInterimCronMessage(latest))) return latest;
	};
	while (Date.now() < gracePeriodDeadline) {
		const latest = await resolveUsableLatestReply();
		if (latest) return latest;
		await new Promise((resolve) => {
			setTimeout(resolve, timings.gracePollMs);
		});
	}
	const latest = await resolveUsableLatestReply();
	if (latest) return latest;
}
//#endregion
export { readDescendantSubagentFallbackReply, waitForDescendantSubagentSummary };
