const { roleOf } = require("./permissions"); const PLATFORM_DEFAULTS = { discord: { markdown: true, html: false, reply_thread: true, max: 1900 }, twitch: { markdown: false, html: false, reply_thread: false, max: 450 }, youtube: { markdown: false, html: false, reply_thread: false, max: 1800 }, kick: { markdown: false, html: false, reply_thread: false, max: 450 }, webui: { markdown: false, html: true, reply_thread: false, max: 4000 }, other: { markdown: false, html: false, reply_thread: false, max: 1000 } }; function buildOriginContext(ctx, command = "assistant") { const platform = ctx.platform || "other"; const defaults = PLATFORM_DEFAULTS[platform] || PLATFORM_DEFAULTS.other; const role = inferRole(ctx); return { origin: platform, platform, channel_id: ctx.meta?.message?.channelId || ctx.meta?.channel || ctx.meta?.liveChatId || null, channel_name: ctx.meta?.message?.channel?.name || ctx.meta?.channel || null, server_id: ctx.meta?.message?.guildId || null, user_id: ctx.user?.id || null, username: ctx.user?.username || ctx.platformUser?.username || null, display_name: ctx.user?.displayName || ctx.platformUser?.displayName || null, role, is_admin: role === "admin", is_mod: role === "mod", message_id: ctx.meta?.message?.id || ctx.meta?.messageId || null, reply_mode: defaults.reply_thread ? "thread" : "same_channel", format_capabilities: { markdown: defaults.markdown, html: defaults.html }, max_message_length: defaults.max, source_plugin: "lumi_ai", source_command: command, permission_context: { identified_user: Boolean(ctx.user?.id), webui_actions_allowed: false } }; } function formatPlatformReply(text, links, origin) { return formatPlatformReplyDetails(text, links, origin).text; } function formatPlatformReplyDetails(text, links, origin) { let output = String(text || "").trim(); const safeLinks = Array.isArray(links) ? links.filter((link) => /^https?:\/\//i.test(link?.href || "") || link?.href?.startsWith("/")) : []; if (safeLinks.length) { const paths = safeLinks.map((link) => origin.format_capabilities.markdown ? `[${link.label}](${link.href})` : `${link.label}: ${link.href}`).join(" | "); output = `${output} ${paths}`.trim(); } if (!origin.format_capabilities.markdown) { output = output.replace(/[*_`~]/g, "").replace(/\[([^\]]+)\]\(([^)]+)\)/g, "$1: $2"); } output = output.replace(/<[^>]+>/g, "").replace(/\s+/g, " ").trim(); const originalLength = output.length; const delivered = truncate(output, origin.max_message_length); return { text: delivered, original_final_length: originalLength, delivered_length: delivered.length }; } function inferRole(ctx) { if (ctx.isAdmin || ctx.user?.isAdmin || hasPermission(ctx, ["Administrator", "ADMINISTRATOR"])) return "admin"; const tags = ctx.meta?.tags || {}; if (ctx.isMod || ctx.user?.isMod || hasPermission(ctx, ["ManageMessages", "MANAGE_MESSAGES"]) || tags.mod === "1" || tags.badges?.broadcaster === "1" || tags.badges?.moderator === "1") return "mod"; return roleOf(ctx.user); } function hasPermission(ctx, names) { const permissions = ctx.meta?.message?.member?.permissions; if (!permissions?.has) return false; return names.some((name) => { try { return Boolean(permissions.has(name)); } catch { return false; } }); } function truncate(value, max) { if (value.length <= max) return value; const suffix = " [reply truncated]"; return `${value.slice(0, Math.max(1, max - suffix.length)).trimEnd()}${suffix}`; } module.exports = { PLATFORM_DEFAULTS, buildOriginContext, formatPlatformReply, formatPlatformReplyDetails, inferRole };