import { commandRegistry } from "../registry.js";
import { PERSISTENT_GOAL_CUSTOM_KEY, defaultMaxTurns, mergeCustomDataPatch, readPersistentGoal, serializePersistentGoal } from "../../agent/goals/state.js";
import { applyPersistentGoalUserAction } from "../../agent/goals/patch-from-user-action.js";
//#region src/chat-commands/builtins/goal.ts
function statusLine(state) {
	const turns = `${state.turnsUsed}/${state.maxTurns} turns`;
	if (state.status === "active") return `⊙ Goal (active, ${turns}): ${state.goal}`;
	if (state.status === "paused") return `⏸ Goal (paused, ${turns}${state.pausedReason ? ` — ${state.pausedReason}` : ""}): ${state.goal}`;
	if (state.status === "done") return `✓ Goal done (${turns}): ${state.goal}`;
	return `Goal (${state.status}, ${turns}): ${state.goal}`;
}
async function patchGoalMetadata(ctx, patchCustom) {
	const apis = ctx.persistentGoalApis;
	if (!apis) return {
		ok: false,
		error: "Goals unavailable on this surface."
	};
	const meta = await apis.getSessionMetadata(ctx.sessionKey);
	if (!meta) return {
		ok: false,
		error: "Session not found"
	};
	const customData = patchCustom({ ...meta.customData });
	await apis.updateSessionMetadata(ctx.sessionKey, { customData });
	return { ok: true };
}
const goalCommand = {
	id: "system.goal",
	name: "goal",
	description: "Set or manage a standing goal (Hermes-style): checklist + judge loop; /subgoal edits criteria; pause, resume, clear",
	category: "system",
	scope: [
		"global",
		"private",
		"group"
	],
	acceptsArgs: true,
	examples: [
		"/goal Ship the fix",
		"/goal status",
		"/goal pause",
		"/goal resume",
		"/goal clear"
	],
	handler: async (ctx, args) => {
		const apis = ctx.persistentGoalApis;
		if (!apis) return {
			content: "Goals unavailable on this surface.",
			success: false
		};
		const t = args.trim();
		const lower = t.toLowerCase();
		if (!t || lower === "status") {
			const s = readPersistentGoal((await apis.getSessionMetadata(ctx.sessionKey))?.customData);
			if (!s || s.status === "cleared") return {
				content: "No active goal. Set one with /goal <text>.",
				success: true
			};
			return {
				content: statusLine(s),
				success: true
			};
		}
		if (lower === "pause") {
			const applied = applyPersistentGoalUserAction((await apis.getSessionMetadata(ctx.sessionKey))?.customData, "pause");
			if (applied.kind === "error") return {
				content: applied.error,
				success: false
			};
			if (applied.kind === "noop") return {
				content: applied.message,
				success: true
			};
			const r = await patchGoalMetadata(ctx, () => applied.customData);
			if (!r.ok) return {
				content: "error" in r ? r.error : "Failed",
				success: false
			};
			return {
				content: `⏸ Goal paused: ${readPersistentGoal(applied.customData)?.goal ?? ""}`,
				success: true
			};
		}
		if (lower === "resume") {
			const applied = applyPersistentGoalUserAction((await apis.getSessionMetadata(ctx.sessionKey))?.customData, "resume");
			if (applied.kind === "error") return {
				content: applied.error,
				success: false
			};
			if (applied.kind === "noop") return {
				content: applied.message,
				success: true
			};
			const r = await patchGoalMetadata(ctx, () => applied.customData);
			if (!r.ok) return {
				content: "error" in r ? r.error : "Failed",
				success: false
			};
			return {
				content: `▶ Goal resumed: ${readPersistentGoal(applied.customData)?.goal ?? ""}\nSend any message to continue, or wait — the next assistant turn will pick up from here.`,
				success: true
			};
		}
		if (lower === "clear" || lower === "stop" || lower === "done") {
			const meta = await apis.getSessionMetadata(ctx.sessionKey);
			const had = !!readPersistentGoal(meta?.customData);
			const applied = applyPersistentGoalUserAction(meta?.customData, "clear");
			if (applied.kind === "error") return {
				content: applied.error,
				success: false
			};
			if (applied.kind === "noop") return {
				content: applied.message,
				success: true
			};
			const r = await patchGoalMetadata(ctx, () => applied.customData);
			if (!r.ok) return {
				content: "error" in r ? r.error : "Failed",
				success: false
			};
			return {
				content: had ? "✓ Goal cleared." : "No active goal.",
				success: true
			};
		}
		if (apis.inboundConcurrentDepth(ctx.sessionKey) > 1) return {
			content: "Agent is running — use /goal status / pause / clear mid-run, or wait for the current turn to finish before setting a new goal.",
			success: false
		};
		const maxTurns = defaultMaxTurns(ctx.config.goals);
		const judgeModelRef = typeof ctx.config.goals?.judgeModelRef === "string" ? ctx.config.goals.judgeModelRef.trim() : void 0;
		const next = {
			goal: t,
			status: "active",
			turnsUsed: 0,
			maxTurns,
			createdAt: Date.now(),
			lastTurnAt: 0,
			decomposed: false,
			consecutiveParseFailures: 0,
			...judgeModelRef ? { judgeModelRef } : {}
		};
		const r = await patchGoalMetadata(ctx, (base) => mergeCustomDataPatch(base, { [PERSISTENT_GOAL_CUSTOM_KEY]: serializePersistentGoal(next) }));
		if (!r.ok) return {
			content: "error" in r ? r.error : "Failed",
			success: false
		};
		apis.scheduleContinuation(ctx.sessionKey, next.goal);
		return {
			content: `⊙ Goal set (${next.maxTurns}-turn budget): ${next.goal}\nI'll keep working until the goal is done, you pause/clear it, or the budget is exhausted.
Controls: /goal status · /goal pause · /goal resume · /goal clear · /subgoal`,
			success: true
		};
	}
};
function registerGoalCommand() {
	commandRegistry.register(goalCommand);
}
//#endregion
export { registerGoalCommand };

//# sourceMappingURL=goal.js.map