import { n as isGatewayRpcUnavailableError } from "./transport-error-D_LRKgla.js";
import { r as truncateUtf16Safe } from "./utf16-slice-D_ngcYKd.js";
import { t as isFastTestRuntimeEnv } from "./test-runtime-env-DQDRzsLt.js";
import "./env-DDC-EStD.js";
import "./src-BntaCZM-.js";
import { a as asOptionalRecord } from "./record-coerce-DItp3I4t.js";
import { n as safeParseJsonRecord } from "./json-coercion-ighRFv8Y.js";
import { s as asFiniteNumber } from "./number-coercion-CLj0HTDM.js";
import { n as getRuntimeConfig } from "./io.runtime-CNGn9TXj.js";
import { n as readTrimmedStringAlias } from "./string-readers-e58-jh1A.js";
import { f as resolveAgentIdFromSessionKey } from "./session-key-FEiNVUl9.js";
import "./agent-scope-CB42Y_8g.js";
import { o as resolveSessionStorePathCore } from "./paths-DVAvlIOc.js";
import { K as isAnnounceSkip } from "./openclaw-state-db-Cb4e1jdd.js";
import { o as isSilentReplyText } from "./tokens-DbQz-n_m.js";
import "./operator-scopes-Dw7Gu2cA.js";
import "./config-D_ojUgx2.js";
import { o as callGateway } from "./call-CU8QpjjS.js";
import { o as getActiveAgentRunDelegatedAuthority } from "./agent-run-registry-CK9EkEg0.js";
import { i as getPluginRuntimeGatewayRequestScope } from "./gateway-request-scope-Bj2ffrHm.js";
import { s as resolveLeastPrivilegeOperatorScopesForMethod } from "./method-scopes-CuEAYEiZ.js";
import "./delivery-context.shared-DhKsSe3b.js";
import "./session-history-eviction-CdhHKsAA.js";
import { o as resolveFreshSessionTotalTokens } from "./types-ukra4D97.js";
import "./session-accessor-Dwfzn6Ej.js";
import "./lifecycle-CZm6Voqr.js";
import { f as resolveProviderRefOwnership } from "./providers-B9Azbl7D.js";
import { t as getGlobalHookRunner } from "./hook-runner-global-BphT2xdR.js";
import { l as resolveContextEngine } from "./registry-oBJBHZ1n.js";
import { a as loadPreparedModelCatalog } from "./prepared-model-catalog-DA2QE8Ku.js";
import { r as wrapPromptDataBlock } from "./sanitize-for-prompt-C5q9LjmF.js";
import { t as formatDurationCompact } from "./format-duration-CfGzOxKC.js";
import { a as buildAgentRunTerminalOutcomeFromWaitResult, o as classifyAgentRunTerminalOutcome } from "./agent-run-terminal-outcome-BRB30wKN.js";
import { u as isAbortedAgentStopReason } from "./run-termination-Bf1l-R4x.js";
import "./session-binding-service-CrA2x7Ud.js";
import { r as getGatewayToolCallerIdentity } from "./gateway-caller-context-CWgOcLDg.js";
import "./runtime-status-B4JKZi92.js";
import { c as withAgentRuntimeExecutionLineage } from "./agent-runtime-identity-token-CV0xh56-.js";
import { a as runWithGatewaySessionSpawnParentExecutionIdentity, o as runWithGatewaySessionSpawnContext, t as callGatewayTool } from "./gateway-vuTMpv-z.js";
import { f as withInProcessAgentRuntimeIdentity, t as dispatchGatewayMethodInProcess } from "./server-plugin-in-process-dispatch-BlaygojH.js";
import { a as hasInProcessGatewayContext } from "./server-plugins-BXZJqF5C.js";
import "./sessions-helpers-Cq07_eFA.js";
import { l as compareSubagentRunGeneration } from "./subagent-registry.store.sqlite-BvwCfenh.js";
import { y as resolveSubagentRunTimerDelayMs } from "./subagent-run-liveness-CpuKir5n.js";
import { t as resolveSubagentCompletionResultText } from "./subagent-completion-result-D6rx9E4J.js";
import { t as forkSessionEntryFromParent } from "./session-fork-olgvR2zK.js";
import { t as ensureContextEnginesInitialized } from "./init-D5uXd8iS.js";
import { o as readSessionMessagesAsync } from "./session-transcript-readers-DeuWju3t.js";
import "./session-utils-DozBEUg6.js";
import "./lanes-CI0_P-yC.js";
import { t as extractStoredAssistantText } from "./chat-history-text-Cj8drMdy.js";
import { t as readSubagentSessionEntry } from "./subagent-announce.runtime.js";
import { promises } from "node:fs";
import { createHash } from "node:crypto";
import { setTimeout as setTimeout$1 } from "node:timers/promises";
//#region src/agents/subagents/registry/subagent-session-cleanup.ts
/**
* Cleanup helper for subagent sessions. It deletes child session state through
* the gateway and preserves lifecycle-hook behavior for session-mode spawns.
*/
function isSessionLifecycleChangedGatewayError(error) {
	if (!(error instanceof Error) || error.name !== "GatewayClientRequestError") return false;
	const requestError = error;
	const details = requestError.details;
	return requestError.gatewayCode === "INVALID_REQUEST" && typeof details === "object" && details !== null && details.reason === "session-changed";
}
/** Deletes a child subagent session and optionally emits session-mode lifecycle hooks. */
async function deleteSubagentSessionForCleanup(params) {
	if (!params.expectedSessionId || !params.expectedLifecycleRevision) return "failed";
	try {
		await params.callGateway({
			method: "sessions.delete",
			params: {
				key: params.childSessionKey,
				deleteTranscript: params.deleteTranscript ?? true,
				emitLifecycleHooks: params.emitLifecycleHooks ?? params.spawnMode === "session",
				expectedSessionId: params.expectedSessionId,
				expectedLifecycleRevision: params.expectedLifecycleRevision
			},
			timeoutMs: params.timeoutMs ?? 1e4
		});
		return "deleted";
	} catch (error) {
		if (isSessionLifecycleChangedGatewayError(error)) return "changed";
		params.onError?.(error);
		return "failed";
	}
}
//#endregion
//#region src/agents/subagents/spawn/subagent-launch-authorization.ts
/** Applies only the exact model choice authorized during spawn planning. */
function applySubagentLaunchAuthorization(request, authorization) {
	const modelOverride = authorization?.modelOverride;
	if (!modelOverride) return request;
	return {
		...request,
		...modelOverride.provider ? { provider: modelOverride.provider } : {},
		model: modelOverride.model
	};
}
//#endregion
//#region src/agents/subagents/spawn/subagent-spawn-deps.ts
const defaultSubagentSpawnDeps = {
	callGateway,
	dispatchGatewayMethodInProcess,
	forkSessionEntryFromParent,
	getGlobalHookRunner,
	getRuntimeConfig,
	hasInProcessGatewayContext,
	ensureContextEnginesInitialized,
	loadPreparedModelCatalog,
	resolveProviderRefOwnership,
	resolveContextEngine
};
let subagentSpawnDeps = defaultSubagentSpawnDeps;
function getSubagentSpawnDeps() {
	return subagentSpawnDeps;
}
function setSubagentSpawnDepsForTest(overrides) {
	subagentSpawnDeps = overrides ? {
		...defaultSubagentSpawnDeps,
		...overrides
	} : defaultSubagentSpawnDeps;
}
//#endregion
//#region src/agents/subagents/spawn/subagent-spawn-execution-identity.ts
const subagentGatewayExecutionIdentities = /* @__PURE__ */ new WeakMap();
function spawnInputRef(kind, value) {
	return `${kind}:${createHash("sha256").update(JSON.stringify(value)).digest("base64url")}`;
}
function buildSubagentExecutionSessionSpawnContext(params) {
	if (!params.enabled) return;
	const allow = params.inheritedToolAllowlist ?? [];
	const deny = params.inheritedToolDenylist ?? [];
	return withAgentRuntimeExecutionLineage({ inheritedToolPolicy: {
		version: 1,
		allow,
		deny
	} }, {
		relation: "sessions_spawn",
		requesterRef: params.requesterRef,
		controllerRef: params.controllerRef,
		depth: params.depth,
		applicableGrantRefs: ["tool:sessions_spawn"],
		localPolicyRefs: [
			spawnInputRef("spawn-depth-policy", [params.depth, params.maxDepth]),
			spawnInputRef("sandbox-policy", [params.backend, params.sandbox]),
			spawnInputRef("inherited-tool-policy", {
				allow: allow.toSorted(),
				deny: deny.toSorted()
			})
		],
		runtimeAssuranceRefs: [`spawn-runtime:${params.backend}`],
		targetPolicyRefs: [spawnInputRef("target-policy", [params.parentAgentId, params.targetAgentId])],
		externalNativeActions: params.backend === "acp" ? "unsupported" : "observable"
	});
}
function withSubagentGatewayExecutionIdentity(params, facts) {
	const carried = { ...params };
	subagentGatewayExecutionIdentities.set(carried, facts);
	return carried;
}
function readSubagentGatewayExecutionIdentity(params) {
	return subagentGatewayExecutionIdentities.get(params);
}
//#endregion
//#region src/agents/subagents/spawn/subagent-spawn-gateway.ts
const DEFAULT_SUBAGENT_AGENT_GATEWAY_TIMEOUT_MS = 6e4;
const MAX_SUBAGENT_AGENT_GATEWAY_TIMEOUT_MS = 3e5;
const SUBAGENT_AGENT_RECONCILE_INTERVAL_MS = 800;
const SUBAGENT_AGENT_RECONCILE_TIMEOUT_MS = 6400;
async function callSubagentGatewayWithDispatchMode(params, authorization, options) {
	const { sessionSpawnContext, parentExecutionIdentityToken } = readSubagentGatewayExecutionIdentity(params) ?? {};
	const authorizedParams = params.params != null && typeof params.params === "object" && !Array.isArray(params.params) ? applySubagentLaunchAuthorization(params.params, authorization) : params.params;
	const leastPrivilegeScopes = resolveLeastPrivilegeOperatorScopesForMethod(params.method, authorizedParams);
	const allowModelOverride = authorization !== void 0;
	const deps = getSubagentSpawnDeps();
	const gatewayCaller = getGatewayToolCallerIdentity();
	const gatewayContextResolver = options?.gatewayContextResolver ?? gatewayCaller?.gatewayContextResolver ?? getPluginRuntimeGatewayRequestScope()?.resolveGatewayContext;
	const hasInProcessGateway = gatewayContextResolver !== void 0 || deps.hasInProcessGatewayContext();
	const needsOutOfProcessModelOverrideAuth = allowModelOverride && !hasInProcessGateway;
	const scopes = params.scopes ?? (leastPrivilegeScopes.includes("operator.admin") || needsOutOfProcessModelOverrideAuth ? ["operator.admin"] : void 0);
	const request = {
		...params,
		params: authorizedParams,
		...scopes != null ? { scopes } : {}
	};
	if (hasInProcessGateway && request.params != null && typeof request.params === "object" && !Array.isArray(request.params)) {
		const forceSyntheticClient = request.method === "agent" || scopes != null;
		const dispatch = async (workerIdentity) => {
			const operationalRunInstance = gatewayCaller?.workerTurnClaim ? workerIdentity?.operationalRunInstance : gatewayCaller?.operationalRunInstance;
			const activeAuthority = operationalRunInstance ? workerIdentity?.delegatedAuthority ?? getActiveAgentRunDelegatedAuthority(operationalRunInstance) : void 0;
			const agentRuntimeIdentity = sessionSpawnContext && gatewayCaller && operationalRunInstance && activeAuthority ? {
				kind: "agentRuntime",
				agentId: workerIdentity?.agentId ?? gatewayCaller.agentId,
				sessionKey: workerIdentity?.sessionKey ?? gatewayCaller.sessionKey,
				operationalRunInstance,
				delegatedAuthority: workerIdentity ? {
					kind: "worker",
					...activeAuthority,
					turnClaim: workerIdentity.turnClaim
				} : {
					kind: "local",
					...activeAuthority
				},
				...parentExecutionIdentityToken ? { executionIdentity: parentExecutionIdentityToken } : {},
				sessionSpawnContext
			} : void 0;
			return await deps.dispatchGatewayMethodInProcess(request.method, request.params, withInProcessAgentRuntimeIdentity({
				expectFinal: request.expectFinal,
				...allowModelOverride ? { allowSyntheticModelOverride: true } : {},
				...options?.agentRunTracking ? { agentRunTracking: options.agentRunTracking } : {},
				...gatewayContextResolver ? { resolveGatewayContext: gatewayContextResolver } : {},
				...forceSyntheticClient ? { forceSyntheticClient: true } : {},
				...typeof request.timeoutMs === "number" ? { timeoutMs: request.timeoutMs } : {},
				...scopes != null ? { syntheticScopes: scopes } : {}
			}, agentRuntimeIdentity));
		};
		const workerCapability = gatewayCaller?.workerTurnExecutionIdentityCapability;
		return {
			response: workerCapability ? await workerCapability.run(async (identity) => {
				if (gatewayCaller?.agentId !== identity.agentId || gatewayCaller.sessionKey !== identity.sessionKey || gatewayCaller.operationalRunInstance !== identity.operationalRunInstance || gatewayCaller.executionIdentityToken !== identity.executionIdentityToken || gatewayCaller.workerTurnClaim !== identity.turnClaim || parentExecutionIdentityToken !== identity.executionIdentityToken) throw new Error("worker child admission identity changed");
				return await dispatch(identity);
			}) : await dispatch(),
			dispatchMode: "in_process"
		};
	}
	const dispatchAgentRequest = (timeoutMs) => sessionSpawnContext && gatewayCaller?.operationalRunInstance ? runWithGatewaySessionSpawnContext(sessionSpawnContext, () => runWithGatewaySessionSpawnParentExecutionIdentity(parentExecutionIdentityToken, () => callGatewayTool(request.method, typeof timeoutMs === "number" ? { timeoutMs } : {}, request.params, {
		expectFinal: request.expectFinal,
		scopes,
		requireAgentRuntimeIdentity: true
	}))) : deps.callGateway(typeof timeoutMs === "number" ? {
		...request,
		timeoutMs
	} : request);
	return {
		response: request.method === "agent" ? await reconcileSubagentAgentDispatch(dispatchAgentRequest, request.timeoutMs) : await dispatchAgentRequest(request.timeoutMs),
		dispatchMode: "out_of_process"
	};
}
async function reconcileSubagentAgentDispatch(dispatch, timeoutMs) {
	try {
		return await dispatch(timeoutMs);
	} catch (error) {
		if (!isGatewayRpcUnavailableError(error)) throw error;
		const deadline = Date.now() + SUBAGENT_AGENT_RECONCILE_TIMEOUT_MS;
		while (true) {
			const remainingMs = deadline - Date.now();
			if (remainingMs <= 0) throw error;
			const response = await dispatch(Math.min(SUBAGENT_AGENT_RECONCILE_INTERVAL_MS, remainingMs));
			const replay = asOptionalRecord(response);
			if (replay?.admissionPending !== true && (replay?.status === "accepted" || replay?.status === "in_flight") && readGatewayRunId(response)) return response;
			if (replay?.admissionPending !== true) throw new Error(`Gateway found no active subagent run (status: ${String(replay?.status)}). Retry the spawn.`, { cause: error });
			await setTimeout$1(Math.min(SUBAGENT_AGENT_RECONCILE_INTERVAL_MS, Math.max(0, deadline - Date.now())));
		}
	}
}
async function callSubagentGateway(params, authorization) {
	return (await callSubagentGatewayWithDispatchMode(params, authorization)).response;
}
async function callNativeSubagentGateway(params, authorization, gatewayContextResolver) {
	const result = await callSubagentGatewayWithDispatchMode(params, authorization, {
		agentRunTracking: "native_subagent",
		gatewayContextResolver
	});
	return {
		response: result.response,
		taskRowOwnership: result.dispatchMode === "in_process" ? "required" : "gateway_best_effort"
	};
}
function readGatewayRunId(response) {
	if (!response || typeof response !== "object") return;
	const { runId } = response;
	return typeof runId === "string" && runId.trim() ? runId.trim() : void 0;
}
function resolveSubagentAgentGatewayTimeoutMs(runTimeoutSeconds) {
	const runTimeoutMs = resolveSubagentRunTimerDelayMs(runTimeoutSeconds) ?? 0;
	if (runTimeoutMs <= 0) return DEFAULT_SUBAGENT_AGENT_GATEWAY_TIMEOUT_MS;
	return Math.min(MAX_SUBAGENT_AGENT_GATEWAY_TIMEOUT_MS, Math.max(DEFAULT_SUBAGENT_AGENT_GATEWAY_TIMEOUT_MS, runTimeoutMs + 5e3));
}
//#endregion
//#region src/agents/subagents/spawn/subagent-spawn-cleanup.ts
const SUBAGENT_CONTROL_GATEWAY_TIMEOUT_MS = 6e4;
function isMatchingAbortResponse(response, gatewayRunId) {
	if (!response || typeof response !== "object") return false;
	const result = response;
	return result.aborted === true && Array.isArray(result.runIds) && result.runIds.some((runId) => runId === gatewayRunId);
}
async function retrySubagentCleanup(attempt, options) {
	for (;;) {
		try {
			if (await attempt()) return true;
		} catch (error) {
			options?.onError?.(error);
		}
		if (options?.shouldRetry?.() === false) return false;
		await new Promise((resolve) => {
			setTimeout(resolve, isFastTestRuntimeEnv() ? 1 : 1e3).unref?.();
		});
	}
}
function requestProvisionalSessionCleanup(childSessionKey, options) {
	return deleteSubagentSessionForCleanup({
		...options,
		childSessionKey,
		callGateway: options?.callGateway ?? callSubagentGateway,
		deleteTranscript: options?.deleteTranscript === true,
		timeoutMs: options?.timeoutMs ?? SUBAGENT_CONTROL_GATEWAY_TIMEOUT_MS
	});
}
async function cleanupProvisionalSession(childSessionKey, options) {
	return await requestProvisionalSessionCleanup(childSessionKey, options) === "deleted";
}
async function waitForProvisionalSessionDeletion(childSessionKey, options) {
	let deleted = false;
	await retrySubagentCleanup(async () => {
		const outcome = await requestProvisionalSessionCleanup(childSessionKey, options);
		deleted = outcome === "deleted";
		return outcome !== "failed";
	});
	return deleted;
}
async function cleanupFailedSpawnBeforeAgentStart(params) {
	const { childSessionKey, attachmentAbsDir, waitForSessionDeletion, ...sessionCleanupOptions } = params;
	let attachmentsRemoved = true;
	if (attachmentAbsDir) try {
		await promises.rm(attachmentAbsDir, {
			recursive: true,
			force: true
		});
	} catch {
		attachmentsRemoved = false;
	}
	return {
		attachmentsRemoved,
		sessionDeleted: await (waitForSessionDeletion ? waitForProvisionalSessionDeletion : cleanupProvisionalSession)(childSessionKey, sessionCleanupOptions)
	};
}
async function terminateAcceptedCollectorRun(params) {
	const call = params.callGateway ?? callSubagentGateway;
	const timeoutMs = params.timeoutMs ?? SUBAGENT_CONTROL_GATEWAY_TIMEOUT_MS;
	await retrySubagentCleanup(async () => {
		try {
			if (isMatchingAbortResponse(await call({
				method: "chat.abort",
				params: {
					sessionKey: params.childSessionKey,
					runId: params.gatewayRunId
				},
				timeoutMs
			}), params.gatewayRunId)) return true;
		} catch {}
		return await requestProvisionalSessionCleanup(params.childSessionKey, {
			deleteTranscript: true,
			expectedSessionId: params.expectedSessionId,
			expectedLifecycleRevision: params.expectedLifecycleRevision,
			callGateway: call,
			timeoutMs
		}) !== "failed";
	});
}
//#endregion
//#region src/agents/subagents/subagent-terminal-outcome.ts
/** Subagents apply explicit cancellation ownership after canonical timeout attribution. */
function classifySubagentTerminalOutcome(outcome) {
	const classification = classifyAgentRunTerminalOutcome(outcome);
	return classification === "timeout" || !isAbortedAgentStopReason(outcome.stopReason) ? classification : "cancellation";
}
//#endregion
//#region src/agents/subagents/announce/subagent-announce-capture.ts
/**
* Helpers for capturing the latest subagent completion reply after a run ends.
*
* Completion output can lag behind lifecycle state, so callers can retry briefly
* before sending an empty or stale announcement.
*/
/** Reads subagent output repeatedly until non-empty text appears or the bounded wait expires. */
async function readLatestSubagentOutputWithRetryUsing(params) {
	const maxWaitMs = Math.max(0, Math.min(params.maxWaitMs, 15e3));
	if (!(maxWaitMs > 0)) return;
	const deadlineAt = performance.now() + maxWaitMs;
	for (;;) {
		const result = await params.readSubagentOutput(params.sessionKey, params.outcome);
		if (result?.trim()) return result;
		const remainingMs = deadlineAt - performance.now();
		if (remainingMs <= 0) return result;
		const sleepMs = Math.min(params.retryIntervalMs, remainingMs);
		await new Promise((resolve) => {
			setTimeout(resolve, sleepMs);
		});
	}
}
/** Captures immediate output first, then optionally waits for a delayed completion reply. */
async function captureSubagentCompletionReplyUsing(params) {
	const immediate = await params.readSubagentOutput(params.sessionKey);
	if (immediate?.trim()) return immediate;
	if (params.waitForReply === false) return;
	return await readLatestSubagentOutputWithRetryUsing({
		sessionKey: params.sessionKey,
		maxWaitMs: params.maxWaitMs,
		retryIntervalMs: params.retryIntervalMs,
		readSubagentOutput: params.readSubagentOutput
	});
}
//#endregion
//#region src/agents/subagents/announce/subagent-yield-output.ts
/**
* sessions_yield transcript detectors.
*
* Accepts provider-specific tool-call and tool-result shapes used by transcript repair and announce capture.
*/
function readToolName(value) {
	const record = asOptionalRecord(value);
	if (!record) return;
	const aliases = [
		"name",
		"toolName",
		"tool_name",
		"functionName",
		"function_name"
	];
	const direct = readTrimmedStringAlias(record, aliases);
	if (direct) return direct;
	const nestedFunction = asOptionalRecord(record.function);
	return nestedFunction ? readTrimmedStringAlias(nestedFunction, aliases) : void 0;
}
function isToolCallBlock(value) {
	const record = asOptionalRecord(value);
	if (!record) return false;
	return record.type === "toolCall" || record.type === "tool_use" || record.type === "toolUse" || record.type === "functionCall" || record.type === "function_call";
}
/** Returns true when an assistant message requested the sessions_yield tool. */
function assistantCallsSessionsYield(message) {
	const record = asOptionalRecord(message);
	if (!record || record.role !== "assistant") return false;
	if (Array.isArray(record.content) && record.content.some((block) => isToolCallBlock(block) && readToolName(block) === "sessions_yield")) return true;
	return [record.toolCalls, record.tool_calls].some((toolCalls) => Array.isArray(toolCalls) && toolCalls.some((toolCall) => readToolName(toolCall) === "sessions_yield"));
}
function parseJsonObject(text) {
	const trimmed = text.trim();
	if (!trimmed.startsWith("{")) return;
	return safeParseJsonRecord(trimmed);
}
function readStructuredToolPayload(content) {
	const record = asOptionalRecord(content);
	if (record) return record;
	if (typeof content === "string") return parseJsonObject(content);
	if (!Array.isArray(content)) return;
	for (const block of content) {
		const blockRecord = asOptionalRecord(block);
		if (!blockRecord) continue;
		const text = blockRecord.text;
		if (typeof text !== "string") continue;
		const parsed = parseJsonObject(text);
		if (parsed) return parsed;
	}
}
/** Returns true when a tool result represents a completed sessions_yield handoff. */
function isSessionsYieldToolResult(message, previousAssistantCalledYield) {
	const record = asOptionalRecord(message);
	if (!record || record.role !== "toolResult" && record.role !== "tool") return false;
	if (readToolName(record) === "sessions_yield") return true;
	if (!previousAssistantCalledYield) return false;
	if (asOptionalRecord(record.details)?.status === "yielded") return true;
	return readStructuredToolPayload(record.content)?.status === "yielded";
}
//#endregion
//#region src/agents/subagents/announce/subagent-announce-output.ts
/**
* Subagent completion output capture.
*
* Reads child session output, detects waiting states, and formats completion findings for announcements.
*/
const FAST_TEST_RETRY_INTERVAL_MS = 8;
const MAX_CHILD_COMPLETION_RESULT_CHARS = 512;
const MAX_CHILD_COMPLETION_FIELD_CHARS = 256;
const MAX_CHILD_COMPLETION_FINDINGS_CHARS = 4096;
const CHILD_RESULT_TRUNCATION_NOTICE = "\n[child result truncated]";
const ASSISTANT_TOOL_CALL_BLOCK_TYPES = /* @__PURE__ */ new Set([
	"toolCall",
	"tool_use",
	"toolUse",
	"functionCall",
	"function_call"
]);
const defaultSubagentAnnounceOutputDeps = {
	callGateway,
	getRuntimeConfig,
	readSubagentSessionEntry,
	readSessionMessagesAsync,
	resolveAgentIdFromSessionKey,
	resolveSessionStorePathCore
};
let subagentAnnounceOutputDeps = defaultSubagentAnnounceOutputDeps;
function isFastTestMode() {
	return isFastTestRuntimeEnv();
}
function withSubagentOutcomeTiming(outcome, timing) {
	const startedAt = asFiniteNumber(timing.startedAt) ?? asFiniteNumber(outcome.startedAt);
	const endedAt = asFiniteNumber(timing.endedAt) ?? asFiniteNumber(outcome.endedAt);
	const nextTiming = {};
	if (typeof startedAt === "number") nextTiming.startedAt = startedAt;
	if (typeof endedAt === "number") nextTiming.endedAt = endedAt;
	if (typeof startedAt === "number" && typeof endedAt === "number") nextTiming.elapsedMs = Math.max(0, endedAt - startedAt);
	return {
		...outcome,
		...nextTiming
	};
}
function countAssistantToolCalls(message) {
	if (!message || typeof message !== "object") return 0;
	const content = message.content;
	const contentToolCalls = Array.isArray(content) ? content.filter((block) => block && typeof block === "object" && ASSISTANT_TOOL_CALL_BLOCK_TYPES.has(block.type ?? "")).length : 0;
	const toolCalls = message.toolCalls ?? message.tool_calls;
	return contentToolCalls + (Array.isArray(toolCalls) ? toolCalls.length : 0);
}
function summarizeSubagentOutputHistory(messages) {
	const snapshot = {};
	let previousAssistantCalledYield = false;
	for (const message of messages) {
		if (!message || typeof message !== "object") continue;
		const role = message.role;
		const provenance = message.provenance;
		if (role === "user" || provenance && typeof provenance === "object" && !Array.isArray(provenance) && provenance.kind === "inter_session") {
			snapshot.latestAssistantText = void 0;
			snapshot.latestSilentText = void 0;
			snapshot.latestToolCallCount = void 0;
			snapshot.waitingForContinuation = false;
			previousAssistantCalledYield = false;
			continue;
		}
		if (role === "assistant") {
			if (assistantCallsSessionsYield(message)) {
				snapshot.latestAssistantText = void 0;
				snapshot.latestSilentText = void 0;
				snapshot.waitingForContinuation = true;
				previousAssistantCalledYield = true;
				continue;
			}
			const toolCallCount = countAssistantToolCalls(message);
			if (toolCallCount > 0) {
				snapshot.latestAssistantText = void 0;
				snapshot.latestSilentText = void 0;
				snapshot.latestToolCallCount = (snapshot.latestToolCallCount ?? 0) + toolCallCount;
				snapshot.waitingForContinuation = false;
				previousAssistantCalledYield = false;
				continue;
			}
			const text = extractStoredAssistantText(message)?.trim();
			if (!text) {
				snapshot.waitingForContinuation = false;
				previousAssistantCalledYield = false;
				continue;
			}
			if (isAnnounceSkip(text) || isSilentReplyText(text, "NO_REPLY")) {
				snapshot.latestSilentText = text;
				snapshot.latestAssistantText = void 0;
				snapshot.waitingForContinuation = false;
				previousAssistantCalledYield = false;
				continue;
			}
			snapshot.latestSilentText = void 0;
			snapshot.latestAssistantText = text;
			snapshot.waitingForContinuation = false;
			previousAssistantCalledYield = false;
			continue;
		}
		if (isSessionsYieldToolResult(message, previousAssistantCalledYield)) {
			snapshot.latestAssistantText = void 0;
			snapshot.latestSilentText = void 0;
			snapshot.waitingForContinuation = true;
			previousAssistantCalledYield = false;
			continue;
		}
		previousAssistantCalledYield = false;
	}
	return snapshot;
}
function selectSubagentOutputText(snapshot, outcome) {
	if (snapshot.waitingForContinuation) return;
	if (snapshot.latestSilentText) return snapshot.latestSilentText;
	if (snapshot.latestAssistantText) return snapshot.latestAssistantText;
	if (outcome?.status === "timeout" && snapshot.latestToolCallCount && snapshot.latestToolCallCount > 0) return `${snapshot.latestToolCallCount} tool call(s) made without visible output.`;
}
async function readSubagentOutput(sessionKey, outcome, options) {
	let messages;
	if (options?.sessionTarget) messages = await subagentAnnounceOutputDeps.readSessionMessagesAsync(options.sessionTarget, {
		mode: "recent",
		maxMessages: 100,
		maxBytes: 1024 * 1024
	});
	const history = messages === void 0 ? await subagentAnnounceOutputDeps.callGateway({
		method: "chat.history",
		params: {
			sessionKey,
			limit: 100
		}
	}) : void 0;
	const selected = selectSubagentOutputText(summarizeSubagentOutputHistory(messages ?? (Array.isArray(history?.messages) ? history.messages : [])), outcome);
	if (selected?.trim()) return selected;
}
async function readLatestSubagentOutputWithRetry(params) {
	return await readLatestSubagentOutputWithRetryUsing({
		sessionKey: params.sessionKey,
		maxWaitMs: params.maxWaitMs,
		outcome: params.outcome,
		retryIntervalMs: isFastTestMode() ? FAST_TEST_RETRY_INTERVAL_MS : 100,
		readSubagentOutput
	});
}
async function readSubagentTimeoutProgress(sessionKey, maxWaitMs, outcome) {
	const initial = await readSubagentOutput(sessionKey, outcome);
	const progress = initial?.trim() ? initial : await readLatestSubagentOutputWithRetry({
		sessionKey,
		maxWaitMs,
		outcome
	});
	return progress && !isAnnounceSkip(progress) && !isSilentReplyText(progress, "NO_REPLY") ? progress : void 0;
}
async function waitForSubagentRunOutcome(runId, timeoutMs) {
	const waitMs = Math.max(0, Math.floor(timeoutMs));
	return await subagentAnnounceOutputDeps.callGateway({
		method: "agent.wait",
		params: {
			runId,
			timeoutMs: waitMs
		},
		timeoutMs: waitMs + 2e3
	});
}
function applySubagentWaitOutcome(params) {
	const next = {
		outcome: params.outcome,
		startedAt: params.startedAt,
		endedAt: params.endedAt
	};
	if (typeof params.wait?.startedAt === "number" && typeof next.startedAt !== "number") next.startedAt = params.wait.startedAt;
	if (typeof params.wait?.endedAt === "number" && typeof next.endedAt !== "number") next.endedAt = params.wait.endedAt;
	const waitError = typeof params.wait?.error === "string" ? params.wait.error : void 0;
	const terminalOutcome = buildAgentRunTerminalOutcomeFromWaitResult(params.wait);
	let outcome = next.outcome;
	if (terminalOutcome) switch (classifySubagentTerminalOutcome(terminalOutcome)) {
		case "timeout": {
			const pendingErrorText = params.wait?.pendingError === true ? terminalOutcome.error ?? waitError : void 0;
			outcome = pendingErrorText ? {
				status: "timeout",
				error: pendingErrorText
			} : { status: "timeout" };
			break;
		}
		case "cancellation":
			outcome = {
				status: "error",
				error: "subagent run terminated"
			};
			break;
		case "failure":
			outcome = {
				status: "error",
				error: terminalOutcome.error ?? waitError
			};
			break;
		case "success":
			outcome = { status: "ok" };
			break;
	}
	next.outcome = outcome ? withSubagentOutcomeTiming(outcome, next) : void 0;
	return next;
}
async function captureSubagentCompletionReply(sessionKey, options) {
	return await captureSubagentCompletionReplyUsing({
		sessionKey,
		waitForReply: options?.waitForReply,
		maxWaitMs: isFastTestMode() ? 50 : 1500,
		retryIntervalMs: isFastTestMode() ? FAST_TEST_RETRY_INTERVAL_MS : 100,
		readSubagentOutput: async (nextSessionKey) => await readSubagentOutput(nextSessionKey, options?.outcome, { sessionTarget: options?.sessionTarget })
	});
}
function describeSubagentOutcome(outcome) {
	if (!outcome) return "unknown";
	if (outcome.status === "ok") return "ok";
	if (outcome.status === "timeout" || outcome.status === "error") {
		const error = outcome.error?.trim();
		return error ? `${outcome.status}: ${error}` : outcome.status;
	}
	return "unknown";
}
function formatChildResultData(resultText) {
	return wrapPromptDataBlock({
		label: "Child result",
		text: resultText?.trim() || "(no output)",
		maxEscapedChars: MAX_CHILD_COMPLETION_RESULT_CHARS,
		truncationMarker: CHILD_RESULT_TRUNCATION_NOTICE
	}) || "Child result: (no output)";
}
function truncateChildCompletionField(value) {
	return value.length > MAX_CHILD_COMPLETION_FIELD_CHARS ? `${truncateUtf16Safe(value, MAX_CHILD_COMPLETION_FIELD_CHARS - 1)}…` : value;
}
function hasCapturedChildCompletionReply(child) {
	return Boolean(child.completion?.terminalReply || child.completion?.resultText?.trim() || child.completion?.fallbackResultText?.trim());
}
function buildChildCompletionFindings(children) {
	const sorted = [...children].toSorted((a, b) => {
		if (a.createdAt !== b.createdAt) return a.createdAt - b.createdAt;
		const aEnded = typeof a.execution.endedAt === "number" ? a.execution.endedAt : Number.MAX_SAFE_INTEGER;
		const bEnded = typeof b.execution.endedAt === "number" ? b.execution.endedAt : Number.MAX_SAFE_INTEGER;
		if (aEnded !== bEnded) return aEnded - bEnded;
		return a.childSessionKey < b.childSessionKey ? -1 : a.childSessionKey > b.childSessionKey ? 1 : 0;
	});
	const sections = [];
	for (const [index, child] of sorted.entries()) {
		const resultText = resolveSubagentCompletionResultText(child);
		const outcome = describeSubagentOutcome(child.execution.outcome);
		if (child.execution.outcome?.status === "ok" && !resultText && hasCapturedChildCompletionReply(child)) continue;
		const title = child.label?.trim() || child.task.trim() || child.childSessionKey.trim() || `child ${index + 1}`;
		const displayIndex = sections.length + 1;
		sections.push({
			index: displayIndex,
			actionable: child.execution.outcome?.status !== "ok",
			text: [
				`${displayIndex}. ${truncateChildCompletionField(title)}`,
				`status: ${truncateChildCompletionField(outcome)}`,
				formatChildResultData(resultText)
			].join("\n")
		});
	}
	if (sections.length === 0) return;
	const render = (visibleSections, omittedCount = 0) => [
		"Child completion results:",
		"",
		...visibleSections,
		...omittedCount > 0 ? [`[${omittedCount} additional child completion result${omittedCount === 1 ? "" : "s"} omitted to fit the context budget.]`] : []
	].join("\n\n");
	const allSections = sections.map((section) => section.text);
	if (render(allSections).length <= MAX_CHILD_COMPLETION_FINDINGS_CHARS) return render(allSections);
	const prioritizedSections = [...sections.filter((section) => section.actionable), ...sections.filter((section) => !section.actionable)];
	let visibleSections = [];
	for (const section of prioritizedSections) {
		const nextSections = [...visibleSections, section].toSorted((left, right) => left.index - right.index);
		const omittedCount = sections.length - nextSections.length;
		if (render(nextSections.map((entry) => entry.text), omittedCount).length <= MAX_CHILD_COMPLETION_FINDINGS_CHARS) visibleSections = nextSections;
	}
	return render(visibleSections.map((section) => section.text), sections.length - visibleSections.length);
}
function dedupeLatestChildCompletionRows(children) {
	const latestByChildSessionKey = /* @__PURE__ */ new Map();
	for (const child of children) {
		const existing = latestByChildSessionKey.get(child.childSessionKey);
		if (!existing || compareSubagentRunGeneration(child, existing) > 0) latestByChildSessionKey.set(child.childSessionKey, child);
	}
	return [...latestByChildSessionKey.values()];
}
function filterCurrentDirectChildCompletionRows(children, params) {
	if (typeof params.getLatestSubagentRunByChildSessionKey !== "function") return children;
	return children.filter((child) => {
		const latest = params.getLatestSubagentRunByChildSessionKey?.(child.childSessionKey);
		if (!latest) return true;
		return latest.runId === child.runId && latest.requesterSessionKey === params.requesterSessionKey && (!params.requesterAgentId || latest.requesterAgentId === params.requesterAgentId);
	});
}
function formatTokenCount(value) {
	if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) return "0";
	if (value >= 1e6) return `${(value / 1e6).toFixed(1)}m`;
	if (value >= 1e3) {
		const formattedThousands = (value / 1e3).toFixed(1);
		if (Number(formattedThousands) >= 1e3) return `${(value / 1e6).toFixed(1)}m`;
		return `${formattedThousands}k`;
	}
	return String(Math.round(value));
}
async function buildCompactAnnounceStatsLine(params) {
	const cfg = subagentAnnounceOutputDeps.getRuntimeConfig();
	const agentId = subagentAnnounceOutputDeps.resolveAgentIdFromSessionKey(params.sessionKey);
	const storePath = subagentAnnounceOutputDeps.resolveSessionStorePathCore(cfg.session?.store, { agentId });
	let entry = subagentAnnounceOutputDeps.readSubagentSessionEntry(storePath, params.sessionKey);
	const tokenWaitAttempts = isFastTestMode() ? 1 : 3;
	for (let attempt = 0; attempt < tokenWaitAttempts; attempt += 1) {
		if (typeof entry?.inputTokens === "number" || typeof entry?.outputTokens === "number" || resolveFreshSessionTotalTokens(entry) !== void 0) break;
		if (!isFastTestMode()) await new Promise((resolve) => {
			setTimeout(resolve, 150);
		});
		entry = subagentAnnounceOutputDeps.readSubagentSessionEntry(storePath, params.sessionKey);
	}
	const input = entry?.inputTokens;
	const output = entry?.outputTokens;
	const hasDirectionalUsage = typeof input === "number" || typeof output === "number";
	const ioTotal = (input ?? 0) + (output ?? 0);
	const promptCache = resolveFreshSessionTotalTokens(entry);
	const parts = [`runtime ${formatDurationCompact(typeof params.startedAt === "number" && typeof params.endedAt === "number" ? Math.max(0, params.endedAt - params.startedAt) : void 0) ?? "n/a"}`, hasDirectionalUsage ? `tokens ${formatTokenCount(ioTotal)} (in ${formatTokenCount(input)} / out ${formatTokenCount(output)})` : promptCache === void 0 ? "tokens unknown" : `tokens ${formatTokenCount(promptCache)} prompt/cache`];
	if (hasDirectionalUsage && typeof promptCache === "number" && promptCache > ioTotal) parts.push(`prompt/cache ${formatTokenCount(promptCache)}`);
	return `Stats: ${parts.join(" • ")}`;
}
const testing = { setDepsForTest(overrides) {
	subagentAnnounceOutputDeps = overrides ? {
		...defaultSubagentAnnounceOutputDeps,
		...overrides
	} : defaultSubagentAnnounceOutputDeps;
} };
if (process.env.VITEST || false) globalThis[Symbol.for("openclaw.subagentAnnounceOutputTestApi")] = testing;
//#endregion
export { getSubagentSpawnDeps as C, deleteSubagentSessionForCleanup as E, withSubagentGatewayExecutionIdentity as S, applySubagentLaunchAuthorization as T, callNativeSubagentGateway as _, dedupeLatestChildCompletionRows as a, resolveSubagentAgentGatewayTimeoutMs as b, readSubagentOutput as c, withSubagentOutcomeTiming as d, classifySubagentTerminalOutcome as f, terminateAcceptedCollectorRun as g, retrySubagentCleanup as h, captureSubagentCompletionReply as i, readSubagentTimeoutProgress as l, cleanupProvisionalSession as m, buildChildCompletionFindings as n, filterCurrentDirectChildCompletionRows as o, cleanupFailedSpawnBeforeAgentStart as p, buildCompactAnnounceStatsLine as r, readLatestSubagentOutputWithRetry as s, applySubagentWaitOutcome as t, waitForSubagentRunOutcome as u, callSubagentGateway as v, setSubagentSpawnDepsForTest as w, buildSubagentExecutionSessionSpawnContext as x, readGatewayRunId as y };
