import { c as stringEnum, i as jsonResult, r as errorResult, s as readStringParam, u as Type } from "../../tool-helpers-CVAcqiCy.mjs";
import { getWalletState } from "../services/walletconnect-service.mjs";
import { getCredentialVault } from "../services/credential-vault.mjs";
import { guardedFetch } from "../services/endpoint-allowlist.mjs";
import { checkToolConfig } from "../services/tool-config-service.mjs";
//#region extensions/crypto/src/tools/molten.ts
/**
* Molten Tool — Intent resolution layer for AI agents via api.molten.gg
*
* Three interaction modes:
*   1. Conversations (guided) — describe what you need, Molten's concierge guides you
*   2. Direct search — programmatic capability search with optional auto-execute
*   3. Intents (async) — post offers/requests, ClawRank matches across the network
*
* Plus: matches, messaging, events, profile management, capability browsing.
*
* API docs: https://molten.gg/skill.md
* Base URL: https://api.molten.gg/api/v1
*
* Requires MOLTEN_API_KEY for authenticated operations.
* Use the `register` action first to get an API key.
*/
const MOLTEN_BASE_URL = "https://api.molten.gg/api/v1";
function getBaseUrl() {
	return process.env.MOLTEN_BASE_URL || MOLTEN_BASE_URL;
}
function getMoltenApiKey() {
	return getCredentialVault().getSecret("bot.molten.apiKey", "molten") ?? _inMemoryApiKey ?? void 0;
}
let _inMemoryApiKey;
function setMoltenApiKey(apiKey) {
	_inMemoryApiKey = apiKey;
}
async function moltenFetch(method, path, body, requireAuth = true) {
	const url = `${getBaseUrl()}${path}`;
	const headers = {
		"Content-Type": "application/json",
		"Accept": "application/json",
		"X-Client-Type": "openclaw"
	};
	if (requireAuth) {
		const apiKey = getMoltenApiKey();
		if (!apiKey) throw new MoltenApiError(401, "No API key set");
		headers["Authorization"] = `Bearer ${apiKey}`;
	}
	const response = await guardedFetch(url, {
		method,
		headers,
		...body ? { body: JSON.stringify(body) } : {},
		signal: AbortSignal.timeout(3e4)
	});
	const data = await response.json().catch(() => ({}));
	if (!response.ok) {
		const errMsg = data?.error?.message || data?.message || response.statusText;
		const errCode = data?.error?.code || void 0;
		throw new MoltenApiError(response.status, errMsg, errCode);
	}
	return data;
}
var MoltenApiError = class extends Error {
	status;
	code;
	constructor(status, message, code) {
		super(message);
		this.name = "MoltenApiError";
		this.status = status;
		this.code = code;
	}
};
const MoltenSchema = Type.Object({
	action: stringEnum([
		"register",
		"profile",
		"update_profile",
		"claim_status",
		"conversation",
		"conversation_reply",
		"conversation_status",
		"list_conversations",
		"search",
		"browse",
		"capability_details",
		"create_intent",
		"list_intents",
		"cancel_intent",
		"list_matches",
		"accept_match",
		"reject_match",
		"complete_match",
		"match_message",
		"check_events",
		"ack_events",
		"setup_webhook"
	], { description: "register: register agent (returns API key). profile: get your profile. update_profile: update info. conversation: start guided conversation. conversation_reply: reply to conversation. search: direct capability search. browse: list all capabilities (no auth). create_intent: post async offer/request. list_intents: your intents. cancel_intent: cancel. list_matches: browse matches. accept_match/reject_match/complete_match: manage matches. match_message: message a match. check_events: poll events. ack_events: acknowledge." }),
	name: Type.Optional(Type.String({ description: "Agent name (lowercase, 2-64 chars)" })),
	description: Type.Optional(Type.String({ description: "Agent/intent description (up to 500 chars)" })),
	client_type: Type.Optional(Type.String({ description: "Client type: \"openclaw\", \"conway\", or \"generic\" (default: openclaw)" })),
	wallet_address: Type.Optional(Type.String({ description: "EVM wallet address (0x...)" })),
	twitter_handle: Type.Optional(Type.String({ description: "X/Twitter handle" })),
	message: Type.Optional(Type.String({ description: "Message for conversation/reply/match_message" })),
	session_id: Type.Optional(Type.String({ description: "Conversation session ID (for replies)" })),
	confirm: Type.Optional(Type.Boolean({ description: "Confirm execution in conversation" })),
	cancel: Type.Optional(Type.Boolean({ description: "Cancel current conversation flow" })),
	selection: Type.Optional(Type.Number({ description: "Select a match by index (1-based) in conversation" })),
	query: Type.Optional(Type.String({ description: "Natural language search query" })),
	category: Type.Optional(Type.String({ description: "Category filter for search/intents" })),
	auto_execute: Type.Optional(Type.Boolean({ description: "Auto-execute top search result (default: false)" })),
	intent_type: Type.Optional(stringEnum(["offer", "request"], { description: "\"offer\" or \"request\"" })),
	attributes: Type.Optional(Type.String({ description: "JSON attributes for intent" })),
	expires_at: Type.Optional(Type.String({ description: "Expiration timestamp (ISO 8601)" })),
	min_match_score: Type.Optional(Type.Number({ description: "Minimum ClawRank score for matches (0-100)" })),
	auto_accept: Type.Optional(Type.Boolean({ description: "Auto-accept matches above min score" })),
	intent_id: Type.Optional(Type.String({ description: "Intent ID" })),
	match_id: Type.Optional(Type.String({ description: "Match ID" })),
	plugin_id: Type.Optional(Type.String({ description: "Capability/plugin ID for details" })),
	event_ids: Type.Optional(Type.String({ description: "Comma-separated event IDs to acknowledge" })),
	webhook_url: Type.Optional(Type.String({ description: "Webhook URL for notifications" })),
	webhook_events: Type.Optional(Type.String({ description: "Comma-separated webhook event types" }))
});
function createMoltenTool() {
	return {
		name: "molten",
		label: "Molten",
		ownerOnly: true,
		description: "Intent resolution layer for AI agents on molten.gg. Start conversations to find capabilities, search the network, post offers/requests, and match with other agents. Use \"browse\" to see available capabilities (no auth needed). Use \"conversation\" for guided discovery. Use \"search\" for direct programmatic lookups.",
		parameters: MoltenSchema,
		execute: async (_toolCallId, args) => {
			const p = args;
			const action = readStringParam(p, "action", { required: true });
			if (![
				"browse",
				"capability_details",
				"register"
			].includes(action)) {
				const notReady = checkToolConfig("molten");
				if (notReady) return notReady;
			}
			try {
				switch (action) {
					case "register": {
						const name = readStringParam(p, "name", { required: true });
						const description = readStringParam(p, "description") || "OpenClawnch DeFi agent";
						const clientType = readStringParam(p, "client_type") || "openclaw";
						const twitterHandle = readStringParam(p, "twitter_handle");
						let walletAddress = readStringParam(p, "wallet_address");
						if (!walletAddress) {
							const walletState = getWalletState();
							if (walletState.connected && walletState.address) walletAddress = walletState.address;
						}
						if (!walletAddress) return errorResult("wallet_address is required for registration. Connect a wallet first (/connect) or provide wallet_address explicitly.");
						const body = {
							name,
							client_type: clientType,
							wallet_address: walletAddress,
							description
						};
						if (twitterHandle) body.twitter_handle = twitterHandle;
						const result = await moltenFetch("POST", "/agents/register", body, false);
						if (result?.agent?.api_key) setMoltenApiKey(result.agent.api_key);
						const maskedKey = result?.agent?.api_key ? `${result.agent.api_key.slice(0, 8)}...${result.agent.api_key.slice(-4)}` : void 0;
						const { api_key: _stripped, ...safeResult } = result?.agent ?? {};
						return jsonResult({
							...result,
							agent: safeResult,
							setup: maskedKey ? `API key active (${maskedKey}). To persist, use /flykeys set MOLTEN_API_KEY with the full key shown during registration.` : void 0,
							claim: result?.agent?.claim_url ? `Claim your agent: ${result.agent.claim_url}` : void 0
						});
					}
					case "profile": return jsonResult(await moltenFetch("GET", "/agents/me"));
					case "update_profile": {
						const body = {};
						const description = readStringParam(p, "description");
						const twitterHandle = readStringParam(p, "twitter_handle");
						if (description) body.description = description;
						if (twitterHandle) body.twitter_handle = twitterHandle;
						return jsonResult(await moltenFetch("PATCH", "/agents/me", body));
					}
					case "claim_status": return jsonResult(await moltenFetch("GET", "/agents/status"));
					case "conversation": return jsonResult(await moltenFetch("POST", "/conversations", { message: readStringParam(p, "message", { required: true }) }));
					case "conversation_reply": {
						const sessionId = readStringParam(p, "session_id", { required: true });
						const body = { message: readStringParam(p, "message") || "" };
						if (p.confirm === true) body.confirm = true;
						if (p.cancel === true) body.cancel = true;
						if (p.selection !== void 0) body.selection = p.selection;
						return jsonResult(await moltenFetch("POST", `/conversations/${sessionId}/message`, body));
					}
					case "conversation_status": return jsonResult(await moltenFetch("GET", `/conversations/${readStringParam(p, "session_id", { required: true })}`));
					case "list_conversations": return jsonResult(await moltenFetch("GET", "/conversations"));
					case "search": {
						const body = { query: readStringParam(p, "query", { required: true }) };
						const category = readStringParam(p, "category");
						if (category) body.category = category;
						if (p.auto_execute === true) body.autoExecute = true;
						return jsonResult(await moltenFetch("POST", "/search", body));
					}
					case "browse": return jsonResult(await moltenFetch("GET", "/plugins", void 0, false));
					case "capability_details": return jsonResult(await moltenFetch("GET", `/plugins/${readStringParam(p, "plugin_id", { required: true })}`, void 0, false));
					case "create_intent": {
						const intentType = readStringParam(p, "intent_type", { required: true });
						const description = readStringParam(p, "description", { required: true });
						const category = readStringParam(p, "category");
						const attributesStr = readStringParam(p, "attributes");
						const expiresAt = readStringParam(p, "expires_at");
						const minMatchScore = p.min_match_score;
						const autoAccept = p.auto_accept;
						let attributes;
						if (attributesStr) try {
							attributes = JSON.parse(attributesStr);
						} catch {
							return errorResult("attributes must be valid JSON");
						}
						const body = {
							type: intentType,
							description
						};
						if (category) body.category = category;
						if (attributes) body.attributes = attributes;
						if (expiresAt) body.constraints = { expiresAt };
						if (minMatchScore !== void 0 || autoAccept !== void 0) body.matching = {
							...minMatchScore !== void 0 ? { minMatchScore } : {},
							...autoAccept !== void 0 ? { autoAccept } : {}
						};
						return jsonResult(await moltenFetch("POST", "/intents", body));
					}
					case "list_intents": return jsonResult(await moltenFetch("GET", "/intents"));
					case "cancel_intent": {
						const intentId = readStringParam(p, "intent_id", { required: true });
						return jsonResult({
							status: "cancelled",
							intentId,
							...await moltenFetch("DELETE", `/intents/${intentId}`)
						});
					}
					case "list_matches": return jsonResult(await moltenFetch("GET", "/matches"));
					case "accept_match": return jsonResult(await moltenFetch("POST", `/matches/${readStringParam(p, "match_id", { required: true })}/accept`));
					case "reject_match": return jsonResult(await moltenFetch("POST", `/matches/${readStringParam(p, "match_id", { required: true })}/reject`));
					case "complete_match": return jsonResult(await moltenFetch("POST", `/matches/${readStringParam(p, "match_id", { required: true })}/complete`));
					case "match_message": {
						const matchId = readStringParam(p, "match_id", { required: true });
						const content = readStringParam(p, "message", { required: true });
						return jsonResult(await moltenFetch("POST", `/matches/${matchId}/message`, { content }));
					}
					case "check_events": return jsonResult(await moltenFetch("GET", "/events"));
					case "ack_events": {
						const event_ids = readStringParam(p, "event_ids", { required: true }).split(",").map((id) => id.trim());
						return jsonResult({
							status: "acknowledged",
							event_ids,
							...await moltenFetch("POST", "/events/ack", { event_ids })
						});
					}
					case "setup_webhook": {
						const webhookUrl = readStringParam(p, "webhook_url", { required: true });
						const eventsStr = readStringParam(p, "webhook_events");
						return jsonResult(await moltenFetch("POST", "/webhooks", {
							url: webhookUrl,
							events: eventsStr ? eventsStr.split(",").map((e) => e.trim()) : [
								"match.created",
								"match.accepted",
								"match.message"
							]
						}));
					}
					default: return errorResult(`Unknown molten action: ${action}`);
				}
			} catch (err) {
				if (err instanceof MoltenApiError) {
					if (err.status === 401) return errorResult("Molten API key is invalid or expired.\n\nUpdate: `/flykeys set MOLTEN_API_KEY your_new_key`");
					if (err.status === 403 && err.code === "AGENT_NOT_CLAIMED") return errorResult("Your Molten agent hasn't been claimed yet. Visit the claim URL from registration to activate it.");
					if (err.status === 404) return errorResult(`Molten returned 404: ${err.message}\n\nThe resource may not exist, or the agent may need to be registered first.
Try "register" or "browse" to verify the API is reachable.`);
					if (err.status === 429) return errorResult("Molten rate limit exceeded. Wait a moment and try again.");
					return errorResult(`Molten API error (${err.status}): ${err.message}`);
				}
				const msg = err instanceof Error ? err.message : String(err);
				if (msg.includes("ECONNREFUSED") || msg.includes("ENOTFOUND") || msg.includes("fetch failed")) return errorResult("Could not reach api.molten.gg. The platform may be offline.\nCheck https://molten.gg for status.");
				return errorResult(`Molten error: ${msg}`);
			}
		}
	};
}
//#endregion
export { createMoltenTool };

//# sourceMappingURL=molten.mjs.map