import { init_write_file_atomic, writeTextAtomic } from "../../infra/write-file-atomic.js";
import { createLogger } from "../../utils/logger/index.js";
import { init_logger } from "../../utils/logger.js";
import { init_agent_scope, resolveAgentHomeDir } from "../agent-scope.js";
import { extractProfileAgentId } from "../../config/agent-profile.js";
import { checklistCounts } from "./checklist-types.js";
import "./goal-run-types.js";
import { createHash, randomUUID } from "node:crypto";
import { readFile } from "node:fs/promises";
import { join } from "node:path";
//#region src/agent/goals/goal-run-store.ts
init_agent_scope();
init_write_file_atomic();
init_logger();
const log = createLogger("GoalRunStore");
const MAX_REASON_CHARS = 4e3;
const MAX_GOAL_CHARS = 4e3;
const MAX_ASSISTANT_PREVIEW_CHARS = 2e3;
const MAX_RUNS_PER_FILE = 400;
function truncate(s, max) {
	const t = s.trim();
	if (t.length <= max) return t;
	return `${t.slice(0, max - 1)}…`;
}
function resolveGoalRunsFilePath(config, sessionKey) {
	return join(resolveAgentHomeDir(config, extractProfileAgentId(sessionKey, config)), "goal-runs", `${createHash("sha256").update(sessionKey, "utf8").digest("hex")}.json`);
}
function isGoalRunFileV1(x) {
	if (!x || typeof x !== "object" || Array.isArray(x)) return false;
	const o = x;
	if (o.version !== 1) return false;
	if (typeof o.sessionKey !== "string" || !o.sessionKey.trim()) return false;
	if (!Array.isArray(o.runs)) return false;
	return true;
}
function parseGoalRunFile(raw) {
	try {
		const parsed = JSON.parse(raw);
		if (!isGoalRunFileV1(parsed)) return null;
		return parsed;
	} catch {
		return null;
	}
}
function buildRecordFromDecision(sessionKey, decision, assistantPlainText) {
	const ns = decision.newState;
	if (!ns) return null;
	const items = ns.checklist ?? [];
	const progress = items.length > 0 ? (() => {
		const c = checklistCounts(items);
		return {
			done: c.completed + c.impossible,
			total: c.total
		};
	})() : void 0;
	return {
		id: randomUUID(),
		at: Date.now(),
		goalTitle: truncate(ns.goal, MAX_GOAL_CHARS),
		turnsUsed: ns.turnsUsed,
		maxTurns: ns.maxTurns,
		verdict: decision.verdict,
		statusAfter: ns.status,
		...decision.reason.trim() ? { reason: truncate(decision.reason, MAX_REASON_CHARS) } : {},
		willContinue: decision.shouldContinue,
		...progress ? { checklistProgress: progress } : {},
		...assistantPlainText.trim() ? { assistantPreview: truncate(assistantPlainText, MAX_ASSISTANT_PREVIEW_CHARS) } : {}
	};
}
/**
* Append one run after persistent-goal post-turn evaluation (best-effort; logs on failure).
*/
async function appendGoalRun(opts) {
	const { config, sessionKey, decision, assistantPlainText } = opts;
	const record = buildRecordFromDecision(sessionKey, decision, assistantPlainText);
	if (!record) return;
	const filePath = resolveGoalRunsFilePath(config, sessionKey);
	let existing = {
		version: 1,
		sessionKey,
		runs: []
	};
	try {
		const parsed = parseGoalRunFile(await readFile(filePath, "utf8"));
		if (parsed) {
			if (parsed.sessionKey !== sessionKey) {
				log.warn({
					sessionKey,
					filePath
				}, "Goal run file sessionKey mismatch; refusing append");
				return;
			}
			existing = parsed;
		}
	} catch (err) {
		if ((err && typeof err === "object" && "code" in err ? String(err.code) : "") !== "ENOENT") {
			log.warn({
				err,
				sessionKey,
				filePath
			}, `Goal run read failed: ${err instanceof Error ? err.message : String(err)}`);
			return;
		}
	}
	const nextRuns = [...existing.runs, record];
	const out = {
		version: 1,
		sessionKey,
		runs: nextRuns.length > MAX_RUNS_PER_FILE ? nextRuns.slice(nextRuns.length - MAX_RUNS_PER_FILE) : nextRuns
	};
	await writeTextAtomic(filePath, `${JSON.stringify(out, null, 2)}\n`);
}
/**
* List runs for a session (newest first). Missing or invalid file yields [].
*/
async function listGoalRuns(config, sessionKey, opts) {
	const limit = Math.min(500, Math.max(1, Math.floor(opts?.limit ?? 50)));
	const filePath = resolveGoalRunsFilePath(config, sessionKey);
	let raw;
	try {
		raw = await readFile(filePath, "utf8");
	} catch (err) {
		if ((err && typeof err === "object" && "code" in err ? String(err.code) : "") === "ENOENT") return [];
		log.debug({
			err,
			sessionKey,
			filePath
		}, `Goal run list read failed: ${err instanceof Error ? err.message : String(err)}`);
		return [];
	}
	const parsed = parseGoalRunFile(raw);
	if (!parsed || parsed.sessionKey !== sessionKey) return [];
	return [...parsed.runs].reverse().slice(0, limit);
}
//#endregion
export { appendGoalRun, listGoalRuns, resolveGoalRunsFilePath };

//# sourceMappingURL=goal-run-store.js.map