import { o as createSubsystemLogger } from "./entry.js";
import { t as emitEvent } from "./emitter-BKo8D7Oj.js";
import process from "node:process";
import * as Sentry from "@sentry/node";

//#region src/infra/sentry.ts
let initialized = false;
/**
* Initialize Sentry error tracking.
* No-ops if SENTRY_DSN is not set (opt-in via env var).
* Call this immediately after loadDotEnv() + normalizeEnv().
*/
function initSentry() {
	const dsn = process.env.SENTRY_DSN;
	if (!dsn) return;
	const sampleRate = parseFloat(process.env.SENTRY_TRACES_SAMPLE_RATE ?? "0.1");
	Sentry.init({
		dsn,
		environment: process.env.NODE_ENV ?? "production",
		release: process.env.npm_package_version,
		tracesSampleRate: isNaN(sampleRate) ? .1 : sampleRate,
		integrations: [
			Sentry.anthropicAIIntegration(),
			Sentry.openAIIntegration(),
			Sentry.httpIntegration({ breadcrumbs: true }),
			Sentry.nativeNodeFetchIntegration()
		]
	});
	initialized = true;
}
/**
* Capture an error in Sentry with optional extra context.
* No-ops if Sentry was not initialized.
*/
function captureError(err, context) {
	if (!initialized) return;
	Sentry.withScope((scope) => {
		if (context) scope.setExtras(context);
		Sentry.captureException(err);
	});
}
/**
* Flush pending Sentry events before process exit.
* Awaiting this ensures queued error reports are sent before the process terminates.
*/
async function flushSentry(timeoutMs = 2e3) {
	if (!initialized) return;
	await Sentry.flush(timeoutMs);
}
/**
* Add a breadcrumb to the current Sentry scope.
* No-ops if Sentry was not initialized.
*/
function addSentryBreadcrumb(crumb) {
	if (!initialized) return;
	Sentry.addBreadcrumb(crumb);
}
/**
* Set a named context object on the current Sentry scope.
* No-ops if Sentry was not initialized.
*/
function setSentryContext(name, data) {
	if (!initialized) return;
	Sentry.setContext(name, data);
}
/**
* Set a tag on the current Sentry scope.
* No-ops if Sentry was not initialized.
*/
function setSentryTag(key, value) {
	if (!initialized) return;
	Sentry.setTag(key, value);
}
/**
* Start a Sentry span wrapping the provided async function.
* No-ops (calls fn directly) if Sentry was not initialized.
*/
async function startSentrySpan(options, fn) {
	if (!initialized) return fn(void 0);
	return Sentry.startSpan({
		op: options.op,
		name: options.name,
		attributes: options.attributes
	}, (span) => fn(span));
}
/**
* Run a function in a Sentry isolation scope so concurrent agent runs
* don't bleed context into each other.
* No-ops (calls fn directly) if Sentry was not initialized.
*/
async function withSentryIsolationScope(fn) {
	if (!initialized) return fn();
	return new Promise((resolve, reject) => {
		Sentry.withIsolationScope(() => {
			fn().then(resolve, reject);
		});
	});
}

//#endregion
//#region src/logging/reliability.ts
const log = createSubsystemLogger("reliability");
let broadcastFn = null;
const startedAtMs = Date.now();
const RATE_LIMIT_MS = 6e4;
const STALE_KEY_CLEANUP_MS = 5 * 6e4;
const rateLimitMap = /* @__PURE__ */ new Map();
let cleanupInterval = null;
function isRateLimited(eventType) {
	const now = Date.now();
	const last = rateLimitMap.get(eventType);
	if (last && now - last < RATE_LIMIT_MS) return true;
	rateLimitMap.set(eventType, now);
	return false;
}
function cleanupStaleKeys() {
	const now = Date.now();
	for (const [key, ts] of rateLimitMap) if (now - ts > RATE_LIMIT_MS * 2) rateLimitMap.delete(key);
}
/**
* Call once at gateway startup to wire the broadcast function.
*
* Broadcast is now handled by the event emitter. This stores the reference
* for backward compatibility — reliability events still broadcast via
* the "reliability" event name for legacy hub clients.
*/
function initReliability(broadcast) {
	broadcastFn = broadcast;
	if (!cleanupInterval) {
		cleanupInterval = setInterval(cleanupStaleKeys, STALE_KEY_CLEANUP_MS);
		cleanupInterval.unref?.();
	}
}
/**
* Emit a reliability event. Thin wrapper around emitEvent() — routes the
* event through the unified event store while preserving backward-compatible
* broadcast on the "reliability" channel for legacy hub clients.
*/
function emitReliabilityEvent(input) {
	if (isRateLimited(input.event)) return;
	const timestamp = Date.now();
	emitEvent({
		category: input.category,
		severity: input.severity,
		event: input.event,
		message: input.message,
		agentId: input.agentId,
		correlationId: input.sessionKey,
		metadata: input.metadata,
		timestamp
	});
	if (broadcastFn) broadcastFn("reliability", {
		...input,
		timestamp
	}, { dropIfSlow: true });
	if (input.severity === "critical" || input.severity === "high") {
		log.warn(`[${input.category}] ${input.event}: ${input.message}`);
		captureError(/* @__PURE__ */ new Error(`[${input.category}] ${input.event}: ${input.message}`), {
			category: input.category,
			event: input.event,
			severity: input.severity,
			metadata: input.metadata
		});
	} else log.debug(`[${input.category}] ${input.event}: ${input.message}`);
}
/**
* Return the epoch ms when the gateway (and thus the buffer) started.
*/
function getReliabilityUptimeStartMs() {
	return startedAtMs;
}
/**
* Track every tool execution (not just skills). Persists to the event store
* under category "agent" (not rate-limited) so we can compute Tool Selection
* Accuracy (TSA) baseline metrics: error rate, retry rate, tool distribution.
* Best-effort — never throws.
*/
function trackToolExecution(stat) {
	try {
		emitEvent({
			category: "agent",
			severity: stat.status === "error" ? "low" : "info",
			event: `tool.exec.${stat.status}`,
			message: `Tool ${stat.toolName}: ${stat.status}`,
			correlationId: stat.runId,
			metadata: {
				toolName: stat.toolName,
				durationMs: stat.durationMs,
				...stat.errorMessage ? { errorMessage: stat.errorMessage } : {}
			},
			timestamp: stat.occurredAt
		});
	} catch {}
}
/**
* Track a skill (plugin) tool execution. Routes through the unified event
* store and forwards to the hub metrics push client if active.
* Best-effort — never throws.
*/
function trackSkillExecution(stat) {
	try {
		emitEvent({
			category: "skill",
			severity: "info",
			event: `skill.${stat.status}`,
			message: `Skill ${stat.skillName}: ${stat.status}`,
			metadata: {
				skillName: stat.skillName,
				durationMs: stat.durationMs,
				errorMessage: stat.errorMessage
			},
			timestamp: stat.occurredAt
		});
	} catch {}
}

//#endregion
export { trackToolExecution as a, flushSentry as c, setSentryTag as d, startSentrySpan as f, trackSkillExecution as i, initSentry as l, getReliabilityUptimeStartMs as n, addSentryBreadcrumb as o, withSentryIsolationScope as p, initReliability as r, captureError as s, emitReliabilityEvent as t, setSentryContext as u };