import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
import { join } from "node:path";
//#region extensions/crypto/src/services/evolution-mode.ts
/**
* Evolution Mode Service — stable vs evolving agent behavior.
*
* Two modes:
*   stable   — default. The agent uses only static skills and does not
*              modify any learned knowledge. Memory and skill tools are
*              registered but return "disabled in stable mode" errors.
*   evolving — full self-improvement. Memory writes, skill creation,
*              skill patching, session recall, and periodic nudges.
*
* The mode is per-user and persisted to disk. A global default can be
* set via OPENCLAWNCH_EVOLUTION_MODE env var.
*
* Nudge system:
*   Every N turns, inject a system message reminder about:
*   - Persisting important discoveries to agent memory
*   - Creating skills from complex workflows
*   The nudge intervals are configurable via env vars.
*/
const MEMORY_NUDGE = `[Self-improvement reminder] If you discovered something useful in this conversation — a tool quirk, an environment fact, a user preference, or a lesson learned — save it to agent memory with the agent_memory tool (action: "add") so you remember it next time.`;
const SKILL_NUDGE = `[Self-improvement reminder] If you just completed a complex multi-step workflow (5+ tool calls), fixed a tricky error, or discovered a non-trivial DeFi strategy, consider saving it as a learned skill with the skill_evolve tool (action: "create") so you can reuse it efficiently next time.`;
var EvolutionModeService = class {
	config;
	users = /* @__PURE__ */ new Map();
	constructor(config = {}) {
		const envDefault = process.env.OPENCLAWNCH_EVOLUTION_MODE;
		this.config = {
			defaultMode: config.defaultMode ?? envDefault ?? "stable",
			memoryNudgeInterval: config.memoryNudgeInterval ?? (parseInt(process.env.OPENCLAWNCH_MEMORY_NUDGE_INTERVAL ?? "", 10) || 10),
			skillNudgeInterval: config.skillNudgeInterval ?? (parseInt(process.env.OPENCLAWNCH_SKILL_NUDGE_INTERVAL ?? "", 10) || 15),
			minTurnsBeforeNudge: config.minTurnsBeforeNudge ?? 5
		};
	}
	getMode(userId) {
		return this.getState(userId).mode;
	}
	setMode(userId, mode) {
		const state = this.getState(userId);
		state.mode = mode;
		state.turnCount = 0;
		state.lastMemoryNudgeTurn = 0;
		state.lastSkillNudgeTurn = 0;
		this.persistState(userId, state);
	}
	isEvolving(userId) {
		return this.getMode(userId) === "evolving";
	}
	/**
	* Record a turn and return any nudge messages that should be injected.
	* Call this from after_tool_call or message_received.
	* Returns null if no nudge is needed.
	*/
	recordTurn(userId) {
		const state = this.getState(userId);
		if (state.mode !== "evolving") return null;
		state.turnCount++;
		if (state.turnCount < this.config.minTurnsBeforeNudge) return null;
		if (state.turnCount - state.lastMemoryNudgeTurn >= this.config.memoryNudgeInterval) {
			state.lastMemoryNudgeTurn = state.turnCount;
			return MEMORY_NUDGE;
		}
		if (state.turnCount - state.lastSkillNudgeTurn >= this.config.skillNudgeInterval) {
			state.lastSkillNudgeTurn = state.turnCount;
			return SKILL_NUDGE;
		}
		return null;
	}
	/**
	* Get the current turn count for a user.
	*/
	getTurnCount(userId) {
		return this.getState(userId).turnCount;
	}
	getState(userId) {
		let state = this.users.get(userId);
		if (!state) {
			state = this.loadState(userId);
			this.users.set(userId, state);
		}
		return state;
	}
	getStateDir() {
		return join(process.env.HOME ?? "/tmp", ".openclawnch", "evolution");
	}
	getStatePath(userId) {
		const safeId = userId.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 64);
		return join(this.getStateDir(), `${safeId}.json`);
	}
	loadState(userId) {
		try {
			const filePath = this.getStatePath(userId);
			if (existsSync(filePath)) return {
				mode: JSON.parse(readFileSync(filePath, "utf8")).mode === "evolving" ? "evolving" : "stable",
				turnCount: 0,
				lastMemoryNudgeTurn: 0,
				lastSkillNudgeTurn: 0
			};
		} catch {}
		return {
			mode: this.config.defaultMode,
			turnCount: 0,
			lastMemoryNudgeTurn: 0,
			lastSkillNudgeTurn: 0
		};
	}
	persistState(userId, state) {
		try {
			const dir = this.getStateDir();
			if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
			writeFileSync(this.getStatePath(userId), JSON.stringify({ mode: state.mode }, null, 2), "utf8");
		} catch {}
	}
	getStatus() {
		return {
			defaultMode: this.config.defaultMode,
			memoryNudgeInterval: this.config.memoryNudgeInterval,
			skillNudgeInterval: this.config.skillNudgeInterval,
			trackedUsers: this.users.size,
			config: this.config
		};
	}
};
let _instance = null;
function getEvolutionMode(config) {
	if (!_instance) _instance = new EvolutionModeService(config);
	return _instance;
}
function resetEvolutionMode() {
	_instance = null;
}
//#endregion
export { getEvolutionMode, resetEvolutionMode };

//# sourceMappingURL=evolution-mode.mjs.map