import { MEMORY_MD_FILENAME } from "./constants.js";
import { clamp01, compareCandidatesByScore, computeCandidateScore, extractPromotionMarkers, isContaminatedSnippet, isExpiredEntry, readFileLines, resolveDeepDefaults, sliceRange, snippetHash } from "./utils.js";
import { loadDreamingStore } from "./short-term-store.js";
import fs from "node:fs/promises";
import path from "node:path";
//#region src/agent/memory/dreaming/preview.ts
async function previewDreamingDeepPromotion(params) {
	const cfg = resolveDeepDefaults(params.config);
	const memoryPath = path.join(params.workspaceDir, MEMORY_MD_FILENAME);
	if (!cfg.enabled) return {
		ok: true,
		reason: "dreaming disabled",
		items: [],
		memoryPath
	};
	const { store } = await loadDreamingStore({ workspaceDir: params.workspaceDir });
	const nowMs = (params.now ?? /* @__PURE__ */ new Date()).getTime();
	const ranked = Object.values(store.entries ?? {}).filter((e) => {
		if (!e || typeof e !== "object") return false;
		if (e.promotedAt) return false;
		if (!e.path || !e.path.startsWith("memory/")) return false;
		if (e.recallCount < cfg.minRecallCount) return false;
		if ((e.queryHashes?.length ?? 0) < cfg.minUniqueQueries) return false;
		if (isExpiredEntry(e.lastRecalledAt, nowMs, cfg.maxAgeDays)) return false;
		return clamp01(e.recallCount > 0 ? e.totalScore / e.recallCount : 0) >= cfg.minScore;
	}).map((e) => {
		const { avgScore, score, recencyDecay } = computeCandidateScore(e, nowMs, cfg.recencyHalfLifeDays);
		return {
			...e,
			avgScore,
			score,
			recencyDecay
		};
	}).sort(compareCandidatesByScore);
	const markers = extractPromotionMarkers(await fs.readFile(memoryPath, "utf-8").catch((err) => {
		if (err?.code === "ENOENT") return "";
		throw err;
	}));
	const limit = Math.min(Math.max(params.limit ?? 20, 1), 50);
	const out = [];
	const scanCap = Math.min(ranked.length, Math.max(limit * 3, limit));
	for (const candidate of ranked.slice(0, scanCap)) {
		if (markers.keys.has(candidate.key)) {
			out.push({
				key: candidate.key,
				hash: "",
				snippet: "",
				path: candidate.path,
				startLine: candidate.startLine,
				endLine: candidate.endLine,
				score: candidate.score,
				avgScore: candidate.avgScore,
				recallCount: candidate.recallCount,
				recencyDecay: candidate.recencyDecay,
				alreadyPromotedByKey: true,
				alreadyPromotedByHash: false,
				skippedReason: "already promoted (key)"
			});
			continue;
		}
		const lines = await readFileLines(path.join(params.workspaceDir, candidate.path));
		if (!lines) continue;
		const startLine = Math.max(1, Math.floor(candidate.startLine));
		const endLine = Math.max(startLine, Math.floor(candidate.endLine));
		const snippet = sliceRange(lines, startLine, endLine);
		if (!snippet) continue;
		if (isContaminatedSnippet(snippet)) continue;
		const hash = snippetHash(snippet);
		const alreadyPromotedByHash = markers.hashes.has(hash);
		out.push({
			key: candidate.key,
			hash,
			snippet,
			path: candidate.path,
			startLine,
			endLine,
			score: candidate.score,
			avgScore: candidate.avgScore,
			recallCount: candidate.recallCount,
			recencyDecay: candidate.recencyDecay,
			alreadyPromotedByKey: false,
			alreadyPromotedByHash,
			skippedReason: alreadyPromotedByHash ? "already promoted (hash)" : null
		});
		if (out.filter((x) => !x.skippedReason).length >= limit) break;
	}
	return {
		ok: true,
		reason: "ok",
		items: out,
		memoryPath
	};
}
//#endregion
export { previewDreamingDeepPromotion };

//# sourceMappingURL=preview.js.map