import { S as resolveExpiresAtMsFromDurationMs, a as asDateTimestampMs, x as resolveDateTimestampMs } from "./number-coercion-CU7MBp2A.js";
import { c as resolveDefaultAgentId } from "./agent-scope-config-CT5O0iC8.js";
import { i as emitAgentEvent } from "./agent-events-e1bpdQ82.js";
import { n as isAbortRequestText } from "./abort-primitives-BAgE1EGI.js";
//#region src/gateway/chat-abort.ts
const DEFAULT_CHAT_RUN_ABORT_GRACE_MS = 6e4;
function isChatStopCommandText(text) {
	return isAbortRequestText(text);
}
function createChatAbortSignalReason(stopReason) {
	if (stopReason !== "timeout") return;
	const reason = /* @__PURE__ */ new Error("chat run timed out");
	reason.name = "TimeoutError";
	return reason;
}
function resolveChatRunExpiresAtMs(params) {
	const { now, timeoutMs, graceMs = DEFAULT_CHAT_RUN_ABORT_GRACE_MS, minMs = 2 * 6e4, maxMs = 1440 * 6e4 } = params;
	const safeNow = asDateTimestampMs(now);
	if (safeNow === void 0) return 0;
	const target = resolveExpiresAtMsFromDurationMs(Math.max(0, timeoutMs) + graceMs, { nowMs: safeNow });
	const min = resolveExpiresAtMsFromDurationMs(minMs, { nowMs: safeNow });
	const max = resolveExpiresAtMsFromDurationMs(maxMs, { nowMs: safeNow });
	if (target === void 0 || min === void 0 || max === void 0) return 0;
	return Math.min(max, Math.max(min, target));
}
function resolveAgentRunExpiresAtMs(params) {
	const graceMs = Math.max(0, params.graceMs ?? DEFAULT_CHAT_RUN_ABORT_GRACE_MS);
	return resolveChatRunExpiresAtMs({
		now: params.now,
		timeoutMs: params.timeoutMs,
		graceMs,
		minMs: graceMs,
		maxMs: Math.max(0, params.timeoutMs) + graceMs
	});
}
function registerChatAbortController(params) {
	const controller = new AbortController();
	const cleanup = () => {
		if (params.chatAbortControllers.get(params.runId)?.controller === controller) params.chatAbortControllers.delete(params.runId);
	};
	if (!params.sessionKey || params.chatAbortControllers.has(params.runId)) return {
		controller,
		registered: false,
		cleanup
	};
	const rawNow = params.now ?? Date.now();
	const now = resolveDateTimestampMs(rawNow, 0);
	const explicitExpiresAtMs = params.expiresAtMs === void 0 ? void 0 : asDateTimestampMs(params.expiresAtMs) ?? 0;
	const entry = {
		controller,
		sessionId: params.sessionId,
		sessionKey: params.sessionKey,
		agentId: normalizeActiveAgentId(params.agentId),
		startedAtMs: now,
		expiresAtMs: explicitExpiresAtMs ?? resolveChatRunExpiresAtMs({
			now: rawNow,
			timeoutMs: params.timeoutMs
		}),
		ownerConnId: params.ownerConnId,
		ownerDeviceId: params.ownerDeviceId,
		providerId: normalizeProviderIdForActiveRun(params.providerId),
		authProviderId: normalizeProviderIdForActiveRun(params.authProviderId),
		projectSessionActive: true,
		kind: params.kind
	};
	params.chatAbortControllers.set(params.runId, entry);
	return {
		controller,
		registered: true,
		entry,
		cleanup
	};
}
function normalizeProviderIdForActiveRun(providerId) {
	return providerId?.trim().toLowerCase() || void 0;
}
function normalizeActiveAgentId(agentId) {
	return agentId?.trim().toLowerCase() || void 0;
}
function resolveChatAbortDeliverySessionKeys(ops, sessionKey, agentId) {
	if (sessionKey !== "global") return [sessionKey];
	const scopedAgentId = normalizeActiveAgentId(agentId);
	if (!scopedAgentId) return [sessionKey];
	const keys = [`agent:${scopedAgentId}:global`];
	const cfg = ops.getRuntimeConfig?.();
	const defaultAgentId = cfg ? resolveDefaultAgentId(cfg) : void 0;
	if (defaultAgentId && scopedAgentId === defaultAgentId) keys.push(sessionKey);
	return keys;
}
function broadcastChatAborted(ops, params) {
	const { runId, sessionKey, stopReason, partialText } = params;
	const defaultGlobalAgentId = sessionKey === "global" ? normalizeActiveAgentId(resolveDefaultGlobalAgentId(ops)) : void 0;
	const payloadAgentId = sessionKey === "global" ? normalizeActiveAgentId(params.agentId) ?? defaultGlobalAgentId : normalizeActiveAgentId(params.agentId);
	const payload = {
		runId,
		sessionKey,
		...payloadAgentId ? { agentId: payloadAgentId } : {},
		seq: (ops.agentRunSeq.get(runId) ?? 0) + 1,
		state: "aborted",
		stopReason,
		message: partialText ? {
			role: "assistant",
			content: [{
				type: "text",
				text: partialText
			}],
			timestamp: Date.now()
		} : void 0
	};
	ops.broadcast("chat", payload);
	for (const deliverySessionKey of resolveChatAbortDeliverySessionKeys(ops, sessionKey, payloadAgentId)) ops.nodeSendToSession(deliverySessionKey, "chat", payload);
}
function resolveDefaultGlobalAgentId(ops) {
	const cfg = ops.getRuntimeConfig?.();
	return cfg ? resolveDefaultAgentId(cfg) : void 0;
}
function abortChatRunById(ops, params) {
	const { runId, sessionKey, stopReason } = params;
	const active = ops.chatAbortControllers.get(runId);
	if (!active) return { aborted: false };
	if (active.sessionKey !== sessionKey) return { aborted: false };
	const bufferedText = ops.chatRunBuffers.get(runId);
	const partialText = bufferedText && bufferedText.trim() ? bufferedText : void 0;
	ops.chatAbortedRuns.set(runId, Date.now());
	if (stopReason) active.abortStopReason = stopReason;
	active.controller.abort(createChatAbortSignalReason(stopReason));
	ops.chatAbortControllers.delete(runId);
	ops.clearChatRunState(runId);
	const removed = ops.removeChatRun(runId, runId, sessionKey);
	broadcastChatAborted(ops, {
		runId,
		sessionKey,
		agentId: active.agentId,
		stopReason,
		partialText
	});
	emitAgentEvent({
		runId,
		sessionKey,
		agentId: active.agentId,
		stream: "lifecycle",
		data: {
			phase: "end",
			status: "cancelled",
			aborted: true,
			stopReason,
			startedAt: active.startedAtMs,
			endedAt: Date.now()
		}
	});
	ops.agentRunSeq.delete(runId);
	if (removed?.clientRunId) ops.agentRunSeq.delete(removed.clientRunId);
	return { aborted: true };
}
function updateChatRunProvider(chatAbortControllers, params) {
	const entry = chatAbortControllers.get(params.runId);
	if (!entry) return false;
	entry.providerId = normalizeProviderIdForActiveRun(params.providerId);
	entry.authProviderId = normalizeProviderIdForActiveRun(params.authProviderId);
	return true;
}
function abortChatRunsForProvider(ops, params) {
	const providerId = normalizeProviderIdForActiveRun(params.providerId);
	if (!providerId) return { runIds: [] };
	const matches = [...ops.chatAbortControllers.entries()].filter(([, entry]) => normalizeProviderIdForActiveRun(entry.authProviderId) === providerId || normalizeProviderIdForActiveRun(entry.providerId) === providerId);
	const runIds = [];
	for (const [runId, entry] of matches) if (abortChatRunById(ops, {
		runId,
		sessionKey: entry.sessionKey,
		stopReason: params.stopReason
	}).aborted) runIds.push(runId);
	return { runIds };
}
//#endregion
export { resolveAgentRunExpiresAtMs as a, registerChatAbortController as i, abortChatRunsForProvider as n, updateChatRunProvider as o, isChatStopCommandText as r, abortChatRunById as t };
