import "./paths-WcYpcMAY.js";
import "./auth-profiles-CaNK0cUT.js";
import { l as normalizeAccountId } from "./session-key-Fto5gqqw.js";
import "./exec-CmvuUufz.js";
import { f as resolveSessionAgentId } from "./agent-scope-E2aR3Ci_.js";
import "./github-copilot-token-CKOQDjEZ.js";
import "./emitter-BKo8D7Oj.js";
import "./sqlite-CVrhPija.js";
import "./reliability-BnL75OlZ.js";
import "./frontmatter-C3D7gE4Z.js";
import "./skills-UwTwDeDw.js";
import "./manifest-registry-AgGLF4V7.js";
import "./validation-B00oOkJ3.js";
import { o as loadConfig } from "./config-CoCeK5B2.js";
import "./client-DtQEs2_8.js";
import "./call-CkgY6Bq7.js";
import { l as normalizeMessageChannel, m as GATEWAY_CLIENT_MODES, p as GATEWAY_CLIENT_IDS } from "./message-channel-DKXbq8GH.js";
import "./sessions-CFJLtXRH.js";
import "./tokens-D-4TlWcT.js";
import "./accounts-CNwod9BY.js";
import "./accounts-C3i8BBiA.js";
import "./normalize-CRf-uoB2.js";
import "./bindings-B1hNZin3.js";
import "./helpers-C1I2eYI4.js";
import { x as listChannelSupportedActions } from "./allow-list-C1QL6XM_.js";
import "./logging-BiuZwq5D.js";
import "./client-BrCP9C3o.js";
import "./plugins-DMpYx7kb.js";
import "./targets-DvKzWjKi.js";
import { d as normalizeTargetForProvider } from "./reply-payloads-DHkZZC3s.js";
import "./image-ops-D0pBQqKh.js";
import "./pi-embedded-helpers-D-q9ylFX.js";
import "./sandbox-C79rEJ_w.js";
import "./chrome-BTLLz_O2.js";
import "./tailscale-V4nwZFBO.js";
import "./auth-Beo6eR0R.js";
import "./server-context-T5wFkzWi.js";
import "./routes-Ch0tqbTH.js";
import "./redact-2qrQ_uJt.js";
import "./errors-BlUw40-o.js";
import "./paths-Cb76_eC_.js";
import "./ssrf-BEPhIfOk.js";
import "./store-Bz34pm8z.js";
import "./ports-BsKQWWi9.js";
import "./trash-Cn3CsF86.js";
import "./dock-BvRrtCWj.js";
import "./accounts-CdYdWklO.js";
import "./paths-CDTtU20P.js";
import "./tool-images-B4eVOjD0.js";
import "./thinking-C03RqJxq.js";
import "./retry-Bdf0L_dZ.js";
import { a as jsonResult, o as readNumberParam, u as readStringParam } from "./common-CxpUJZLb.js";
import "./chunk-CNObemR3.js";
import "./markdown-tables-Cex18ib0.js";
import "./fetch-guard-BLrk92iq.js";
import "./fetch-DFo2YRBT.js";
import "./media-PPft1pQs.js";
import "./ir-CRxad2DW.js";
import { t as stripReasoningTagsFromText } from "./reasoning-tags-BeAYH9mO.js";
import "./fetch-CbnJhXfl.js";
import "./pairing-store-BHSQgDEs.js";
import { r as resolveGatewayOptions } from "./gateway-CWnGRD4E.js";
import "./resolve-route-CjJJ3gIl.js";
import "./outbound-attachment-BhyLC0RY.js";
import "./targets-Df3HJYGb.js";
import "./send-oTQYKgod.js";
import { i as stringEnum, n as channelTargetsSchema, t as channelTargetSchema } from "./typebox-C14oleuH.js";
import { a as supportsChannelMessageButtons, c as supportsChannelMessageCardsForChannel, i as listChannelMessageActions, n as runMessageAction, o as supportsChannelMessageButtonsForChannel, r as CHANNEL_MESSAGE_ACTION_NAMES, s as supportsChannelMessageCards, t as getToolResult } from "./message-action-runner-BlCGKCbJ.js";
import "./deliver-i2e9PiiC.js";
import "./channel-selection-BjgSQnKE.js";
import "./outbound-session-CJD2yPJr.js";
import "./delivery-queue-Db61Fz6r.js";
import { Type } from "@sinclair/typebox";

//#region src/channels/plugins/bluebubbles-actions.ts
const BLUEBUBBLES_ACTIONS = {
	react: { gate: "reactions" },
	edit: {
		gate: "edit",
		unsupportedOnMacOS26: true
	},
	unsend: { gate: "unsend" },
	reply: { gate: "reply" },
	sendWithEffect: { gate: "sendWithEffect" },
	renameGroup: {
		gate: "renameGroup",
		groupOnly: true
	},
	setGroupIcon: {
		gate: "setGroupIcon",
		groupOnly: true
	},
	addParticipant: {
		gate: "addParticipant",
		groupOnly: true
	},
	removeParticipant: {
		gate: "removeParticipant",
		groupOnly: true
	},
	leaveGroup: {
		gate: "leaveGroup",
		groupOnly: true
	},
	sendAttachment: { gate: "sendAttachment" }
};
const BLUEBUBBLES_ACTION_SPECS = BLUEBUBBLES_ACTIONS;
const BLUEBUBBLES_ACTION_NAMES = Object.keys(BLUEBUBBLES_ACTIONS);
const BLUEBUBBLES_GROUP_ACTIONS = new Set(BLUEBUBBLES_ACTION_NAMES.filter((action) => BLUEBUBBLES_ACTION_SPECS[action]?.groupOnly));

//#endregion
//#region src/agents/tools/messaging/message-tool.ts
const AllMessageActions = CHANNEL_MESSAGE_ACTION_NAMES;
const EXPLICIT_TARGET_ACTIONS = new Set([
	"send",
	"sendWithEffect",
	"sendAttachment",
	"reply",
	"thread-reply",
	"broadcast"
]);
function actionNeedsExplicitTarget(action) {
	return EXPLICIT_TARGET_ACTIONS.has(action);
}
function buildRoutingSchema() {
	return {
		channel: Type.Optional(Type.String()),
		target: Type.Optional(channelTargetSchema({ description: "Target channel/user id or name." })),
		targets: Type.Optional(channelTargetsSchema()),
		accountId: Type.Optional(Type.String()),
		dryRun: Type.Optional(Type.Boolean())
	};
}
const discordComponentEmojiSchema = Type.Object({
	name: Type.String(),
	id: Type.Optional(Type.String()),
	animated: Type.Optional(Type.Boolean())
});
const discordComponentOptionSchema = Type.Object({
	label: Type.String(),
	value: Type.String(),
	description: Type.Optional(Type.String()),
	emoji: Type.Optional(discordComponentEmojiSchema),
	default: Type.Optional(Type.Boolean())
});
const discordComponentButtonSchema = Type.Object({
	label: Type.String(),
	style: Type.Optional(stringEnum([
		"primary",
		"secondary",
		"success",
		"danger",
		"link"
	])),
	url: Type.Optional(Type.String()),
	emoji: Type.Optional(discordComponentEmojiSchema),
	disabled: Type.Optional(Type.Boolean()),
	allowedUsers: Type.Optional(Type.Array(Type.String({ description: "Discord user ids or names allowed to interact with this button." })))
});
const discordComponentSelectSchema = Type.Object({
	type: Type.Optional(stringEnum([
		"string",
		"user",
		"role",
		"mentionable",
		"channel"
	])),
	placeholder: Type.Optional(Type.String()),
	minValues: Type.Optional(Type.Number()),
	maxValues: Type.Optional(Type.Number()),
	options: Type.Optional(Type.Array(discordComponentOptionSchema))
});
const discordComponentBlockSchema = Type.Object({
	type: Type.String(),
	text: Type.Optional(Type.String()),
	texts: Type.Optional(Type.Array(Type.String())),
	accessory: Type.Optional(Type.Object({
		type: Type.String(),
		url: Type.Optional(Type.String()),
		button: Type.Optional(discordComponentButtonSchema)
	})),
	spacing: Type.Optional(stringEnum(["small", "large"])),
	divider: Type.Optional(Type.Boolean()),
	buttons: Type.Optional(Type.Array(discordComponentButtonSchema)),
	select: Type.Optional(discordComponentSelectSchema),
	items: Type.Optional(Type.Array(Type.Object({
		url: Type.String(),
		description: Type.Optional(Type.String()),
		spoiler: Type.Optional(Type.Boolean())
	}))),
	file: Type.Optional(Type.String()),
	spoiler: Type.Optional(Type.Boolean())
});
const discordComponentModalFieldSchema = Type.Object({
	type: Type.String(),
	name: Type.Optional(Type.String()),
	label: Type.String(),
	description: Type.Optional(Type.String()),
	placeholder: Type.Optional(Type.String()),
	required: Type.Optional(Type.Boolean()),
	options: Type.Optional(Type.Array(discordComponentOptionSchema)),
	minValues: Type.Optional(Type.Number()),
	maxValues: Type.Optional(Type.Number()),
	minLength: Type.Optional(Type.Number()),
	maxLength: Type.Optional(Type.Number()),
	style: Type.Optional(stringEnum(["short", "paragraph"]))
});
const discordComponentModalSchema = Type.Object({
	title: Type.String(),
	triggerLabel: Type.Optional(Type.String()),
	triggerStyle: Type.Optional(stringEnum([
		"primary",
		"secondary",
		"success",
		"danger",
		"link"
	])),
	fields: Type.Array(discordComponentModalFieldSchema)
});
const discordComponentMessageSchema = Type.Object({
	text: Type.Optional(Type.String()),
	reusable: Type.Optional(Type.Boolean({ description: "Allow components to be used multiple times until they expire." })),
	container: Type.Optional(Type.Object({
		accentColor: Type.Optional(Type.String()),
		spoiler: Type.Optional(Type.Boolean())
	})),
	blocks: Type.Optional(Type.Array(discordComponentBlockSchema)),
	modal: Type.Optional(discordComponentModalSchema)
}, { description: "Discord components v2 payload. Set reusable=true to keep buttons, selects, and forms active until expiry." });
function buildSendSchema(options) {
	const props = {
		message: Type.Optional(Type.String()),
		effectId: Type.Optional(Type.String({ description: "Message effect name/id for sendWithEffect (e.g., invisible ink)." })),
		effect: Type.Optional(Type.String({ description: "Alias for effectId (e.g., invisible-ink, balloons)." })),
		media: Type.Optional(Type.String({ description: "Media URL or local path. data: URLs are not supported here, use buffer." })),
		filename: Type.Optional(Type.String()),
		buffer: Type.Optional(Type.String({ description: "Base64 payload for attachments (optionally a data: URL)." })),
		contentType: Type.Optional(Type.String()),
		mimeType: Type.Optional(Type.String()),
		caption: Type.Optional(Type.String()),
		path: Type.Optional(Type.String()),
		filePath: Type.Optional(Type.String()),
		replyTo: Type.Optional(Type.String()),
		threadId: Type.Optional(Type.String()),
		asVoice: Type.Optional(Type.Boolean()),
		silent: Type.Optional(Type.Boolean()),
		quoteText: Type.Optional(Type.String({ description: "Quote text for Telegram reply_parameters" })),
		bestEffort: Type.Optional(Type.Boolean()),
		gifPlayback: Type.Optional(Type.Boolean()),
		buttons: Type.Optional(Type.Array(Type.Array(Type.Object({
			text: Type.String(),
			callback_data: Type.String(),
			style: Type.Optional(stringEnum([
				"danger",
				"success",
				"primary"
			]))
		})), { description: "Telegram inline keyboard buttons (array of button rows)" })),
		card: Type.Optional(Type.Object({}, {
			additionalProperties: true,
			description: "Adaptive Card JSON object (when supported by the channel)"
		})),
		components: Type.Optional(discordComponentMessageSchema)
	};
	if (!options.includeButtons) delete props.buttons;
	if (!options.includeCards) delete props.card;
	if (!options.includeComponents) delete props.components;
	return props;
}
function buildReactionSchema() {
	return {
		messageId: Type.Optional(Type.String()),
		emoji: Type.Optional(Type.String()),
		remove: Type.Optional(Type.Boolean()),
		targetAuthor: Type.Optional(Type.String()),
		targetAuthorUuid: Type.Optional(Type.String()),
		groupId: Type.Optional(Type.String())
	};
}
function buildFetchSchema() {
	return {
		limit: Type.Optional(Type.Number()),
		before: Type.Optional(Type.String()),
		after: Type.Optional(Type.String()),
		around: Type.Optional(Type.String()),
		fromMe: Type.Optional(Type.Boolean()),
		includeArchived: Type.Optional(Type.Boolean())
	};
}
function buildPollSchema() {
	return {
		pollQuestion: Type.Optional(Type.String()),
		pollOption: Type.Optional(Type.Array(Type.String())),
		pollDurationHours: Type.Optional(Type.Number()),
		pollMulti: Type.Optional(Type.Boolean())
	};
}
function buildChannelTargetSchema() {
	return {
		channelId: Type.Optional(Type.String({ description: "Channel id filter (search/thread list/event create)." })),
		channelIds: Type.Optional(Type.Array(Type.String({ description: "Channel id filter (repeatable)." }))),
		guildId: Type.Optional(Type.String()),
		userId: Type.Optional(Type.String()),
		authorId: Type.Optional(Type.String()),
		authorIds: Type.Optional(Type.Array(Type.String())),
		roleId: Type.Optional(Type.String()),
		roleIds: Type.Optional(Type.Array(Type.String())),
		participant: Type.Optional(Type.String())
	};
}
function buildStickerSchema() {
	return {
		emojiName: Type.Optional(Type.String()),
		stickerId: Type.Optional(Type.Array(Type.String())),
		stickerName: Type.Optional(Type.String()),
		stickerDesc: Type.Optional(Type.String()),
		stickerTags: Type.Optional(Type.String())
	};
}
function buildThreadSchema() {
	return {
		threadName: Type.Optional(Type.String()),
		autoArchiveMin: Type.Optional(Type.Number())
	};
}
function buildEventSchema() {
	return {
		query: Type.Optional(Type.String()),
		eventName: Type.Optional(Type.String()),
		eventType: Type.Optional(Type.String()),
		startTime: Type.Optional(Type.String()),
		endTime: Type.Optional(Type.String()),
		desc: Type.Optional(Type.String()),
		location: Type.Optional(Type.String()),
		durationMin: Type.Optional(Type.Number()),
		until: Type.Optional(Type.String())
	};
}
function buildModerationSchema() {
	return {
		reason: Type.Optional(Type.String()),
		deleteDays: Type.Optional(Type.Number())
	};
}
function buildGatewaySchema() {
	return {
		gatewayUrl: Type.Optional(Type.String()),
		gatewayToken: Type.Optional(Type.String()),
		timeoutMs: Type.Optional(Type.Number())
	};
}
function buildPresenceSchema() {
	return {
		activityType: Type.Optional(Type.String({ description: "Activity type: playing, streaming, listening, watching, competing, custom." })),
		activityName: Type.Optional(Type.String({ description: "Activity name shown in sidebar (e.g. 'with fire'). Ignored for custom type." })),
		activityUrl: Type.Optional(Type.String({ description: "Streaming URL (Twitch or YouTube). Only used with streaming type; may not render for bots." })),
		activityState: Type.Optional(Type.String({ description: "State text. For custom type this is the status text; for others it shows in the flyout." })),
		status: Type.Optional(Type.String({ description: "Bot status: online, dnd, idle, invisible." }))
	};
}
function buildChannelManagementSchema() {
	return {
		name: Type.Optional(Type.String()),
		type: Type.Optional(Type.Number()),
		parentId: Type.Optional(Type.String()),
		topic: Type.Optional(Type.String()),
		position: Type.Optional(Type.Number()),
		nsfw: Type.Optional(Type.Boolean()),
		rateLimitPerUser: Type.Optional(Type.Number()),
		categoryId: Type.Optional(Type.String()),
		clearParent: Type.Optional(Type.Boolean({ description: "Clear the parent/category when supported by the provider." }))
	};
}
function buildMessageToolSchemaProps(options) {
	return {
		...buildRoutingSchema(),
		...buildSendSchema(options),
		...buildReactionSchema(),
		...buildFetchSchema(),
		...buildPollSchema(),
		...buildChannelTargetSchema(),
		...buildStickerSchema(),
		...buildThreadSchema(),
		...buildEventSchema(),
		...buildModerationSchema(),
		...buildGatewaySchema(),
		...buildChannelManagementSchema(),
		...buildPresenceSchema()
	};
}
function buildMessageToolSchemaFromActions(actions, options) {
	const props = buildMessageToolSchemaProps(options);
	return Type.Object({
		action: stringEnum(actions),
		...props
	});
}
const MessageToolSchema = buildMessageToolSchemaFromActions(AllMessageActions, {
	includeButtons: true,
	includeCards: true,
	includeComponents: true
});
function resolveMessageToolSchemaActions(params) {
	const currentChannel = normalizeMessageChannel(params.currentChannelProvider);
	if (currentChannel) {
		const scopedActions = filterActionsForContext({
			actions: listChannelSupportedActions({
				cfg: params.cfg,
				channel: currentChannel
			}),
			channel: currentChannel,
			currentChannelId: params.currentChannelId
		});
		const withSend = new Set(["send", ...scopedActions]);
		return Array.from(withSend);
	}
	const actions = listChannelMessageActions(params.cfg);
	return actions.length > 0 ? actions : ["send"];
}
function resolveIncludeComponents(params) {
	const currentChannel = normalizeMessageChannel(params.currentChannelProvider);
	if (currentChannel) return currentChannel === "discord";
	return listChannelSupportedActions({
		cfg: params.cfg,
		channel: "discord"
	}).length > 0;
}
function buildMessageToolSchema(params) {
	const currentChannel = normalizeMessageChannel(params.currentChannelProvider);
	const actions = resolveMessageToolSchemaActions(params);
	const includeButtons = currentChannel ? supportsChannelMessageButtonsForChannel({
		cfg: params.cfg,
		channel: currentChannel
	}) : supportsChannelMessageButtons(params.cfg);
	const includeCards = currentChannel ? supportsChannelMessageCardsForChannel({
		cfg: params.cfg,
		channel: currentChannel
	}) : supportsChannelMessageCards(params.cfg);
	const includeComponents = resolveIncludeComponents(params);
	return buildMessageToolSchemaFromActions(actions.length > 0 ? actions : ["send"], {
		includeButtons,
		includeCards,
		includeComponents
	});
}
function resolveAgentAccountId(value) {
	const trimmed = value?.trim();
	if (!trimmed) return;
	return normalizeAccountId(trimmed);
}
function filterActionsForContext(params) {
	const channel = normalizeMessageChannel(params.channel);
	if (!channel || channel !== "bluebubbles") return params.actions;
	const currentChannelId = params.currentChannelId?.trim();
	if (!currentChannelId) return params.actions;
	const lowered = (normalizeTargetForProvider(channel, currentChannelId) ?? currentChannelId).trim().toLowerCase();
	if (lowered.startsWith("chat_guid:") || lowered.startsWith("chat_id:") || lowered.startsWith("chat_identifier:") || lowered.startsWith("group:")) return params.actions;
	return params.actions.filter((action) => !BLUEBUBBLES_GROUP_ACTIONS.has(action));
}
function buildMessageToolDescription(options) {
	const baseDescription = "Send, delete, and manage messages via channel plugins.";
	if (options?.currentChannel) {
		const channelActions = filterActionsForContext({
			actions: listChannelSupportedActions({
				cfg: options.config,
				channel: options.currentChannel
			}),
			channel: options.currentChannel,
			currentChannelId: options.currentChannelId
		});
		if (channelActions.length > 0) {
			const allActions = new Set(["send", ...channelActions]);
			const actionList = Array.from(allActions).toSorted().join(", ");
			return `${baseDescription} Current channel (${options.currentChannel}) supports: ${actionList}.`;
		}
	}
	if (options?.config) {
		const actions = listChannelMessageActions(options.config);
		if (actions.length > 0) return `${baseDescription} Supports actions: ${actions.join(", ")}.`;
	}
	return `${baseDescription} Supports actions: send, delete, react, poll, pin, threads, and more.`;
}
function createMessageTool(options) {
	const agentAccountId = resolveAgentAccountId(options?.agentAccountId);
	const schema = options?.config ? buildMessageToolSchema({
		cfg: options.config,
		currentChannelProvider: options.currentChannelProvider,
		currentChannelId: options.currentChannelId
	}) : MessageToolSchema;
	return {
		label: "Message",
		name: "message",
		description: buildMessageToolDescription({
			config: options?.config,
			currentChannel: options?.currentChannelProvider,
			currentChannelId: options?.currentChannelId
		}),
		parameters: schema,
		execute: async (_toolCallId, args, signal) => {
			if (signal?.aborted) {
				const err = /* @__PURE__ */ new Error("Message send aborted");
				err.name = "AbortError";
				throw err;
			}
			const params = { ...args };
			for (const field of [
				"text",
				"content",
				"message",
				"caption"
			]) if (typeof params[field] === "string") params[field] = stripReasoningTagsFromText(params[field]);
			const cfg = options?.config ?? loadConfig();
			const action = readStringParam(params, "action", { required: true });
			if (options?.requireExplicitTarget === true && actionNeedsExplicitTarget(action)) {
				if (!(typeof params.target === "string" && params.target.trim().length > 0 || typeof params.to === "string" && params.to.trim().length > 0 || typeof params.channelId === "string" && params.channelId.trim().length > 0 || Array.isArray(params.targets) && params.targets.some((value) => typeof value === "string" && value.trim().length > 0))) throw new Error("Explicit message target required for this run. Provide target/targets (and channel when needed).");
			}
			const accountId = readStringParam(params, "accountId") ?? agentAccountId;
			if (accountId) params.accountId = accountId;
			const gatewayResolved = resolveGatewayOptions({
				gatewayUrl: readStringParam(params, "gatewayUrl", { trim: false }),
				gatewayToken: readStringParam(params, "gatewayToken", { trim: false }),
				timeoutMs: readNumberParam(params, "timeoutMs")
			});
			const gateway = {
				url: gatewayResolved.url,
				token: gatewayResolved.token,
				timeoutMs: gatewayResolved.timeoutMs,
				clientName: GATEWAY_CLIENT_IDS.GATEWAY_CLIENT,
				clientDisplayName: "agent",
				mode: GATEWAY_CLIENT_MODES.BACKEND
			};
			const toolContext = options?.currentChannelId || options?.currentChannelProvider || options?.currentThreadTs || options?.replyToMode || options?.hasRepliedRef ? {
				currentChannelId: options?.currentChannelId,
				currentChannelProvider: options?.currentChannelProvider,
				currentThreadTs: options?.currentThreadTs,
				replyToMode: options?.replyToMode,
				hasRepliedRef: options?.hasRepliedRef,
				skipCrossContextDecoration: true
			} : void 0;
			const result = await runMessageAction({
				cfg,
				action,
				params,
				defaultAccountId: accountId ?? void 0,
				gateway,
				toolContext,
				sessionKey: options?.agentSessionKey,
				agentId: options?.agentSessionKey ? resolveSessionAgentId({
					sessionKey: options.agentSessionKey,
					config: cfg
				}) : void 0,
				sandboxRoot: options?.sandboxRoot,
				abortSignal: signal
			});
			const toolResult = getToolResult(result);
			if (toolResult) return toolResult;
			return jsonResult(result.payload);
		}
	};
}

//#endregion
export { createMessageTool };