import { g as registerSecretValueForRedaction } from "./redact-ClDPSbEB.js";
import { E as normalizeSqliteNumber, X as executeSqliteQueryTakeFirstSync, Y as executeSqliteQuerySync, Z as getNodeSqliteKysely, f as openOpenClawStateDatabase, h as runOpenClawStateWriteTransaction } from "./openclaw-state-db-BcDMx5Fu.js";
import { createHmac, randomBytes, randomUUID } from "node:crypto";
//#region src/audit/audit-event-types.ts
const AUDIT_INBOUND_MESSAGE_COMPLETED_REASONS = [
	"fast_abort",
	"plugin_bound_handled",
	"plugin_bound_unavailable",
	"plugin_bound_declined",
	"before_dispatch_handled",
	"acp_dispatch_completed",
	"acp_dispatch_empty"
];
const AUDIT_INBOUND_MESSAGE_SKIPPED_REASONS = [
	"duplicate",
	"reply_operation_active",
	"reply_operation_aborted",
	"acp_dispatch_aborted"
];
const AUDIT_OUTBOUND_MESSAGE_SUPPRESSED_REASONS = [
	"cancelled_by_message_sending_hook",
	"cancelled_by_reply_payload_sending_hook",
	"empty_after_message_sending_hook",
	"empty_after_reply_payload_sending_hook",
	"no_visible_payload"
];
//#endregion
//#region src/audit/audit-identity.ts
/** Stable installation-local pseudonyms for sensitive audit identifiers. */
const AUDIT_IDENTITY_SINGLETON_ID = 1;
const AUDIT_IDENTITY_KEY_BYTES = 32;
const AUDIT_IDENTITY_KEY_ID_BYTES = 16;
const AUDIT_IDENTITY_KEY_ID_RE = /^[a-f0-9]{32}$/u;
const AUDIT_IDENTITY_DOMAIN = "openclaw.audit.identity.v1";
const identityByDatabase = /* @__PURE__ */ new WeakMap();
function registerAuditIdentityKeyForRedaction(key) {
	const bytes = Buffer.from(key);
	registerSecretValueForRedaction(bytes.toString("hex"));
	registerSecretValueForRedaction(bytes.toString("base64url"));
}
function parseAuditIdentityKey(row) {
	if (typeof row.key_id !== "string" || !AUDIT_IDENTITY_KEY_ID_RE.test(row.key_id) || !(row.key instanceof Uint8Array) || row.key.byteLength !== AUDIT_IDENTITY_KEY_BYTES) throw new Error("audit identity key is corrupt");
	const key = Buffer.from(row.key);
	registerAuditIdentityKeyForRedaction(key);
	return {
		keyId: row.key_id,
		key
	};
}
/** Load the stable audit identity key or create it transactionally on first use. */
function loadOrCreateAuditIdentityKey(db) {
	const cached = identityByDatabase.get(db);
	if (cached) return cached;
	const kysely = getNodeSqliteKysely(db);
	const existing = executeSqliteQueryTakeFirstSync(db, kysely.selectFrom("audit_identity_keys").select(["key_id", "key"]).where("id", "=", AUDIT_IDENTITY_SINGLETON_ID));
	if (existing) {
		const identity = parseAuditIdentityKey(existing);
		identityByDatabase.set(db, identity);
		return identity;
	}
	if (executeSqliteQueryTakeFirstSync(db, kysely.selectFrom("audit_events").select("sequence").where("kind", "=", "message").limit(1))) throw new Error("audit identity key is missing");
	const candidate = {
		id: AUDIT_IDENTITY_SINGLETON_ID,
		key_id: randomBytes(AUDIT_IDENTITY_KEY_ID_BYTES).toString("hex"),
		key: randomBytes(AUDIT_IDENTITY_KEY_BYTES),
		created_at: Date.now()
	};
	executeSqliteQuerySync(db, kysely.insertInto("audit_identity_keys").values(candidate).onConflict((conflict) => conflict.column("id").doNothing()));
	const stored = executeSqliteQueryTakeFirstSync(db, kysely.selectFrom("audit_identity_keys").select(["key_id", "key"]).where("id", "=", AUDIT_IDENTITY_SINGLETON_ID));
	if (!stored) throw new Error("audit identity key could not be created");
	const identity = parseAuditIdentityKey(stored);
	identityByDatabase.set(db, identity);
	return identity;
}
/** Forget transaction-local key state after a failed or rolled-back write. */
function clearAuditIdentityKeyCacheForDatabase(db) {
	identityByDatabase.delete(db);
}
/** Produce a stable, domain-separated pseudonym without retaining raw identity bytes. */
function pseudonymizeAuditIdentity(params) {
	if (params.value === void 0 || params.value.length === 0) return;
	const digest = createHmac("sha256", params.identity.key).update(JSON.stringify([
		AUDIT_IDENTITY_DOMAIN,
		params.kind,
		params.channel,
		params.accountId ?? null,
		params.kind === "message" ? params.conversationId ?? null : null,
		params.value
	]), "utf8").digest("hex");
	return `hmac-sha256:v1:${params.identity.keyId}:${digest}`;
}
//#endregion
//#region src/audit/audit-event-store.ts
/** SQLite persistence and stable cursor queries for metadata-only audit events. */
const AUDIT_EVENT_RETENTION_MS = 720 * 60 * 6e4;
const AUDIT_EVENT_MAX_ROWS = 1e5;
const AUDIT_EVENT_PRUNE_BATCH_ROWS = 1024;
const auditEventRowCounts = /* @__PURE__ */ new WeakMap();
function getAuditKysely(db) {
	return getNodeSqliteKysely(db);
}
const RUN_ACTIONS = ["agent.run.started", "agent.run.finished"];
const TOOL_ACTIONS = ["tool.action.started", "tool.action.finished"];
const CONVERSATION_KINDS = [
	"direct",
	"group",
	"channel",
	"unknown"
];
const DELIVERY_KINDS = [
	"text",
	"media",
	"other"
];
const FAILURE_STAGES = [
	"platform_send",
	"queue",
	"unknown"
];
const AUDIT_HMAC_REF_RE = /^hmac-sha256:v1:[a-f0-9]{32}:[a-f0-9]{64}$/u;
const MESSAGE_COLUMNS = [
	"direction",
	"channel",
	"conversation_kind",
	"message_outcome",
	"reason_code",
	"delivery_kind",
	"failure_stage",
	"duration_ms",
	"result_count",
	"account_ref",
	"conversation_ref",
	"message_ref",
	"target_ref"
];
function corruptAuditRow(row, problem) {
	const sequence = normalizeSqliteNumber(row.sequence);
	const location = sequence === void 0 ? "" : ` ${sequence}`;
	throw new Error(`corrupt audit event row${location}: ${problem}`);
}
function requiredInteger(row, value, field, minimum) {
	const normalized = normalizeSqliteNumber(value);
	if (normalized === void 0 || !Number.isSafeInteger(normalized) || normalized < minimum) corruptAuditRow(row, `invalid ${field}`);
	return normalized;
}
function optionalInteger(row, value, field, minimum) {
	if (value === null) return;
	return requiredInteger(row, value, field, minimum);
}
function requiredText(row, value, field) {
	if (typeof value !== "string" || value.length === 0) corruptAuditRow(row, `invalid ${field}`);
	return value;
}
function optionalText(row, value, field) {
	if (value === null || value === void 0) return;
	return requiredText(row, value, field);
}
function requiredEnum(row, value, field, allowed) {
	for (const candidate of allowed) if (value === candidate) return candidate;
	return corruptAuditRow(row, `invalid ${field}`);
}
function optionalEnum(row, value, field, allowed) {
	if (value === null || value === void 0) return;
	return requiredEnum(row, value, field, allowed);
}
function requiredHmacRef(row, value, field) {
	const ref = requiredText(row, value, field);
	if (!AUDIT_HMAC_REF_RE.test(ref)) corruptAuditRow(row, `invalid ${field}`);
	return ref;
}
function optionalHmacRef(row, value, field) {
	if (value === null || value === void 0) return;
	return requiredHmacRef(row, value, field);
}
function requireNull(row, field) {
	if (row[field] !== null) corruptAuditRow(row, `unexpected ${field}`);
}
function requireNullColumns(row, fields) {
	for (const field of fields) requireNull(row, field);
}
function parseAuditRecordBase(row) {
	const schemaVersion = requiredInteger(row, row.schema_version, "schemaVersion", 1);
	if (schemaVersion !== 1) corruptAuditRow(row, `unsupported schemaVersion ${schemaVersion}`);
	return {
		schemaVersion,
		sequence: requiredInteger(row, row.sequence, "sequence", 1),
		eventId: requiredText(row, row.event_id, "eventId"),
		sourceSequence: requiredInteger(row, row.source_sequence, "sourceSequence", 1),
		occurredAt: requiredInteger(row, row.occurred_at, "occurredAt", 0),
		redaction: "metadata_only"
	};
}
function parseAgentRecordFields(row) {
	requireNullColumns(row, MESSAGE_COLUMNS);
	return {
		...parseAuditRecordBase(row),
		actorType: requiredEnum(row, row.actor_type, "actorType", ["agent", "system"]),
		actorId: requiredText(row, row.actor_id, "actorId"),
		agentId: requiredText(row, row.agent_id, "agentId"),
		...optionalText(row, row.session_key, "sessionKey") !== void 0 ? { sessionKey: requiredText(row, row.session_key, "sessionKey") } : {},
		...optionalText(row, row.session_id, "sessionId") !== void 0 ? { sessionId: requiredText(row, row.session_id, "sessionId") } : {},
		runId: requiredText(row, row.run_id, "runId")
	};
}
function parseAgentRunRow(row) {
	requireNull(row, "tool_call_id");
	requireNull(row, "tool_name");
	const common = {
		...parseAgentRecordFields(row),
		kind: "agent_run"
	};
	const action = requiredEnum(row, row.action, "action", RUN_ACTIONS);
	if (action === "agent.run.started") {
		requiredEnum(row, row.status, "status", ["started"]);
		requireNull(row, "error_code");
		return {
			...common,
			action,
			status: "started"
		};
	}
	if (row.status === "succeeded") {
		requireNull(row, "error_code");
		return {
			...common,
			action,
			status: "succeeded"
		};
	}
	const terminal = row.status === "failed" ? {
		status: "failed",
		errorCode: "run_failed"
	} : row.status === "cancelled" ? {
		status: "cancelled",
		errorCode: "run_cancelled"
	} : row.status === "timed_out" ? {
		status: "timed_out",
		errorCode: "run_timed_out"
	} : row.status === "blocked" ? {
		status: "blocked",
		errorCode: "run_blocked"
	} : corruptAuditRow(row, "invalid run terminal status");
	requiredEnum(row, row.error_code, "errorCode", [terminal.errorCode]);
	return {
		...common,
		action,
		...terminal
	};
}
function parseToolActionRow(row) {
	const toolCallId = optionalText(row, row.tool_call_id, "toolCallId");
	const toolName = optionalText(row, row.tool_name, "toolName");
	const common = {
		...parseAgentRecordFields(row),
		kind: "tool_action",
		...toolCallId ? { toolCallId } : {},
		...toolName ? { toolName } : {}
	};
	const action = requiredEnum(row, row.action, "action", TOOL_ACTIONS);
	if (action === "tool.action.started") {
		requiredEnum(row, row.status, "status", ["started"]);
		requireNull(row, "error_code");
		return {
			...common,
			action,
			status: "started"
		};
	}
	if (row.status === "succeeded") {
		requireNull(row, "error_code");
		return {
			...common,
			action,
			status: "succeeded"
		};
	}
	const terminal = row.status === "failed" ? {
		status: "failed",
		errorCode: "tool_failed"
	} : row.status === "cancelled" ? {
		status: "cancelled",
		errorCode: "tool_cancelled"
	} : row.status === "timed_out" ? {
		status: "timed_out",
		errorCode: "tool_timed_out"
	} : row.status === "blocked" ? {
		status: "blocked",
		errorCode: "tool_blocked"
	} : row.status === "unknown" ? {
		status: "unknown",
		errorCode: "tool_outcome_unknown"
	} : corruptAuditRow(row, "invalid tool terminal status");
	requiredEnum(row, row.error_code, "errorCode", [terminal.errorCode]);
	return {
		...common,
		action,
		...terminal
	};
}
function parseMessageRecordFields(row) {
	requireNullColumns(row, [
		"session_key",
		"session_id",
		"tool_call_id",
		"tool_name"
	]);
	const agentId = optionalText(row, row.agent_id, "agentId");
	const runId = optionalText(row, row.run_id, "runId");
	const durationMs = optionalInteger(row, row.duration_ms, "durationMs", 0);
	const resultCount = optionalInteger(row, row.result_count, "resultCount", 0);
	const accountRef = optionalHmacRef(row, row.account_ref, "accountRef");
	const conversationRef = optionalHmacRef(row, row.conversation_ref, "conversationRef");
	const messageRef = optionalHmacRef(row, row.message_ref, "messageRef");
	const targetRef = optionalHmacRef(row, row.target_ref, "targetRef");
	return {
		...parseAuditRecordBase(row),
		kind: "message",
		channel: requiredText(row, row.channel, "channel"),
		conversationKind: requiredEnum(row, row.conversation_kind, "conversationKind", CONVERSATION_KINDS),
		...agentId ? { agentId } : {},
		...runId ? { runId } : {},
		...durationMs !== void 0 ? { durationMs } : {},
		...resultCount !== void 0 ? { resultCount } : {},
		...accountRef ? { accountRef } : {},
		...conversationRef ? { conversationRef } : {},
		...messageRef ? { messageRef } : {},
		...targetRef ? { targetRef } : {}
	};
}
function parseInboundMessageRow(row) {
	requiredEnum(row, row.action, "action", ["message.inbound.processed"]);
	requiredEnum(row, row.direction, "direction", ["inbound"]);
	requireNull(row, "delivery_kind");
	requireNull(row, "failure_stage");
	const actorType = requiredEnum(row, row.actor_type, "actorType", ["channel_sender", "system"]);
	const actorId = actorType === "channel_sender" ? requiredHmacRef(row, row.actor_id, "actorId") : requiredText(row, row.actor_id, "actorId");
	const common = {
		...parseMessageRecordFields(row),
		action: "message.inbound.processed",
		direction: "inbound",
		actorType,
		actorId
	};
	if (row.status === "succeeded") {
		requiredEnum(row, row.message_outcome, "outcome", ["completed"]);
		requireNull(row, "error_code");
		const reasonCode = optionalEnum(row, row.reason_code, "reasonCode", AUDIT_INBOUND_MESSAGE_COMPLETED_REASONS);
		return {
			...common,
			status: "succeeded",
			outcome: "completed",
			...reasonCode ? { reasonCode } : {}
		};
	}
	if (row.status === "blocked") {
		requiredEnum(row, row.message_outcome, "outcome", ["skipped"]);
		requireNull(row, "error_code");
		const reasonCode = optionalEnum(row, row.reason_code, "reasonCode", AUDIT_INBOUND_MESSAGE_SKIPPED_REASONS);
		return {
			...common,
			status: "blocked",
			outcome: "skipped",
			...reasonCode ? { reasonCode } : {}
		};
	}
	if (row.status === "failed") {
		requiredEnum(row, row.message_outcome, "outcome", ["failed"]);
		requiredEnum(row, row.error_code, "errorCode", ["message_processing_failed"]);
		const reasonCode = optionalEnum(row, row.reason_code, "reasonCode", ["acp_dispatch_failed", "plugin_bound_error"]);
		return {
			...common,
			status: "failed",
			outcome: "failed",
			errorCode: "message_processing_failed",
			...reasonCode ? { reasonCode } : {}
		};
	}
	return corruptAuditRow(row, "invalid inbound status");
}
function parseOutboundMessageRow(row) {
	requiredEnum(row, row.action, "action", ["message.outbound.finished"]);
	requiredEnum(row, row.direction, "direction", ["outbound"]);
	const actorType = requiredEnum(row, row.actor_type, "actorType", ["agent", "system"]);
	const actorId = requiredText(row, row.actor_id, "actorId");
	const common = {
		...parseMessageRecordFields(row),
		action: "message.outbound.finished",
		direction: "outbound",
		actorType,
		actorId
	};
	if (row.status === "succeeded") {
		const deliveryKind = optionalEnum(row, row.delivery_kind, "deliveryKind", DELIVERY_KINDS);
		requiredEnum(row, row.message_outcome, "outcome", ["sent"]);
		requireNullColumns(row, [
			"error_code",
			"reason_code",
			"failure_stage"
		]);
		return {
			...common,
			status: "succeeded",
			outcome: "sent",
			...deliveryKind ? { deliveryKind } : {}
		};
	}
	if (row.status === "blocked") {
		requireNull(row, "delivery_kind");
		requiredEnum(row, row.message_outcome, "outcome", ["suppressed"]);
		requireNullColumns(row, ["error_code", "failure_stage"]);
		const reasonCode = requiredEnum(row, row.reason_code, "reasonCode", AUDIT_OUTBOUND_MESSAGE_SUPPRESSED_REASONS);
		return {
			...common,
			status: "blocked",
			outcome: "suppressed",
			reasonCode
		};
	}
	if (row.status === "failed") {
		const deliveryKind = optionalEnum(row, row.delivery_kind, "deliveryKind", DELIVERY_KINDS);
		requiredEnum(row, row.message_outcome, "outcome", ["failed"]);
		requireNull(row, "reason_code");
		const errorCode = requiredEnum(row, row.error_code, "errorCode", ["message_delivery_failed", "message_delivery_partial_failure"]);
		const failureStage = requiredEnum(row, row.failure_stage, "failureStage", FAILURE_STAGES);
		return {
			...common,
			status: "failed",
			outcome: "failed",
			errorCode,
			failureStage,
			...deliveryKind ? { deliveryKind } : {}
		};
	}
	if (row.status === "unknown") {
		requireNull(row, "delivery_kind");
		requiredEnum(row, row.message_outcome, "outcome", ["unknown"]);
		requireNullColumns(row, ["error_code", "reason_code"]);
		const failureStage = requiredEnum(row, row.failure_stage, "failureStage", FAILURE_STAGES);
		return {
			...common,
			status: "unknown",
			outcome: "unknown",
			failureStage
		};
	}
	return corruptAuditRow(row, "invalid outbound status");
}
function rowToAuditEvent(row) {
	if (row.kind === "agent_run") return parseAgentRunRow(row);
	if (row.kind === "tool_action") return parseToolActionRow(row);
	if (row.kind !== "message") corruptAuditRow(row, "invalid kind");
	if (row.direction === "inbound") return parseInboundMessageRow(row);
	if (row.direction === "outbound") return parseOutboundMessageRow(row);
	return corruptAuditRow(row, "invalid message direction");
}
function projectMessageIdentities(db, input) {
	const identity = loadOrCreateAuditIdentityKey(db);
	const conversationId = input.conversationId ?? (input.direction === "outbound" ? input.targetId : void 0);
	const ref = (kind, value) => pseudonymizeAuditIdentity({
		identity,
		kind,
		channel: input.channel,
		...kind !== "account" && input.accountId !== void 0 ? { accountId: input.accountId } : {},
		...kind === "message" && conversationId !== void 0 ? { conversationId } : {},
		value
	});
	return {
		actorId: input.actorType === "channel_sender" ? ref("actor", input.actorId) : input.actorId,
		accountRef: ref("account", input.accountId),
		conversationRef: ref("conversation", conversationId),
		messageRef: ref("message", input.messageId),
		targetRef: ref("target", input.targetId)
	};
}
function bindAuditEvent(db, input) {
	const message = input.kind === "message" ? projectMessageIdentities(db, input) : void 0;
	return {
		event_id: randomUUID(),
		source_id: input.sourceId,
		source_sequence: input.sourceSequence,
		schema_version: 1,
		occurred_at: input.occurredAt,
		kind: input.kind,
		action: input.action,
		status: input.status,
		error_code: input.errorCode ?? null,
		actor_type: input.actorType,
		actor_id: message?.actorId ?? input.actorId,
		agent_id: input.agentId ?? null,
		session_key: input.kind === "message" ? null : input.sessionKey ?? null,
		session_id: input.kind === "message" ? null : input.sessionId ?? null,
		run_id: input.runId ?? null,
		tool_call_id: input.kind === "tool_action" ? input.toolCallId ?? null : null,
		tool_name: input.kind === "tool_action" ? input.toolName : null,
		direction: input.kind === "message" ? input.direction : null,
		channel: input.kind === "message" ? input.channel : null,
		conversation_kind: input.kind === "message" ? input.conversationKind : null,
		message_outcome: input.kind === "message" ? input.outcome : null,
		reason_code: input.kind === "message" ? input.reasonCode ?? null : null,
		delivery_kind: input.kind === "message" ? input.deliveryKind ?? null : null,
		failure_stage: input.kind === "message" ? input.failureStage ?? null : null,
		duration_ms: input.kind === "message" ? input.durationMs ?? null : null,
		result_count: input.kind === "message" ? input.resultCount ?? null : null,
		account_ref: message?.accountRef ?? null,
		conversation_ref: message?.conversationRef ?? null,
		message_ref: message?.messageRef ?? null,
		target_ref: message?.targetRef ?? null
	};
}
function countAuditEvents(db) {
	return normalizeSqliteNumber(executeSqliteQueryTakeFirstSync(db, getAuditKysely(db).selectFrom("audit_events").select((expression) => expression.fn.countAll().as("count")))?.count ?? null) ?? 0;
}
function pruneAuditEventsAfterInsert(db, now, limits = {
	maxRows: AUDIT_EVENT_MAX_ROWS,
	pruneBatchRows: AUDIT_EVENT_PRUNE_BATCH_ROWS
}) {
	const kysely = getAuditKysely(db);
	const expired = executeSqliteQuerySync(db, kysely.deleteFrom("audit_events").where("occurred_at", "<", now - AUDIT_EVENT_RETENTION_MS));
	const cachedCount = auditEventRowCounts.get(db);
	let rowCount = cachedCount === void 0 ? countAuditEvents(db) : Math.max(0, cachedCount + 1 - Number(expired.numAffectedRows ?? 0n));
	if (rowCount <= limits.maxRows) {
		auditEventRowCounts.set(db, rowCount);
		return;
	}
	const retainedRows = Math.max(0, limits.maxRows - limits.pruneBatchRows);
	const overflowRow = executeSqliteQueryTakeFirstSync(db, kysely.selectFrom("audit_events").select("sequence").orderBy("sequence", "desc").offset(retainedRows).limit(1));
	const sequenceCutoff = overflowRow ? normalizeSqliteNumber(overflowRow.sequence) : void 0;
	if (sequenceCutoff !== void 0) {
		const pruned = executeSqliteQuerySync(db, kysely.deleteFrom("audit_events").where("sequence", "<=", sequenceCutoff));
		rowCount = Math.max(0, rowCount - Number(pruned.numAffectedRows ?? 0n));
	}
	auditEventRowCounts.set(db, rowCount);
}
/** Persist one projected event idempotently and prune fixed retention bounds. */
function recordAuditEvent(input, options = {}) {
	let countCacheDatabase;
	try {
		return runOpenClawStateWriteTransaction(({ db }) => {
			countCacheDatabase = db;
			const insert = executeSqliteQuerySync(db, getAuditKysely(db).insertInto("audit_events").values(bindAuditEvent(db, input)).onConflict((conflict) => conflict.column("source_id").doNothing()));
			if (insert.insertId === void 0) return;
			const insertedSequence = Number(insert.insertId);
			if (!Number.isSafeInteger(insertedSequence) || insertedSequence < 1) throw new Error("audit event sequence is outside the supported integer range");
			pruneAuditEventsAfterInsert(db, Date.now());
			const row = executeSqliteQueryTakeFirstSync(db, getAuditKysely(db).selectFrom("audit_events").selectAll().where("sequence", "=", insertedSequence));
			return row ? rowToAuditEvent(row) : void 0;
		}, options);
	} catch (error) {
		if (countCacheDatabase) {
			auditEventRowCounts.delete(countCacheDatabase);
			clearAuditIdentityKeyCacheForDatabase(countCacheDatabase);
		}
		throw error;
	}
}
/** List newest-first records using a stable sequence cursor. */
function listAuditEvents(params) {
	const { db } = openOpenClawStateDatabase(params.database);
	const filters = params.filters ?? {};
	const retainedAfter = (params.now ?? Date.now()) - AUDIT_EVENT_RETENTION_MS;
	let query = getAuditKysely(db).selectFrom("audit_events").selectAll().where("occurred_at", ">=", retainedAfter);
	if (params.cursor !== void 0) query = query.where("sequence", "<", params.cursor);
	if (filters.agentId) query = query.where("agent_id", "=", filters.agentId);
	if (filters.sessionKey) query = query.where("session_key", "=", filters.sessionKey);
	if (filters.runId) query = query.where("run_id", "=", filters.runId);
	if (filters.kind) query = query.where("kind", "=", filters.kind);
	else if (filters.includeMessages !== true) query = query.where("kind", "!=", "message");
	if (filters.status) query = query.where("status", "=", filters.status);
	if (filters.direction) query = query.where("direction", "=", filters.direction);
	if (filters.channel) query = query.where("channel", "=", filters.channel);
	if (filters.after !== void 0) query = query.where("occurred_at", ">=", filters.after);
	if (filters.before !== void 0) query = query.where("occurred_at", "<=", filters.before);
	const rows = executeSqliteQuerySync(db, query.orderBy("sequence", "desc").limit(params.limit + 1)).rows;
	const hasMore = rows.length > params.limit;
	const events = (hasMore ? rows.slice(0, params.limit) : rows).map(rowToAuditEvent);
	return {
		events,
		...hasMore && events.length > 0 ? { nextCursor: events[events.length - 1]?.sequence } : {}
	};
}
/** Delete expired metadata during Gateway startup and periodic worker maintenance. */
function pruneExpiredAuditEvents(params = {}) {
	runOpenClawStateWriteTransaction(({ db }) => {
		executeSqliteQuerySync(db, getAuditKysely(db).deleteFrom("audit_events").where("occurred_at", "<", (params.now ?? Date.now()) - AUDIT_EVENT_RETENTION_MS));
		auditEventRowCounts.delete(db);
	}, params.database);
}
//#endregion
export { pruneExpiredAuditEvents as n, recordAuditEvent as r, listAuditEvents as t };
