import{existsSync as h}from"fs";import{fileURLToPath as g}from"url";import{dirname as u,resolve as m}from"path";import{resolveIntegrationToken as _}from"@zibby/core/backend-client.js";var d=Object.freeze({SENTRY:"sentry",JIRA:"jira",GITHUB:"github",GITLAB:"gitlab",SLACK:"slack",LARK:"lark",OPENAI_BILLING:"openai_billing",ANTHROPIC_BILLING:"anthropic_billing",CURSOR_ADMIN:"cursor_admin",NOTION:"notion",GOOGLE:"google",PLANE:"plane",LINEAR:"linear",FIGMA:"figma",HUBSPOT:"hubspot",OPEN_DESIGN:"open_design",LINKEDIN_PERSONAL:"linkedin_personal",LINKEDIN_BUSINESS:"linkedin_business",DISCORD:"discord"}),S=Object.freeze({sentry:{id:"sentry",name:"Sentry",connectPath:"/integrations?provider=sentry"},jira:{id:"jira",name:"Jira",connectPath:"/integrations?provider=jira"},github:{id:"github",name:"GitHub",connectPath:"/integrations?provider=github"},gitlab:{id:"gitlab",name:"GitLab",connectPath:"/integrations?provider=gitlab"},slack:{id:"slack",name:"Slack",connectPath:"/integrations?provider=slack"},lark:{id:"lark",name:"Lark",connectPath:"/integrations?provider=lark"},openai_billing:{id:"openai_billing",name:"OpenAI Admin",connectPath:"/integrations?provider=openai_billing"},anthropic_billing:{id:"anthropic_billing",name:"Anthropic Admin",connectPath:"/integrations?provider=anthropic_billing"},cursor_admin:{id:"cursor_admin",name:"Cursor Admin",connectPath:"/integrations?provider=cursor_admin"},notion:{id:"notion",name:"Notion",connectPath:"/integrations?provider=notion"},google:{id:"google",name:"Google Docs",connectPath:"/integrations?provider=google"},plane:{id:"plane",name:"Plane",connectPath:"/integrations?provider=plane"},linear:{id:"linear",name:"Linear",connectPath:"/integrations?provider=linear"},figma:{id:"figma",name:"Figma",connectPath:"/integrations?provider=figma"},hubspot:{id:"hubspot",name:"HubSpot",connectPath:"/integrations?provider=hubspot"},open_design:{id:"open_design",name:"OpenDesign",connectPath:"/integrations?provider=open_design"},linkedin_personal:{id:"linkedin_personal",name:"LinkedIn (Personal)",connectPath:"/integrations?provider=linkedin_personal"},linkedin_business:{id:"linkedin_business",name:"LinkedIn (Business)",connectPath:"/integrations?provider=linkedin_business"},discord:{id:"discord",name:"Discord",connectPath:"/integrations?provider=discord"}});function I(){if(process.env.MCP_SKILL_PATH)return process.env.MCP_SKILL_PATH;let i=u(g(import.meta.url)),e=m(i,"..","bin","mcp-skill.mjs");return h(e)?e:null}var f=process.env.DISCORD_API_URL||"https://discord.com/api/v10",D=2e3;function v(i,e=D){let n=String(i??"");if(!n.trim())return[];if(n.length<=e)return[n];let s=[],o=n;for(;o.length>e;){let t=o.slice(0,e).lastIndexOf(`
`),a=t>e/2?t+1:e;s.push(o.slice(0,a)),o=o.slice(a)}return o&&s.push(o),s}async function p(){let i=(process.env.DISCORD_BOT_TOKEN||"").trim();if(i)return{token:i,guildId:(process.env.DISCORD_GUILD_ID||"").trim()};let e=await _(d.DISCORD),n=(e&&e.token?String(e.token):"").trim();if(!n)throw new Error("Discord is not connected: connect Discord in the Zibby dashboard or set DISCORD_BOT_TOKEN.");return{token:n,guildId:(e.guildId||"").trim()}}async function l(i,e,{token:n,body:s}={}){let o=n.startsWith("Bot ")?n:`Bot ${n}`,r=await fetch(`${f}${e}`,{method:i,headers:{Authorization:o,...s!==void 0?{"Content-Type":"application/json"}:{}},...s!==void 0?{body:JSON.stringify(s)}:{}}),t=await r.json().catch(()=>null);if(!r.ok){let a=t&&(t.message||t.error)?t.message||t.error:`HTTP ${r.status}`;throw new Error(`Discord API error (${r.status}): ${a}`)}return t}async function O({token:i,guildId:e},n){let s=String(n||"").trim()||e||(process.env.DISCORD_GUILD_ID||"").trim();if(s)return s;let o=await l("GET","/users/@me/guilds",{token:i}),r=Array.isArray(o)?o:[];if(r.length===1)return r[0].id;if(r.length===0)throw new Error("The bot is not in any Discord server \u2014 invite it to a server first.");let t=r.slice(0,10).map(a=>`${a.name} (${a.id})`).join(", ");throw new Error(`The bot is in ${r.length} servers \u2014 pass guildId explicitly. Servers: ${t}`)}var A={id:"discord",serverName:"discord",allowedTools:["mcp__discord__*"],requiresIntegration:d.DISCORD,envKeys:["DISCORD_BOT_TOKEN","DISCORD_GUILD_ID"],description:"Discord bot tools (send messages, list channels)",promptFragment:`## Discord (connected)
You can post to the user's Discord server as their bot. Tools:
- discord_send_message(channelId, text) \u2014 post a message to a channel (long text is auto-chunked to Discord's 2000-char limit)
- discord_list_channels(guildId?) \u2014 list the server's text channels (id + name) to find where to post; guildId is optional when the bot is in one server`,resolve(){let i={};for(let n of this.envKeys)process.env[n]&&(i[n]=process.env[n]);for(let n of["PROJECT_API_TOKEN","ZIBBY_USER_TOKEN","ZIBBY_ACCOUNT_API_URL","ZIBBY_ENV","ZIBBY_PROD_ACCOUNT_API_URL","ZIBBY_SELF_HOST","DISCORD_API_URL","EXECUTION_ID","PROJECT_ID","STAGE"])process.env[n]&&(i[n]=process.env[n]);let e=I();return e?{type:"stdio",command:"node",args:[e,"../dist/discord.js","discordSkill"],env:i,description:this.description,alwaysLoad:!0}:{command:null,args:[],env:i,description:this.description}},async handleToolCall(i,e={}){try{switch(i){case"discord_send_message":{let n=String(e.channelId||"").trim(),s=String(e.text||"");if(!n||!s.trim())return JSON.stringify({ok:!1,error:"channelId and text are required"});let o=await p(),r=v(s),t=[];for(let a of r){let c=await l("POST",`/channels/${encodeURIComponent(n)}/messages`,{token:o.token,body:{content:a}});t.push(c&&c.id?c.id:"")}return JSON.stringify({ok:!0,channelId:n,messageIds:t,chunks:r.length})}case"discord_list_channels":{let n=await p(),s=await O(n,e.guildId),o=await l("GET",`/guilds/${encodeURIComponent(s)}/channels`,{token:n.token}),r=(Array.isArray(o)?o:[]).filter(t=>t&&(t.type===0||t.type===5)).map(t=>({id:t.id,name:t.name,type:t.type===5?"announcement":"text",...t.topic?{topic:t.topic}:{}}));return JSON.stringify({ok:!0,guildId:s,channels:r})}default:return JSON.stringify({ok:!1,error:`Unknown tool: ${i}`})}}catch(n){return JSON.stringify({ok:!1,error:n.message})}},tools:[{name:"discord_send_message",description:"Post a message to a Discord channel as the connected bot. Text over 2000 chars is automatically split into sequential messages.",input_schema:{type:"object",properties:{channelId:{type:"string",description:"Discord channel id (snowflake). Use discord_list_channels to find it."},text:{type:"string",description:"Message text (Discord markdown supported)"}},required:["channelId","text"]}},{name:"discord_list_channels",description:"List the text channels of the connected Discord server (id + name). Pass guildId only when the bot is in multiple servers.",input_schema:{type:"object",properties:{guildId:{type:"string",description:"Discord server (guild) id \u2014 optional when the bot is in exactly one server or one was captured at connect time"}}}}]};export{D as DISCORD_MAX_CONTENT,v as chunkDiscordContent,A as discordSkill};
