import { createLogger } from "../utils/logger/index.js";
import { init_logger } from "../utils/logger.js";
import { SessionStore } from "./store.js";
import { applySessionPatchToMetadata } from "./patch-metadata.js";
import EventEmitter$1 from "events";
//#region src/session/manager.ts
init_logger();
const log = createLogger("SessionIndex");
var SessionIndex = class extends EventEmitter$1 {
	store;
	constructor(config) {
		super();
		this.store = new SessionStore({
			config: config.config,
			agentId: config.agentId,
			sessionsDir: config.sessionsDir
		}, config.windowConfig, config.compactionConfig);
	}
	async initialize() {
		await this.store.initialize();
		this.emit("ready");
	}
	/** Low-level store (e.g. cron resolving weixin delivery from session index). */
	getStore() {
		return this.store;
	}
	async listSessions(query) {
		return this.store.list(query);
	}
	/**
	* List all subagent sessions.
	* Subagent sessions have keys starting with 'subagent:'.
	*/
	async listSubagents(query = {}) {
		const subagentQuery = {
			...query,
			search: query.search ? `subagent:${query.search}` : "subagent:"
		};
		const result = await this.store.list(subagentQuery);
		const subagentSessions = result.items.filter((s) => s.key.startsWith("subagent:"));
		return {
			...result,
			items: subagentSessions,
			total: subagentSessions.length,
			hasMore: false
		};
	}
	async getSession(key, options) {
		const session = await this.store.get(key, options);
		if (session) this.emit("sessionAccessed", { key });
		return session;
	}
	async getSessionMessagePage(key, options) {
		const result = await this.store.getMessagePage(key, options);
		if (result) this.emit("sessionAccessed", { key });
		return result;
	}
	/**
	* OpenClaw-style `sessions.patch`: partial metadata (name, tags, customData shallow merge).
	*/
	async patchSession(key, patch) {
		const meta = await this.store.getMetadata(key);
		if (!meta) return {
			ok: false,
			error: "Session not found"
		};
		const updates = applySessionPatchToMetadata(meta, patch);
		if (Object.keys(updates).length === 0) return { ok: true };
		await this.store.updateMetadata(key, updates);
		this.emit("sessionUpdated", { key });
		return { ok: true };
	}
	async getSessionMetadata(key) {
		return this.store.getMetadata(key);
	}
	async deleteSession(key) {
		const result = await this.store.delete(key);
		if (result) this.emit("sessionDeleted", { key });
		return result;
	}
	async deleteSessions(keys) {
		const result = await this.store.deleteMany(keys);
		for (const key of result.success) this.emit("sessionDeleted", { key });
		return result;
	}
	async renameSession(key, name) {
		await this.store.updateMetadata(key, { name });
		this.emit("sessionUpdated", {
			key,
			name
		});
	}
	/** Partial metadata update (caller merges nested fields like `customData` when needed). */
	async updateSessionMetadata(key, updates) {
		await this.store.updateMetadata(key, updates);
		this.emit("sessionUpdated", { key });
	}
	async tagSession(key, tags) {
		const existing = await this.store.getMetadata(key);
		if (!existing) throw new Error(`Session not found: ${key}`);
		const mergedTags = [...new Set([...existing.tags, ...tags])];
		await this.store.updateMetadata(key, { tags: mergedTags });
		this.emit("sessionUpdated", {
			key,
			tags: mergedTags
		});
	}
	async untagSession(key, tags) {
		const existing = await this.store.getMetadata(key);
		if (!existing) throw new Error(`Session not found: ${key}`);
		const filteredTags = existing.tags.filter((t) => !tags.includes(t));
		await this.store.updateMetadata(key, { tags: filteredTags });
		this.emit("sessionUpdated", {
			key,
			tags: filteredTags
		});
	}
	async setSessionTags(key, tags) {
		await this.store.updateMetadata(key, { tags: [...new Set(tags)] });
		this.emit("sessionUpdated", {
			key,
			tags
		});
	}
	async archiveSession(key) {
		await this.store.archive(key);
		this.emit("sessionArchived", { key });
	}
	async unarchiveSession(key) {
		await this.store.unarchive(key);
		this.emit("sessionRestored", { key });
	}
	async pinSession(key) {
		await this.store.pin(key);
		this.emit("sessionPinned", { key });
	}
	async unpinSession(key) {
		await this.store.unpin(key);
		this.emit("sessionUnpinned", { key });
	}
	async setSessionStatus(key, status) {
		await this.store.setStatus(key, status);
		this.emit("sessionStatusChanged", {
			key,
			status
		});
	}
	async searchSessions(query) {
		return (await this.store.list({
			search: query,
			limit: 100
		})).items;
	}
	async searchInSession(key, keyword) {
		return this.store.searchInSession(key, keyword);
	}
	async exportSession(key, format) {
		return this.store.exportSession(key, format);
	}
	async getStats() {
		return this.store.getStats();
	}
	async archiveOldSessions(olderThanDays) {
		const count = await this.store.archiveOld(olderThanDays);
		log.info({
			count,
			olderThanDays
		}, "Archived old sessions");
		return count;
	}
	onSessionCreated(callback) {
		this.on("sessionCreated", callback);
	}
	onSessionUpdated(callback) {
		this.on("sessionUpdated", callback);
	}
	onSessionDeleted(callback) {
		this.on("sessionDeleted", callback);
	}
	onSessionArchived(callback) {
		this.on("sessionArchived", callback);
	}
	onSessionRestored(callback) {
		this.on("sessionRestored", callback);
	}
	onSessionPinned(callback) {
		this.on("sessionPinned", callback);
	}
	onSessionUnpinned(callback) {
		this.on("sessionUnpinned", callback);
	}
	onSessionStatusChanged(callback) {
		this.on("sessionStatusChanged", callback);
	}
	onSessionAccessed(callback) {
		this.on("sessionAccessed", callback);
	}
	/** Load messages for a session key */
	async loadMessages(key) {
		return this.store.loadMessages(key);
	}
	/** Wrapped transcript document (stable id, compaction history); null if missing or not a valid envelope. */
	async loadTranscriptDocument(key) {
		return this.store.loadTranscriptDocument(key);
	}
	/**
	* Runtime turns must use PiTranscriptManager.appendMessage; this entry point
	* is reserved for compaction, tests, and admin tools.
	*/
	async saveMessages(key, messages) {
		return this.store.saveMessages(key, messages);
	}
	/**
	* Append `kind: 'context'` transcript row (persisted, excluded from {@link loadMessages} / LLM).
	*/
	async appendTranscriptContextEntry(key, entry) {
		await this.store.appendTranscriptContextEntry(key, entry);
		this.emit("sessionUpdated", { key });
	}
	/** Delete session data */
	async delete(key) {
		await this.store.delete(key);
	}
	/** Archive transcript and start a new session id for the same key. */
	async resetSession(key) {
		const result = await this.store.reset(key);
		if (result) this.emit("sessionUpdated", { key });
		return result;
	}
	/** Token/window stats for a message list */
	getWindowStats(messages) {
		return this.store.getWindowStats(messages);
	}
	/** Prepare compaction run */
	prepareCompaction(key, messages, contextWindow) {
		return this.store.prepareCompaction(key, messages, contextWindow);
	}
	/** Compact session messages */
	compact(key, messages, contextWindow, instructions, force) {
		return this.store.compact(key, messages, contextWindow, instructions, force);
	}
	/** Compaction stats for a session */
	async getCompactionStats(key) {
		return this.store.getCompactionStats(key);
	}
	/** List pre-compaction transcript snapshots (newest first). */
	listCompactionCheckpoints(key) {
		return this.store.listCompactionCheckpoints(key);
	}
	getCompactionCheckpointDetail(key, checkpointId) {
		return this.store.getCompactionCheckpointDetail(key, checkpointId);
	}
	restoreCompactionCheckpoint(key, checkpointId) {
		return this.store.restoreCompactionCheckpoint(key, checkpointId);
	}
	/** Estimate token usage for messages */
	async estimateTokenUsage(key, messages) {
		return this.store.estimateTokens(messages);
	}
};
//#endregion
export { SessionIndex };

//# sourceMappingURL=manager.js.map