import { r as formatErrorMessage } from "./errors-CGMew-1w.js";
import { T as setVerbose } from "./logger-CGXjC0Hv.js";
import { n as defaultRuntime } from "./runtime-CgZZEqw7.js";
import { _ as shortenHomePath, g as shortenHomeInString } from "./utils-CE5zxr9Z.js";
import { n as isRich, r as theme, t as colorize } from "./theme-AvNURkOg.js";
import { _ as resolveStateDir } from "./paths-CAiS8AEq.js";
import { m as resolveDefaultAgentId } from "./agent-scope-BA9YeMqS.js";
import { a as loadConfig } from "./io-B_JNqEVl.js";
import { n as asNullableRecord } from "./record-coerce-L40G7Uo_.js";
import { c as resolveSessionTranscriptsDirForAgent } from "./paths-DRORteAV.js";
import { t as resolveCommandSecretRefsViaGateway } from "./command-secret-gateway-6dp4RvyC.js";
import { t as buildAgentSessionKey } from "./resolve-route-4dFm8GmO.js";
import "./routing-B-Ak3ZgB.js";
import "./text-runtime-Drz6LusC.js";
import { r as withManager } from "./cli-utils-CcAr2vZx.js";
import "./memory-core-host-runtime-core-U6sKUgXg.js";
import { n as withProgress, r as withProgressTotals } from "./progress-BrVGmJbK.js";
import "./memory-core-host-runtime-cli-CYb7Fymf.js";
import { c as listMemoryFiles, l as normalizeExtraMemoryPaths } from "./internal-CkeoFN5P.js";
import "./memory-core-host-runtime-files-B2fQPfa9.js";
import { a as rankShortTermPromotionCandidates, c as repairShortTermPromotionArtifacts, d as resolveShortTermRecallStorePath, l as resolveShortTermPromotionConfig, n as applyShortTermPromotions, o as recordShortTermRecalls, r as auditShortTermPromotionArtifacts, u as resolveShortTermRecallLockPath } from "./short-term-promotion-hQ_XK28_.js";
import { n as getMemorySearchManager } from "./memory-DXBCTm5C.js";
import fs from "node:fs";
import path from "node:path";
import os from "node:os";
import fs$1 from "node:fs/promises";
//#region extensions/memory-core/src/cli.runtime.ts
function getMemoryCommandSecretTargetIds() {
	return new Set(["agents.defaults.memorySearch.remote.apiKey", "agents.list[].memorySearch.remote.apiKey"]);
}
async function loadMemoryCommandConfig(commandName) {
	const { resolvedConfig, diagnostics } = await resolveCommandSecretRefsViaGateway({
		config: loadConfig(),
		commandName,
		targetIds: getMemoryCommandSecretTargetIds()
	});
	return {
		config: resolvedConfig,
		diagnostics
	};
}
function emitMemorySecretResolveDiagnostics(diagnostics, params) {
	if (diagnostics.length === 0) return;
	const toStderr = params?.json === true;
	for (const entry of diagnostics) {
		const message = theme.warn(`[secrets] ${entry}`);
		if (toStderr) defaultRuntime.error(message);
		else defaultRuntime.log(message);
	}
}
function resolveMemoryPluginConfig(cfg) {
	return asNullableRecord(asNullableRecord(cfg.plugins?.entries?.["memory-core"])?.config) ?? {};
}
function formatAuditCounts(audit) {
	const scriptCoverage = audit.conceptTagScripts ? [
		audit.conceptTagScripts.latinEntryCount > 0 ? `${audit.conceptTagScripts.latinEntryCount} latin` : null,
		audit.conceptTagScripts.cjkEntryCount > 0 ? `${audit.conceptTagScripts.cjkEntryCount} cjk` : null,
		audit.conceptTagScripts.mixedEntryCount > 0 ? `${audit.conceptTagScripts.mixedEntryCount} mixed` : null,
		audit.conceptTagScripts.otherEntryCount > 0 ? `${audit.conceptTagScripts.otherEntryCount} other` : null
	].filter(Boolean).join(", ") : "";
	const suffix = scriptCoverage ? ` · scripts=${scriptCoverage}` : "";
	return `${audit.entryCount} entries · ${audit.promotedCount} promoted · ${audit.conceptTaggedEntryCount} concept-tagged · ${audit.spacedEntryCount} spaced${suffix}`;
}
function formatRepairSummary(repair) {
	const actions = [];
	if (repair.rewroteStore) actions.push(`rewrote store${repair.removedInvalidEntries > 0 ? ` (-${repair.removedInvalidEntries} invalid)` : ""}`);
	if (repair.removedStaleLock) actions.push("removed stale lock");
	return actions.length > 0 ? actions.join(" · ") : "no changes";
}
function formatSourceLabel(source, workspaceDir, agentId) {
	if (source === "memory") return shortenHomeInString(`memory (MEMORY.md + ${path.join(workspaceDir, "memory")}${path.sep}*.md)`);
	if (source === "sessions") {
		const stateDir = resolveStateDir(process.env, os.homedir);
		return shortenHomeInString(`sessions (${path.join(stateDir, "agents", agentId, "sessions")}${path.sep}*.jsonl)`);
	}
	return source;
}
function resolveAgent(cfg, agent) {
	const trimmed = agent?.trim();
	if (trimmed) return trimmed;
	return resolveDefaultAgentId(cfg);
}
function buildCliMemorySearchSessionKey(agentId) {
	return buildAgentSessionKey({
		agentId,
		channel: "cli",
		peer: {
			kind: "direct",
			id: "memory-search"
		},
		dmScope: "per-channel-peer"
	});
}
function resolveAgentIds(cfg, agent) {
	const trimmed = agent?.trim();
	if (trimmed) return [trimmed];
	const list = cfg.agents?.list ?? [];
	if (list.length > 0) return list.map((entry) => entry.id).filter(Boolean);
	return [resolveDefaultAgentId(cfg)];
}
function formatExtraPaths(workspaceDir, extraPaths) {
	return normalizeExtraMemoryPaths(workspaceDir, extraPaths).map((entry) => shortenHomePath(entry));
}
function matchesPromotionSelector(candidate, selector) {
	const trimmed = selector.trim().toLowerCase();
	if (!trimmed) return false;
	return candidate.key.toLowerCase() === trimmed || candidate.key.toLowerCase().includes(trimmed) || candidate.path.toLowerCase().includes(trimmed) || candidate.snippet.toLowerCase().includes(trimmed);
}
async function withMemoryManagerForAgent(params) {
	const managerParams = {
		cfg: params.cfg,
		agentId: params.agentId
	};
	if (params.purpose) managerParams.purpose = params.purpose;
	await withManager({
		getManager: () => getMemorySearchManager(managerParams),
		onMissing: (error) => defaultRuntime.log(error ?? "Memory search disabled."),
		onCloseError: (err) => defaultRuntime.error(`Memory manager close failed: ${formatErrorMessage(err)}`),
		close: async (manager) => {
			await manager.close?.();
		},
		run: params.run
	});
}
async function checkReadableFile(pathname) {
	try {
		await fs$1.access(pathname, fs.constants.R_OK);
		return { exists: true };
	} catch (err) {
		const code = err.code;
		if (code === "ENOENT") return { exists: false };
		return {
			exists: true,
			issue: `${shortenHomePath(pathname)} not readable (${code ?? "error"})`
		};
	}
}
async function scanSessionFiles(agentId) {
	const issues = [];
	const sessionsDir = resolveSessionTranscriptsDirForAgent(agentId);
	try {
		return {
			source: "sessions",
			totalFiles: (await fs$1.readdir(sessionsDir, { withFileTypes: true })).filter((entry) => entry.isFile() && entry.name.endsWith(".jsonl")).length,
			issues
		};
	} catch (err) {
		const code = err.code;
		if (code === "ENOENT") {
			issues.push(`sessions directory missing (${shortenHomePath(sessionsDir)})`);
			return {
				source: "sessions",
				totalFiles: 0,
				issues
			};
		}
		issues.push(`sessions directory not accessible (${shortenHomePath(sessionsDir)}): ${code ?? "error"}`);
		return {
			source: "sessions",
			totalFiles: null,
			issues
		};
	}
}
async function scanMemoryFiles(workspaceDir, extraPaths = []) {
	const issues = [];
	const memoryFile = path.join(workspaceDir, "MEMORY.md");
	const altMemoryFile = path.join(workspaceDir, "memory.md");
	const memoryDir = path.join(workspaceDir, "memory");
	const primary = await checkReadableFile(memoryFile);
	const alt = await checkReadableFile(altMemoryFile);
	if (primary.issue) issues.push(primary.issue);
	if (alt.issue) issues.push(alt.issue);
	const resolvedExtraPaths = normalizeExtraMemoryPaths(workspaceDir, extraPaths);
	for (const extraPath of resolvedExtraPaths) try {
		if ((await fs$1.lstat(extraPath)).isSymbolicLink()) continue;
		const extraCheck = await checkReadableFile(extraPath);
		if (extraCheck.issue) issues.push(extraCheck.issue);
	} catch (err) {
		const code = err.code;
		if (code === "ENOENT") issues.push(`additional memory path missing (${shortenHomePath(extraPath)})`);
		else issues.push(`additional memory path not accessible (${shortenHomePath(extraPath)}): ${code ?? "error"}`);
	}
	let dirReadable = null;
	try {
		await fs$1.access(memoryDir, fs.constants.R_OK);
		dirReadable = true;
	} catch (err) {
		const code = err.code;
		if (code === "ENOENT") {
			issues.push(`memory directory missing (${shortenHomePath(memoryDir)})`);
			dirReadable = false;
		} else {
			issues.push(`memory directory not accessible (${shortenHomePath(memoryDir)}): ${code ?? "error"}`);
			dirReadable = null;
		}
	}
	let listed = [];
	let listedOk = false;
	try {
		listed = await listMemoryFiles(workspaceDir, resolvedExtraPaths);
		listedOk = true;
	} catch (err) {
		const code = err.code;
		if (dirReadable !== null) {
			issues.push(`memory directory scan failed (${shortenHomePath(memoryDir)}): ${code ?? "error"}`);
			dirReadable = null;
		}
	}
	let totalFiles = 0;
	if (dirReadable === null) totalFiles = null;
	else {
		const files = new Set(listedOk ? listed : []);
		if (!listedOk) {
			if (primary.exists) files.add(memoryFile);
			if (alt.exists) files.add(altMemoryFile);
		}
		totalFiles = files.size;
	}
	if ((totalFiles ?? 0) === 0 && issues.length === 0) issues.push(`no memory files found in ${shortenHomePath(workspaceDir)}`);
	return {
		source: "memory",
		totalFiles,
		issues
	};
}
async function summarizeQmdIndexArtifact(manager) {
	const status = manager.status?.();
	if (!status || status.backend !== "qmd") return null;
	const dbPath = status.dbPath?.trim();
	if (!dbPath) return null;
	let stat;
	try {
		stat = await fs$1.stat(dbPath);
	} catch (err) {
		const code = err.code;
		if (code === "ENOENT") throw new Error(`QMD index file not found: ${shortenHomePath(dbPath)}`, { cause: err });
		throw new Error(`QMD index file check failed: ${shortenHomePath(dbPath)} (${code ?? "error"})`, { cause: err });
	}
	if (!stat.isFile() || stat.size <= 0) throw new Error(`QMD index file is empty: ${shortenHomePath(dbPath)}`);
	return `QMD index: ${shortenHomePath(dbPath)} (${stat.size} bytes)`;
}
async function scanMemorySources(params) {
	const scans = [];
	const extraPaths = params.extraPaths ?? [];
	for (const source of params.sources) {
		if (source === "memory") scans.push(await scanMemoryFiles(params.workspaceDir, extraPaths));
		if (source === "sessions") scans.push(await scanSessionFiles(params.agentId));
	}
	const issues = scans.flatMap((scan) => scan.issues);
	const totals = scans.map((scan) => scan.totalFiles);
	const numericTotals = totals.filter((total) => total !== null);
	return {
		sources: scans,
		totalFiles: totals.some((total) => total === null) ? null : numericTotals.reduce((sum, total) => sum + total, 0),
		issues
	};
}
async function runMemoryStatus(opts) {
	setVerbose(Boolean(opts.verbose));
	const { config: cfg, diagnostics } = await loadMemoryCommandConfig("memory status");
	emitMemorySecretResolveDiagnostics(diagnostics, { json: Boolean(opts.json) });
	const agentIds = resolveAgentIds(cfg, opts.agent);
	const allResults = [];
	for (const agentId of agentIds) await withMemoryManagerForAgent({
		cfg,
		agentId,
		purpose: opts.index ? "default" : "status",
		run: async (manager) => {
			const deep = Boolean(opts.deep || opts.index);
			let embeddingProbe;
			let indexError;
			const syncFn = manager.sync ? manager.sync.bind(manager) : void 0;
			if (deep) {
				await withProgress({
					label: "Checking memory…",
					total: 2
				}, async (progress) => {
					progress.setLabel("Probing vector…");
					await manager.probeVectorAvailability();
					progress.tick();
					progress.setLabel("Probing embeddings…");
					embeddingProbe = await manager.probeEmbeddingAvailability();
					progress.tick();
				});
				if (opts.index && syncFn) await withProgressTotals({
					label: "Indexing memory…",
					total: 0,
					fallback: opts.verbose ? "line" : void 0
				}, async (update, progress) => {
					try {
						await syncFn({
							reason: "cli",
							force: Boolean(opts.force),
							progress: (syncUpdate) => {
								update({
									completed: syncUpdate.completed,
									total: syncUpdate.total,
									label: syncUpdate.label
								});
								if (syncUpdate.label) progress.setLabel(syncUpdate.label);
							}
						});
					} catch (err) {
						indexError = formatErrorMessage(err);
						defaultRuntime.error(`Memory index failed: ${indexError}`);
						process.exitCode = 1;
					}
				});
				else if (opts.index && !syncFn) defaultRuntime.log("Memory backend does not support manual reindex.");
			} else await manager.probeVectorAvailability();
			const status = manager.status();
			const sources = status.sources?.length ? status.sources : ["memory"];
			const workspaceDir = status.workspaceDir;
			const scan = workspaceDir ? await scanMemorySources({
				workspaceDir,
				agentId,
				sources,
				extraPaths: status.extraPaths
			}) : void 0;
			let audit;
			let repair;
			if (workspaceDir) {
				if (opts.fix) repair = await repairShortTermPromotionArtifacts({ workspaceDir });
				const customQmd = asNullableRecord(asNullableRecord(status.custom)?.qmd);
				audit = await auditShortTermPromotionArtifacts({
					workspaceDir,
					qmd: status.backend === "qmd" ? {
						dbPath: status.dbPath,
						collections: typeof customQmd?.collections === "number" ? customQmd.collections : void 0
					} : void 0
				});
			}
			allResults.push({
				agentId,
				status,
				embeddingProbe,
				indexError,
				scan,
				audit,
				repair
			});
		}
	});
	if (opts.json) {
		defaultRuntime.writeJson(allResults);
		return;
	}
	const rich = isRich();
	const heading = (text) => colorize(rich, theme.heading, text);
	const muted = (text) => colorize(rich, theme.muted, text);
	const info = (text) => colorize(rich, theme.info, text);
	const success = (text) => colorize(rich, theme.success, text);
	const warn = (text) => colorize(rich, theme.warn, text);
	const accent = (text) => colorize(rich, theme.accent, text);
	const label = (text) => muted(`${text}:`);
	for (const result of allResults) {
		const { agentId, status, embeddingProbe, indexError, scan, audit, repair } = result;
		const filesIndexed = status.files ?? 0;
		const chunksIndexed = status.chunks ?? 0;
		const totalFiles = scan?.totalFiles ?? null;
		const indexedLabel = totalFiles === null ? `${filesIndexed}/? files · ${chunksIndexed} chunks` : `${filesIndexed}/${totalFiles} files · ${chunksIndexed} chunks`;
		if (opts.index) {
			const line = indexError ? `Memory index failed: ${indexError}` : "Memory index complete.";
			defaultRuntime.log(line);
		}
		const requestedProvider = status.requestedProvider ?? status.provider;
		const modelLabel = status.model ?? status.provider;
		const storePath = status.dbPath ? shortenHomePath(status.dbPath) : "<unknown>";
		const workspacePath = status.workspaceDir ? shortenHomePath(status.workspaceDir) : "<unknown>";
		const sourceList = status.sources?.length ? status.sources.join(", ") : null;
		const extraPaths = status.workspaceDir ? formatExtraPaths(status.workspaceDir, status.extraPaths ?? []) : [];
		const lines = [
			`${heading("Memory Search")} ${muted(`(${agentId})`)}`,
			`${label("Provider")} ${info(status.provider)} ${muted(`(requested: ${requestedProvider})`)}`,
			`${label("Model")} ${info(modelLabel)}`,
			sourceList ? `${label("Sources")} ${info(sourceList)}` : null,
			extraPaths.length ? `${label("Extra paths")} ${info(extraPaths.join(", "))}` : null,
			`${label("Indexed")} ${success(indexedLabel)}`,
			`${label("Dirty")} ${status.dirty ? warn("yes") : muted("no")}`,
			`${label("Store")} ${info(storePath)}`,
			`${label("Workspace")} ${info(workspacePath)}`
		].filter(Boolean);
		if (embeddingProbe) {
			const state = embeddingProbe.ok ? "ready" : "unavailable";
			const stateColor = embeddingProbe.ok ? theme.success : theme.warn;
			lines.push(`${label("Embeddings")} ${colorize(rich, stateColor, state)}`);
			if (embeddingProbe.error) lines.push(`${label("Embeddings error")} ${warn(embeddingProbe.error)}`);
		}
		if (status.sourceCounts?.length) {
			lines.push(label("By source"));
			for (const entry of status.sourceCounts) {
				const total = scan?.sources?.find((scanEntry) => scanEntry.source === entry.source)?.totalFiles;
				const counts = total === null ? `${entry.files}/? files · ${entry.chunks} chunks` : `${entry.files}/${total} files · ${entry.chunks} chunks`;
				lines.push(`  ${accent(entry.source)} ${muted("·")} ${muted(counts)}`);
			}
		}
		if (status.fallback) lines.push(`${label("Fallback")} ${warn(status.fallback.from)}`);
		if (status.vector) {
			const vectorState = status.vector.enabled ? status.vector.available === void 0 ? "unknown" : status.vector.available ? "ready" : "unavailable" : "disabled";
			const vectorColor = vectorState === "ready" ? theme.success : vectorState === "unavailable" ? theme.warn : theme.muted;
			lines.push(`${label("Vector")} ${colorize(rich, vectorColor, vectorState)}`);
			if (status.vector.dims) lines.push(`${label("Vector dims")} ${info(String(status.vector.dims))}`);
			if (status.vector.extensionPath) lines.push(`${label("Vector path")} ${info(shortenHomePath(status.vector.extensionPath))}`);
			if (status.vector.loadError) lines.push(`${label("Vector error")} ${warn(status.vector.loadError)}`);
		}
		if (status.fts) {
			const ftsState = status.fts.enabled ? status.fts.available ? "ready" : "unavailable" : "disabled";
			const ftsColor = ftsState === "ready" ? theme.success : ftsState === "unavailable" ? theme.warn : theme.muted;
			lines.push(`${label("FTS")} ${colorize(rich, ftsColor, ftsState)}`);
			if (status.fts.error) lines.push(`${label("FTS error")} ${warn(status.fts.error)}`);
		}
		if (status.cache) {
			const cacheState = status.cache.enabled ? "enabled" : "disabled";
			const cacheColor = status.cache.enabled ? theme.success : theme.muted;
			const suffix = status.cache.enabled && typeof status.cache.entries === "number" ? ` (${status.cache.entries} entries)` : "";
			lines.push(`${label("Embedding cache")} ${colorize(rich, cacheColor, cacheState)}${suffix}`);
			if (status.cache.enabled && typeof status.cache.maxEntries === "number") lines.push(`${label("Cache cap")} ${info(String(status.cache.maxEntries))}`);
		}
		if (status.batch) {
			const batchState = status.batch.enabled ? "enabled" : "disabled";
			const batchColor = status.batch.enabled ? theme.success : theme.warn;
			const batchSuffix = ` (failures ${status.batch.failures}/${status.batch.limit})`;
			lines.push(`${label("Batch")} ${colorize(rich, batchColor, batchState)}${muted(batchSuffix)}`);
			if (status.batch.lastError) lines.push(`${label("Batch error")} ${warn(status.batch.lastError)}`);
		}
		if (audit) {
			lines.push(`${label("Recall store")} ${info(formatAuditCounts(audit))}`);
			lines.push(`${label("Recall path")} ${info(shortenHomePath(audit.storePath))}`);
			if (audit.updatedAt) lines.push(`${label("Recall updated")} ${info(audit.updatedAt)}`);
			if (status.backend === "qmd" && audit.qmd) {
				const qmdBits = [
					audit.qmd.dbPath ? shortenHomePath(audit.qmd.dbPath) : "<unknown>",
					typeof audit.qmd.dbBytes === "number" ? `${audit.qmd.dbBytes} bytes` : null,
					typeof audit.qmd.collections === "number" ? `${audit.qmd.collections} collections` : null
				].filter(Boolean);
				lines.push(`${label("QMD audit")} ${info(qmdBits.join(" · "))}`);
			}
		}
		if (repair) lines.push(`${label("Repair")} ${info(formatRepairSummary(repair))}`);
		if (status.fallback?.reason) lines.push(muted(status.fallback.reason));
		if (indexError) lines.push(`${label("Index error")} ${warn(indexError)}`);
		if (scan?.issues.length) {
			lines.push(label("Issues"));
			for (const issue of scan.issues) lines.push(`  ${warn(issue)}`);
		}
		if (audit?.issues.length) {
			if (!scan?.issues.length) lines.push(label("Issues"));
			for (const issue of audit.issues) lines.push(`  ${issue.severity === "error" ? warn(issue.message) : muted(issue.message)}`);
			if (!opts.fix) lines.push(`  ${muted(`Fix: kaijibot memory status --fix --agent ${agentId}`)}`);
		}
		defaultRuntime.log(lines.join("\n"));
		defaultRuntime.log("");
	}
}
async function runMemoryIndex(opts) {
	setVerbose(Boolean(opts.verbose));
	const { config: cfg, diagnostics } = await loadMemoryCommandConfig("memory index");
	emitMemorySecretResolveDiagnostics(diagnostics);
	const agentIds = resolveAgentIds(cfg, opts.agent);
	for (const agentId of agentIds) await withMemoryManagerForAgent({
		cfg,
		agentId,
		run: async (manager) => {
			try {
				const syncFn = manager.sync ? manager.sync.bind(manager) : void 0;
				if (opts.verbose) {
					const status = manager.status();
					const rich = isRich();
					const heading = (text) => colorize(rich, theme.heading, text);
					const muted = (text) => colorize(rich, theme.muted, text);
					const info = (text) => colorize(rich, theme.info, text);
					const warn = (text) => colorize(rich, theme.warn, text);
					const label = (text) => muted(`${text}:`);
					const sourceLabels = (status.sources ?? []).map((source) => formatSourceLabel(source, status.workspaceDir ?? "", agentId));
					const extraPaths = status.workspaceDir ? formatExtraPaths(status.workspaceDir, status.extraPaths ?? []) : [];
					const requestedProvider = status.requestedProvider ?? status.provider;
					const modelLabel = status.model ?? status.provider;
					const lines = [
						`${heading("Memory Index")} ${muted(`(${agentId})`)}`,
						`${label("Provider")} ${info(status.provider)} ${muted(`(requested: ${requestedProvider})`)}`,
						`${label("Model")} ${info(modelLabel)}`,
						sourceLabels.length ? `${label("Sources")} ${info(sourceLabels.join(", "))}` : null,
						extraPaths.length ? `${label("Extra paths")} ${info(extraPaths.join(", "))}` : null
					].filter(Boolean);
					if (status.fallback) lines.push(`${label("Fallback")} ${warn(status.fallback.from)}`);
					defaultRuntime.log(lines.join("\n"));
					defaultRuntime.log("");
				}
				const startedAt = Date.now();
				let lastLabel = "Indexing memory…";
				let lastCompleted = 0;
				let lastTotal = 0;
				const formatElapsed = () => {
					const elapsedMs = Math.max(0, Date.now() - startedAt);
					const seconds = Math.floor(elapsedMs / 1e3);
					const minutes = Math.floor(seconds / 60);
					const remainingSeconds = seconds % 60;
					return `${minutes}:${String(remainingSeconds).padStart(2, "0")}`;
				};
				const formatEta = () => {
					if (lastTotal <= 0 || lastCompleted <= 0) return null;
					const elapsedMs = Math.max(1, Date.now() - startedAt);
					const rate = lastCompleted / elapsedMs;
					if (!Number.isFinite(rate) || rate <= 0) return null;
					const remainingMs = Math.max(0, (lastTotal - lastCompleted) / rate);
					const seconds = Math.floor(remainingMs / 1e3);
					const minutes = Math.floor(seconds / 60);
					const remainingSeconds = seconds % 60;
					return `${minutes}:${String(remainingSeconds).padStart(2, "0")}`;
				};
				const buildLabel = () => {
					const elapsed = formatElapsed();
					const eta = formatEta();
					return eta ? `${lastLabel} · elapsed ${elapsed} · eta ${eta}` : `${lastLabel} · elapsed ${elapsed}`;
				};
				if (!syncFn) {
					defaultRuntime.log("Memory backend does not support manual reindex.");
					return;
				}
				await withProgressTotals({
					label: "Indexing memory…",
					total: 0,
					fallback: opts.verbose ? "line" : void 0
				}, async (update, progress) => {
					const interval = setInterval(() => {
						progress.setLabel(buildLabel());
					}, 1e3);
					try {
						await syncFn({
							reason: "cli",
							force: Boolean(opts.force),
							progress: (syncUpdate) => {
								if (syncUpdate.label) lastLabel = syncUpdate.label;
								lastCompleted = syncUpdate.completed;
								lastTotal = syncUpdate.total;
								update({
									completed: syncUpdate.completed,
									total: syncUpdate.total,
									label: buildLabel()
								});
								progress.setLabel(buildLabel());
							}
						});
					} finally {
						clearInterval(interval);
					}
				});
				const qmdIndexSummary = await summarizeQmdIndexArtifact(manager);
				if (qmdIndexSummary) defaultRuntime.log(qmdIndexSummary);
				const postIndexStatus = manager.status();
				const vectorEnabled = postIndexStatus.vector?.enabled ?? false;
				const vectorAvailable = postIndexStatus.vector?.available;
				const vectorLoadErr = postIndexStatus.vector?.loadError;
				if (vectorEnabled && vectorAvailable === false) {
					const errDetail = vectorLoadErr ? `: ${vectorLoadErr}` : "";
					defaultRuntime.error(`Memory index WARNING (${agentId}): chunks_vec not updated — sqlite-vec unavailable${errDetail}. Vector recall degraded.`);
				} else defaultRuntime.log(`Memory index updated (${agentId}).`);
			} catch (err) {
				const message = formatErrorMessage(err);
				defaultRuntime.error(`Memory index failed (${agentId}): ${message}`);
				process.exitCode = 1;
			}
		}
	});
}
async function runMemorySearch(queryArg, opts) {
	const query = opts.query ?? queryArg;
	if (!query) {
		defaultRuntime.error("Missing search query. Provide a positional query or use --query <text>.");
		process.exitCode = 1;
		return;
	}
	const { config: cfg, diagnostics } = await loadMemoryCommandConfig("memory search");
	emitMemorySecretResolveDiagnostics(diagnostics, { json: Boolean(opts.json) });
	const agentId = resolveAgent(cfg, opts.agent);
	const shortTermConfig = resolveShortTermPromotionConfig({
		pluginConfig: resolveMemoryPluginConfig(cfg),
		cfg
	});
	await withMemoryManagerForAgent({
		cfg,
		agentId,
		run: async (manager) => {
			const sessionKey = buildCliMemorySearchSessionKey(agentId);
			let results;
			try {
				results = await manager.search(query, {
					maxResults: opts.maxResults,
					minScore: opts.minScore,
					sessionKey
				});
			} catch (err) {
				const message = formatErrorMessage(err);
				defaultRuntime.error(`Memory search failed: ${message}`);
				process.exitCode = 1;
				return;
			}
			recordShortTermRecalls({
				workspaceDir: typeof manager.status === "function" ? manager.status().workspaceDir : void 0,
				query,
				results,
				timezone: shortTermConfig.timezone
			}).catch(() => {});
			if (opts.json) {
				defaultRuntime.writeJson({ results });
				return;
			}
			if (results.length === 0) {
				defaultRuntime.log("No matches.");
				return;
			}
			const rich = isRich();
			const lines = [];
			for (const result of results) {
				lines.push(`${colorize(rich, theme.success, result.score.toFixed(3))} ${colorize(rich, theme.accent, `${shortenHomePath(result.path)}:${result.startLine}-${result.endLine}`)}`);
				lines.push(colorize(rich, theme.muted, result.snippet));
				lines.push("");
			}
			defaultRuntime.log(lines.join("\n").trim());
		}
	});
}
async function runMemoryPromote(opts) {
	const { config: cfg, diagnostics } = await loadMemoryCommandConfig("memory promote");
	emitMemorySecretResolveDiagnostics(diagnostics, { json: Boolean(opts.json) });
	const agentId = resolveAgent(cfg, opts.agent);
	await withMemoryManagerForAgent({
		cfg,
		agentId,
		purpose: "status",
		run: async (manager) => {
			const status = manager.status();
			const workspaceDir = status.workspaceDir?.trim();
			const promotionConfig = resolveShortTermPromotionConfig({
				pluginConfig: resolveMemoryPluginConfig(cfg),
				cfg
			});
			if (!workspaceDir) {
				defaultRuntime.error("Memory promote requires a resolvable workspace directory.");
				process.exitCode = 1;
				return;
			}
			let candidates;
			try {
				candidates = await rankShortTermPromotionCandidates({
					workspaceDir,
					limit: opts.limit,
					minScore: opts.minScore ?? promotionConfig.minScore,
					minRecallCount: opts.minRecallCount ?? promotionConfig.minRecallCount,
					minUniqueQueries: opts.minUniqueQueries ?? promotionConfig.minUniqueQueries,
					recencyHalfLifeDays: promotionConfig.recencyHalfLifeDays,
					maxAgeDays: promotionConfig.maxAgeDays,
					includePromoted: Boolean(opts.includePromoted)
				});
			} catch (err) {
				defaultRuntime.error(`Memory promote ranking failed: ${formatErrorMessage(err)}`);
				process.exitCode = 1;
				return;
			}
			let applyResult;
			if (opts.apply) try {
				applyResult = await applyShortTermPromotions({
					workspaceDir,
					candidates,
					limit: opts.limit,
					minScore: opts.minScore ?? promotionConfig.minScore,
					minRecallCount: opts.minRecallCount ?? promotionConfig.minRecallCount,
					minUniqueQueries: opts.minUniqueQueries ?? promotionConfig.minUniqueQueries,
					maxAgeDays: promotionConfig.maxAgeDays,
					timezone: promotionConfig.timezone
				});
			} catch (err) {
				defaultRuntime.error(`Memory promote apply failed: ${formatErrorMessage(err)}`);
				process.exitCode = 1;
				return;
			}
			const storePath = resolveShortTermRecallStorePath(workspaceDir);
			const lockPath = resolveShortTermRecallLockPath(workspaceDir);
			const customQmd = asNullableRecord(asNullableRecord(status.custom)?.qmd);
			const audit = await auditShortTermPromotionArtifacts({
				workspaceDir,
				qmd: status.backend === "qmd" ? {
					dbPath: status.dbPath,
					collections: typeof customQmd?.collections === "number" ? customQmd.collections : void 0
				} : void 0
			});
			if (opts.json) {
				defaultRuntime.writeJson({
					workspaceDir,
					storePath,
					lockPath,
					audit,
					candidates,
					apply: applyResult ? {
						applied: applyResult.applied,
						appended: applyResult.appended,
						reconciledExisting: applyResult.reconciledExisting,
						memoryPath: applyResult.memoryPath,
						appliedCandidates: applyResult.appliedCandidates
					} : void 0
				});
				return;
			}
			if (candidates.length === 0) {
				defaultRuntime.log("No short-term recall candidates.");
				defaultRuntime.log(`Recall store: ${shortenHomePath(storePath)}`);
				if (audit.issues.length > 0) for (const issue of audit.issues) defaultRuntime.log(issue.message);
				return;
			}
			const rich = isRich();
			const lines = [];
			lines.push(`${colorize(rich, theme.heading, "Short-Term Promotion Candidates")} ${colorize(rich, theme.muted, `(${agentId})`)}`);
			lines.push(`${colorize(rich, theme.muted, "Recall store:")} ${shortenHomePath(storePath)}`);
			lines.push(colorize(rich, theme.muted, `Store health: ${formatAuditCounts(audit)}`));
			for (const candidate of candidates) {
				lines.push(`${colorize(rich, theme.success, candidate.score.toFixed(3))} ${colorize(rich, theme.accent, `${shortenHomePath(candidate.path)}:${candidate.startLine}-${candidate.endLine}`)}`);
				lines.push(colorize(rich, theme.muted, `recalls=${candidate.recallCount} avg=${candidate.avgScore.toFixed(3)} queries=${candidate.uniqueQueries} age=${candidate.ageDays.toFixed(1)}d consolidate=${candidate.components.consolidation.toFixed(2)} conceptual=${candidate.components.conceptual.toFixed(2)}`));
				if (candidate.conceptTags.length > 0) lines.push(colorize(rich, theme.muted, `concepts=${candidate.conceptTags.join(", ")}`));
				if (candidate.snippet) lines.push(colorize(rich, theme.muted, candidate.snippet));
				lines.push("");
			}
			if (audit.issues.length > 0) {
				lines.push(colorize(rich, theme.warn, "Audit issues:"));
				for (const issue of audit.issues) lines.push(colorize(rich, issue.severity === "error" ? theme.warn : theme.muted, issue.message));
				lines.push("");
			}
			if (applyResult) if (applyResult.applied > 0) {
				lines.push(colorize(rich, theme.success, `Processed ${applyResult.applied} candidate(s) for ${shortenHomePath(applyResult.memoryPath)}.`));
				lines.push(colorize(rich, theme.muted, `appended=${applyResult.appended} reconciledExisting=${applyResult.reconciledExisting}`));
			} else lines.push(colorize(rich, theme.warn, "No candidates met apply criteria."));
			defaultRuntime.log(lines.join("\n").trim());
		}
	});
}
async function runMemoryPromoteExplain(selectorArg, opts) {
	const selector = selectorArg?.trim();
	if (!selector) {
		defaultRuntime.error("Memory promote-explain requires a non-empty selector.");
		process.exitCode = 1;
		return;
	}
	const { config: cfg, diagnostics } = await loadMemoryCommandConfig("memory promote-explain");
	emitMemorySecretResolveDiagnostics(diagnostics, { json: Boolean(opts.json) });
	const agentId = resolveAgent(cfg, opts.agent);
	await withMemoryManagerForAgent({
		cfg,
		agentId,
		purpose: "status",
		run: async (manager) => {
			const workspaceDir = manager.status().workspaceDir?.trim();
			const promotionConfig = resolveShortTermPromotionConfig({
				pluginConfig: resolveMemoryPluginConfig(cfg),
				cfg
			});
			if (!workspaceDir) {
				defaultRuntime.error("Memory promote-explain requires a resolvable workspace directory.");
				process.exitCode = 1;
				return;
			}
			let candidates;
			try {
				candidates = await rankShortTermPromotionCandidates({
					workspaceDir,
					minScore: 0,
					minRecallCount: 0,
					minUniqueQueries: 0,
					includePromoted: Boolean(opts.includePromoted),
					recencyHalfLifeDays: promotionConfig.recencyHalfLifeDays,
					maxAgeDays: promotionConfig.maxAgeDays
				});
			} catch (err) {
				defaultRuntime.error(`Memory promote-explain failed: ${formatErrorMessage(err)}`);
				process.exitCode = 1;
				return;
			}
			const candidate = candidates.find((entry) => matchesPromotionSelector(entry, selector));
			if (!candidate) {
				defaultRuntime.error(`No promotion candidate matched "${selector}".`);
				process.exitCode = 1;
				return;
			}
			const thresholds = {
				minScore: promotionConfig.minScore,
				minRecallCount: promotionConfig.minRecallCount,
				minUniqueQueries: promotionConfig.minUniqueQueries,
				maxAgeDays: promotionConfig.maxAgeDays ?? null
			};
			if (opts.json) {
				defaultRuntime.writeJson({
					workspaceDir,
					thresholds,
					candidate,
					passes: {
						score: candidate.score >= thresholds.minScore,
						recallCount: candidate.recallCount >= thresholds.minRecallCount,
						uniqueQueries: candidate.uniqueQueries >= thresholds.minUniqueQueries,
						maxAge: thresholds.maxAgeDays === null ? true : candidate.ageDays <= thresholds.maxAgeDays
					}
				});
				return;
			}
			const rich = isRich();
			const lines = [
				`${colorize(rich, theme.heading, "Promotion Explain")} ${colorize(rich, theme.muted, "(" + agentId + ")")}`,
				colorize(rich, theme.accent, candidate.key),
				colorize(rich, theme.muted, `${shortenHomePath(candidate.path)}:${String(candidate.startLine)}-${String(candidate.endLine)}`),
				candidate.snippet,
				colorize(rich, theme.muted, `score=${candidate.score.toFixed(3)} recallCount=${candidate.recallCount} uniqueQueries=${candidate.uniqueQueries} ageDays=${candidate.ageDays.toFixed(1)}`),
				colorize(rich, theme.muted, `components: frequency=${candidate.components.frequency.toFixed(2)} relevance=${candidate.components.relevance.toFixed(2)} diversity=${candidate.components.diversity.toFixed(2)} recency=${candidate.components.recency.toFixed(2)} consolidation=${candidate.components.consolidation.toFixed(2)} conceptual=${candidate.components.conceptual.toFixed(2)}`),
				colorize(rich, theme.muted, `thresholds: minScore=${thresholds.minScore} minRecallCount=${thresholds.minRecallCount} minUniqueQueries=${thresholds.minUniqueQueries} maxAgeDays=${thresholds.maxAgeDays ?? "none"}`)
			];
			if (candidate.conceptTags.length > 0) lines.push(colorize(rich, theme.muted, `concepts=${candidate.conceptTags.join(", ")}`));
			defaultRuntime.log(lines.join("\n"));
		}
	});
}
//#endregion
export { runMemoryIndex, runMemoryPromote, runMemoryPromoteExplain, runMemorySearch, runMemoryStatus };
