import { h as __exportAll } from "./pi-embedded-utils-Dx4_ysu7.js";
import { t as createSubsystemLogger } from "./subsystem-B57zAnh3.js";
import { t as emitReliabilityEvent } from "./reliability-CU83NHOD.js";
import { i as pruneDiagnosticSessionStates, r as getDiagnosticSessionState, t as diagnosticSessionStates } from "./diagnostic-session-state-D0dd2bM8.js";

//#region src/infra/diagnostic-events.ts
let seq = 0;
const listeners = /* @__PURE__ */ new Set();
function isDiagnosticsEnabled(config) {
	return config?.diagnostics?.enabled === true;
}
function emitDiagnosticEvent(event) {
	const enriched = {
		...event,
		seq: seq += 1,
		ts: Date.now()
	};
	for (const listener of listeners) try {
		listener(enriched);
	} catch {}
}

//#endregion
//#region src/logging/diagnostic.ts
var diagnostic_exports = /* @__PURE__ */ __exportAll({
	diagnosticLogger: () => diag,
	logLaneDequeue: () => logLaneDequeue,
	logLaneEnqueue: () => logLaneEnqueue,
	logMessageProcessed: () => logMessageProcessed,
	logMessageQueued: () => logMessageQueued,
	logSessionStateChange: () => logSessionStateChange,
	logSessionStuck: () => logSessionStuck,
	logToolLoopAction: () => logToolLoopAction,
	logWebhookError: () => logWebhookError,
	logWebhookProcessed: () => logWebhookProcessed,
	logWebhookReceived: () => logWebhookReceived,
	startDiagnosticHeartbeat: () => startDiagnosticHeartbeat,
	stopDiagnosticHeartbeat: () => stopDiagnosticHeartbeat
});
const diag = createSubsystemLogger("diagnostic");
const webhookStats = {
	received: 0,
	processed: 0,
	errors: 0,
	lastReceived: 0
};
let lastActivityAt = 0;
function markActivity() {
	lastActivityAt = Date.now();
}
function logWebhookReceived(params) {
	webhookStats.received += 1;
	webhookStats.lastReceived = Date.now();
	if (diag.isEnabled("debug")) diag.debug(`webhook received: channel=${params.channel} type=${params.updateType ?? "unknown"} chatId=${params.chatId ?? "unknown"} total=${webhookStats.received}`);
	emitDiagnosticEvent({
		type: "webhook.received",
		channel: params.channel,
		updateType: params.updateType,
		chatId: params.chatId
	});
	markActivity();
}
function logWebhookProcessed(params) {
	webhookStats.processed += 1;
	if (diag.isEnabled("debug")) diag.debug(`webhook processed: channel=${params.channel} type=${params.updateType ?? "unknown"} chatId=${params.chatId ?? "unknown"} duration=${params.durationMs ?? 0}ms processed=${webhookStats.processed}`);
	emitDiagnosticEvent({
		type: "webhook.processed",
		channel: params.channel,
		updateType: params.updateType,
		chatId: params.chatId,
		durationMs: params.durationMs
	});
	markActivity();
}
function logWebhookError(params) {
	webhookStats.errors += 1;
	diag.error(`webhook error: channel=${params.channel} type=${params.updateType ?? "unknown"} chatId=${params.chatId ?? "unknown"} error="${params.error}" errors=${webhookStats.errors}`);
	emitDiagnosticEvent({
		type: "webhook.error",
		channel: params.channel,
		updateType: params.updateType,
		chatId: params.chatId,
		error: params.error
	});
	emitReliabilityEvent({
		category: "general",
		severity: "high",
		event: "general.agent_error",
		message: `Webhook error on ${params.channel}: ${params.error}`,
		metadata: {
			channel: params.channel,
			updateType: params.updateType
		}
	});
	markActivity();
}
function logMessageQueued(params) {
	const state = getDiagnosticSessionState(params);
	state.queueDepth += 1;
	state.lastActivity = Date.now();
	if (diag.isEnabled("debug")) diag.debug(`message queued: sessionId=${state.sessionId ?? "unknown"} sessionKey=${state.sessionKey ?? "unknown"} source=${params.source} queueDepth=${state.queueDepth} sessionState=${state.state}`);
	emitDiagnosticEvent({
		type: "message.queued",
		sessionId: state.sessionId,
		sessionKey: state.sessionKey,
		channel: params.channel,
		source: params.source,
		queueDepth: state.queueDepth
	});
	markActivity();
}
function logMessageProcessed(params) {
	if (params.outcome === "error" ? diag.isEnabled("error") : diag.isEnabled("debug")) {
		const payload = `message processed: channel=${params.channel} chatId=${params.chatId ?? "unknown"} messageId=${params.messageId ?? "unknown"} sessionId=${params.sessionId ?? "unknown"} sessionKey=${params.sessionKey ?? "unknown"} outcome=${params.outcome} duration=${params.durationMs ?? 0}ms${params.reason ? ` reason=${params.reason}` : ""}${params.error ? ` error="${params.error}"` : ""}`;
		if (params.outcome === "error") diag.error(payload);
		else diag.debug(payload);
	}
	emitDiagnosticEvent({
		type: "message.processed",
		channel: params.channel,
		chatId: params.chatId,
		messageId: params.messageId,
		sessionId: params.sessionId,
		sessionKey: params.sessionKey,
		durationMs: params.durationMs,
		outcome: params.outcome,
		reason: params.reason,
		error: params.error
	});
	markActivity();
}
function logSessionStateChange(params) {
	const state = getDiagnosticSessionState(params);
	const isProbeSession = state.sessionId?.startsWith("probe-") ?? false;
	const prevState = state.state;
	state.state = params.state;
	state.lastActivity = Date.now();
	if (params.state === "idle") state.queueDepth = Math.max(0, state.queueDepth - 1);
	if (!isProbeSession && diag.isEnabled("debug")) diag.debug(`session state: sessionId=${state.sessionId ?? "unknown"} sessionKey=${state.sessionKey ?? "unknown"} prev=${prevState} new=${params.state} reason="${params.reason ?? ""}" queueDepth=${state.queueDepth}`);
	emitDiagnosticEvent({
		type: "session.state",
		sessionId: state.sessionId,
		sessionKey: state.sessionKey,
		prevState,
		state: params.state,
		reason: params.reason,
		queueDepth: state.queueDepth
	});
	markActivity();
}
function logSessionStuck(params) {
	const state = getDiagnosticSessionState(params);
	diag.warn(`stuck session: sessionId=${state.sessionId ?? "unknown"} sessionKey=${state.sessionKey ?? "unknown"} state=${params.state} age=${Math.round(params.ageMs / 1e3)}s queueDepth=${state.queueDepth}`);
	emitDiagnosticEvent({
		type: "session.stuck",
		sessionId: state.sessionId,
		sessionKey: state.sessionKey,
		state: params.state,
		ageMs: params.ageMs,
		queueDepth: state.queueDepth
	});
	emitReliabilityEvent({
		category: "general",
		severity: "high",
		event: "general.session_stuck",
		message: `Session stuck for ${Math.round(params.ageMs / 1e3)}s: ${state.sessionKey ?? state.sessionId ?? "unknown"}`,
		sessionKey: state.sessionKey ?? void 0,
		metadata: {
			ageMs: params.ageMs,
			queueDepth: state.queueDepth
		}
	});
	markActivity();
}
function logLaneEnqueue(lane, queueSize) {
	diag.debug(`lane enqueue: lane=${lane} queueSize=${queueSize}`);
	emitDiagnosticEvent({
		type: "queue.lane.enqueue",
		lane,
		queueSize
	});
	markActivity();
}
function logLaneDequeue(lane, waitMs, queueSize) {
	diag.debug(`lane dequeue: lane=${lane} waitMs=${waitMs} queueSize=${queueSize}`);
	emitDiagnosticEvent({
		type: "queue.lane.dequeue",
		lane,
		queueSize,
		waitMs
	});
	markActivity();
}
function logToolLoopAction(params) {
	const payload = `tool loop: sessionId=${params.sessionId ?? "unknown"} sessionKey=${params.sessionKey ?? "unknown"} tool=${params.toolName} level=${params.level} action=${params.action} detector=${params.detector} count=${params.count}${params.pairedToolName ? ` pairedTool=${params.pairedToolName}` : ""} message="${params.message}"`;
	if (params.level === "critical") diag.error(payload);
	else diag.warn(payload);
	emitDiagnosticEvent({
		type: "tool.loop",
		sessionId: params.sessionId,
		sessionKey: params.sessionKey,
		toolName: params.toolName,
		level: params.level,
		action: params.action,
		detector: params.detector,
		count: params.count,
		message: params.message,
		pairedToolName: params.pairedToolName
	});
	if (params.action === "block") emitReliabilityEvent({
		category: "general",
		severity: "medium",
		event: "general.tool_loop",
		message: `Tool loop blocked: ${params.toolName} (${params.detector}, count=${params.count})`,
		sessionKey: params.sessionKey ?? void 0,
		metadata: {
			toolName: params.toolName,
			detector: params.detector,
			count: params.count,
			pairedToolName: params.pairedToolName
		}
	});
	markActivity();
}
let heartbeatInterval = null;
function startDiagnosticHeartbeat() {
	if (heartbeatInterval) return;
	heartbeatInterval = setInterval(() => {
		const now = Date.now();
		pruneDiagnosticSessionStates(now, true);
		const activeCount = Array.from(diagnosticSessionStates.values()).filter((s) => s.state === "processing").length;
		const waitingCount = Array.from(diagnosticSessionStates.values()).filter((s) => s.state === "waiting").length;
		const totalQueued = Array.from(diagnosticSessionStates.values()).reduce((sum, s) => sum + s.queueDepth, 0);
		if (!(lastActivityAt > 0 || webhookStats.received > 0 || activeCount > 0 || waitingCount > 0 || totalQueued > 0)) return;
		if (now - lastActivityAt > 12e4 && activeCount === 0 && waitingCount === 0) return;
		diag.debug(`heartbeat: webhooks=${webhookStats.received}/${webhookStats.processed}/${webhookStats.errors} active=${activeCount} waiting=${waitingCount} queued=${totalQueued}`);
		emitDiagnosticEvent({
			type: "diagnostic.heartbeat",
			webhooks: {
				received: webhookStats.received,
				processed: webhookStats.processed,
				errors: webhookStats.errors
			},
			active: activeCount,
			waiting: waitingCount,
			queued: totalQueued
		});
		import("./command-poll-backoff-BlZDIQX-.js").then((n) => n.t).then(({ pruneStaleCommandPolls }) => {
			for (const [, state] of diagnosticSessionStates) pruneStaleCommandPolls(state);
		}).catch((err) => {
			diag.debug(`command-poll-backoff prune failed: ${String(err)}`);
		});
		for (const [, state] of diagnosticSessionStates) {
			const ageMs = now - state.lastActivity;
			if (state.state === "processing" && ageMs > 12e4) logSessionStuck({
				sessionId: state.sessionId,
				sessionKey: state.sessionKey,
				state: state.state,
				ageMs
			});
		}
	}, 3e4);
	heartbeatInterval.unref?.();
}
function stopDiagnosticHeartbeat() {
	if (heartbeatInterval) {
		clearInterval(heartbeatInterval);
		heartbeatInterval = null;
	}
}

//#endregion
export { logMessageProcessed as a, logWebhookError as c, startDiagnosticHeartbeat as d, stopDiagnosticHeartbeat as f, logLaneEnqueue as i, logWebhookProcessed as l, isDiagnosticsEnabled as m, diagnostic_exports as n, logMessageQueued as o, emitDiagnosticEvent as p, logLaneDequeue as r, logSessionStateChange as s, diag as t, logWebhookReceived as u };