import { c as stringEnum, i as jsonResult, r as errorResult, u as Type } from "../../tool-helpers-CVAcqiCy.mjs";
import { CATEGORY_LABELS, TOOL_CATEGORIES } from "../services/policy-types.mjs";
import { getPolicyStore } from "../services/policy-store.mjs";
import { buildPolicyDisplay, evaluatePolicies, extractPolicyUserId, renderPolicyDisplay } from "../services/policy-evaluator.mjs";
import { randomUUID } from "node:crypto";
//#region extensions/crypto/src/tools/policy-manage.ts
/**
* policy_manage — LLM-facing tool for creating and managing spending policies.
*
* Creation flow (multi-turn with explicit confirmation):
* 1. User says something like "don't spend more than $500/day on swaps"
* 2. LLM calls `propose` with structured interpretation
* 3. Tool saves as DRAFT and returns the exact rules for user to verify
* 4. User says "yes" / adjusts → LLM calls `confirm` to activate
*
* The LLM MUST NOT call `confirm` without the user explicitly approving.
* If the user's intent is ambiguous, the LLM should ask follow-up questions
* BEFORE calling `propose`.
*/
const PolicyManageSchema = Type.Object({
	action: stringEnum([
		"propose",
		"confirm",
		"revise",
		"list",
		"get",
		"disable",
		"enable",
		"delete",
		"evaluate",
		"usage",
		"categories"
	], { description: "Action to perform. IMPORTANT: \"propose\" creates a DRAFT — you MUST show the user the exact rules and get explicit approval before calling \"confirm\"." }),
	name: Type.Optional(Type.String({ description: "Short policy name (e.g., \"daily DeFi limit\")" })),
	description: Type.Optional(Type.String({ description: "The user's EXACT original words that define this policy. Do not paraphrase." })),
	rules: Type.Optional(Type.Array(Type.Object({
		type: stringEnum([
			"spending_limit",
			"rate_limit",
			"allowlist",
			"blocklist",
			"time_window",
			"approval_threshold",
			"max_amount"
		], { description: "Rule type" }),
		maxAmountUsd: Type.Optional(Type.Number({ description: "USD limit (spending_limit, max_amount)" })),
		period: Type.Optional(stringEnum([
			"hourly",
			"daily",
			"weekly",
			"monthly"
		], { description: "Period (spending_limit)" })),
		maxCalls: Type.Optional(Type.Number({ description: "Max calls (rate_limit)" })),
		periodMs: Type.Optional(Type.Number({ description: "Window in ms (rate_limit)" })),
		field: Type.Optional(stringEnum([
			"tokens",
			"chains",
			"addresses",
			"contracts"
		], { description: "Field (allowlist, blocklist)" })),
		values: Type.Optional(Type.Array(Type.String(), { description: "Values (allowlist, blocklist)" })),
		allowedHours: Type.Optional(Type.Object({
			start: Type.Number({ description: "Start hour 0-23" }),
			end: Type.Number({ description: "End hour 0-23" })
		})),
		allowedDays: Type.Optional(Type.Array(Type.Number(), { description: "Days 0=Sun..6=Sat" })),
		timezone: Type.Optional(Type.String({ description: "IANA timezone" })),
		amountUsd: Type.Optional(Type.Number({ description: "USD threshold (approval_threshold)" }))
	}), { description: "Policy rules. Each is independently evaluated." })),
	scope: Type.Optional(Type.Object({
		type: stringEnum([
			"all_write",
			"tools",
			"categories"
		], { description: "Scope type" }),
		tools: Type.Optional(Type.Array(Type.String(), { description: "Tool names (scope=tools)" })),
		categories: Type.Optional(Type.Array(Type.String(), { description: "Category names (scope=categories)" }))
	})),
	policyId: Type.Optional(Type.String({ description: "Policy ID" })),
	toolName: Type.Optional(Type.String({ description: "Tool to check (evaluate)" })),
	amountUsd: Type.Optional(Type.Number({ description: "USD amount to check (evaluate)" })),
	token: Type.Optional(Type.String({ description: "Token to check (evaluate)" }))
});
function createPolicyManageTool() {
	return {
		name: "policy_manage",
		label: "Policy Manager",
		ownerOnly: true,
		description: [
			"Create and manage spending policies that limit what the agent can do autonomously.",
			"",
			"CRITICAL WORKFLOW for creating policies:",
			"1. If the user's request is ambiguous, ASK CLARIFYING QUESTIONS first.",
			"2. Call \"propose\" with your structured interpretation — this creates a DRAFT.",
			"3. Show the user EXACTLY what will be enforced (the tool returns this).",
			"4. WAIT for the user to explicitly approve.",
			"5. Only then call \"confirm\" to activate.",
			"",
			"NEVER skip step 3-4. NEVER call \"confirm\" without user approval.",
			"NEVER guess what the user means — ask if unclear.",
			"",
			"Actions: propose, confirm, revise, list, get, disable, enable, delete, evaluate, usage, categories"
		].join("\n"),
		parameters: PolicyManageSchema,
		execute: async (_toolCallId, args, ctx) => {
			const params = args;
			const action = params.action;
			const userId = extractPolicyUserId(ctx);
			switch (action) {
				case "propose": return handlePropose(params, userId);
				case "confirm": return handleConfirm(params, userId);
				case "revise": return handleRevise(params, userId);
				case "list": return handleList(userId);
				case "get": return handleGet(params, userId);
				case "disable": return handleDisable(params, userId);
				case "enable": return handleEnable(params, userId);
				case "delete": return handleDelete(params, userId);
				case "evaluate": return handleEvaluate(params, userId);
				case "usage": return handleUsage(params, userId);
				case "categories": return handleCategories();
				default: return errorResult(`Unknown action: ${action}`);
			}
		}
	};
}
function handlePropose(params, userId) {
	const name = params.name;
	const description = params.description;
	const rawRules = params.rules;
	const rawScope = params.scope;
	if (!name) return errorResult("Policy name is required.");
	if (!description) return errorResult("Description is required — use the user's exact words.");
	if (!rawRules || rawRules.length === 0) return errorResult("At least one rule is required.");
	if (!rawScope) return errorResult("Scope is required (all_write, tools, or categories).");
	const store = getPolicyStore();
	const existing = store.getPolicyByName(userId, name);
	if (existing) return errorResult(`A policy named "${name}" already exists (id: ${existing.id}).`);
	let rules;
	try {
		rules = rawRules.map(parseRule);
	} catch (err) {
		return errorResult(`Invalid rule: ${err instanceof Error ? err.message : String(err)}`);
	}
	const scope = parseScope(rawScope);
	const policy = {
		id: randomUUID(),
		name,
		description,
		rules,
		scope,
		status: "draft",
		createdAt: Date.now(),
		updatedAt: Date.now(),
		userId
	};
	try {
		store.savePolicy(policy);
	} catch (err) {
		return errorResult(err instanceof Error ? err.message : String(err));
	}
	const rendered = renderPolicyDisplay(buildPolicyDisplay(policy, userId));
	return jsonResult({
		status: "draft_created",
		policyId: policy.id,
		message: [
			"DRAFT policy created. Show the user this exact interpretation and ask them to confirm:",
			"",
			rendered,
			"",
			"Ask the user: \"Does this match what you want? Say yes to activate, or tell me what to change.\"",
			"Call \"confirm\" ONLY after the user explicitly approves."
		].join("\n")
	});
}
function handleConfirm(params, userId) {
	const policyId = params.policyId;
	if (!policyId) return errorResult("policyId is required.");
	const store = getPolicyStore();
	const policy = store.getPolicy(userId, policyId);
	if (!policy) return errorResult(`Policy ${policyId} not found.`);
	if (policy.status === "active") return errorResult("Policy is already active.");
	policy.status = "active";
	policy.confirmedAt = Date.now();
	policy.updatedAt = Date.now();
	store.savePolicy(policy);
	const rendered = renderPolicyDisplay(buildPolicyDisplay(policy, userId));
	return jsonResult({
		status: "activated",
		policyId: policy.id,
		message: `Policy "${policy.name}" is now ACTIVE.\n\n${rendered}`
	});
}
function handleRevise(params, userId) {
	const policyId = params.policyId;
	if (!policyId) return errorResult("policyId is required.");
	const store = getPolicyStore();
	const policy = store.getPolicy(userId, policyId);
	if (!policy) return errorResult(`Policy ${policyId} not found.`);
	if (policy.status === "active") return errorResult("Cannot revise an active policy. Disable it first, or delete and re-propose.");
	if (params.name) {
		const newName = params.name;
		const dup = store.getPolicyByName(userId, newName);
		if (dup && dup.id !== policy.id) return errorResult(`A policy named "${newName}" already exists (id: ${dup.id}).`);
		policy.name = newName;
	}
	if (params.description) policy.description = params.description;
	if (params.rules && Array.isArray(params.rules) && params.rules.length > 0) try {
		policy.rules = params.rules.map(parseRule);
	} catch (err) {
		return errorResult(`Invalid rule: ${err instanceof Error ? err.message : String(err)}`);
	}
	if (params.scope) policy.scope = parseScope(params.scope);
	policy.updatedAt = Date.now();
	store.savePolicy(policy);
	const rendered = renderPolicyDisplay(buildPolicyDisplay(policy, userId));
	return jsonResult({
		status: "draft_revised",
		policyId: policy.id,
		message: [
			"Draft revised. Show the user this updated interpretation:",
			"",
			rendered,
			"",
			"Ask: \"Does this look right now?\""
		].join("\n")
	});
}
function handleList(userId) {
	const policies = getPolicyStore().listPolicies(userId);
	if (policies.length === 0) return jsonResult({
		policies: [],
		message: "No policies set. The user can say something like \"don't let me spend more than $500 a day\" to create one."
	});
	const summaries = policies.map((p) => {
		return renderPolicyDisplay(buildPolicyDisplay(p, userId));
	});
	return jsonResult({
		count: policies.length,
		policies: policies.map((p) => ({
			id: p.id,
			name: p.name,
			status: p.status,
			ruleCount: p.rules.length
		})),
		rendered: summaries.join("\n\n---\n\n")
	});
}
function handleGet(params, userId) {
	const policyId = params.policyId;
	if (!policyId) return errorResult("policyId is required.");
	const policy = getPolicyStore().getPolicy(userId, policyId);
	if (!policy) return errorResult(`Policy ${policyId} not found.`);
	const display = buildPolicyDisplay(policy, userId);
	return jsonResult({
		policy: {
			id: policy.id,
			name: policy.name,
			status: policy.status,
			description: policy.description,
			rules: policy.rules,
			scope: policy.scope,
			createdAt: new Date(policy.createdAt).toISOString(),
			updatedAt: new Date(policy.updatedAt).toISOString()
		},
		rendered: renderPolicyDisplay(display)
	});
}
function handleDisable(params, userId) {
	const policyId = params.policyId;
	if (!policyId) return errorResult("policyId is required.");
	const store = getPolicyStore();
	const policy = store.getPolicy(userId, policyId);
	if (!policy) return errorResult(`Policy ${policyId} not found.`);
	policy.status = "disabled";
	policy.updatedAt = Date.now();
	store.savePolicy(policy);
	return jsonResult({
		status: "disabled",
		message: `Policy "${policy.name}" is now disabled. It will not be enforced until re-enabled.`
	});
}
function handleEnable(params, userId) {
	const policyId = params.policyId;
	if (!policyId) return errorResult("policyId is required.");
	const store = getPolicyStore();
	const policy = store.getPolicy(userId, policyId);
	if (!policy) return errorResult(`Policy ${policyId} not found.`);
	policy.status = "active";
	policy.updatedAt = Date.now();
	store.savePolicy(policy);
	return jsonResult({
		status: "active",
		message: `Policy "${policy.name}" is now active and being enforced.`
	});
}
function handleDelete(params, userId) {
	const policyId = params.policyId;
	if (!policyId) return errorResult("policyId is required.");
	const store = getPolicyStore();
	const policy = store.getPolicy(userId, policyId);
	if (!policy) return errorResult(`Policy ${policyId} not found.`);
	store.deletePolicy(userId, policyId);
	return jsonResult({
		status: "deleted",
		message: `Policy "${policy.name}" has been deleted.`
	});
}
function handleEvaluate(params, userId) {
	const toolName = params.toolName;
	if (!toolName) return errorResult("toolName is required for evaluate.");
	const decision = evaluatePolicies({
		toolName,
		userId,
		amountUsd: params.amountUsd,
		token: params.token
	});
	return jsonResult({
		decision: decision.action,
		reason: decision.reason ?? "No policy violations.",
		policyName: decision.policyName,
		ruleSummary: decision.ruleSummary
	});
}
function handleUsage(params, userId) {
	const policyId = params.policyId;
	if (!policyId) return errorResult("policyId is required.");
	const store = getPolicyStore();
	const policy = store.getPolicy(userId, policyId);
	if (!policy) return errorResult(`Policy ${policyId} not found.`);
	const usage = store.getUsage(userId, policyId);
	const display = buildPolicyDisplay(policy, userId);
	return jsonResult({
		policyName: policy.name,
		usageSummary: display.usageSummary ?? "No usage tracked (no spending/rate limits).",
		recentEntries: (usage?.entries ?? []).slice(-20).map((e) => ({
			time: new Date(e.timestamp).toISOString(),
			tool: e.toolName,
			action: e.action,
			amountUsd: e.amountUsd
		}))
	});
}
function handleCategories() {
	return jsonResult({
		categories: Object.entries(CATEGORY_LABELS).map(([key, label]) => ({
			key,
			label,
			tools: TOOL_CATEGORIES[key] ?? []
		})),
		message: "Available tool categories for policy scopes. Use category keys in scope.categories."
	});
}
/**
* Parse and validate a raw rule from the LLM.
* Throws on missing required fields or unknown types instead of silently
* defaulting (which could create zero-limit policies that block everything
* or miss enforcement entirely).
*/
function parseRule(raw) {
	const type = raw.type;
	switch (type) {
		case "spending_limit": {
			if (raw.maxAmountUsd == null || typeof raw.maxAmountUsd !== "number") throw new Error("spending_limit rule requires maxAmountUsd (number).");
			if (raw.period == null) throw new Error("spending_limit rule requires period (hourly|daily|weekly|monthly).");
			const validPeriods = [
				"hourly",
				"daily",
				"weekly",
				"monthly"
			];
			if (!validPeriods.includes(raw.period)) throw new Error(`spending_limit period must be one of: ${validPeriods.join(", ")}. Got: "${raw.period}".`);
			return {
				type: "spending_limit",
				maxAmountUsd: raw.maxAmountUsd,
				period: raw.period
			};
		}
		case "rate_limit":
			if (raw.maxCalls == null || typeof raw.maxCalls !== "number") throw new Error("rate_limit rule requires maxCalls (number).");
			if (raw.periodMs == null || typeof raw.periodMs !== "number") throw new Error("rate_limit rule requires periodMs (number, milliseconds).");
			return {
				type: "rate_limit",
				maxCalls: raw.maxCalls,
				periodMs: raw.periodMs
			};
		case "allowlist":
			if (!raw.field) throw new Error("allowlist rule requires field (tokens|chains|addresses|contracts).");
			if (!raw.values || !Array.isArray(raw.values) || raw.values.length === 0) throw new Error("allowlist rule requires values (non-empty array).");
			return {
				type: "allowlist",
				field: raw.field,
				values: raw.values.map((v) => v.toLowerCase())
			};
		case "blocklist":
			if (!raw.field) throw new Error("blocklist rule requires field (tokens|chains|addresses|contracts).");
			if (!raw.values || !Array.isArray(raw.values) || raw.values.length === 0) throw new Error("blocklist rule requires values (non-empty array).");
			return {
				type: "blocklist",
				field: raw.field,
				values: raw.values.map((v) => v.toLowerCase())
			};
		case "time_window":
			if (raw.allowedHours) {
				const { start, end } = raw.allowedHours;
				if (typeof start !== "number" || typeof end !== "number" || start < 0 || start > 23 || end < 0 || end > 23) throw new Error("time_window allowedHours start/end must be 0-23.");
			}
			if (raw.allowedDays && Array.isArray(raw.allowedDays)) {
				for (const d of raw.allowedDays) if (typeof d !== "number" || d < 0 || d > 6) throw new Error("time_window allowedDays must be numbers 0 (Sun) - 6 (Sat).");
			}
			if (!raw.allowedHours && !raw.allowedDays) throw new Error("time_window rule requires at least allowedHours or allowedDays.");
			return {
				type: "time_window",
				allowedHours: raw.allowedHours,
				allowedDays: raw.allowedDays,
				timezone: raw.timezone
			};
		case "approval_threshold":
			if (raw.amountUsd == null || typeof raw.amountUsd !== "number") throw new Error("approval_threshold rule requires amountUsd (number).");
			return {
				type: "approval_threshold",
				amountUsd: raw.amountUsd
			};
		case "max_amount":
			if (raw.maxAmountUsd == null || typeof raw.maxAmountUsd !== "number") throw new Error("max_amount rule requires maxAmountUsd (number).");
			return {
				type: "max_amount",
				maxAmountUsd: raw.maxAmountUsd
			};
		default: throw new Error(`Unknown rule type: "${type}". Valid types: spending_limit, rate_limit, allowlist, blocklist, time_window, approval_threshold, max_amount.`);
	}
}
function parseScope(raw) {
	return {
		type: raw.type ?? "all_write",
		tools: raw.tools,
		categories: raw.categories
	};
}
//#endregion
export { createPolicyManageTool };

//# sourceMappingURL=policy-manage.mjs.map