@toolpack-sdk/agents 2.4.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/channels/index.cjs +2 -2
- package/dist/channels/index.d.cts +1 -1
- package/dist/channels/index.d.ts +1 -1
- package/dist/channels/index.js +2 -2
- package/dist/{index-C0OlSL3f.d.ts → index-BCBukKC4.d.ts} +14 -4
- package/dist/{index-Cg5gWiPj.d.cts → index-CA38tE7C.d.cts} +14 -4
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/package.json +3 -3
package/dist/channels/index.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"use strict";var D=Object.create;var C=Object.defineProperty;var E=Object.getOwnPropertyDescriptor;var R=Object.getOwnPropertyNames;var O=Object.getPrototypeOf,N=Object.prototype.hasOwnProperty;var U=(a,e)=>{for(var n in e)C(a,n,{get:e[n],enumerable:!0})},A=(a,e,n,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of R(e))!N.call(a,i)&&i!==n&&C(a,i,{get:()=>e[i],enumerable:!(t=E(e,i))||t.enumerable});return a};var p=(a,e,n)=>(n=a!=null?D(O(a)):{},A(e||!a||!a.__esModule?C(n,"default",{value:a,enumerable:!0}):n,a)),B=a=>A(C({},"__esModule",{value:!0}),a);var j={};U(j,{BaseChannel:()=>d,DiscordChannel:()=>I,EmailChannel:()=>T,McpChannel:()=>x,SMSChannel:()=>P,ScheduledChannel:()=>S,SlackChannel:()=>v,TelegramChannel:()=>b,WebhookChannel:()=>k});module.exports=B(j);var d=class{name;_handler;onMessage(e){this._handler=e}async handleMessage(e){this._handler&&await this._handler(e)}};var y=require("crypto");var v=class extends d{isTriggerChannel=!1;config;server;participantCache=new Map;botUserId;allowedChannels;constructor(e){super(),this.config={port:3e3,...e},this.name=e.name;let n=e.channel;this.allowedChannels=n==null?null:Array.isArray(n)?n:[n]}listen(){typeof process<"u"&&import("http").then(e=>{this.server=e.createServer((n,t)=>{this.handleRequest(n,t)}),this.server.listen(this.config.port,()=>{console.log(`[SlackChannel] Listening on port ${this.config.port}`),this.runStartupCheck().catch(()=>{})})}).catch(e=>{console.error("[SlackChannel] Failed to start HTTP server:",e)})}async runStartupCheck(){try{let n=await(await fetch("https://slack.com/api/auth.test",{method:"POST",headers:{Authorization:`Bearer ${this.config.token}`,"Content-Type":"application/json"}})).json();n.ok?(this.botUserId=n.user_id,console.log(`[SlackChannel] Connected as @${n.user} (${n.user_id}) in workspace "${n.team}" \u2014 ${n.url}`)):console.warn(`[SlackChannel] auth.test failed: ${n.error}. Check your bot token.`)}catch(e){console.warn("[SlackChannel] Startup self-check failed (network error):",e)}}verifySignature(e,n){let t=e["x-slack-request-timestamp"],i=e["x-slack-signature"];if(!t||!i||Array.isArray(t)||Array.isArray(i))return!1;let r=parseInt(t,10),s=Math.floor(Date.now()/1e3);if(isNaN(r)||Math.abs(s-r)>300)return!1;let o=`v0:${t}:${n}`,c=`v0=${(0,y.createHmac)("sha256",this.config.signingSecret).update(o).digest("hex")}`;if(c.length!==i.length)return!1;try{return(0,y.timingSafeEqual)(Buffer.from(c),Buffer.from(i))}catch{return!1}}async send(e){let n=e.metadata?.threadTs??e.metadata?.thread_ts??e.metadata?.threadId,i=e.metadata?.channelId??(this.allowedChannels&&this.allowedChannels.length>0?this.allowedChannels[0]:void 0);if(!i)throw new Error("[SlackChannel] Cannot send: no channel configured and metadata.channelId is missing. Provide a target via SlackChannelConfig.channel or output.metadata.channelId.");let r={channel:i,text:e.output};n&&(r.thread_ts=n);let s=await fetch("https://slack.com/api/chat.postMessage",{method:"POST",headers:{Authorization:`Bearer ${this.config.token}`,"Content-Type":"application/json"},body:JSON.stringify(r)});if(!s.ok)throw new Error(`Failed to send Slack message: ${s.statusText}`);let o=await s.json();if(!o.ok)throw new Error(`Slack API error: ${o.error}`)}normalize(e){let n=e,i=(n.text||"").replace(/<(https?:\/\/[^|>]+)\|([^>]+)>/g,"$2 ($1)").replace(/<(https?:\/\/[^>]+)>/g,"$1").replace(/<!here>/g,"@here").replace(/<!channel>/g,"@channel").replace(/<!everyone>/g,"@everyone"),r=n.ts,s=n.thread_ts,o=s!==void 0&&s!==r,l=n.user,c=l?{kind:"user",id:l}:void 0,m=/<@([A-Z0-9]+)>/g,g=[],f;for(;(f=m.exec(i))!==null;)g.push(f[1]);let u=n.channel;return{message:i,conversationId:o?s:u||r||"",data:n,participant:c,context:{user:l,channel:u,team:n.team,channelType:n.channel_type,threadId:o?s:void 0,mentions:g.length>0?g:void 0,channelId:u,channelName:typeof this.config.channel=="string"?this.config.channel:u}}}async resolveParticipant(e){let n=e.participant?.id??e.context?.user;if(!n)return;let t=this.participantCache.get(n);if(t)return t;try{let i=await fetch(`https://slack.com/api/users.info?user=${encodeURIComponent(n)}`,{method:"GET",headers:{Authorization:`Bearer ${this.config.token}`}});if(!i.ok)return{kind:"user",id:n};let r=await i.json();if(!r.ok||!r.user){let l={kind:"user",id:n};return this.participantCache.set(n,l),l}let s=r.user.profile?.display_name||r.user.profile?.real_name||r.user.real_name||r.user.name||n,o={kind:"user",id:n,displayName:s,metadata:{slackUser:r.user}};return this.participantCache.set(n,o),o}catch{return{kind:"user",id:n}}}invalidateParticipant(e){this.participantCache.delete(e)}shouldProcessEvent(e){let n=e.type;if(n!=="message"&&n!=="app_mention")return!1;if(this.allowedChannels!==null){let s=e.channel_type;if(!(s==="im"||s==="mpim")){let l=e.channel;if(!l||!this.allowedChannels.includes(l))return!1}}let t=e.user;if(this.botUserId&&t===this.botUserId)return!1;let i=e.bot_id;if(!i)return!0;let r=this.config.blockedBotIds??[];if(r.includes(i)||t!==void 0&&r.includes(t))return!1;if(this.config.allowedBotIds!==void 0){let s=this.config.allowedBotIds;return s.includes(i)||t!==void 0&&s.includes(t)}return!0}handleRequest(e,n){if(e.method!=="POST"){n.writeHead(405),n.end("Method not allowed");return}let t="";e.on("data",i=>{t+=i.toString()}),e.on("end",()=>{if(!this.verifySignature(e.headers,t)){n.writeHead(401),n.end("Invalid signature");return}try{let i=JSON.parse(t);if(i.type==="url_verification"){n.writeHead(200,{"Content-Type":"application/json"}),n.end(JSON.stringify({challenge:i.challenge}));return}if(i.type==="event_callback"&&i.event){let r=i.event;if(this.shouldProcessEvent(r)){let s=this.normalize(r);this.handleMessage(s)}else r.type==="user_change"&&r.user&&this.invalidateParticipant(r.user.id);n.writeHead(200),n.end("OK");return}n.writeHead(200),n.end("OK")}catch(i){console.error("[SlackChannel] Error handling request:",i),n.writeHead(400),n.end("Bad request")}})}async stop(){if(this.server)return new Promise(e=>{this.server.close(e)})}};var k=class extends d{isTriggerChannel=!1;config;server;pendingResponses=new Map;constructor(e){super(),this.name=e.name,this.config={port:e.port??3e3,path:e.path??"/webhook"}}listen(){typeof process<"u"&&import("http").then(e=>{this.server=e.createServer((n,t)=>{this.handleRequest(n,t)}),this.server.listen(this.config.port,()=>{console.log(`[WebhookChannel] Listening on port ${this.config.port}${this.config.path}`)})}).catch(e=>{console.error("[WebhookChannel] Failed to start HTTP server:",e)})}async send(e){let n=e.metadata?.conversationId;if(n&&this.pendingResponses.has(n)){let t=this.pendingResponses.get(n);this.pendingResponses.delete(n),t.resolve({output:e.output,metadata:e.metadata})}}normalize(e){let n=e,t=n.headers||{},i=t["x-session-id"]||t["X-Session-Id"]||n.sessionId||n.conversationId||this.generateSessionId();return{message:n.message||n.text||"",intent:n.intent,conversationId:i,data:n,context:{headers:n.headers,method:n.method,sessionId:i}}}handleRequest(e,n){if(e.url!==this.config.path){n.writeHead(404),n.end("Not found");return}if(e.method!=="POST"){n.writeHead(405),n.end("Method not allowed");return}let t="";e.on("data",i=>{t+=i.toString()}),e.on("end",()=>{try{let i=JSON.parse(t),r=this.normalize(i),s=r.conversationId||this.generateSessionId(),o=new Promise((l,c)=>{this.pendingResponses.set(s,{resolve:l,reject:c}),setTimeout(()=>{this.pendingResponses.has(s)&&(this.pendingResponses.delete(s),c(new Error("Agent response timeout")))},3e4)});this.handleMessage({...r,conversationId:s,context:{...r.context,sessionId:s}}),o.then(l=>{n.writeHead(200,{"Content-Type":"application/json"}),n.end(JSON.stringify(l))}).catch(l=>{n.writeHead(500,{"Content-Type":"application/json"}),n.end(JSON.stringify({error:l.message}))})}catch(i){console.error("[WebhookChannel] Error handling request:",i),n.writeHead(400,{"Content-Type":"application/json"}),n.end(JSON.stringify({error:"Bad request"}))}})}generateSessionId(){return`webhook-${Date.now()}-${Math.random().toString(36).substring(2,9)}`}async stop(){if(this.server)return new Promise(e=>{this.server.close(e)})}};var _=require("cron-parser"),S=class extends d{isTriggerChannel=!0;config;timer;_stopped=!1;_generation=0;constructor(e){if(super(),!e.cron&&!e.store)throw new Error("ScheduledChannel: provide at least one of `cron` (static schedule) or `store` (dynamic scheduling).");if(e.cron)try{_.CronExpressionParser.parse(e.cron)}catch(n){throw new Error(`ScheduledChannel: invalid cron expression '${e.cron}': ${n.message}`)}if(e.store&&!e.name&&console.warn("[ScheduledChannel] A `store` was provided without a `name`. All store queries will be unscoped and will pick up jobs from every channel. Set `name` to scope this channel to its own jobs."),e.idlePollMs!==void 0&&e.idlePollMs<1e3)throw new Error(`ScheduledChannel: idlePollMs must be at least 1000ms (got ${e.idlePollMs}). Values below 1 second create a tight polling loop.`);this.config=e,this.name=e.name}listen(){this._generation++,this.timer&&(clearTimeout(this.timer),this.timer=void 0),this._stopped=!1,this.config.store?this._listenWithStore():this._listenStatic()}async stop(){this._stopped=!0,this.timer&&(clearTimeout(this.timer),this.timer=void 0)}async send(e){}normalize(e){let n=e,t=new Date,i=`${t.getFullYear()}-${t.getMonth()+1}-${t.getDate()}`;return{intent:n?.intent??this.config.intent,message:n?.message??this.config.message??`Scheduled task triggered at ${t.toISOString()}`,conversationId:`scheduled:${this.name??"default"}:${i}`,data:{...n?.payload??{},scheduled:!0,jobId:n?.id,cron:n?.cron??this.config.cron,timestamp:t.toISOString()}}}_listenStatic(){this._scheduleNextStatic(this._generation)}_scheduleNextStatic(e){if(this._stopped||e!==this._generation)return;let n=this._nextRunFromCron(this.config.cron),t=n.getTime()-Date.now();if(t<=0){this.timer=setTimeout(()=>this._scheduleNextStatic(e),0);return}console.log(`[ScheduledChannel:${this.name??"default"}] Next run: ${n.toISOString()}`),this.timer=setTimeout(async()=>{this._stopped||e!==this._generation||(await this._triggerStatic(),this._scheduleNextStatic(e))},t)}async _triggerStatic(){if(!this._handler){console.warn(`[ScheduledChannel:${this.name??"default"}] Cron fired but no message handler is registered. Call onMessage() before listen() to avoid silently losing triggers.`);return}let e=this.normalize(null);try{await this.handleMessage(e)}catch(n){console.error(`[ScheduledChannel:${this.name??"default"}] Error on trigger:`,n)}}_listenWithStore(){let e=this.config.store,n=this._generation;if(n===1){let i=e.resetStuck(this.name);i>0&&console.log(`[ScheduledChannel:${this.name??"default"}] Reset ${i} stuck 'running' job(s) to 'pending'.`)}if(this.config.cron){let{duplicate:i}=e.create({channelName:this.name,cron:this.config.cron,intent:this.config.intent,message:this.config.message});i||console.log(`[ScheduledChannel:${this.name??"default"}] Seeded static cron '${this.config.cron}' into store.`)}let t=e.getDue(Date.now(),this.name);t.length>0&&(console.log(`[ScheduledChannel:${this.name??"default"}] Recovering ${t.length} overdue job(s).`),Promise.allSettled(t.map(i=>this._triggerJob(i)))),this._scheduleNextFromStore(n)}_scheduleNextFromStore(e){if(this._stopped||e!==this._generation)return;let n=this.config.store,t=n.getNextPending(this.name);if(!t){let r=this.config.idlePollMs??3e4;this.timer=setTimeout(()=>this._scheduleNextFromStore(e),r);return}let i=Math.max(0,t.nextRunAt-Date.now());console.log(`[ScheduledChannel:${this.name??"default"}] Next store job at ${new Date(t.nextRunAt).toISOString()} (in ${Math.round(i/1e3)}s)`),this.timer=setTimeout(async()=>{if(this._stopped||e!==this._generation)return;let r=n.getDue(Date.now(),this.name);await Promise.allSettled(r.map(s=>this._triggerJob(s))),this._scheduleNextFromStore(e)},i)}async _triggerJob(e){let n=this.config.store;if(!this._handler){console.warn(`[ScheduledChannel:${this.name??"default"}] Job ${e.id} fired but no message handler is registered. Call onMessage() before listen() to avoid silently losing jobs.`),n.markFailed(e.id,"No message handler registered");return}n.markRunning(e.id);let t=this.normalize(e);try{await this.handleMessage(t),n.markCompleted(e.id)}catch(i){let r=i instanceof Error?i.message:String(i);console.error(`[ScheduledChannel:${this.name??"default"}] Job ${e.id} failed:`,i),n.markFailed(e.id,r)}}_nextRunFromCron(e){return _.CronExpressionParser.parse(e,{currentDate:new Date}).next().toDate()}};var b=class extends d{isTriggerChannel=!1;config;offset=0;pollingInterval;server;botUserId;botUsername;constructor(e){super(),this.name=e.name,this.config=e}listen(){this.runStartupCheck().catch(()=>{}),this.config.webhookUrl?this.startWebhook():this.startPolling()}async runStartupCheck(){try{let n=await(await fetch(`https://api.telegram.org/bot${this.config.token}/getMe`)).json();if(n.ok&&n.result){let t=n.result;this.botUserId=t.id!=null?String(t.id):void 0,this.botUsername=t.username,console.log(`[TelegramChannel] Connected as @${t.username} (id: ${t.id}, name: ${t.first_name})`)}else console.warn(`[TelegramChannel] getMe failed: ${n.description??"unknown error"}. Check your bot token.`)}catch(e){console.warn("[TelegramChannel] Startup self-check failed (network error):",e)}}async send(e){let n=e.metadata?.chatId;if(!n)throw new Error("Telegram send requires chatId in metadata");let t=await fetch(`https://api.telegram.org/bot${this.config.token}/sendMessage`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({chat_id:n,text:e.output,parse_mode:"Markdown"})});if(!t.ok)throw new Error(`Failed to send Telegram message: ${t.statusText}`);let i=await t.json();if(!i.ok)throw new Error(`Telegram API error: ${i.description}`)}normalize(e){let n=e,t=n.message||n.edited_message||{},i=t.text||"",r=t.chat||{},s=t.from||{},o=s.id!=null?String(s.id):void 0,l=s.first_name||s.username||o,c=o?{kind:"user",id:o,displayName:l??o}:void 0,m=t.entities??[],g=[];for(let w of m)if(w.type==="text_mention"&&w.user){let $=w.user;$.id!=null&&g.push(String($.id))}let f=r.type,u=r.id!=null?String(r.id):"";return{message:i,conversationId:u,data:n,participant:c,context:{chatId:r.id,userId:s.id,username:s.username,firstName:s.first_name,lastName:s.last_name,messageId:t.message_id,channelType:f,channelId:u,channelName:r.title,mentions:g.length>0?g:void 0}}}startPolling(){console.log("[TelegramChannel] Starting polling mode"),this.pollingInterval=setInterval(async()=>{try{await this.pollUpdates()}catch(e){console.error("[TelegramChannel] Polling error:",e)}},5e3)}async pollUpdates(){let e=`https://api.telegram.org/bot${this.config.token}/getUpdates?offset=${this.offset}&limit=100`,n=await fetch(e);if(!n.ok)throw new Error(`Telegram getUpdates failed: ${n.statusText}`);let t=await n.json();if(!t.ok)throw new Error("Telegram getUpdates returned not ok");for(let i of t.result){let r=i.update_id;r>=this.offset&&(this.offset=r+1);try{let s=this.normalize(i);await this.handleMessage(s)}catch(s){console.error("[TelegramChannel] Error processing update:",s)}}}startWebhook(){typeof process>"u"||(console.log("[TelegramChannel] Starting webhook mode"),import("http").then(e=>{this.server=e.createServer((i,r)=>{this.handleWebhookRequest(i,r)});let n=new URL(this.config.webhookUrl||"http://localhost:3000"),t=parseInt(n.port,10)||3e3;this.server.listen(t,()=>{console.log(`[TelegramChannel] Webhook server listening on port ${t}`)}),this.setWebhook()}).catch(e=>{console.error("[TelegramChannel] Failed to start webhook server:",e)}))}async setWebhook(){if(!this.config.webhookUrl)return;let e=await fetch(`https://api.telegram.org/bot${this.config.token}/setWebhook`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({url:this.config.webhookUrl})});if(!e.ok){console.error("[TelegramChannel] Failed to set webhook");return}let n=await e.json();n.ok?console.log("[TelegramChannel] Webhook set successfully"):console.error("[TelegramChannel] Failed to set webhook:",n.description)}handleWebhookRequest(e,n){if(e.method!=="POST"){n.writeHead(405),n.end("Method not allowed");return}let t="";e.on("data",i=>{t+=i.toString()}),e.on("end",()=>{try{let i=JSON.parse(t);this.handleMessage(this.normalize(i)).catch(r=>{console.error("[TelegramChannel] Error processing webhook:",r)}),n.writeHead(200),n.end("OK")}catch(i){console.error("[TelegramChannel] Error parsing webhook:",i),n.writeHead(400),n.end("Bad request")}})}async stop(){if(this.pollingInterval&&(clearInterval(this.pollingInterval),this.pollingInterval=void 0),this.server)return new Promise(e=>{this.server.close(e)});if(this.config.webhookUrl)try{await fetch(`https://api.telegram.org/bot${this.config.token}/deleteWebhook`,{method:"POST"})}catch(e){console.error("[TelegramChannel] Failed to delete webhook:",e)}}};var z=new Set([1,3]),M=/<@!?(\d+)>/g,F="https://discord.com/api/v10",I=class extends d{isTriggerChannel=!1;config;allowedChannelIds;botUserId;participantCache=new Map;client;constructor(e){super(),this.config=e,this.name=e.name,e.channelId==null?this.allowedChannelIds=new Set:Array.isArray(e.channelId)?this.allowedChannelIds=new Set(e.channelId):this.allowedChannelIds=new Set([e.channelId])}shouldProcessEvent(e){return!e.author||e.webhookId||this.botUserId&&e.author.id===this.botUserId||this.config.guildId&&e.guildId!==this.config.guildId||this.allowedChannelIds.size>0&&(!e.channelId||!this.allowedChannelIds.has(e.channelId))?!1:e.author.bot||e.author.system?this.config.blockedBotIds?.includes(e.author.id)?!1:this.config.allowedBotIds?this.config.allowedBotIds.includes(e.author.id):!1:!0}normalize(e){let n=e,t=n.channelId,i=(t??"")+(n.thread?.id?`:${n.thread.id}`:""),r=n.channel?.type,s=r!==void 0&&z.has(r),o=n.author?.id,l=n.author?.globalName??n.author?.username,c=[];if(n.content){M.lastIndex=0;let m;for(;(m=M.exec(n.content))!==null;)c.push(m[1])}return{message:n.content,conversationId:i,data:n,participant:o?{kind:"user",id:o,displayName:l??void 0}:void 0,context:{userId:o,username:n.author?.username,channelType:s?"dm":"channel",channelId:t,channelName:n.channel?.name,guildId:n.guildId,threadId:n.thread?.id,messageId:n.id,mentions:c.length>0?c:void 0,isMentioned:this.botUserId?c.includes(this.botUserId):void 0}}}async resolveParticipant(e){let n=e.participant?.id??e.context?.userId;if(!n)return;let t=this.participantCache.get(n);if(t)return t;try{let i=await fetch(`${F}/users/${n}`,{headers:{Authorization:`Bot ${this.config.token}`}});if(!i.ok)return console.warn(`[DiscordChannel] Failed to resolve user ${n}: HTTP ${i.status}`),{kind:"user",id:n};let r=await i.json(),s=r.global_name??r.username,o={kind:"user",id:r.id,displayName:s};return this.participantCache.set(n,o),o}catch(i){return console.warn(`[DiscordChannel] resolveParticipant error for ${n}:`,i),{kind:"user",id:n}}}invalidateParticipant(e){this.participantCache.delete(e)}async send(e){if(!this.client)throw new Error("[DiscordChannel] Client not initialized. Did you call listen()?");let n=e.metadata?.threadId;if(n){let r=await this.client.channels.fetch(n);if(r&&"send"in r)try{await r.send({content:e.output});return}catch(s){throw console.error("[DiscordChannel] Failed to send to thread:",s),new Error(`[DiscordChannel] Failed to send Discord message: ${s instanceof Error?s.message:String(s)}`)}console.warn(`[DiscordChannel] Thread ${n} not found or not sendable; falling back to channel send.`)}let t=e.metadata?.channelId??(this.allowedChannelIds.size>0?[...this.allowedChannelIds][0]:void 0);if(!t)throw new Error("[DiscordChannel] No channel ID available for sending. Configure channelId or pass output.metadata.channelId.");let i=await this.client.channels.fetch(t);if(!i||!("send"in i))throw new Error(`[DiscordChannel] Channel ${t} not found or is not a text channel`);try{await i.send({content:e.output})}catch(r){throw console.error("[DiscordChannel] Failed to send to channel:",r),new Error(`[DiscordChannel] Failed to send Discord message: ${r instanceof Error?r.message:String(r)}`)}}listen(){typeof process>"u"||import("discord.js").then(e=>{let{Client:n,GatewayIntentBits:t}=e;this.client=new n({intents:[t.Guilds,t.GuildMessages,t.MessageContent,t.DirectMessages]}),this.client.on("ready",()=>{let i=this.client.user;this.botUserId=i?.id;let r=this.allowedChannelIds.size===0?"all channels":[...this.allowedChannelIds].join(", "),s=this.config.guildId??"all guilds";console.log(`[DiscordChannel] Logged in as ${i?.tag??"unknown"} (botUserId=${this.botUserId??"unknown"}) | guild=${s} | channels=${r}`)}),this.client.on("messageCreate",i=>{let r=i;if(!this.shouldProcessEvent(r))return;let s=this.normalize(r);this.handleMessage(s)}),this.client.on("userUpdate",(i,r)=>{let s=r;s?.id&&this.invalidateParticipant(s.id)}),this.client.login(this.config.token).catch(i=>{console.error("[DiscordChannel] Failed to login to Discord:",i)})}).catch(e=>{console.error("[DiscordChannel] Failed to initialize Discord client:",e),console.error("[DiscordChannel] Make sure discord.js is installed: npm install discord.js")})}async stop(){this.client&&(await this.client.destroy(),this.client=void 0)}};var T=class extends d{isTriggerChannel=!0;config;transporter;constructor(e){super(),this.config=e,this.name=e.name}listen(){typeof process<"u"&&import("nodemailer").then(e=>{this.transporter=e.default.createTransport({host:this.config.smtp.host,port:this.config.smtp.port,secure:this.config.smtp.secure??this.config.smtp.port===465,auth:{user:this.config.smtp.auth.user,pass:this.config.smtp.auth.pass}}),console.log(`[EmailChannel] Email transporter initialized for ${this.config.from}`)}).catch(e=>{console.error("[EmailChannel] Failed to initialize nodemailer:",e),console.error("[EmailChannel] Make sure to install nodemailer: npm install nodemailer")})}async send(e){if(!this.transporter)throw new Error("Email transporter not initialized. Did you call listen()?");let n=Array.isArray(this.config.to)?this.config.to:[this.config.to],t=this.config.subject||"Message from Agent",i={from:this.config.from,to:n.join(", "),subject:t,text:e.output,html:this.formatAsHtml(e.output)};try{await this.transporter.sendMail(i)}catch(r){throw console.error("[EmailChannel] Failed to send email:",r),new Error(`Failed to send email: ${r instanceof Error?r.message:String(r)}`)}}normalize(e){throw new Error("EmailChannel is outbound-only. Use WebhookChannel with email webhook events for inbound email.")}formatAsHtml(e){return e.split(`
|
|
1
|
+
"use strict";var D=Object.create;var C=Object.defineProperty;var E=Object.getOwnPropertyDescriptor;var R=Object.getOwnPropertyNames;var O=Object.getPrototypeOf,N=Object.prototype.hasOwnProperty;var U=(a,e)=>{for(var n in e)C(a,n,{get:e[n],enumerable:!0})},A=(a,e,n,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of R(e))!N.call(a,i)&&i!==n&&C(a,i,{get:()=>e[i],enumerable:!(t=E(e,i))||t.enumerable});return a};var p=(a,e,n)=>(n=a!=null?D(O(a)):{},A(e||!a||!a.__esModule?C(n,"default",{value:a,enumerable:!0}):n,a)),B=a=>A(C({},"__esModule",{value:!0}),a);var j={};U(j,{BaseChannel:()=>l,DiscordChannel:()=>I,EmailChannel:()=>T,McpChannel:()=>x,SMSChannel:()=>P,ScheduledChannel:()=>b,SlackChannel:()=>v,TelegramChannel:()=>S,WebhookChannel:()=>k});module.exports=B(j);var l=class{name;_handler;onMessage(e){this._handler=e}async handleMessage(e){this._handler&&await this._handler(e)}};var y=require("crypto");var v=class extends l{isTriggerChannel=!1;config;server;participantCache=new Map;botUserId;botId;allowedChannels;constructor(e){super(),this.config={port:3e3,...e},this.name=e.name;let n=e.channel;this.allowedChannels=n==null?null:Array.isArray(n)?n:[n]}listen(){typeof process<"u"&&import("http").then(e=>{this.server=e.createServer((n,t)=>{this.handleRequest(n,t)}),this.server.listen(this.config.port,()=>{console.log(`[SlackChannel] Listening on port ${this.config.port}`),this.runStartupCheck().catch(()=>{})})}).catch(e=>{console.error("[SlackChannel] Failed to start HTTP server:",e)})}async runStartupCheck(){try{let n=await(await fetch("https://slack.com/api/auth.test",{method:"POST",headers:{Authorization:`Bearer ${this.config.token}`,"Content-Type":"application/json"}})).json();n.ok?(this.botUserId=n.user_id,this.botId=n.bot_id,console.log(`[SlackChannel] Connected as @${n.user} (${n.user_id}) in workspace "${n.team}" \u2014 ${n.url}`)):console.warn(`[SlackChannel] auth.test failed: ${n.error}. Check your bot token.`)}catch(e){console.warn("[SlackChannel] Startup self-check failed (network error):",e)}}verifySignature(e,n){let t=e["x-slack-request-timestamp"],i=e["x-slack-signature"];if(!t||!i||Array.isArray(t)||Array.isArray(i))return!1;let s=parseInt(t,10),r=Math.floor(Date.now()/1e3);if(isNaN(s)||Math.abs(r-s)>300)return!1;let o=`v0:${t}:${n}`,c=`v0=${(0,y.createHmac)("sha256",this.config.signingSecret).update(o).digest("hex")}`;if(c.length!==i.length)return!1;try{return(0,y.timingSafeEqual)(Buffer.from(c),Buffer.from(i))}catch{return!1}}async send(e){let n=e.metadata?.threadTs??e.metadata?.thread_ts??e.metadata?.threadId,i=e.metadata?.channelId??(this.allowedChannels&&this.allowedChannels.length>0?this.allowedChannels[0]:void 0);if(!i)throw new Error("[SlackChannel] Cannot send: no channel configured and metadata.channelId is missing. Provide a target via SlackChannelConfig.channel or output.metadata.channelId.");let s={channel:i,text:e.output};n&&(s.thread_ts=n);let r=await fetch("https://slack.com/api/chat.postMessage",{method:"POST",headers:{Authorization:`Bearer ${this.config.token}`,"Content-Type":"application/json"},body:JSON.stringify(s)});if(!r.ok)throw new Error(`Failed to send Slack message: ${r.statusText}`);let o=await r.json();if(!o.ok)throw new Error(`Slack API error: ${o.error}`)}normalize(e){let n=e,i=(n.text||"").replace(/<(https?:\/\/[^|>]+)\|([^>]+)>/g,"$2 ($1)").replace(/<(https?:\/\/[^>]+)>/g,"$1").replace(/<!here>/g,"@here").replace(/<!channel>/g,"@channel").replace(/<!everyone>/g,"@everyone"),s=n.ts,r=n.thread_ts,o=r!==void 0&&r!==s,d=n.user,c=d?{kind:"user",id:d}:void 0,m=/<@([A-Z0-9]+)>/g,u=[],f;for(;(f=m.exec(i))!==null;)u.push(f[1]);let g=n.channel;return{message:i,conversationId:o?r:g||s||"",data:n,participant:c,context:{user:d,channel:g,team:n.team,channelType:n.channel_type,threadId:o?r:void 0,mentions:u.length>0?u:void 0,channelId:g,channelName:typeof this.config.channel=="string"?this.config.channel:g}}}async resolveParticipant(e){let n=e.participant?.id??e.context?.user;if(!n)return;let t=this.participantCache.get(n);if(t)return t;try{let i=await fetch(`https://slack.com/api/users.info?user=${encodeURIComponent(n)}`,{method:"GET",headers:{Authorization:`Bearer ${this.config.token}`}});if(!i.ok)return{kind:"user",id:n};let s=await i.json();if(!s.ok||!s.user){let d={kind:"user",id:n};return this.participantCache.set(n,d),d}let r=s.user.profile?.display_name||s.user.profile?.real_name||s.user.real_name||s.user.name||n,o={kind:"user",id:n,displayName:r,metadata:{slackUser:s.user}};return this.participantCache.set(n,o),o}catch{return{kind:"user",id:n}}}invalidateParticipant(e){this.participantCache.delete(e)}shouldProcessEvent(e){let n=e.type;if(n!=="message"&&n!=="app_mention")return!1;if(this.allowedChannels!==null){let r=e.channel_type;if(!(r==="im"||r==="mpim")){let d=e.channel;if(!d||!this.allowedChannels.includes(d))return!1}}let t=e.user;if(this.botUserId&&t===this.botUserId)return!1;let i=e.bot_id;if(console.log(`[SlackChannel:shouldProcessEvent] subtype=${e.subtype} user=${t} bot_id=${i} this.botUserId=${this.botUserId} this.botId=${this.botId}`),!i)return!0;if(this.botId&&i===this.botId)return!1;let s=this.config.blockedBotIds??[];if(s.includes(i)||t!==void 0&&s.includes(t))return!1;if(this.config.allowedBotIds!==void 0){let r=this.config.allowedBotIds;return r.includes(i)||t!==void 0&&r.includes(t)}return!0}handleRequest(e,n){if(e.method!=="POST"){n.writeHead(405),n.end("Method not allowed");return}let t="";e.on("data",i=>{t+=i.toString()}),e.on("end",()=>{if(!this.verifySignature(e.headers,t)){n.writeHead(401),n.end("Invalid signature");return}try{let i=JSON.parse(t);if(i.type==="url_verification"){n.writeHead(200,{"Content-Type":"application/json"}),n.end(JSON.stringify({challenge:i.challenge}));return}if(i.type==="event_callback"&&i.event){let s=i.event;if(this.shouldProcessEvent(s)){let r=this.normalize(s);this.handleMessage(r)}else s.type==="user_change"&&s.user&&this.invalidateParticipant(s.user.id);n.writeHead(200),n.end("OK");return}n.writeHead(200),n.end("OK")}catch(i){console.error("[SlackChannel] Error handling request:",i),n.writeHead(400),n.end("Bad request")}})}async stop(){if(this.server)return new Promise(e=>{this.server.close(e)})}};var k=class extends l{isTriggerChannel=!1;config;server;pendingResponses=new Map;constructor(e){super(),this.name=e.name,this.config={port:e.port??3e3,path:e.path??"/webhook"}}listen(){typeof process<"u"&&import("http").then(e=>{this.server=e.createServer((n,t)=>{this.handleRequest(n,t)}),this.server.listen(this.config.port,()=>{console.log(`[WebhookChannel] Listening on port ${this.config.port}${this.config.path}`)})}).catch(e=>{console.error("[WebhookChannel] Failed to start HTTP server:",e)})}async send(e){let n=e.metadata?.conversationId;if(n&&this.pendingResponses.has(n)){let t=this.pendingResponses.get(n);this.pendingResponses.delete(n),t.resolve({output:e.output,metadata:e.metadata})}}normalize(e){let n=e,t=n.headers||{},i=t["x-session-id"]||t["X-Session-Id"]||n.sessionId||n.conversationId||this.generateSessionId();return{message:n.message||n.text||"",intent:n.intent,conversationId:i,data:n,context:{headers:n.headers,method:n.method,sessionId:i}}}handleRequest(e,n){if(e.url!==this.config.path){n.writeHead(404),n.end("Not found");return}if(e.method!=="POST"){n.writeHead(405),n.end("Method not allowed");return}let t="";e.on("data",i=>{t+=i.toString()}),e.on("end",()=>{try{let i=JSON.parse(t),s=this.normalize(i),r=s.conversationId||this.generateSessionId(),o=new Promise((d,c)=>{this.pendingResponses.set(r,{resolve:d,reject:c}),setTimeout(()=>{this.pendingResponses.has(r)&&(this.pendingResponses.delete(r),c(new Error("Agent response timeout")))},3e4)});this.handleMessage({...s,conversationId:r,context:{...s.context,sessionId:r}}),o.then(d=>{n.writeHead(200,{"Content-Type":"application/json"}),n.end(JSON.stringify(d))}).catch(d=>{n.writeHead(500,{"Content-Type":"application/json"}),n.end(JSON.stringify({error:d.message}))})}catch(i){console.error("[WebhookChannel] Error handling request:",i),n.writeHead(400,{"Content-Type":"application/json"}),n.end(JSON.stringify({error:"Bad request"}))}})}generateSessionId(){return`webhook-${Date.now()}-${Math.random().toString(36).substring(2,9)}`}async stop(){if(this.server)return new Promise(e=>{this.server.close(e)})}};var _=require("cron-parser"),b=class extends l{isTriggerChannel=!0;config;timer;_stopped=!1;_generation=0;constructor(e){if(super(),!e.cron&&!e.store)throw new Error("ScheduledChannel: provide at least one of `cron` (static schedule) or `store` (dynamic scheduling).");if(e.cron)try{_.CronExpressionParser.parse(e.cron)}catch(n){throw new Error(`ScheduledChannel: invalid cron expression '${e.cron}': ${n.message}`)}if(e.store&&!e.name&&console.warn("[ScheduledChannel] A `store` was provided without a `name`. All store queries will be unscoped and will pick up jobs from every channel. Set `name` to scope this channel to its own jobs."),e.idlePollMs!==void 0&&e.idlePollMs<1e3)throw new Error(`ScheduledChannel: idlePollMs must be at least 1000ms (got ${e.idlePollMs}). Values below 1 second create a tight polling loop.`);this.config=e,this.name=e.name}listen(){this._generation++,this.timer&&(clearTimeout(this.timer),this.timer=void 0),this._stopped=!1,this.config.store?this._listenWithStore():this._listenStatic()}async stop(){this._stopped=!0,this.timer&&(clearTimeout(this.timer),this.timer=void 0)}async send(e){}normalize(e){let n=e,t=new Date,i=`${t.getFullYear()}-${t.getMonth()+1}-${t.getDate()}`;return{intent:n?.intent??this.config.intent,message:n?.message??this.config.message??`Scheduled task triggered at ${t.toISOString()}`,conversationId:`scheduled:${this.name??"default"}:${i}`,data:{...n?.payload??{},scheduled:!0,jobId:n?.id,cron:n?.cron??this.config.cron,timestamp:t.toISOString()}}}_listenStatic(){this._scheduleNextStatic(this._generation)}_scheduleNextStatic(e){if(this._stopped||e!==this._generation)return;let n=this._nextRunFromCron(this.config.cron),t=n.getTime()-Date.now();if(t<=0){this.timer=setTimeout(()=>this._scheduleNextStatic(e),0);return}console.log(`[ScheduledChannel:${this.name??"default"}] Next run: ${n.toISOString()}`),this.timer=setTimeout(async()=>{this._stopped||e!==this._generation||(await this._triggerStatic(),this._scheduleNextStatic(e))},t)}async _triggerStatic(){if(!this._handler){console.warn(`[ScheduledChannel:${this.name??"default"}] Cron fired but no message handler is registered. Call onMessage() before listen() to avoid silently losing triggers.`);return}let e=this.normalize(null);try{await this.handleMessage(e)}catch(n){console.error(`[ScheduledChannel:${this.name??"default"}] Error on trigger:`,n)}}_listenWithStore(){let e=this.config.store,n=this._generation;if(n===1){let i=e.resetStuck(this.name);i>0&&console.log(`[ScheduledChannel:${this.name??"default"}] Reset ${i} stuck 'running' job(s) to 'pending'.`)}if(this.config.cron){let{duplicate:i}=e.create({channelName:this.name,cron:this.config.cron,intent:this.config.intent,message:this.config.message});i||console.log(`[ScheduledChannel:${this.name??"default"}] Seeded static cron '${this.config.cron}' into store.`)}let t=e.getDue(Date.now(),this.name);t.length>0&&(console.log(`[ScheduledChannel:${this.name??"default"}] Recovering ${t.length} overdue job(s).`),Promise.allSettled(t.map(i=>this._triggerJob(i)))),this._scheduleNextFromStore(n)}_scheduleNextFromStore(e){if(this._stopped||e!==this._generation)return;let n=this.config.store,t=n.getNextPending(this.name);if(!t){let s=this.config.idlePollMs??3e4;this.timer=setTimeout(()=>this._scheduleNextFromStore(e),s);return}let i=Math.max(0,t.nextRunAt-Date.now());console.log(`[ScheduledChannel:${this.name??"default"}] Next store job at ${new Date(t.nextRunAt).toISOString()} (in ${Math.round(i/1e3)}s)`),this.timer=setTimeout(async()=>{if(this._stopped||e!==this._generation)return;let s=n.getDue(Date.now(),this.name);await Promise.allSettled(s.map(r=>this._triggerJob(r))),this._scheduleNextFromStore(e)},i)}async _triggerJob(e){let n=this.config.store;if(!this._handler){console.warn(`[ScheduledChannel:${this.name??"default"}] Job ${e.id} fired but no message handler is registered. Call onMessage() before listen() to avoid silently losing jobs.`),n.markFailed(e.id,"No message handler registered");return}n.markRunning(e.id);let t=this.normalize(e);try{await this.handleMessage(t),n.markCompleted(e.id)}catch(i){let s=i instanceof Error?i.message:String(i);console.error(`[ScheduledChannel:${this.name??"default"}] Job ${e.id} failed:`,i),n.markFailed(e.id,s)}}_nextRunFromCron(e){return _.CronExpressionParser.parse(e,{currentDate:new Date}).next().toDate()}};var S=class extends l{isTriggerChannel=!1;config;offset=0;pollingInterval;server;botUserId;botUsername;constructor(e){super(),this.name=e.name,this.config=e}listen(){this.runStartupCheck().catch(()=>{}),this.config.webhookUrl?this.startWebhook():this.startPolling()}async runStartupCheck(){try{let n=await(await fetch(`https://api.telegram.org/bot${this.config.token}/getMe`)).json();if(n.ok&&n.result){let t=n.result;this.botUserId=t.id!=null?String(t.id):void 0,this.botUsername=t.username,console.log(`[TelegramChannel] Connected as @${t.username} (id: ${t.id}, name: ${t.first_name})`)}else console.warn(`[TelegramChannel] getMe failed: ${n.description??"unknown error"}. Check your bot token.`)}catch(e){console.warn("[TelegramChannel] Startup self-check failed (network error):",e)}}async send(e){let n=e.metadata?.chatId;if(!n)throw new Error("Telegram send requires chatId in metadata");let t=await fetch(`https://api.telegram.org/bot${this.config.token}/sendMessage`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({chat_id:n,text:e.output,parse_mode:"Markdown"})});if(!t.ok)throw new Error(`Failed to send Telegram message: ${t.statusText}`);let i=await t.json();if(!i.ok)throw new Error(`Telegram API error: ${i.description}`)}normalize(e){let n=e,t=n.message||n.edited_message||{},i=t.text||"",s=t.chat||{},r=t.from||{},o=r.id!=null?String(r.id):void 0,d=r.first_name||r.username||o,c=o?{kind:"user",id:o,displayName:d??o}:void 0,m=t.entities??[],u=[];for(let w of m)if(w.type==="text_mention"&&w.user){let $=w.user;$.id!=null&&u.push(String($.id))}let f=s.type,g=s.id!=null?String(s.id):"";return{message:i,conversationId:g,data:n,participant:c,context:{chatId:s.id,userId:r.id,username:r.username,firstName:r.first_name,lastName:r.last_name,messageId:t.message_id,channelType:f,channelId:g,channelName:s.title,mentions:u.length>0?u:void 0}}}startPolling(){console.log("[TelegramChannel] Starting polling mode"),this.pollingInterval=setInterval(async()=>{try{await this.pollUpdates()}catch(e){console.error("[TelegramChannel] Polling error:",e)}},5e3)}async pollUpdates(){let e=`https://api.telegram.org/bot${this.config.token}/getUpdates?offset=${this.offset}&limit=100`,n=await fetch(e);if(!n.ok)throw new Error(`Telegram getUpdates failed: ${n.statusText}`);let t=await n.json();if(!t.ok)throw new Error("Telegram getUpdates returned not ok");for(let i of t.result){let s=i.update_id;s>=this.offset&&(this.offset=s+1);try{let r=this.normalize(i);await this.handleMessage(r)}catch(r){console.error("[TelegramChannel] Error processing update:",r)}}}startWebhook(){typeof process>"u"||(console.log("[TelegramChannel] Starting webhook mode"),import("http").then(e=>{this.server=e.createServer((i,s)=>{this.handleWebhookRequest(i,s)});let n=new URL(this.config.webhookUrl||"http://localhost:3000"),t=parseInt(n.port,10)||3e3;this.server.listen(t,()=>{console.log(`[TelegramChannel] Webhook server listening on port ${t}`)}),this.setWebhook()}).catch(e=>{console.error("[TelegramChannel] Failed to start webhook server:",e)}))}async setWebhook(){if(!this.config.webhookUrl)return;let e=await fetch(`https://api.telegram.org/bot${this.config.token}/setWebhook`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({url:this.config.webhookUrl})});if(!e.ok){console.error("[TelegramChannel] Failed to set webhook");return}let n=await e.json();n.ok?console.log("[TelegramChannel] Webhook set successfully"):console.error("[TelegramChannel] Failed to set webhook:",n.description)}handleWebhookRequest(e,n){if(e.method!=="POST"){n.writeHead(405),n.end("Method not allowed");return}let t="";e.on("data",i=>{t+=i.toString()}),e.on("end",()=>{try{let i=JSON.parse(t);this.handleMessage(this.normalize(i)).catch(s=>{console.error("[TelegramChannel] Error processing webhook:",s)}),n.writeHead(200),n.end("OK")}catch(i){console.error("[TelegramChannel] Error parsing webhook:",i),n.writeHead(400),n.end("Bad request")}})}async stop(){if(this.pollingInterval&&(clearInterval(this.pollingInterval),this.pollingInterval=void 0),this.server)return new Promise(e=>{this.server.close(e)});if(this.config.webhookUrl)try{await fetch(`https://api.telegram.org/bot${this.config.token}/deleteWebhook`,{method:"POST"})}catch(e){console.error("[TelegramChannel] Failed to delete webhook:",e)}}};var z=new Set([1,3]),M=/<@!?(\d+)>/g,F="https://discord.com/api/v10",I=class extends l{isTriggerChannel=!1;config;allowedChannelIds;botUserId;participantCache=new Map;client;constructor(e){super(),this.config=e,this.name=e.name,e.channelId==null?this.allowedChannelIds=new Set:Array.isArray(e.channelId)?this.allowedChannelIds=new Set(e.channelId):this.allowedChannelIds=new Set([e.channelId])}shouldProcessEvent(e){return!e.author||e.webhookId||this.botUserId&&e.author.id===this.botUserId||this.config.guildId&&e.guildId!==this.config.guildId||this.allowedChannelIds.size>0&&(!e.channelId||!this.allowedChannelIds.has(e.channelId))?!1:e.author.bot||e.author.system?this.config.blockedBotIds?.includes(e.author.id)?!1:this.config.allowedBotIds?this.config.allowedBotIds.includes(e.author.id):!1:!0}normalize(e){let n=e,t=n.channelId,i=(t??"")+(n.thread?.id?`:${n.thread.id}`:""),s=n.channel?.type,r=s!==void 0&&z.has(s),o=n.author?.id,d=n.author?.globalName??n.author?.username,c=[];if(n.content){M.lastIndex=0;let m;for(;(m=M.exec(n.content))!==null;)c.push(m[1])}return{message:n.content,conversationId:i,data:n,participant:o?{kind:"user",id:o,displayName:d??void 0}:void 0,context:{userId:o,username:n.author?.username,channelType:r?"dm":"channel",channelId:t,channelName:n.channel?.name,guildId:n.guildId,threadId:n.thread?.id,messageId:n.id,mentions:c.length>0?c:void 0,isMentioned:this.botUserId?c.includes(this.botUserId):void 0}}}async resolveParticipant(e){let n=e.participant?.id??e.context?.userId;if(!n)return;let t=this.participantCache.get(n);if(t)return t;try{let i=await fetch(`${F}/users/${n}`,{headers:{Authorization:`Bot ${this.config.token}`}});if(!i.ok)return console.warn(`[DiscordChannel] Failed to resolve user ${n}: HTTP ${i.status}`),{kind:"user",id:n};let s=await i.json(),r=s.global_name??s.username,o={kind:"user",id:s.id,displayName:r};return this.participantCache.set(n,o),o}catch(i){return console.warn(`[DiscordChannel] resolveParticipant error for ${n}:`,i),{kind:"user",id:n}}}invalidateParticipant(e){this.participantCache.delete(e)}async send(e){if(!this.client)throw new Error("[DiscordChannel] Client not initialized. Did you call listen()?");let n=e.metadata?.threadId;if(n){let s=await this.client.channels.fetch(n);if(s&&"send"in s)try{await s.send({content:e.output});return}catch(r){throw console.error("[DiscordChannel] Failed to send to thread:",r),new Error(`[DiscordChannel] Failed to send Discord message: ${r instanceof Error?r.message:String(r)}`)}console.warn(`[DiscordChannel] Thread ${n} not found or not sendable; falling back to channel send.`)}let t=e.metadata?.channelId??(this.allowedChannelIds.size>0?[...this.allowedChannelIds][0]:void 0);if(!t)throw new Error("[DiscordChannel] No channel ID available for sending. Configure channelId or pass output.metadata.channelId.");let i=await this.client.channels.fetch(t);if(!i||!("send"in i))throw new Error(`[DiscordChannel] Channel ${t} not found or is not a text channel`);try{await i.send({content:e.output})}catch(s){throw console.error("[DiscordChannel] Failed to send to channel:",s),new Error(`[DiscordChannel] Failed to send Discord message: ${s instanceof Error?s.message:String(s)}`)}}listen(){typeof process>"u"||import("discord.js").then(e=>{let{Client:n,GatewayIntentBits:t}=e;this.client=new n({intents:[t.Guilds,t.GuildMessages,t.MessageContent,t.DirectMessages]}),this.client.on("ready",()=>{let i=this.client.user;this.botUserId=i?.id;let s=this.allowedChannelIds.size===0?"all channels":[...this.allowedChannelIds].join(", "),r=this.config.guildId??"all guilds";console.log(`[DiscordChannel] Logged in as ${i?.tag??"unknown"} (botUserId=${this.botUserId??"unknown"}) | guild=${r} | channels=${s}`)}),this.client.on("messageCreate",i=>{let s=i;if(!this.shouldProcessEvent(s))return;let r=this.normalize(s);this.handleMessage(r)}),this.client.on("userUpdate",(i,s)=>{let r=s;r?.id&&this.invalidateParticipant(r.id)}),this.client.login(this.config.token).catch(i=>{console.error("[DiscordChannel] Failed to login to Discord:",i)})}).catch(e=>{console.error("[DiscordChannel] Failed to initialize Discord client:",e),console.error("[DiscordChannel] Make sure discord.js is installed: npm install discord.js")})}async stop(){this.client&&(await this.client.destroy(),this.client=void 0)}};var T=class extends l{isTriggerChannel=!0;config;transporter;constructor(e){super(),this.config=e,this.name=e.name}listen(){typeof process<"u"&&import("nodemailer").then(e=>{this.transporter=e.default.createTransport({host:this.config.smtp.host,port:this.config.smtp.port,secure:this.config.smtp.secure??this.config.smtp.port===465,auth:{user:this.config.smtp.auth.user,pass:this.config.smtp.auth.pass}}),console.log(`[EmailChannel] Email transporter initialized for ${this.config.from}`)}).catch(e=>{console.error("[EmailChannel] Failed to initialize nodemailer:",e),console.error("[EmailChannel] Make sure to install nodemailer: npm install nodemailer")})}async send(e){if(!this.transporter)throw new Error("Email transporter not initialized. Did you call listen()?");let n=Array.isArray(this.config.to)?this.config.to:[this.config.to],t=this.config.subject||"Message from Agent",i={from:this.config.from,to:n.join(", "),subject:t,text:e.output,html:this.formatAsHtml(e.output)};try{await this.transporter.sendMail(i)}catch(s){throw console.error("[EmailChannel] Failed to send email:",s),new Error(`Failed to send email: ${s instanceof Error?s.message:String(s)}`)}}normalize(e){throw new Error("EmailChannel is outbound-only. Use WebhookChannel with email webhook events for inbound email.")}formatAsHtml(e){return e.split(`
|
|
2
2
|
|
|
3
|
-
`).map(n=>`<p>${n.replace(/\n/g,"<br>")}</p>`).join("")}async stop(){this.transporter&&(this.transporter.close(),this.transporter=void 0)}};var P=class extends
|
|
3
|
+
`).map(n=>`<p>${n.replace(/\n/g,"<br>")}</p>`).join("")}async stop(){this.transporter&&(this.transporter.close(),this.transporter=void 0)}};var P=class extends l{config;twilioClient;server;constructor(e){super(),this.config={port:3e3,...e},this.name=e.name}get isTriggerChannel(){return!this.config.webhookPath}listen(){typeof process<"u"&&import("twilio").then(e=>{this.twilioClient=e.default(this.config.accountSid,this.config.authToken),console.log("[SMSChannel] Twilio client initialized"),this.config.webhookPath&&this.startWebhookServer()}).catch(e=>{console.error("[SMSChannel] Failed to initialize Twilio client:",e),console.error("[SMSChannel] Make sure to install twilio: npm install twilio")})}async send(e){if(!this.twilioClient)throw new Error("Twilio client not initialized. Did you call listen()?");let n=e.metadata?.from||this.config.to;if(!n)throw new Error('No recipient phone number specified. Set "to" in config or provide in output.metadata.from');try{await this.twilioClient.messages.create({body:e.output,from:this.config.from,to:n})}catch(t){throw console.error("[SMSChannel] Failed to send SMS:",t),new Error(`Failed to send SMS: ${t instanceof Error?t.message:String(t)}`)}}normalize(e){let n=e,t=n.From,i=n.Body,s=n.MessageSid;return{message:i,conversationId:t,data:n,context:{from:t,to:n.To,messageSid:s}}}startWebhookServer(){import("http").then(e=>{this.server=e.createServer((n,t)=>{this.handleWebhookRequest(n,t)}),this.server.listen(this.config.port,()=>{console.log(`[SMSChannel] Webhook server listening on port ${this.config.port} at ${this.config.webhookPath}`)})}).catch(e=>{console.error("[SMSChannel] Failed to start webhook server:",e)})}handleWebhookRequest(e,n){if(e.method!=="POST"||e.url!==this.config.webhookPath){n.writeHead(404),n.end("Not found");return}let t="";e.on("data",i=>{t+=i.toString()}),e.on("end",()=>{try{let i=new URLSearchParams(t),s={};i.forEach((o,d)=>{s[d]=o});let r=this.normalize(s);this.handleMessage(r),n.writeHead(200,{"Content-Type":"text/xml"}),n.end('<?xml version="1.0" encoding="UTF-8"?><Response></Response>')}catch(i){console.error("[SMSChannel] Error handling webhook:",i),n.writeHead(400),n.end("Bad request")}})}async stop(){if(this.server)return new Promise(e=>{this.server.close(e)})}};var x=class extends l{isTriggerChannel=!1;_timeout;_pendingResolve;constructor(e={}){super(),this._timeout=e.timeout??12e4}listen(){}async send(e){this._pendingResolve?.(e),this._pendingResolve=void 0}normalize(e){let n=e;return{message:typeof n.message=="string"?n.message:JSON.stringify(n),data:n,conversationId:`mcp-${Date.now()}-${Math.random().toString(36).slice(2,7)}`}}async trigger(e){let n=this.normalize(e);return new Promise((t,i)=>{let s=setTimeout(()=>{this._pendingResolve=void 0,i(new Error(`McpChannel: agent did not respond within ${this._timeout}ms`))},this._timeout);this._pendingResolve=r=>{clearTimeout(s),t(r.output)},this.handleMessage(n).catch(r=>{clearTimeout(s),this._pendingResolve=void 0,i(r instanceof Error?r:new Error(String(r)))})})}asAgentDefinition(e,n){return{name:e.name,description:e.description,...n!==void 0&&{inputSchema:n},invoke:t=>this.trigger(t)}}};0&&(module.exports={BaseChannel,DiscordChannel,EmailChannel,McpChannel,SMSChannel,ScheduledChannel,SlackChannel,TelegramChannel,WebhookChannel});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { B as BaseChannel, D as DiscordChannel, b as DiscordChannelConfig, E as EmailChannel, c as EmailChannelConfig, M as McpChannel, d as McpChannelConfig, e as SMSChannel, f as SMSChannelConfig, g as ScheduledChannel, h as ScheduledChannelConfig, j as SlackChannel, k as SlackChannelConfig, T as TelegramChannel, l as TelegramChannelConfig, W as WebhookChannel, m as WebhookChannelConfig } from '../index-
|
|
1
|
+
export { B as BaseChannel, D as DiscordChannel, b as DiscordChannelConfig, E as EmailChannel, c as EmailChannelConfig, M as McpChannel, d as McpChannelConfig, e as SMSChannel, f as SMSChannelConfig, g as ScheduledChannel, h as ScheduledChannelConfig, j as SlackChannel, k as SlackChannelConfig, T as TelegramChannel, l as TelegramChannelConfig, W as WebhookChannel, m as WebhookChannelConfig } from '../index-CA38tE7C.cjs';
|
|
2
2
|
import '../types-C3EZvpe0.cjs';
|
|
3
3
|
import 'toolpack-sdk';
|
|
4
4
|
import 'events';
|
package/dist/channels/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { B as BaseChannel, D as DiscordChannel, b as DiscordChannelConfig, E as EmailChannel, c as EmailChannelConfig, M as McpChannel, d as McpChannelConfig, e as SMSChannel, f as SMSChannelConfig, g as ScheduledChannel, h as ScheduledChannelConfig, j as SlackChannel, k as SlackChannelConfig, T as TelegramChannel, l as TelegramChannelConfig, W as WebhookChannel, m as WebhookChannelConfig } from '../index-
|
|
1
|
+
export { B as BaseChannel, D as DiscordChannel, b as DiscordChannelConfig, E as EmailChannel, c as EmailChannelConfig, M as McpChannel, d as McpChannelConfig, e as SMSChannel, f as SMSChannelConfig, g as ScheduledChannel, h as ScheduledChannelConfig, j as SlackChannel, k as SlackChannelConfig, T as TelegramChannel, l as TelegramChannelConfig, W as WebhookChannel, m as WebhookChannelConfig } from '../index-BCBukKC4.js';
|
|
2
2
|
import '../types-C3EZvpe0.js';
|
|
3
3
|
import 'toolpack-sdk';
|
|
4
4
|
import 'events';
|
package/dist/channels/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var l=class{name;_handler;onMessage(e){this._handler=e}async handleMessage(e){this._handler&&await this._handler(e)}};import{createHmac as $,timingSafeEqual as A}from"crypto";var C=class extends l{isTriggerChannel=!1;config;server;participantCache=new Map;botUserId;allowedChannels;constructor(e){super(),this.config={port:3e3,...e},this.name=e.name;let n=e.channel;this.allowedChannels=n==null?null:Array.isArray(n)?n:[n]}listen(){typeof process<"u"&&import("http").then(e=>{this.server=e.createServer((n,t)=>{this.handleRequest(n,t)}),this.server.listen(this.config.port,()=>{console.log(`[SlackChannel] Listening on port ${this.config.port}`),this.runStartupCheck().catch(()=>{})})}).catch(e=>{console.error("[SlackChannel] Failed to start HTTP server:",e)})}async runStartupCheck(){try{let n=await(await fetch("https://slack.com/api/auth.test",{method:"POST",headers:{Authorization:`Bearer ${this.config.token}`,"Content-Type":"application/json"}})).json();n.ok?(this.botUserId=n.user_id,console.log(`[SlackChannel] Connected as @${n.user} (${n.user_id}) in workspace "${n.team}" \u2014 ${n.url}`)):console.warn(`[SlackChannel] auth.test failed: ${n.error}. Check your bot token.`)}catch(e){console.warn("[SlackChannel] Startup self-check failed (network error):",e)}}verifySignature(e,n){let t=e["x-slack-request-timestamp"],i=e["x-slack-signature"];if(!t||!i||Array.isArray(t)||Array.isArray(i))return!1;let r=parseInt(t,10),s=Math.floor(Date.now()/1e3);if(isNaN(r)||Math.abs(s-r)>300)return!1;let o=`v0:${t}:${n}`,d=`v0=${$("sha256",this.config.signingSecret).update(o).digest("hex")}`;if(d.length!==i.length)return!1;try{return A(Buffer.from(d),Buffer.from(i))}catch{return!1}}async send(e){let n=e.metadata?.threadTs??e.metadata?.thread_ts??e.metadata?.threadId,i=e.metadata?.channelId??(this.allowedChannels&&this.allowedChannels.length>0?this.allowedChannels[0]:void 0);if(!i)throw new Error("[SlackChannel] Cannot send: no channel configured and metadata.channelId is missing. Provide a target via SlackChannelConfig.channel or output.metadata.channelId.");let r={channel:i,text:e.output};n&&(r.thread_ts=n);let s=await fetch("https://slack.com/api/chat.postMessage",{method:"POST",headers:{Authorization:`Bearer ${this.config.token}`,"Content-Type":"application/json"},body:JSON.stringify(r)});if(!s.ok)throw new Error(`Failed to send Slack message: ${s.statusText}`);let o=await s.json();if(!o.ok)throw new Error(`Slack API error: ${o.error}`)}normalize(e){let n=e,i=(n.text||"").replace(/<(https?:\/\/[^|>]+)\|([^>]+)>/g,"$2 ($1)").replace(/<(https?:\/\/[^>]+)>/g,"$1").replace(/<!here>/g,"@here").replace(/<!channel>/g,"@channel").replace(/<!everyone>/g,"@everyone"),r=n.ts,s=n.thread_ts,o=s!==void 0&&s!==r,a=n.user,d=a?{kind:"user",id:a}:void 0,m=/<@([A-Z0-9]+)>/g,u=[],f;for(;(f=m.exec(i))!==null;)u.push(f[1]);let p=n.channel;return{message:i,conversationId:o?s:p||r||"",data:n,participant:d,context:{user:a,channel:p,team:n.team,channelType:n.channel_type,threadId:o?s:void 0,mentions:u.length>0?u:void 0,channelId:p,channelName:typeof this.config.channel=="string"?this.config.channel:p}}}async resolveParticipant(e){let n=e.participant?.id??e.context?.user;if(!n)return;let t=this.participantCache.get(n);if(t)return t;try{let i=await fetch(`https://slack.com/api/users.info?user=${encodeURIComponent(n)}`,{method:"GET",headers:{Authorization:`Bearer ${this.config.token}`}});if(!i.ok)return{kind:"user",id:n};let r=await i.json();if(!r.ok||!r.user){let a={kind:"user",id:n};return this.participantCache.set(n,a),a}let s=r.user.profile?.display_name||r.user.profile?.real_name||r.user.real_name||r.user.name||n,o={kind:"user",id:n,displayName:s,metadata:{slackUser:r.user}};return this.participantCache.set(n,o),o}catch{return{kind:"user",id:n}}}invalidateParticipant(e){this.participantCache.delete(e)}shouldProcessEvent(e){let n=e.type;if(n!=="message"&&n!=="app_mention")return!1;if(this.allowedChannels!==null){let s=e.channel_type;if(!(s==="im"||s==="mpim")){let a=e.channel;if(!a||!this.allowedChannels.includes(a))return!1}}let t=e.user;if(this.botUserId&&t===this.botUserId)return!1;let i=e.bot_id;if(!i)return!0;let r=this.config.blockedBotIds??[];if(r.includes(i)||t!==void 0&&r.includes(t))return!1;if(this.config.allowedBotIds!==void 0){let s=this.config.allowedBotIds;return s.includes(i)||t!==void 0&&s.includes(t)}return!0}handleRequest(e,n){if(e.method!=="POST"){n.writeHead(405),n.end("Method not allowed");return}let t="";e.on("data",i=>{t+=i.toString()}),e.on("end",()=>{if(!this.verifySignature(e.headers,t)){n.writeHead(401),n.end("Invalid signature");return}try{let i=JSON.parse(t);if(i.type==="url_verification"){n.writeHead(200,{"Content-Type":"application/json"}),n.end(JSON.stringify({challenge:i.challenge}));return}if(i.type==="event_callback"&&i.event){let r=i.event;if(this.shouldProcessEvent(r)){let s=this.normalize(r);this.handleMessage(s)}else r.type==="user_change"&&r.user&&this.invalidateParticipant(r.user.id);n.writeHead(200),n.end("OK");return}n.writeHead(200),n.end("OK")}catch(i){console.error("[SlackChannel] Error handling request:",i),n.writeHead(400),n.end("Bad request")}})}async stop(){if(this.server)return new Promise(e=>{this.server.close(e)})}};var v=class extends l{isTriggerChannel=!1;config;server;pendingResponses=new Map;constructor(e){super(),this.name=e.name,this.config={port:e.port??3e3,path:e.path??"/webhook"}}listen(){typeof process<"u"&&import("http").then(e=>{this.server=e.createServer((n,t)=>{this.handleRequest(n,t)}),this.server.listen(this.config.port,()=>{console.log(`[WebhookChannel] Listening on port ${this.config.port}${this.config.path}`)})}).catch(e=>{console.error("[WebhookChannel] Failed to start HTTP server:",e)})}async send(e){let n=e.metadata?.conversationId;if(n&&this.pendingResponses.has(n)){let t=this.pendingResponses.get(n);this.pendingResponses.delete(n),t.resolve({output:e.output,metadata:e.metadata})}}normalize(e){let n=e,t=n.headers||{},i=t["x-session-id"]||t["X-Session-Id"]||n.sessionId||n.conversationId||this.generateSessionId();return{message:n.message||n.text||"",intent:n.intent,conversationId:i,data:n,context:{headers:n.headers,method:n.method,sessionId:i}}}handleRequest(e,n){if(e.url!==this.config.path){n.writeHead(404),n.end("Not found");return}if(e.method!=="POST"){n.writeHead(405),n.end("Method not allowed");return}let t="";e.on("data",i=>{t+=i.toString()}),e.on("end",()=>{try{let i=JSON.parse(t),r=this.normalize(i),s=r.conversationId||this.generateSessionId(),o=new Promise((a,d)=>{this.pendingResponses.set(s,{resolve:a,reject:d}),setTimeout(()=>{this.pendingResponses.has(s)&&(this.pendingResponses.delete(s),d(new Error("Agent response timeout")))},3e4)});this.handleMessage({...r,conversationId:s,context:{...r.context,sessionId:s}}),o.then(a=>{n.writeHead(200,{"Content-Type":"application/json"}),n.end(JSON.stringify(a))}).catch(a=>{n.writeHead(500,{"Content-Type":"application/json"}),n.end(JSON.stringify({error:a.message}))})}catch(i){console.error("[WebhookChannel] Error handling request:",i),n.writeHead(400,{"Content-Type":"application/json"}),n.end(JSON.stringify({error:"Bad request"}))}})}generateSessionId(){return`webhook-${Date.now()}-${Math.random().toString(36).substring(2,9)}`}async stop(){if(this.server)return new Promise(e=>{this.server.close(e)})}};import{CronExpressionParser as x}from"cron-parser";var y=class extends l{isTriggerChannel=!0;config;timer;_stopped=!1;_generation=0;constructor(e){if(super(),!e.cron&&!e.store)throw new Error("ScheduledChannel: provide at least one of `cron` (static schedule) or `store` (dynamic scheduling).");if(e.cron)try{x.parse(e.cron)}catch(n){throw new Error(`ScheduledChannel: invalid cron expression '${e.cron}': ${n.message}`)}if(e.store&&!e.name&&console.warn("[ScheduledChannel] A `store` was provided without a `name`. All store queries will be unscoped and will pick up jobs from every channel. Set `name` to scope this channel to its own jobs."),e.idlePollMs!==void 0&&e.idlePollMs<1e3)throw new Error(`ScheduledChannel: idlePollMs must be at least 1000ms (got ${e.idlePollMs}). Values below 1 second create a tight polling loop.`);this.config=e,this.name=e.name}listen(){this._generation++,this.timer&&(clearTimeout(this.timer),this.timer=void 0),this._stopped=!1,this.config.store?this._listenWithStore():this._listenStatic()}async stop(){this._stopped=!0,this.timer&&(clearTimeout(this.timer),this.timer=void 0)}async send(e){}normalize(e){let n=e,t=new Date,i=`${t.getFullYear()}-${t.getMonth()+1}-${t.getDate()}`;return{intent:n?.intent??this.config.intent,message:n?.message??this.config.message??`Scheduled task triggered at ${t.toISOString()}`,conversationId:`scheduled:${this.name??"default"}:${i}`,data:{...n?.payload??{},scheduled:!0,jobId:n?.id,cron:n?.cron??this.config.cron,timestamp:t.toISOString()}}}_listenStatic(){this._scheduleNextStatic(this._generation)}_scheduleNextStatic(e){if(this._stopped||e!==this._generation)return;let n=this._nextRunFromCron(this.config.cron),t=n.getTime()-Date.now();if(t<=0){this.timer=setTimeout(()=>this._scheduleNextStatic(e),0);return}console.log(`[ScheduledChannel:${this.name??"default"}] Next run: ${n.toISOString()}`),this.timer=setTimeout(async()=>{this._stopped||e!==this._generation||(await this._triggerStatic(),this._scheduleNextStatic(e))},t)}async _triggerStatic(){if(!this._handler){console.warn(`[ScheduledChannel:${this.name??"default"}] Cron fired but no message handler is registered. Call onMessage() before listen() to avoid silently losing triggers.`);return}let e=this.normalize(null);try{await this.handleMessage(e)}catch(n){console.error(`[ScheduledChannel:${this.name??"default"}] Error on trigger:`,n)}}_listenWithStore(){let e=this.config.store,n=this._generation;if(n===1){let i=e.resetStuck(this.name);i>0&&console.log(`[ScheduledChannel:${this.name??"default"}] Reset ${i} stuck 'running' job(s) to 'pending'.`)}if(this.config.cron){let{duplicate:i}=e.create({channelName:this.name,cron:this.config.cron,intent:this.config.intent,message:this.config.message});i||console.log(`[ScheduledChannel:${this.name??"default"}] Seeded static cron '${this.config.cron}' into store.`)}let t=e.getDue(Date.now(),this.name);t.length>0&&(console.log(`[ScheduledChannel:${this.name??"default"}] Recovering ${t.length} overdue job(s).`),Promise.allSettled(t.map(i=>this._triggerJob(i)))),this._scheduleNextFromStore(n)}_scheduleNextFromStore(e){if(this._stopped||e!==this._generation)return;let n=this.config.store,t=n.getNextPending(this.name);if(!t){let r=this.config.idlePollMs??3e4;this.timer=setTimeout(()=>this._scheduleNextFromStore(e),r);return}let i=Math.max(0,t.nextRunAt-Date.now());console.log(`[ScheduledChannel:${this.name??"default"}] Next store job at ${new Date(t.nextRunAt).toISOString()} (in ${Math.round(i/1e3)}s)`),this.timer=setTimeout(async()=>{if(this._stopped||e!==this._generation)return;let r=n.getDue(Date.now(),this.name);await Promise.allSettled(r.map(s=>this._triggerJob(s))),this._scheduleNextFromStore(e)},i)}async _triggerJob(e){let n=this.config.store;if(!this._handler){console.warn(`[ScheduledChannel:${this.name??"default"}] Job ${e.id} fired but no message handler is registered. Call onMessage() before listen() to avoid silently losing jobs.`),n.markFailed(e.id,"No message handler registered");return}n.markRunning(e.id);let t=this.normalize(e);try{await this.handleMessage(t),n.markCompleted(e.id)}catch(i){let r=i instanceof Error?i.message:String(i);console.error(`[ScheduledChannel:${this.name??"default"}] Job ${e.id} failed:`,i),n.markFailed(e.id,r)}}_nextRunFromCron(e){return x.parse(e,{currentDate:new Date}).next().toDate()}};var k=class extends l{isTriggerChannel=!1;config;offset=0;pollingInterval;server;botUserId;botUsername;constructor(e){super(),this.name=e.name,this.config=e}listen(){this.runStartupCheck().catch(()=>{}),this.config.webhookUrl?this.startWebhook():this.startPolling()}async runStartupCheck(){try{let n=await(await fetch(`https://api.telegram.org/bot${this.config.token}/getMe`)).json();if(n.ok&&n.result){let t=n.result;this.botUserId=t.id!=null?String(t.id):void 0,this.botUsername=t.username,console.log(`[TelegramChannel] Connected as @${t.username} (id: ${t.id}, name: ${t.first_name})`)}else console.warn(`[TelegramChannel] getMe failed: ${n.description??"unknown error"}. Check your bot token.`)}catch(e){console.warn("[TelegramChannel] Startup self-check failed (network error):",e)}}async send(e){let n=e.metadata?.chatId;if(!n)throw new Error("Telegram send requires chatId in metadata");let t=await fetch(`https://api.telegram.org/bot${this.config.token}/sendMessage`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({chat_id:n,text:e.output,parse_mode:"Markdown"})});if(!t.ok)throw new Error(`Failed to send Telegram message: ${t.statusText}`);let i=await t.json();if(!i.ok)throw new Error(`Telegram API error: ${i.description}`)}normalize(e){let n=e,t=n.message||n.edited_message||{},i=t.text||"",r=t.chat||{},s=t.from||{},o=s.id!=null?String(s.id):void 0,a=s.first_name||s.username||o,d=o?{kind:"user",id:o,displayName:a??o}:void 0,m=t.entities??[],u=[];for(let w of m)if(w.type==="text_mention"&&w.user){let P=w.user;P.id!=null&&u.push(String(P.id))}let f=r.type,p=r.id!=null?String(r.id):"";return{message:i,conversationId:p,data:n,participant:d,context:{chatId:r.id,userId:s.id,username:s.username,firstName:s.first_name,lastName:s.last_name,messageId:t.message_id,channelType:f,channelId:p,channelName:r.title,mentions:u.length>0?u:void 0}}}startPolling(){console.log("[TelegramChannel] Starting polling mode"),this.pollingInterval=setInterval(async()=>{try{await this.pollUpdates()}catch(e){console.error("[TelegramChannel] Polling error:",e)}},5e3)}async pollUpdates(){let e=`https://api.telegram.org/bot${this.config.token}/getUpdates?offset=${this.offset}&limit=100`,n=await fetch(e);if(!n.ok)throw new Error(`Telegram getUpdates failed: ${n.statusText}`);let t=await n.json();if(!t.ok)throw new Error("Telegram getUpdates returned not ok");for(let i of t.result){let r=i.update_id;r>=this.offset&&(this.offset=r+1);try{let s=this.normalize(i);await this.handleMessage(s)}catch(s){console.error("[TelegramChannel] Error processing update:",s)}}}startWebhook(){typeof process>"u"||(console.log("[TelegramChannel] Starting webhook mode"),import("http").then(e=>{this.server=e.createServer((i,r)=>{this.handleWebhookRequest(i,r)});let n=new URL(this.config.webhookUrl||"http://localhost:3000"),t=parseInt(n.port,10)||3e3;this.server.listen(t,()=>{console.log(`[TelegramChannel] Webhook server listening on port ${t}`)}),this.setWebhook()}).catch(e=>{console.error("[TelegramChannel] Failed to start webhook server:",e)}))}async setWebhook(){if(!this.config.webhookUrl)return;let e=await fetch(`https://api.telegram.org/bot${this.config.token}/setWebhook`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({url:this.config.webhookUrl})});if(!e.ok){console.error("[TelegramChannel] Failed to set webhook");return}let n=await e.json();n.ok?console.log("[TelegramChannel] Webhook set successfully"):console.error("[TelegramChannel] Failed to set webhook:",n.description)}handleWebhookRequest(e,n){if(e.method!=="POST"){n.writeHead(405),n.end("Method not allowed");return}let t="";e.on("data",i=>{t+=i.toString()}),e.on("end",()=>{try{let i=JSON.parse(t);this.handleMessage(this.normalize(i)).catch(r=>{console.error("[TelegramChannel] Error processing webhook:",r)}),n.writeHead(200),n.end("OK")}catch(i){console.error("[TelegramChannel] Error parsing webhook:",i),n.writeHead(400),n.end("Bad request")}})}async stop(){if(this.pollingInterval&&(clearInterval(this.pollingInterval),this.pollingInterval=void 0),this.server)return new Promise(e=>{this.server.close(e)});if(this.config.webhookUrl)try{await fetch(`https://api.telegram.org/bot${this.config.token}/deleteWebhook`,{method:"POST"})}catch(e){console.error("[TelegramChannel] Failed to delete webhook:",e)}}};var M=new Set([1,3]),_=/<@!?(\d+)>/g,D="https://discord.com/api/v10",S=class extends l{isTriggerChannel=!1;config;allowedChannelIds;botUserId;participantCache=new Map;client;constructor(e){super(),this.config=e,this.name=e.name,e.channelId==null?this.allowedChannelIds=new Set:Array.isArray(e.channelId)?this.allowedChannelIds=new Set(e.channelId):this.allowedChannelIds=new Set([e.channelId])}shouldProcessEvent(e){return!e.author||e.webhookId||this.botUserId&&e.author.id===this.botUserId||this.config.guildId&&e.guildId!==this.config.guildId||this.allowedChannelIds.size>0&&(!e.channelId||!this.allowedChannelIds.has(e.channelId))?!1:e.author.bot||e.author.system?this.config.blockedBotIds?.includes(e.author.id)?!1:this.config.allowedBotIds?this.config.allowedBotIds.includes(e.author.id):!1:!0}normalize(e){let n=e,t=n.channelId,i=(t??"")+(n.thread?.id?`:${n.thread.id}`:""),r=n.channel?.type,s=r!==void 0&&M.has(r),o=n.author?.id,a=n.author?.globalName??n.author?.username,d=[];if(n.content){_.lastIndex=0;let m;for(;(m=_.exec(n.content))!==null;)d.push(m[1])}return{message:n.content,conversationId:i,data:n,participant:o?{kind:"user",id:o,displayName:a??void 0}:void 0,context:{userId:o,username:n.author?.username,channelType:s?"dm":"channel",channelId:t,channelName:n.channel?.name,guildId:n.guildId,threadId:n.thread?.id,messageId:n.id,mentions:d.length>0?d:void 0,isMentioned:this.botUserId?d.includes(this.botUserId):void 0}}}async resolveParticipant(e){let n=e.participant?.id??e.context?.userId;if(!n)return;let t=this.participantCache.get(n);if(t)return t;try{let i=await fetch(`${D}/users/${n}`,{headers:{Authorization:`Bot ${this.config.token}`}});if(!i.ok)return console.warn(`[DiscordChannel] Failed to resolve user ${n}: HTTP ${i.status}`),{kind:"user",id:n};let r=await i.json(),s=r.global_name??r.username,o={kind:"user",id:r.id,displayName:s};return this.participantCache.set(n,o),o}catch(i){return console.warn(`[DiscordChannel] resolveParticipant error for ${n}:`,i),{kind:"user",id:n}}}invalidateParticipant(e){this.participantCache.delete(e)}async send(e){if(!this.client)throw new Error("[DiscordChannel] Client not initialized. Did you call listen()?");let n=e.metadata?.threadId;if(n){let r=await this.client.channels.fetch(n);if(r&&"send"in r)try{await r.send({content:e.output});return}catch(s){throw console.error("[DiscordChannel] Failed to send to thread:",s),new Error(`[DiscordChannel] Failed to send Discord message: ${s instanceof Error?s.message:String(s)}`)}console.warn(`[DiscordChannel] Thread ${n} not found or not sendable; falling back to channel send.`)}let t=e.metadata?.channelId??(this.allowedChannelIds.size>0?[...this.allowedChannelIds][0]:void 0);if(!t)throw new Error("[DiscordChannel] No channel ID available for sending. Configure channelId or pass output.metadata.channelId.");let i=await this.client.channels.fetch(t);if(!i||!("send"in i))throw new Error(`[DiscordChannel] Channel ${t} not found or is not a text channel`);try{await i.send({content:e.output})}catch(r){throw console.error("[DiscordChannel] Failed to send to channel:",r),new Error(`[DiscordChannel] Failed to send Discord message: ${r instanceof Error?r.message:String(r)}`)}}listen(){typeof process>"u"||import("discord.js").then(e=>{let{Client:n,GatewayIntentBits:t}=e;this.client=new n({intents:[t.Guilds,t.GuildMessages,t.MessageContent,t.DirectMessages]}),this.client.on("ready",()=>{let i=this.client.user;this.botUserId=i?.id;let r=this.allowedChannelIds.size===0?"all channels":[...this.allowedChannelIds].join(", "),s=this.config.guildId??"all guilds";console.log(`[DiscordChannel] Logged in as ${i?.tag??"unknown"} (botUserId=${this.botUserId??"unknown"}) | guild=${s} | channels=${r}`)}),this.client.on("messageCreate",i=>{let r=i;if(!this.shouldProcessEvent(r))return;let s=this.normalize(r);this.handleMessage(s)}),this.client.on("userUpdate",(i,r)=>{let s=r;s?.id&&this.invalidateParticipant(s.id)}),this.client.login(this.config.token).catch(i=>{console.error("[DiscordChannel] Failed to login to Discord:",i)})}).catch(e=>{console.error("[DiscordChannel] Failed to initialize Discord client:",e),console.error("[DiscordChannel] Make sure discord.js is installed: npm install discord.js")})}async stop(){this.client&&(await this.client.destroy(),this.client=void 0)}};var b=class extends l{isTriggerChannel=!0;config;transporter;constructor(e){super(),this.config=e,this.name=e.name}listen(){typeof process<"u"&&import("nodemailer").then(e=>{this.transporter=e.default.createTransport({host:this.config.smtp.host,port:this.config.smtp.port,secure:this.config.smtp.secure??this.config.smtp.port===465,auth:{user:this.config.smtp.auth.user,pass:this.config.smtp.auth.pass}}),console.log(`[EmailChannel] Email transporter initialized for ${this.config.from}`)}).catch(e=>{console.error("[EmailChannel] Failed to initialize nodemailer:",e),console.error("[EmailChannel] Make sure to install nodemailer: npm install nodemailer")})}async send(e){if(!this.transporter)throw new Error("Email transporter not initialized. Did you call listen()?");let n=Array.isArray(this.config.to)?this.config.to:[this.config.to],t=this.config.subject||"Message from Agent",i={from:this.config.from,to:n.join(", "),subject:t,text:e.output,html:this.formatAsHtml(e.output)};try{await this.transporter.sendMail(i)}catch(r){throw console.error("[EmailChannel] Failed to send email:",r),new Error(`Failed to send email: ${r instanceof Error?r.message:String(r)}`)}}normalize(e){throw new Error("EmailChannel is outbound-only. Use WebhookChannel with email webhook events for inbound email.")}formatAsHtml(e){return e.split(`
|
|
1
|
+
var d=class{name;_handler;onMessage(e){this._handler=e}async handleMessage(e){this._handler&&await this._handler(e)}};import{createHmac as $,timingSafeEqual as A}from"crypto";var C=class extends d{isTriggerChannel=!1;config;server;participantCache=new Map;botUserId;botId;allowedChannels;constructor(e){super(),this.config={port:3e3,...e},this.name=e.name;let n=e.channel;this.allowedChannels=n==null?null:Array.isArray(n)?n:[n]}listen(){typeof process<"u"&&import("http").then(e=>{this.server=e.createServer((n,t)=>{this.handleRequest(n,t)}),this.server.listen(this.config.port,()=>{console.log(`[SlackChannel] Listening on port ${this.config.port}`),this.runStartupCheck().catch(()=>{})})}).catch(e=>{console.error("[SlackChannel] Failed to start HTTP server:",e)})}async runStartupCheck(){try{let n=await(await fetch("https://slack.com/api/auth.test",{method:"POST",headers:{Authorization:`Bearer ${this.config.token}`,"Content-Type":"application/json"}})).json();n.ok?(this.botUserId=n.user_id,this.botId=n.bot_id,console.log(`[SlackChannel] Connected as @${n.user} (${n.user_id}) in workspace "${n.team}" \u2014 ${n.url}`)):console.warn(`[SlackChannel] auth.test failed: ${n.error}. Check your bot token.`)}catch(e){console.warn("[SlackChannel] Startup self-check failed (network error):",e)}}verifySignature(e,n){let t=e["x-slack-request-timestamp"],i=e["x-slack-signature"];if(!t||!i||Array.isArray(t)||Array.isArray(i))return!1;let s=parseInt(t,10),r=Math.floor(Date.now()/1e3);if(isNaN(s)||Math.abs(r-s)>300)return!1;let o=`v0:${t}:${n}`,l=`v0=${$("sha256",this.config.signingSecret).update(o).digest("hex")}`;if(l.length!==i.length)return!1;try{return A(Buffer.from(l),Buffer.from(i))}catch{return!1}}async send(e){let n=e.metadata?.threadTs??e.metadata?.thread_ts??e.metadata?.threadId,i=e.metadata?.channelId??(this.allowedChannels&&this.allowedChannels.length>0?this.allowedChannels[0]:void 0);if(!i)throw new Error("[SlackChannel] Cannot send: no channel configured and metadata.channelId is missing. Provide a target via SlackChannelConfig.channel or output.metadata.channelId.");let s={channel:i,text:e.output};n&&(s.thread_ts=n);let r=await fetch("https://slack.com/api/chat.postMessage",{method:"POST",headers:{Authorization:`Bearer ${this.config.token}`,"Content-Type":"application/json"},body:JSON.stringify(s)});if(!r.ok)throw new Error(`Failed to send Slack message: ${r.statusText}`);let o=await r.json();if(!o.ok)throw new Error(`Slack API error: ${o.error}`)}normalize(e){let n=e,i=(n.text||"").replace(/<(https?:\/\/[^|>]+)\|([^>]+)>/g,"$2 ($1)").replace(/<(https?:\/\/[^>]+)>/g,"$1").replace(/<!here>/g,"@here").replace(/<!channel>/g,"@channel").replace(/<!everyone>/g,"@everyone"),s=n.ts,r=n.thread_ts,o=r!==void 0&&r!==s,a=n.user,l=a?{kind:"user",id:a}:void 0,m=/<@([A-Z0-9]+)>/g,g=[],f;for(;(f=m.exec(i))!==null;)g.push(f[1]);let p=n.channel;return{message:i,conversationId:o?r:p||s||"",data:n,participant:l,context:{user:a,channel:p,team:n.team,channelType:n.channel_type,threadId:o?r:void 0,mentions:g.length>0?g:void 0,channelId:p,channelName:typeof this.config.channel=="string"?this.config.channel:p}}}async resolveParticipant(e){let n=e.participant?.id??e.context?.user;if(!n)return;let t=this.participantCache.get(n);if(t)return t;try{let i=await fetch(`https://slack.com/api/users.info?user=${encodeURIComponent(n)}`,{method:"GET",headers:{Authorization:`Bearer ${this.config.token}`}});if(!i.ok)return{kind:"user",id:n};let s=await i.json();if(!s.ok||!s.user){let a={kind:"user",id:n};return this.participantCache.set(n,a),a}let r=s.user.profile?.display_name||s.user.profile?.real_name||s.user.real_name||s.user.name||n,o={kind:"user",id:n,displayName:r,metadata:{slackUser:s.user}};return this.participantCache.set(n,o),o}catch{return{kind:"user",id:n}}}invalidateParticipant(e){this.participantCache.delete(e)}shouldProcessEvent(e){let n=e.type;if(n!=="message"&&n!=="app_mention")return!1;if(this.allowedChannels!==null){let r=e.channel_type;if(!(r==="im"||r==="mpim")){let a=e.channel;if(!a||!this.allowedChannels.includes(a))return!1}}let t=e.user;if(this.botUserId&&t===this.botUserId)return!1;let i=e.bot_id;if(console.log(`[SlackChannel:shouldProcessEvent] subtype=${e.subtype} user=${t} bot_id=${i} this.botUserId=${this.botUserId} this.botId=${this.botId}`),!i)return!0;if(this.botId&&i===this.botId)return!1;let s=this.config.blockedBotIds??[];if(s.includes(i)||t!==void 0&&s.includes(t))return!1;if(this.config.allowedBotIds!==void 0){let r=this.config.allowedBotIds;return r.includes(i)||t!==void 0&&r.includes(t)}return!0}handleRequest(e,n){if(e.method!=="POST"){n.writeHead(405),n.end("Method not allowed");return}let t="";e.on("data",i=>{t+=i.toString()}),e.on("end",()=>{if(!this.verifySignature(e.headers,t)){n.writeHead(401),n.end("Invalid signature");return}try{let i=JSON.parse(t);if(i.type==="url_verification"){n.writeHead(200,{"Content-Type":"application/json"}),n.end(JSON.stringify({challenge:i.challenge}));return}if(i.type==="event_callback"&&i.event){let s=i.event;if(this.shouldProcessEvent(s)){let r=this.normalize(s);this.handleMessage(r)}else s.type==="user_change"&&s.user&&this.invalidateParticipant(s.user.id);n.writeHead(200),n.end("OK");return}n.writeHead(200),n.end("OK")}catch(i){console.error("[SlackChannel] Error handling request:",i),n.writeHead(400),n.end("Bad request")}})}async stop(){if(this.server)return new Promise(e=>{this.server.close(e)})}};var v=class extends d{isTriggerChannel=!1;config;server;pendingResponses=new Map;constructor(e){super(),this.name=e.name,this.config={port:e.port??3e3,path:e.path??"/webhook"}}listen(){typeof process<"u"&&import("http").then(e=>{this.server=e.createServer((n,t)=>{this.handleRequest(n,t)}),this.server.listen(this.config.port,()=>{console.log(`[WebhookChannel] Listening on port ${this.config.port}${this.config.path}`)})}).catch(e=>{console.error("[WebhookChannel] Failed to start HTTP server:",e)})}async send(e){let n=e.metadata?.conversationId;if(n&&this.pendingResponses.has(n)){let t=this.pendingResponses.get(n);this.pendingResponses.delete(n),t.resolve({output:e.output,metadata:e.metadata})}}normalize(e){let n=e,t=n.headers||{},i=t["x-session-id"]||t["X-Session-Id"]||n.sessionId||n.conversationId||this.generateSessionId();return{message:n.message||n.text||"",intent:n.intent,conversationId:i,data:n,context:{headers:n.headers,method:n.method,sessionId:i}}}handleRequest(e,n){if(e.url!==this.config.path){n.writeHead(404),n.end("Not found");return}if(e.method!=="POST"){n.writeHead(405),n.end("Method not allowed");return}let t="";e.on("data",i=>{t+=i.toString()}),e.on("end",()=>{try{let i=JSON.parse(t),s=this.normalize(i),r=s.conversationId||this.generateSessionId(),o=new Promise((a,l)=>{this.pendingResponses.set(r,{resolve:a,reject:l}),setTimeout(()=>{this.pendingResponses.has(r)&&(this.pendingResponses.delete(r),l(new Error("Agent response timeout")))},3e4)});this.handleMessage({...s,conversationId:r,context:{...s.context,sessionId:r}}),o.then(a=>{n.writeHead(200,{"Content-Type":"application/json"}),n.end(JSON.stringify(a))}).catch(a=>{n.writeHead(500,{"Content-Type":"application/json"}),n.end(JSON.stringify({error:a.message}))})}catch(i){console.error("[WebhookChannel] Error handling request:",i),n.writeHead(400,{"Content-Type":"application/json"}),n.end(JSON.stringify({error:"Bad request"}))}})}generateSessionId(){return`webhook-${Date.now()}-${Math.random().toString(36).substring(2,9)}`}async stop(){if(this.server)return new Promise(e=>{this.server.close(e)})}};import{CronExpressionParser as x}from"cron-parser";var y=class extends d{isTriggerChannel=!0;config;timer;_stopped=!1;_generation=0;constructor(e){if(super(),!e.cron&&!e.store)throw new Error("ScheduledChannel: provide at least one of `cron` (static schedule) or `store` (dynamic scheduling).");if(e.cron)try{x.parse(e.cron)}catch(n){throw new Error(`ScheduledChannel: invalid cron expression '${e.cron}': ${n.message}`)}if(e.store&&!e.name&&console.warn("[ScheduledChannel] A `store` was provided without a `name`. All store queries will be unscoped and will pick up jobs from every channel. Set `name` to scope this channel to its own jobs."),e.idlePollMs!==void 0&&e.idlePollMs<1e3)throw new Error(`ScheduledChannel: idlePollMs must be at least 1000ms (got ${e.idlePollMs}). Values below 1 second create a tight polling loop.`);this.config=e,this.name=e.name}listen(){this._generation++,this.timer&&(clearTimeout(this.timer),this.timer=void 0),this._stopped=!1,this.config.store?this._listenWithStore():this._listenStatic()}async stop(){this._stopped=!0,this.timer&&(clearTimeout(this.timer),this.timer=void 0)}async send(e){}normalize(e){let n=e,t=new Date,i=`${t.getFullYear()}-${t.getMonth()+1}-${t.getDate()}`;return{intent:n?.intent??this.config.intent,message:n?.message??this.config.message??`Scheduled task triggered at ${t.toISOString()}`,conversationId:`scheduled:${this.name??"default"}:${i}`,data:{...n?.payload??{},scheduled:!0,jobId:n?.id,cron:n?.cron??this.config.cron,timestamp:t.toISOString()}}}_listenStatic(){this._scheduleNextStatic(this._generation)}_scheduleNextStatic(e){if(this._stopped||e!==this._generation)return;let n=this._nextRunFromCron(this.config.cron),t=n.getTime()-Date.now();if(t<=0){this.timer=setTimeout(()=>this._scheduleNextStatic(e),0);return}console.log(`[ScheduledChannel:${this.name??"default"}] Next run: ${n.toISOString()}`),this.timer=setTimeout(async()=>{this._stopped||e!==this._generation||(await this._triggerStatic(),this._scheduleNextStatic(e))},t)}async _triggerStatic(){if(!this._handler){console.warn(`[ScheduledChannel:${this.name??"default"}] Cron fired but no message handler is registered. Call onMessage() before listen() to avoid silently losing triggers.`);return}let e=this.normalize(null);try{await this.handleMessage(e)}catch(n){console.error(`[ScheduledChannel:${this.name??"default"}] Error on trigger:`,n)}}_listenWithStore(){let e=this.config.store,n=this._generation;if(n===1){let i=e.resetStuck(this.name);i>0&&console.log(`[ScheduledChannel:${this.name??"default"}] Reset ${i} stuck 'running' job(s) to 'pending'.`)}if(this.config.cron){let{duplicate:i}=e.create({channelName:this.name,cron:this.config.cron,intent:this.config.intent,message:this.config.message});i||console.log(`[ScheduledChannel:${this.name??"default"}] Seeded static cron '${this.config.cron}' into store.`)}let t=e.getDue(Date.now(),this.name);t.length>0&&(console.log(`[ScheduledChannel:${this.name??"default"}] Recovering ${t.length} overdue job(s).`),Promise.allSettled(t.map(i=>this._triggerJob(i)))),this._scheduleNextFromStore(n)}_scheduleNextFromStore(e){if(this._stopped||e!==this._generation)return;let n=this.config.store,t=n.getNextPending(this.name);if(!t){let s=this.config.idlePollMs??3e4;this.timer=setTimeout(()=>this._scheduleNextFromStore(e),s);return}let i=Math.max(0,t.nextRunAt-Date.now());console.log(`[ScheduledChannel:${this.name??"default"}] Next store job at ${new Date(t.nextRunAt).toISOString()} (in ${Math.round(i/1e3)}s)`),this.timer=setTimeout(async()=>{if(this._stopped||e!==this._generation)return;let s=n.getDue(Date.now(),this.name);await Promise.allSettled(s.map(r=>this._triggerJob(r))),this._scheduleNextFromStore(e)},i)}async _triggerJob(e){let n=this.config.store;if(!this._handler){console.warn(`[ScheduledChannel:${this.name??"default"}] Job ${e.id} fired but no message handler is registered. Call onMessage() before listen() to avoid silently losing jobs.`),n.markFailed(e.id,"No message handler registered");return}n.markRunning(e.id);let t=this.normalize(e);try{await this.handleMessage(t),n.markCompleted(e.id)}catch(i){let s=i instanceof Error?i.message:String(i);console.error(`[ScheduledChannel:${this.name??"default"}] Job ${e.id} failed:`,i),n.markFailed(e.id,s)}}_nextRunFromCron(e){return x.parse(e,{currentDate:new Date}).next().toDate()}};var k=class extends d{isTriggerChannel=!1;config;offset=0;pollingInterval;server;botUserId;botUsername;constructor(e){super(),this.name=e.name,this.config=e}listen(){this.runStartupCheck().catch(()=>{}),this.config.webhookUrl?this.startWebhook():this.startPolling()}async runStartupCheck(){try{let n=await(await fetch(`https://api.telegram.org/bot${this.config.token}/getMe`)).json();if(n.ok&&n.result){let t=n.result;this.botUserId=t.id!=null?String(t.id):void 0,this.botUsername=t.username,console.log(`[TelegramChannel] Connected as @${t.username} (id: ${t.id}, name: ${t.first_name})`)}else console.warn(`[TelegramChannel] getMe failed: ${n.description??"unknown error"}. Check your bot token.`)}catch(e){console.warn("[TelegramChannel] Startup self-check failed (network error):",e)}}async send(e){let n=e.metadata?.chatId;if(!n)throw new Error("Telegram send requires chatId in metadata");let t=await fetch(`https://api.telegram.org/bot${this.config.token}/sendMessage`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({chat_id:n,text:e.output,parse_mode:"Markdown"})});if(!t.ok)throw new Error(`Failed to send Telegram message: ${t.statusText}`);let i=await t.json();if(!i.ok)throw new Error(`Telegram API error: ${i.description}`)}normalize(e){let n=e,t=n.message||n.edited_message||{},i=t.text||"",s=t.chat||{},r=t.from||{},o=r.id!=null?String(r.id):void 0,a=r.first_name||r.username||o,l=o?{kind:"user",id:o,displayName:a??o}:void 0,m=t.entities??[],g=[];for(let w of m)if(w.type==="text_mention"&&w.user){let P=w.user;P.id!=null&&g.push(String(P.id))}let f=s.type,p=s.id!=null?String(s.id):"";return{message:i,conversationId:p,data:n,participant:l,context:{chatId:s.id,userId:r.id,username:r.username,firstName:r.first_name,lastName:r.last_name,messageId:t.message_id,channelType:f,channelId:p,channelName:s.title,mentions:g.length>0?g:void 0}}}startPolling(){console.log("[TelegramChannel] Starting polling mode"),this.pollingInterval=setInterval(async()=>{try{await this.pollUpdates()}catch(e){console.error("[TelegramChannel] Polling error:",e)}},5e3)}async pollUpdates(){let e=`https://api.telegram.org/bot${this.config.token}/getUpdates?offset=${this.offset}&limit=100`,n=await fetch(e);if(!n.ok)throw new Error(`Telegram getUpdates failed: ${n.statusText}`);let t=await n.json();if(!t.ok)throw new Error("Telegram getUpdates returned not ok");for(let i of t.result){let s=i.update_id;s>=this.offset&&(this.offset=s+1);try{let r=this.normalize(i);await this.handleMessage(r)}catch(r){console.error("[TelegramChannel] Error processing update:",r)}}}startWebhook(){typeof process>"u"||(console.log("[TelegramChannel] Starting webhook mode"),import("http").then(e=>{this.server=e.createServer((i,s)=>{this.handleWebhookRequest(i,s)});let n=new URL(this.config.webhookUrl||"http://localhost:3000"),t=parseInt(n.port,10)||3e3;this.server.listen(t,()=>{console.log(`[TelegramChannel] Webhook server listening on port ${t}`)}),this.setWebhook()}).catch(e=>{console.error("[TelegramChannel] Failed to start webhook server:",e)}))}async setWebhook(){if(!this.config.webhookUrl)return;let e=await fetch(`https://api.telegram.org/bot${this.config.token}/setWebhook`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({url:this.config.webhookUrl})});if(!e.ok){console.error("[TelegramChannel] Failed to set webhook");return}let n=await e.json();n.ok?console.log("[TelegramChannel] Webhook set successfully"):console.error("[TelegramChannel] Failed to set webhook:",n.description)}handleWebhookRequest(e,n){if(e.method!=="POST"){n.writeHead(405),n.end("Method not allowed");return}let t="";e.on("data",i=>{t+=i.toString()}),e.on("end",()=>{try{let i=JSON.parse(t);this.handleMessage(this.normalize(i)).catch(s=>{console.error("[TelegramChannel] Error processing webhook:",s)}),n.writeHead(200),n.end("OK")}catch(i){console.error("[TelegramChannel] Error parsing webhook:",i),n.writeHead(400),n.end("Bad request")}})}async stop(){if(this.pollingInterval&&(clearInterval(this.pollingInterval),this.pollingInterval=void 0),this.server)return new Promise(e=>{this.server.close(e)});if(this.config.webhookUrl)try{await fetch(`https://api.telegram.org/bot${this.config.token}/deleteWebhook`,{method:"POST"})}catch(e){console.error("[TelegramChannel] Failed to delete webhook:",e)}}};var M=new Set([1,3]),_=/<@!?(\d+)>/g,D="https://discord.com/api/v10",b=class extends d{isTriggerChannel=!1;config;allowedChannelIds;botUserId;participantCache=new Map;client;constructor(e){super(),this.config=e,this.name=e.name,e.channelId==null?this.allowedChannelIds=new Set:Array.isArray(e.channelId)?this.allowedChannelIds=new Set(e.channelId):this.allowedChannelIds=new Set([e.channelId])}shouldProcessEvent(e){return!e.author||e.webhookId||this.botUserId&&e.author.id===this.botUserId||this.config.guildId&&e.guildId!==this.config.guildId||this.allowedChannelIds.size>0&&(!e.channelId||!this.allowedChannelIds.has(e.channelId))?!1:e.author.bot||e.author.system?this.config.blockedBotIds?.includes(e.author.id)?!1:this.config.allowedBotIds?this.config.allowedBotIds.includes(e.author.id):!1:!0}normalize(e){let n=e,t=n.channelId,i=(t??"")+(n.thread?.id?`:${n.thread.id}`:""),s=n.channel?.type,r=s!==void 0&&M.has(s),o=n.author?.id,a=n.author?.globalName??n.author?.username,l=[];if(n.content){_.lastIndex=0;let m;for(;(m=_.exec(n.content))!==null;)l.push(m[1])}return{message:n.content,conversationId:i,data:n,participant:o?{kind:"user",id:o,displayName:a??void 0}:void 0,context:{userId:o,username:n.author?.username,channelType:r?"dm":"channel",channelId:t,channelName:n.channel?.name,guildId:n.guildId,threadId:n.thread?.id,messageId:n.id,mentions:l.length>0?l:void 0,isMentioned:this.botUserId?l.includes(this.botUserId):void 0}}}async resolveParticipant(e){let n=e.participant?.id??e.context?.userId;if(!n)return;let t=this.participantCache.get(n);if(t)return t;try{let i=await fetch(`${D}/users/${n}`,{headers:{Authorization:`Bot ${this.config.token}`}});if(!i.ok)return console.warn(`[DiscordChannel] Failed to resolve user ${n}: HTTP ${i.status}`),{kind:"user",id:n};let s=await i.json(),r=s.global_name??s.username,o={kind:"user",id:s.id,displayName:r};return this.participantCache.set(n,o),o}catch(i){return console.warn(`[DiscordChannel] resolveParticipant error for ${n}:`,i),{kind:"user",id:n}}}invalidateParticipant(e){this.participantCache.delete(e)}async send(e){if(!this.client)throw new Error("[DiscordChannel] Client not initialized. Did you call listen()?");let n=e.metadata?.threadId;if(n){let s=await this.client.channels.fetch(n);if(s&&"send"in s)try{await s.send({content:e.output});return}catch(r){throw console.error("[DiscordChannel] Failed to send to thread:",r),new Error(`[DiscordChannel] Failed to send Discord message: ${r instanceof Error?r.message:String(r)}`)}console.warn(`[DiscordChannel] Thread ${n} not found or not sendable; falling back to channel send.`)}let t=e.metadata?.channelId??(this.allowedChannelIds.size>0?[...this.allowedChannelIds][0]:void 0);if(!t)throw new Error("[DiscordChannel] No channel ID available for sending. Configure channelId or pass output.metadata.channelId.");let i=await this.client.channels.fetch(t);if(!i||!("send"in i))throw new Error(`[DiscordChannel] Channel ${t} not found or is not a text channel`);try{await i.send({content:e.output})}catch(s){throw console.error("[DiscordChannel] Failed to send to channel:",s),new Error(`[DiscordChannel] Failed to send Discord message: ${s instanceof Error?s.message:String(s)}`)}}listen(){typeof process>"u"||import("discord.js").then(e=>{let{Client:n,GatewayIntentBits:t}=e;this.client=new n({intents:[t.Guilds,t.GuildMessages,t.MessageContent,t.DirectMessages]}),this.client.on("ready",()=>{let i=this.client.user;this.botUserId=i?.id;let s=this.allowedChannelIds.size===0?"all channels":[...this.allowedChannelIds].join(", "),r=this.config.guildId??"all guilds";console.log(`[DiscordChannel] Logged in as ${i?.tag??"unknown"} (botUserId=${this.botUserId??"unknown"}) | guild=${r} | channels=${s}`)}),this.client.on("messageCreate",i=>{let s=i;if(!this.shouldProcessEvent(s))return;let r=this.normalize(s);this.handleMessage(r)}),this.client.on("userUpdate",(i,s)=>{let r=s;r?.id&&this.invalidateParticipant(r.id)}),this.client.login(this.config.token).catch(i=>{console.error("[DiscordChannel] Failed to login to Discord:",i)})}).catch(e=>{console.error("[DiscordChannel] Failed to initialize Discord client:",e),console.error("[DiscordChannel] Make sure discord.js is installed: npm install discord.js")})}async stop(){this.client&&(await this.client.destroy(),this.client=void 0)}};var S=class extends d{isTriggerChannel=!0;config;transporter;constructor(e){super(),this.config=e,this.name=e.name}listen(){typeof process<"u"&&import("nodemailer").then(e=>{this.transporter=e.default.createTransport({host:this.config.smtp.host,port:this.config.smtp.port,secure:this.config.smtp.secure??this.config.smtp.port===465,auth:{user:this.config.smtp.auth.user,pass:this.config.smtp.auth.pass}}),console.log(`[EmailChannel] Email transporter initialized for ${this.config.from}`)}).catch(e=>{console.error("[EmailChannel] Failed to initialize nodemailer:",e),console.error("[EmailChannel] Make sure to install nodemailer: npm install nodemailer")})}async send(e){if(!this.transporter)throw new Error("Email transporter not initialized. Did you call listen()?");let n=Array.isArray(this.config.to)?this.config.to:[this.config.to],t=this.config.subject||"Message from Agent",i={from:this.config.from,to:n.join(", "),subject:t,text:e.output,html:this.formatAsHtml(e.output)};try{await this.transporter.sendMail(i)}catch(s){throw console.error("[EmailChannel] Failed to send email:",s),new Error(`Failed to send email: ${s instanceof Error?s.message:String(s)}`)}}normalize(e){throw new Error("EmailChannel is outbound-only. Use WebhookChannel with email webhook events for inbound email.")}formatAsHtml(e){return e.split(`
|
|
2
2
|
|
|
3
|
-
`).map(n=>`<p>${n.replace(/\n/g,"<br>")}</p>`).join("")}async stop(){this.transporter&&(this.transporter.close(),this.transporter=void 0)}};var I=class extends
|
|
3
|
+
`).map(n=>`<p>${n.replace(/\n/g,"<br>")}</p>`).join("")}async stop(){this.transporter&&(this.transporter.close(),this.transporter=void 0)}};var I=class extends d{config;twilioClient;server;constructor(e){super(),this.config={port:3e3,...e},this.name=e.name}get isTriggerChannel(){return!this.config.webhookPath}listen(){typeof process<"u"&&import("twilio").then(e=>{this.twilioClient=e.default(this.config.accountSid,this.config.authToken),console.log("[SMSChannel] Twilio client initialized"),this.config.webhookPath&&this.startWebhookServer()}).catch(e=>{console.error("[SMSChannel] Failed to initialize Twilio client:",e),console.error("[SMSChannel] Make sure to install twilio: npm install twilio")})}async send(e){if(!this.twilioClient)throw new Error("Twilio client not initialized. Did you call listen()?");let n=e.metadata?.from||this.config.to;if(!n)throw new Error('No recipient phone number specified. Set "to" in config or provide in output.metadata.from');try{await this.twilioClient.messages.create({body:e.output,from:this.config.from,to:n})}catch(t){throw console.error("[SMSChannel] Failed to send SMS:",t),new Error(`Failed to send SMS: ${t instanceof Error?t.message:String(t)}`)}}normalize(e){let n=e,t=n.From,i=n.Body,s=n.MessageSid;return{message:i,conversationId:t,data:n,context:{from:t,to:n.To,messageSid:s}}}startWebhookServer(){import("http").then(e=>{this.server=e.createServer((n,t)=>{this.handleWebhookRequest(n,t)}),this.server.listen(this.config.port,()=>{console.log(`[SMSChannel] Webhook server listening on port ${this.config.port} at ${this.config.webhookPath}`)})}).catch(e=>{console.error("[SMSChannel] Failed to start webhook server:",e)})}handleWebhookRequest(e,n){if(e.method!=="POST"||e.url!==this.config.webhookPath){n.writeHead(404),n.end("Not found");return}let t="";e.on("data",i=>{t+=i.toString()}),e.on("end",()=>{try{let i=new URLSearchParams(t),s={};i.forEach((o,a)=>{s[a]=o});let r=this.normalize(s);this.handleMessage(r),n.writeHead(200,{"Content-Type":"text/xml"}),n.end('<?xml version="1.0" encoding="UTF-8"?><Response></Response>')}catch(i){console.error("[SMSChannel] Error handling webhook:",i),n.writeHead(400),n.end("Bad request")}})}async stop(){if(this.server)return new Promise(e=>{this.server.close(e)})}};var T=class extends d{isTriggerChannel=!1;_timeout;_pendingResolve;constructor(e={}){super(),this._timeout=e.timeout??12e4}listen(){}async send(e){this._pendingResolve?.(e),this._pendingResolve=void 0}normalize(e){let n=e;return{message:typeof n.message=="string"?n.message:JSON.stringify(n),data:n,conversationId:`mcp-${Date.now()}-${Math.random().toString(36).slice(2,7)}`}}async trigger(e){let n=this.normalize(e);return new Promise((t,i)=>{let s=setTimeout(()=>{this._pendingResolve=void 0,i(new Error(`McpChannel: agent did not respond within ${this._timeout}ms`))},this._timeout);this._pendingResolve=r=>{clearTimeout(s),t(r.output)},this.handleMessage(n).catch(r=>{clearTimeout(s),this._pendingResolve=void 0,i(r instanceof Error?r:new Error(String(r)))})})}asAgentDefinition(e,n){return{name:e.name,description:e.description,...n!==void 0&&{inputSchema:n},invoke:t=>this.trigger(t)}}};export{d as BaseChannel,b as DiscordChannel,S as EmailChannel,T as McpChannel,I as SMSChannel,y as ScheduledChannel,C as SlackChannel,k as TelegramChannel,v as WebhookChannel};
|
|
@@ -132,6 +132,15 @@ declare class SlackChannel extends BaseChannel {
|
|
|
132
132
|
* ```
|
|
133
133
|
*/
|
|
134
134
|
botUserId?: string;
|
|
135
|
+
/**
|
|
136
|
+
* The bot's Slack integration id (e.g. `'B_BOT123'`), populated by the
|
|
137
|
+
* startup self-check (`auth.test`) alongside `botUserId`.
|
|
138
|
+
*
|
|
139
|
+
* Used internally for self-suppression of DM `bot_message` events where
|
|
140
|
+
* Slack omits the `user` field (so `botUserId` comparison cannot fire).
|
|
141
|
+
* Not needed for regular channel posts — those carry `event.user`.
|
|
142
|
+
*/
|
|
143
|
+
private botId?;
|
|
135
144
|
/**
|
|
136
145
|
* Normalized allowlist of channel identifiers, or `null` to accept any channel.
|
|
137
146
|
* Derived from `config.channel` at construction time.
|
|
@@ -200,10 +209,11 @@ declare class SlackChannel extends BaseChannel {
|
|
|
200
209
|
* 2. Channel allowlist (from `config.channel`): events outside the allowlist
|
|
201
210
|
* are dropped. DMs (`im`/`mpim`) always pass because they are per-user, not
|
|
202
211
|
* per-channel. Skipped entirely when `config.channel` is null/omitted.
|
|
203
|
-
* 3. **Self-suppression (automatic):** events where `event.user` matches
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
212
|
+
* 3. **Self-suppression (automatic):** events where `event.user` matches
|
|
213
|
+
* `botUserId`, OR where `event.bot_id` matches `botId`, are dropped. This
|
|
214
|
+
* handles both channel posts (where Slack sets `event.user`) and DM posts
|
|
215
|
+
* (where Slack omits `event.user` but sets `event.bot_id`). Requires no
|
|
216
|
+
* configuration — both ids are discovered via `auth.test` at startup.
|
|
207
217
|
* 4. Events without `bot_id` (human messages) pass.
|
|
208
218
|
* 5. Explicit blocklist check (`blockedBotIds`) runs first for bot messages.
|
|
209
219
|
* 6. If `allowedBotIds` is provided, strict mode applies: only listed bots
|
|
@@ -132,6 +132,15 @@ declare class SlackChannel extends BaseChannel {
|
|
|
132
132
|
* ```
|
|
133
133
|
*/
|
|
134
134
|
botUserId?: string;
|
|
135
|
+
/**
|
|
136
|
+
* The bot's Slack integration id (e.g. `'B_BOT123'`), populated by the
|
|
137
|
+
* startup self-check (`auth.test`) alongside `botUserId`.
|
|
138
|
+
*
|
|
139
|
+
* Used internally for self-suppression of DM `bot_message` events where
|
|
140
|
+
* Slack omits the `user` field (so `botUserId` comparison cannot fire).
|
|
141
|
+
* Not needed for regular channel posts — those carry `event.user`.
|
|
142
|
+
*/
|
|
143
|
+
private botId?;
|
|
135
144
|
/**
|
|
136
145
|
* Normalized allowlist of channel identifiers, or `null` to accept any channel.
|
|
137
146
|
* Derived from `config.channel` at construction time.
|
|
@@ -200,10 +209,11 @@ declare class SlackChannel extends BaseChannel {
|
|
|
200
209
|
* 2. Channel allowlist (from `config.channel`): events outside the allowlist
|
|
201
210
|
* are dropped. DMs (`im`/`mpim`) always pass because they are per-user, not
|
|
202
211
|
* per-channel. Skipped entirely when `config.channel` is null/omitted.
|
|
203
|
-
* 3. **Self-suppression (automatic):** events where `event.user` matches
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
212
|
+
* 3. **Self-suppression (automatic):** events where `event.user` matches
|
|
213
|
+
* `botUserId`, OR where `event.bot_id` matches `botId`, are dropped. This
|
|
214
|
+
* handles both channel posts (where Slack sets `event.user`) and DM posts
|
|
215
|
+
* (where Slack omits `event.user` but sets `event.bot_id`). Requires no
|
|
216
|
+
* configuration — both ids are discovered via `auth.test` at startup.
|
|
207
217
|
* 4. Events without `bot_id` (human messages) pass.
|
|
208
218
|
* 5. Explicit blocklist check (`blockedBotIds`) runs first for bot messages.
|
|
209
219
|
* 6. If `allowedBotIds` is provided, strict mode applies: only listed bots
|
package/dist/index.cjs
CHANGED
|
@@ -29,7 +29,7 @@ ${St}`:"")+U},G=`${this.name}-replica`,W=this.description,O=this.model}else Q={.
|
|
|
29
29
|
Question: "${e}"
|
|
30
30
|
Answer: "${t}"
|
|
31
31
|
|
|
32
|
-
Is this answer sufficient? Reply with ONLY "yes" or "no".`,{workflow:{mode:"single-shot"}})).output.toLowerCase().trim().startsWith("yes")}async handlePendingAsk(e,t,n,r){return await this.evaluateAnswer(e.question,t,{simpleValidation:i=>i.trim().length>3})?(await this.resolvePendingAsk(e.id,t),n(t)):e.retries>=e.maxRetries?(await this.resolvePendingAsk(e.id,"__insufficient__"),this._triggeringChannel&&await this.sendTo(this._triggeringChannel,"I was unable to get enough information to proceed. Skipping this step."),r?r():{output:"Step skipped due to insufficient input.",metadata:{skipped:!0,askId:e.id}}):(this._registry?.incrementRetries(e.id),this.ask(`I need a bit more clarity on: "${e.question}". Could you provide more details?`,{context:e.context,maxRetries:e.maxRetries}))}async delegateAndWait(e,t){if(!this._registry)throw new I("Agent not registered - cannot use delegateAndWait()");let n={message:t.message,intent:t.intent,data:t.data,context:{...t.context||{},delegatedBy:this.name},conversationId:t.conversationId||this._conversationId||`delegation-${Date.now()}`};return await this._registry.invoke(e,n)}async onBeforeRun(e){}async onComplete(e){}async onError(e){}_resolveAssemblerOptions(){let e=this.channels.map(r=>r.botUserId).filter(r=>typeof r=="string"&&r.length>0),t=this.assemblerOptions?.agentAliases??[];if(e.length===0&&t.length===0)return this.assemblerOptions;let n=Array.from(new Set([...t,...e]));return{...this.assemblerOptions,agentAliases:n}}_getEffectiveInterceptors(){return this.interceptors.some(t=>t[re]===!0)?this.interceptors:[Y({store:this.conversationHistory}),...this.interceptors]}_bindChannel(e){e.onMessage(async t=>{if(!t.conversationId){console.warn(`[${this.name}] Message received without conversationId \u2014 skipping`);return}let n=await this._acquireConversationLock(t.conversationId);try{this._triggeringChannel=e.name,this._isTriggerChannel=e.isTriggerChannel,this._conversationId=t.conversationId;let r=te(this._getEffectiveInterceptors(),this,e,this._registry??null),s=await ne(r,t);if(s===null)return;let i={output:s.output,metadata:s.metadata};await e.send({output:i.output,metadata:{...i.metadata,conversationId:t.conversationId,...t.context}})}catch(r){let s=r instanceof Error?r.message:"Unknown error occurred";console.error(`[${this.name}] Error in agent invocation: ${s}`);try{await e.send({output:`Error: ${s}`,metadata:{conversationId:t.conversationId,error:!0,...t.context}})}catch(i){console.error(`[${this.name}] Failed to send error to channel: ${i}`)}}finally{n()}})}async _acquireConversationLock(e){for(;this._conversationLocks.has(e);)try{await this._conversationLocks.get(e)}catch{}let t,n=new Promise(r=>{t=r});return this._conversationLocks.set(e,n),()=>{this._conversationLocks.delete(e),t()}}extractSteps(e){let t=e;if(t.plan&&typeof t.plan=="object"){let n=t.plan;if(Array.isArray(n.steps))return n.steps.map(r=>({number:r.number||0,description:r.description||"",status:r.status||"completed",result:r.result}))}if(Array.isArray(t.steps))return t.steps}}});var qn={};nt(qn,{AgentError:()=>I,AgentJsonRpcServer:()=>de,AgentMind:()=>ie,AgentRegistry:()=>Se,BaseAgent:()=>R,BaseChannel:()=>C,BrowserAgent:()=>Me,CodingAgent:()=>Ee,ContainsScorer:()=>ve,CustomScorer:()=>Ae,DataAgent:()=>Pe,DepthExceededError:()=>q,DiscordChannel:()=>Be,EmailChannel:()=>Le,EphemeralAgent:()=>ae,EvalDataset:()=>he,EvalRunner:()=>fe,ExactMatchScorer:()=>ye,HotReloadWatcher:()=>Te,InMemoryConversationStore:()=>Ge.InMemoryConversationStore,IntentClassifierAgent:()=>le,InvocationDepthExceededError:()=>V,JsonRpcTransport:()=>ce,LLMJudgeScorer:()=>we,LocalTransport:()=>z,McpChannel:()=>Ue,OTelSpanStatusCode:()=>ue,ResearchAgent:()=>_e,SKIP_SENTINEL:()=>J,SMSChannel:()=>Fe,ScheduledChannel:()=>$e,SchedulerStore:()=>me,SlackChannel:()=>De,SummarizerAgent:()=>pe,TelegramChannel:()=>je,WebhookChannel:()=>Ne,assemblePrompt:()=>se,compareEvalRuns:()=>kt,composeChain:()=>te,createAddressCheckInterceptor:()=>Ke,createCaptureInterceptor:()=>Y,createConversationSearchTool:()=>wt,createDepthGuardInterceptor:()=>Ye,createEventDedupInterceptor:()=>Je,createIntentClassifierInterceptor:()=>Ve,createNoiseFilterInterceptor:()=>ze,createOTelTracerInterceptor:()=>Qe,createParticipantResolverInterceptor:()=>He,createRateLimitInterceptor:()=>We,createSchedulerTools:()=>Ct,createSelfFilterInterceptor:()=>qe,createTracerInterceptor:()=>Xe,executeChain:()=>ne,formatEvalReport:()=>Rt,isSkipSentinel:()=>j,skip:()=>ee});module.exports=an(qn);d();d();B();xe();d();var Gt=require("crypto");d();var yt=require("crypto");oe();var z=class{constructor(e){this.registry=e}registry;async invoke(e,t){let n=this.registry.getAgent(e);if(!n)throw new I(`Agent "${e}" not found in registry. Available agents: ${this.registry.getAllAgents().map(p=>p.name).join(", ")}`);let r=n.conversationHistory,s=t.conversationId,i=t.context?.delegatedBy;if(r&&s&&i){let p={id:t.context?.messageId??(0,yt.randomUUID)(),conversationId:s,participant:{kind:"agent",id:i,displayName:i},content:t.message??"",timestamp:new Date().toISOString(),scope:"channel",metadata:{}};try{await r.append(p)}catch{}}let c=await n.invokeAgent(t);if(r&&s){let p={id:(0,yt.randomUUID)(),conversationId:s,participant:{kind:"agent",id:e,displayName:e},content:c.output,timestamp:new Date().toISOString(),scope:"channel",metadata:{}};try{await r.append(p)}catch{}}return c}};var Se=class{agentList;instances=new Map;channels=new Map;_transport;pendingAsks=new Map;_started=!1;_restarting=!1;_restartScheduled=!1;_deadlineTimer;constructor(e,t){this.agentList=e,this._transport=t?.transport||new z(this)}async start(){for(let e of this.agentList){await e._ensureToolpack(),e._registry=this,this.instances.set(e.name,e);for(let t of e.channels??[])t.name&&this.channels.set(t.name,t)}for(let e of this.agentList)await e.start();this._started=!0}async addAgent(e){if(this.agentList.push(e),!!this._started){await e._ensureToolpack(),e._registry=this,this.instances.set(e.name,e);for(let t of e.channels??[])t.name&&this.channels.set(t.name,t);await e.start()}}async removeAgent(e){let t=this.instances.get(e);if(t){await t.stop(),this.instances.delete(e),this.agentList=this.agentList.filter(n=>n.name!==e);for(let n of t.channels??[])n.name&&this.channels.delete(n.name)}}isAllIdle(){return this.agentList.every(e=>e.isIdle())}scheduleRestart(e){if(this._restartScheduled)return;this._restartScheduled=!0;let t=(e?.maxWaitMinutes??30)*60*1e3,n=()=>{!this._restarting&&this.isAllIdle()&&this._executeRestart()};if(n(),!this._restarting){for(let r of this.agentList)r.on("agent:complete",n);this._deadlineTimer=setTimeout(()=>{this._executeRestart()},t)}}async _executeRestart(){if(this._restarting)return;this._restarting=!0,this._deadlineTimer&&(clearTimeout(this._deadlineTimer),this._deadlineTimer=void 0),await this.stop();let e=Date.now()+3e4;for(;!this.isAllIdle()&&Date.now()<e;)await new Promise(t=>setTimeout(t,100));this._exit(0)}_exit(e){process.exit(e)}async sendTo(e,t){let n=this.channels.get(e);if(!n)throw new Error(`No channel registered with name "${e}"`);await n.send(t)}getAgent(e){return this.instances.get(e)}getAllAgents(){return Array.from(this.instances.values())}getChannel(e){return this.channels.get(e)}async invoke(e,t){return this._transport.invoke(e,t)}async stop(){for(let e of this.agentList)await e.stop();this.instances.clear(),this.channels.clear(),this.pendingAsks.clear()}getPendingAsk(e){let t=this.pendingAsks.get(e);if(!t||t.length===0)return;let n=new Date;for(;t.length>0;){let r=t[0];if(r.expiresAt&&r.expiresAt<n)t.shift();else break}if(t.length===0){this.pendingAsks.delete(e);return}return t[0]}hasPendingAsks(e){let t=this.pendingAsks.get(e);if(!t||t.length===0)return!1;let n=new Date,r=t.filter(s=>!s.expiresAt||s.expiresAt>=n);return r.length===0?(this.pendingAsks.delete(e),!1):(r.length!==t.length&&this.pendingAsks.set(e,r),r.some(s=>s.status==="pending"))}cleanupExpiredAsks(){let e=0,t=new Date;for(let[n,r]of this.pendingAsks.entries()){let s=r.filter(i=>!i.expiresAt||i.expiresAt>=t);e+=r.length-s.length,s.length===0?this.pendingAsks.delete(n):s.length!==r.length&&this.pendingAsks.set(n,s)}return e}addPendingAsk(e){let t={...e,id:(0,Gt.randomUUID)(),askedAt:new Date,retries:0,status:"pending"},n=this.pendingAsks.get(e.conversationId);return n?n.push(t):this.pendingAsks.set(e.conversationId,[t]),t}incrementRetries(e){for(let t of this.pendingAsks.values()){let n=t.find(r=>r.id===e);if(n)return n.retries+=1,n.retries}}async resolvePendingAsk(e,t){for(let[n,r]of this.pendingAsks.entries()){let s=r.findIndex(i=>i.id===e);if(s!==-1){r[s].status="answered",r[s].answer=t;let i=r[s].channelName;if(r.splice(s,1),r.length>0){let c=r[0];if(i&&i.trim()!=="")try{await this.sendTo(i,{output:c.question})}catch(p){console.error(`[AgentRegistry] Failed to auto-send next ask: ${p instanceof Error?p.message:"Unknown error"}`)}else console.warn(`[AgentRegistry] Cannot auto-send next ask: channelName is empty for conversation ${n}`)}r.length===0&&this.pendingAsks.delete(n);return}}throw new Error(`Pending ask with id "${e}" not found`)}};oe();d();var Jt=require("fs"),zt=require("child_process"),qt=require("path"),Te=class{cwd;debounceMs;onRestartNeeded;onCompileError;spawnFn;watchFn;watchPaths;watchers=[];debounceTimer;constructor(e){this.watchPaths=e.watchPaths,this.cwd=e.cwd??process.cwd(),this.debounceMs=e.debounceMs??3e4,this.onRestartNeeded=e.onRestartNeeded,this.onCompileError=e.onCompileError,this.spawnFn=e.spawnFn??zt.spawn,this.watchFn=e.watchFn??Jt.watch}start(){for(let e of this.watchPaths){let t=this.watchFn(e,{recursive:!0},(n,r)=>{r&&this._handleFileChange(r)});this.watchers.push(t)}}stop(){for(let e of this.watchers)e.close();this.watchers=[],this.debounceTimer!==void 0&&(clearTimeout(this.debounceTimer),this.debounceTimer=void 0)}_handleFileChange(e){this.debounceTimer!==void 0&&clearTimeout(this.debounceTimer),this.debounceTimer=setTimeout(()=>{this.debounceTimer=void 0,(0,qt.basename)(e).startsWith(".env")?this.onRestartNeeded():(e.endsWith(".ts")||e.endsWith(".tsx"))&&this._runCompile()},this.debounceMs)}_runCompile(){return new Promise(e=>{let t="",n=this.spawnFn("npx",["tsc","--build"],{cwd:this.cwd,stdio:["ignore","ignore","pipe"]});n.stderr?.on("data",r=>{t+=r.toString()}),n.on("close",r=>{if(r===0)this.onRestartNeeded();else{let s=t||`tsc --build exited with code ${String(r)}`;this.onCompileError?.(s)}e()}),n.on("error",r=>{let s=r instanceof Error?r.message:String(r);this.onCompileError?.(s),e()})})}};d();B();var Wt=require("toolpack-sdk"),On={...Wt.AGENT_MODE,name:"research-agent-mode",systemPrompt:["You are a research agent specialized in web research and information gathering.","Use web.search to find relevant information, web.fetch to retrieve content, and web.scrape when needed.","Always cite your sources with URLs.","Provide comprehensive, well-structured summaries.","Flag any conflicting information or uncertainty in your findings."].join(" ")},_e=class extends R{name="research-agent";description="Web research agent for summarization, fact-finding, competitive analysis, and trend monitoring";mode=On;constructor(e){super(e)}async invokeAgent(e){let t=await this.run(e.message||"",void 0,{conversationId:e.conversationId});return await this.onComplete(t),t}};d();B();var Ht=require("toolpack-sdk"),Nn={...Ht.CODING_MODE,name:"coding-agent-mode",systemPrompt:["You are a coding agent specialized in software development tasks.","Use coding.* tools for code analysis, fs.* for file operations, and git.* for version control.","Write clean, idiomatic code following best practices.","Always verify your changes and check for potential issues.","Provide clear explanations of your code changes."].join(" ")},Ee=class extends R{name="coding-agent";description="Coding agent for code generation, refactoring, debugging, test writing, and code review";mode=Nn;constructor(e){super(e)}async invokeAgent(e){let t=await this.run(e.message||"",void 0,{conversationId:e.conversationId});return await this.onComplete(t),t}};d();B();var Kt=require("toolpack-sdk"),$n={...Kt.AGENT_MODE,name:"data-agent-mode",systemPrompt:["You are a data agent specialized in database operations and data analysis.","Use db.* tools for database queries, fs.* for file operations, and http.* for API requests.","Generate clear, well-formatted reports and summaries.","Always validate data integrity and handle errors gracefully.","Provide insights and patterns when analyzing data."].join(" ")},Pe=class extends R{name="data-agent";description="Data agent for database queries, CSV generation, data analysis, reporting, and aggregation";mode=$n;constructor(e){super(e)}async invokeAgent(e){let t=await this.run(e.message||"",void 0,{conversationId:e.conversationId});return await this.onComplete(t),t}};d();B();var Vt=require("toolpack-sdk"),jn={...Vt.CHAT_MODE,name:"browser-agent-mode",systemPrompt:["You are a browser agent specialized in web interaction and content extraction.","Use web.fetch to retrieve pages, web.screenshot for visual content, and web.extract_links for navigation.","Follow links intelligently to gather comprehensive information.","Extract structured data from web pages when possible.","Be mindful of rate limits and respectful of website resources."].join(" ")},Me=class extends R{name="browser-agent";description="Browser agent for web browsing, form interaction, page extraction, and link following";mode=jn;constructor(e){super(e)}async invokeAgent(e){let t=await this.run(e.message||"",void 0,{conversationId:e.conversationId});return await this.onComplete(t),t}};d();var C=class{name;_handler;onMessage(e){this._handler=e}async handleMessage(e){this._handler&&await this._handler(e)}};d();var Oe=require("crypto");var De=class extends C{isTriggerChannel=!1;config;server;participantCache=new Map;botUserId;allowedChannels;constructor(e){super(),this.config={port:3e3,...e},this.name=e.name;let t=e.channel;this.allowedChannels=t==null?null:Array.isArray(t)?t:[t]}listen(){typeof process<"u"&&import("http").then(e=>{this.server=e.createServer((t,n)=>{this.handleRequest(t,n)}),this.server.listen(this.config.port,()=>{console.log(`[SlackChannel] Listening on port ${this.config.port}`),this.runStartupCheck().catch(()=>{})})}).catch(e=>{console.error("[SlackChannel] Failed to start HTTP server:",e)})}async runStartupCheck(){try{let t=await(await fetch("https://slack.com/api/auth.test",{method:"POST",headers:{Authorization:`Bearer ${this.config.token}`,"Content-Type":"application/json"}})).json();t.ok?(this.botUserId=t.user_id,console.log(`[SlackChannel] Connected as @${t.user} (${t.user_id}) in workspace "${t.team}" \u2014 ${t.url}`)):console.warn(`[SlackChannel] auth.test failed: ${t.error}. Check your bot token.`)}catch(e){console.warn("[SlackChannel] Startup self-check failed (network error):",e)}}verifySignature(e,t){let n=e["x-slack-request-timestamp"],r=e["x-slack-signature"];if(!n||!r||Array.isArray(n)||Array.isArray(r))return!1;let s=parseInt(n,10),i=Math.floor(Date.now()/1e3);if(isNaN(s)||Math.abs(i-s)>300)return!1;let c=`v0:${n}:${t}`,a=`v0=${(0,Oe.createHmac)("sha256",this.config.signingSecret).update(c).digest("hex")}`;if(a.length!==r.length)return!1;try{return(0,Oe.timingSafeEqual)(Buffer.from(a),Buffer.from(r))}catch{return!1}}async send(e){let t=e.metadata?.threadTs??e.metadata?.thread_ts??e.metadata?.threadId,r=e.metadata?.channelId??(this.allowedChannels&&this.allowedChannels.length>0?this.allowedChannels[0]:void 0);if(!r)throw new Error("[SlackChannel] Cannot send: no channel configured and metadata.channelId is missing. Provide a target via SlackChannelConfig.channel or output.metadata.channelId.");let s={channel:r,text:e.output};t&&(s.thread_ts=t);let i=await fetch("https://slack.com/api/chat.postMessage",{method:"POST",headers:{Authorization:`Bearer ${this.config.token}`,"Content-Type":"application/json"},body:JSON.stringify(s)});if(!i.ok)throw new Error(`Failed to send Slack message: ${i.statusText}`);let c=await i.json();if(!c.ok)throw new Error(`Slack API error: ${c.error}`)}normalize(e){let t=e,r=(t.text||"").replace(/<(https?:\/\/[^|>]+)\|([^>]+)>/g,"$2 ($1)").replace(/<(https?:\/\/[^>]+)>/g,"$1").replace(/<!here>/g,"@here").replace(/<!channel>/g,"@channel").replace(/<!everyone>/g,"@everyone"),s=t.ts,i=t.thread_ts,c=i!==void 0&&i!==s,p=t.user,a=p?{kind:"user",id:p}:void 0,l=/<@([A-Z0-9]+)>/g,m=[],u;for(;(u=l.exec(r))!==null;)m.push(u[1]);let g=t.channel;return{message:r,conversationId:c?i:g||s||"",data:t,participant:a,context:{user:p,channel:g,team:t.team,channelType:t.channel_type,threadId:c?i:void 0,mentions:m.length>0?m:void 0,channelId:g,channelName:typeof this.config.channel=="string"?this.config.channel:g}}}async resolveParticipant(e){let t=e.participant?.id??e.context?.user;if(!t)return;let n=this.participantCache.get(t);if(n)return n;try{let r=await fetch(`https://slack.com/api/users.info?user=${encodeURIComponent(t)}`,{method:"GET",headers:{Authorization:`Bearer ${this.config.token}`}});if(!r.ok)return{kind:"user",id:t};let s=await r.json();if(!s.ok||!s.user){let p={kind:"user",id:t};return this.participantCache.set(t,p),p}let i=s.user.profile?.display_name||s.user.profile?.real_name||s.user.real_name||s.user.name||t,c={kind:"user",id:t,displayName:i,metadata:{slackUser:s.user}};return this.participantCache.set(t,c),c}catch{return{kind:"user",id:t}}}invalidateParticipant(e){this.participantCache.delete(e)}shouldProcessEvent(e){let t=e.type;if(t!=="message"&&t!=="app_mention")return!1;if(this.allowedChannels!==null){let i=e.channel_type;if(!(i==="im"||i==="mpim")){let p=e.channel;if(!p||!this.allowedChannels.includes(p))return!1}}let n=e.user;if(this.botUserId&&n===this.botUserId)return!1;let r=e.bot_id;if(!r)return!0;let s=this.config.blockedBotIds??[];if(s.includes(r)||n!==void 0&&s.includes(n))return!1;if(this.config.allowedBotIds!==void 0){let i=this.config.allowedBotIds;return i.includes(r)||n!==void 0&&i.includes(n)}return!0}handleRequest(e,t){if(e.method!=="POST"){t.writeHead(405),t.end("Method not allowed");return}let n="";e.on("data",r=>{n+=r.toString()}),e.on("end",()=>{if(!this.verifySignature(e.headers,n)){t.writeHead(401),t.end("Invalid signature");return}try{let r=JSON.parse(n);if(r.type==="url_verification"){t.writeHead(200,{"Content-Type":"application/json"}),t.end(JSON.stringify({challenge:r.challenge}));return}if(r.type==="event_callback"&&r.event){let s=r.event;if(this.shouldProcessEvent(s)){let i=this.normalize(s);this.handleMessage(i)}else s.type==="user_change"&&s.user&&this.invalidateParticipant(s.user.id);t.writeHead(200),t.end("OK");return}t.writeHead(200),t.end("OK")}catch(r){console.error("[SlackChannel] Error handling request:",r),t.writeHead(400),t.end("Bad request")}})}async stop(){if(this.server)return new Promise(e=>{this.server.close(e)})}};d();var Ne=class extends C{isTriggerChannel=!1;config;server;pendingResponses=new Map;constructor(e){super(),this.name=e.name,this.config={port:e.port??3e3,path:e.path??"/webhook"}}listen(){typeof process<"u"&&import("http").then(e=>{this.server=e.createServer((t,n)=>{this.handleRequest(t,n)}),this.server.listen(this.config.port,()=>{console.log(`[WebhookChannel] Listening on port ${this.config.port}${this.config.path}`)})}).catch(e=>{console.error("[WebhookChannel] Failed to start HTTP server:",e)})}async send(e){let t=e.metadata?.conversationId;if(t&&this.pendingResponses.has(t)){let n=this.pendingResponses.get(t);this.pendingResponses.delete(t),n.resolve({output:e.output,metadata:e.metadata})}}normalize(e){let t=e,n=t.headers||{},r=n["x-session-id"]||n["X-Session-Id"]||t.sessionId||t.conversationId||this.generateSessionId();return{message:t.message||t.text||"",intent:t.intent,conversationId:r,data:t,context:{headers:t.headers,method:t.method,sessionId:r}}}handleRequest(e,t){if(e.url!==this.config.path){t.writeHead(404),t.end("Not found");return}if(e.method!=="POST"){t.writeHead(405),t.end("Method not allowed");return}let n="";e.on("data",r=>{n+=r.toString()}),e.on("end",()=>{try{let r=JSON.parse(n),s=this.normalize(r),i=s.conversationId||this.generateSessionId(),c=new Promise((p,a)=>{this.pendingResponses.set(i,{resolve:p,reject:a}),setTimeout(()=>{this.pendingResponses.has(i)&&(this.pendingResponses.delete(i),a(new Error("Agent response timeout")))},3e4)});this.handleMessage({...s,conversationId:i,context:{...s.context,sessionId:i}}),c.then(p=>{t.writeHead(200,{"Content-Type":"application/json"}),t.end(JSON.stringify(p))}).catch(p=>{t.writeHead(500,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:p.message}))})}catch(r){console.error("[WebhookChannel] Error handling request:",r),t.writeHead(400,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Bad request"}))}})}generateSessionId(){return`webhook-${Date.now()}-${Math.random().toString(36).substring(2,9)}`}async stop(){if(this.server)return new Promise(e=>{this.server.close(e)})}};d();var vt=require("cron-parser"),$e=class extends C{isTriggerChannel=!0;config;timer;_stopped=!1;_generation=0;constructor(e){if(super(),!e.cron&&!e.store)throw new Error("ScheduledChannel: provide at least one of `cron` (static schedule) or `store` (dynamic scheduling).");if(e.cron)try{vt.CronExpressionParser.parse(e.cron)}catch(t){throw new Error(`ScheduledChannel: invalid cron expression '${e.cron}': ${t.message}`)}if(e.store&&!e.name&&console.warn("[ScheduledChannel] A `store` was provided without a `name`. All store queries will be unscoped and will pick up jobs from every channel. Set `name` to scope this channel to its own jobs."),e.idlePollMs!==void 0&&e.idlePollMs<1e3)throw new Error(`ScheduledChannel: idlePollMs must be at least 1000ms (got ${e.idlePollMs}). Values below 1 second create a tight polling loop.`);this.config=e,this.name=e.name}listen(){this._generation++,this.timer&&(clearTimeout(this.timer),this.timer=void 0),this._stopped=!1,this.config.store?this._listenWithStore():this._listenStatic()}async stop(){this._stopped=!0,this.timer&&(clearTimeout(this.timer),this.timer=void 0)}async send(e){}normalize(e){let t=e,n=new Date,r=`${n.getFullYear()}-${n.getMonth()+1}-${n.getDate()}`;return{intent:t?.intent??this.config.intent,message:t?.message??this.config.message??`Scheduled task triggered at ${n.toISOString()}`,conversationId:`scheduled:${this.name??"default"}:${r}`,data:{...t?.payload??{},scheduled:!0,jobId:t?.id,cron:t?.cron??this.config.cron,timestamp:n.toISOString()}}}_listenStatic(){this._scheduleNextStatic(this._generation)}_scheduleNextStatic(e){if(this._stopped||e!==this._generation)return;let t=this._nextRunFromCron(this.config.cron),n=t.getTime()-Date.now();if(n<=0){this.timer=setTimeout(()=>this._scheduleNextStatic(e),0);return}console.log(`[ScheduledChannel:${this.name??"default"}] Next run: ${t.toISOString()}`),this.timer=setTimeout(async()=>{this._stopped||e!==this._generation||(await this._triggerStatic(),this._scheduleNextStatic(e))},n)}async _triggerStatic(){if(!this._handler){console.warn(`[ScheduledChannel:${this.name??"default"}] Cron fired but no message handler is registered. Call onMessage() before listen() to avoid silently losing triggers.`);return}let e=this.normalize(null);try{await this.handleMessage(e)}catch(t){console.error(`[ScheduledChannel:${this.name??"default"}] Error on trigger:`,t)}}_listenWithStore(){let e=this.config.store,t=this._generation;if(t===1){let r=e.resetStuck(this.name);r>0&&console.log(`[ScheduledChannel:${this.name??"default"}] Reset ${r} stuck 'running' job(s) to 'pending'.`)}if(this.config.cron){let{duplicate:r}=e.create({channelName:this.name,cron:this.config.cron,intent:this.config.intent,message:this.config.message});r||console.log(`[ScheduledChannel:${this.name??"default"}] Seeded static cron '${this.config.cron}' into store.`)}let n=e.getDue(Date.now(),this.name);n.length>0&&(console.log(`[ScheduledChannel:${this.name??"default"}] Recovering ${n.length} overdue job(s).`),Promise.allSettled(n.map(r=>this._triggerJob(r)))),this._scheduleNextFromStore(t)}_scheduleNextFromStore(e){if(this._stopped||e!==this._generation)return;let t=this.config.store,n=t.getNextPending(this.name);if(!n){let s=this.config.idlePollMs??3e4;this.timer=setTimeout(()=>this._scheduleNextFromStore(e),s);return}let r=Math.max(0,n.nextRunAt-Date.now());console.log(`[ScheduledChannel:${this.name??"default"}] Next store job at ${new Date(n.nextRunAt).toISOString()} (in ${Math.round(r/1e3)}s)`),this.timer=setTimeout(async()=>{if(this._stopped||e!==this._generation)return;let s=t.getDue(Date.now(),this.name);await Promise.allSettled(s.map(i=>this._triggerJob(i))),this._scheduleNextFromStore(e)},r)}async _triggerJob(e){let t=this.config.store;if(!this._handler){console.warn(`[ScheduledChannel:${this.name??"default"}] Job ${e.id} fired but no message handler is registered. Call onMessage() before listen() to avoid silently losing jobs.`),t.markFailed(e.id,"No message handler registered");return}t.markRunning(e.id);let n=this.normalize(e);try{await this.handleMessage(n),t.markCompleted(e.id)}catch(r){let s=r instanceof Error?r.message:String(r);console.error(`[ScheduledChannel:${this.name??"default"}] Job ${e.id} failed:`,r),t.markFailed(e.id,s)}}_nextRunFromCron(e){return vt.CronExpressionParser.parse(e,{currentDate:new Date}).next().toDate()}};d();var je=class extends C{isTriggerChannel=!1;config;offset=0;pollingInterval;server;botUserId;botUsername;constructor(e){super(),this.name=e.name,this.config=e}listen(){this.runStartupCheck().catch(()=>{}),this.config.webhookUrl?this.startWebhook():this.startPolling()}async runStartupCheck(){try{let t=await(await fetch(`https://api.telegram.org/bot${this.config.token}/getMe`)).json();if(t.ok&&t.result){let n=t.result;this.botUserId=n.id!=null?String(n.id):void 0,this.botUsername=n.username,console.log(`[TelegramChannel] Connected as @${n.username} (id: ${n.id}, name: ${n.first_name})`)}else console.warn(`[TelegramChannel] getMe failed: ${t.description??"unknown error"}. Check your bot token.`)}catch(e){console.warn("[TelegramChannel] Startup self-check failed (network error):",e)}}async send(e){let t=e.metadata?.chatId;if(!t)throw new Error("Telegram send requires chatId in metadata");let n=await fetch(`https://api.telegram.org/bot${this.config.token}/sendMessage`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({chat_id:t,text:e.output,parse_mode:"Markdown"})});if(!n.ok)throw new Error(`Failed to send Telegram message: ${n.statusText}`);let r=await n.json();if(!r.ok)throw new Error(`Telegram API error: ${r.description}`)}normalize(e){let t=e,n=t.message||t.edited_message||{},r=n.text||"",s=n.chat||{},i=n.from||{},c=i.id!=null?String(i.id):void 0,p=i.first_name||i.username||c,a=c?{kind:"user",id:c,displayName:p??c}:void 0,l=n.entities??[],m=[];for(let v of l)if(v.type==="text_mention"&&v.user){let f=v.user;f.id!=null&&m.push(String(f.id))}let u=s.type,g=s.id!=null?String(s.id):"";return{message:r,conversationId:g,data:t,participant:a,context:{chatId:s.id,userId:i.id,username:i.username,firstName:i.first_name,lastName:i.last_name,messageId:n.message_id,channelType:u,channelId:g,channelName:s.title,mentions:m.length>0?m:void 0}}}startPolling(){console.log("[TelegramChannel] Starting polling mode"),this.pollingInterval=setInterval(async()=>{try{await this.pollUpdates()}catch(e){console.error("[TelegramChannel] Polling error:",e)}},5e3)}async pollUpdates(){let e=`https://api.telegram.org/bot${this.config.token}/getUpdates?offset=${this.offset}&limit=100`,t=await fetch(e);if(!t.ok)throw new Error(`Telegram getUpdates failed: ${t.statusText}`);let n=await t.json();if(!n.ok)throw new Error("Telegram getUpdates returned not ok");for(let r of n.result){let s=r.update_id;s>=this.offset&&(this.offset=s+1);try{let i=this.normalize(r);await this.handleMessage(i)}catch(i){console.error("[TelegramChannel] Error processing update:",i)}}}startWebhook(){typeof process>"u"||(console.log("[TelegramChannel] Starting webhook mode"),import("http").then(e=>{this.server=e.createServer((r,s)=>{this.handleWebhookRequest(r,s)});let t=new URL(this.config.webhookUrl||"http://localhost:3000"),n=parseInt(t.port,10)||3e3;this.server.listen(n,()=>{console.log(`[TelegramChannel] Webhook server listening on port ${n}`)}),this.setWebhook()}).catch(e=>{console.error("[TelegramChannel] Failed to start webhook server:",e)}))}async setWebhook(){if(!this.config.webhookUrl)return;let e=await fetch(`https://api.telegram.org/bot${this.config.token}/setWebhook`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({url:this.config.webhookUrl})});if(!e.ok){console.error("[TelegramChannel] Failed to set webhook");return}let t=await e.json();t.ok?console.log("[TelegramChannel] Webhook set successfully"):console.error("[TelegramChannel] Failed to set webhook:",t.description)}handleWebhookRequest(e,t){if(e.method!=="POST"){t.writeHead(405),t.end("Method not allowed");return}let n="";e.on("data",r=>{n+=r.toString()}),e.on("end",()=>{try{let r=JSON.parse(n);this.handleMessage(this.normalize(r)).catch(s=>{console.error("[TelegramChannel] Error processing webhook:",s)}),t.writeHead(200),t.end("OK")}catch(r){console.error("[TelegramChannel] Error parsing webhook:",r),t.writeHead(400),t.end("Bad request")}})}async stop(){if(this.pollingInterval&&(clearInterval(this.pollingInterval),this.pollingInterval=void 0),this.server)return new Promise(e=>{this.server.close(e)});if(this.config.webhookUrl)try{await fetch(`https://api.telegram.org/bot${this.config.token}/deleteWebhook`,{method:"POST"})}catch(e){console.error("[TelegramChannel] Failed to delete webhook:",e)}}};d();var Bn=new Set([1,3]),Yt=/<@!?(\d+)>/g,Ln="https://discord.com/api/v10",Be=class extends C{isTriggerChannel=!1;config;allowedChannelIds;botUserId;participantCache=new Map;client;constructor(e){super(),this.config=e,this.name=e.name,e.channelId==null?this.allowedChannelIds=new Set:Array.isArray(e.channelId)?this.allowedChannelIds=new Set(e.channelId):this.allowedChannelIds=new Set([e.channelId])}shouldProcessEvent(e){return!e.author||e.webhookId||this.botUserId&&e.author.id===this.botUserId||this.config.guildId&&e.guildId!==this.config.guildId||this.allowedChannelIds.size>0&&(!e.channelId||!this.allowedChannelIds.has(e.channelId))?!1:e.author.bot||e.author.system?this.config.blockedBotIds?.includes(e.author.id)?!1:this.config.allowedBotIds?this.config.allowedBotIds.includes(e.author.id):!1:!0}normalize(e){let t=e,n=t.channelId,r=(n??"")+(t.thread?.id?`:${t.thread.id}`:""),s=t.channel?.type,i=s!==void 0&&Bn.has(s),c=t.author?.id,p=t.author?.globalName??t.author?.username,a=[];if(t.content){Yt.lastIndex=0;let l;for(;(l=Yt.exec(t.content))!==null;)a.push(l[1])}return{message:t.content,conversationId:r,data:t,participant:c?{kind:"user",id:c,displayName:p??void 0}:void 0,context:{userId:c,username:t.author?.username,channelType:i?"dm":"channel",channelId:n,channelName:t.channel?.name,guildId:t.guildId,threadId:t.thread?.id,messageId:t.id,mentions:a.length>0?a:void 0,isMentioned:this.botUserId?a.includes(this.botUserId):void 0}}}async resolveParticipant(e){let t=e.participant?.id??e.context?.userId;if(!t)return;let n=this.participantCache.get(t);if(n)return n;try{let r=await fetch(`${Ln}/users/${t}`,{headers:{Authorization:`Bot ${this.config.token}`}});if(!r.ok)return console.warn(`[DiscordChannel] Failed to resolve user ${t}: HTTP ${r.status}`),{kind:"user",id:t};let s=await r.json(),i=s.global_name??s.username,c={kind:"user",id:s.id,displayName:i};return this.participantCache.set(t,c),c}catch(r){return console.warn(`[DiscordChannel] resolveParticipant error for ${t}:`,r),{kind:"user",id:t}}}invalidateParticipant(e){this.participantCache.delete(e)}async send(e){if(!this.client)throw new Error("[DiscordChannel] Client not initialized. Did you call listen()?");let t=e.metadata?.threadId;if(t){let s=await this.client.channels.fetch(t);if(s&&"send"in s)try{await s.send({content:e.output});return}catch(i){throw console.error("[DiscordChannel] Failed to send to thread:",i),new Error(`[DiscordChannel] Failed to send Discord message: ${i instanceof Error?i.message:String(i)}`)}console.warn(`[DiscordChannel] Thread ${t} not found or not sendable; falling back to channel send.`)}let n=e.metadata?.channelId??(this.allowedChannelIds.size>0?[...this.allowedChannelIds][0]:void 0);if(!n)throw new Error("[DiscordChannel] No channel ID available for sending. Configure channelId or pass output.metadata.channelId.");let r=await this.client.channels.fetch(n);if(!r||!("send"in r))throw new Error(`[DiscordChannel] Channel ${n} not found or is not a text channel`);try{await r.send({content:e.output})}catch(s){throw console.error("[DiscordChannel] Failed to send to channel:",s),new Error(`[DiscordChannel] Failed to send Discord message: ${s instanceof Error?s.message:String(s)}`)}}listen(){typeof process>"u"||import("discord.js").then(e=>{let{Client:t,GatewayIntentBits:n}=e;this.client=new t({intents:[n.Guilds,n.GuildMessages,n.MessageContent,n.DirectMessages]}),this.client.on("ready",()=>{let r=this.client.user;this.botUserId=r?.id;let s=this.allowedChannelIds.size===0?"all channels":[...this.allowedChannelIds].join(", "),i=this.config.guildId??"all guilds";console.log(`[DiscordChannel] Logged in as ${r?.tag??"unknown"} (botUserId=${this.botUserId??"unknown"}) | guild=${i} | channels=${s}`)}),this.client.on("messageCreate",r=>{let s=r;if(!this.shouldProcessEvent(s))return;let i=this.normalize(s);this.handleMessage(i)}),this.client.on("userUpdate",(r,s)=>{let i=s;i?.id&&this.invalidateParticipant(i.id)}),this.client.login(this.config.token).catch(r=>{console.error("[DiscordChannel] Failed to login to Discord:",r)})}).catch(e=>{console.error("[DiscordChannel] Failed to initialize Discord client:",e),console.error("[DiscordChannel] Make sure discord.js is installed: npm install discord.js")})}async stop(){this.client&&(await this.client.destroy(),this.client=void 0)}};d();var Le=class extends C{isTriggerChannel=!0;config;transporter;constructor(e){super(),this.config=e,this.name=e.name}listen(){typeof process<"u"&&import("nodemailer").then(e=>{this.transporter=e.default.createTransport({host:this.config.smtp.host,port:this.config.smtp.port,secure:this.config.smtp.secure??this.config.smtp.port===465,auth:{user:this.config.smtp.auth.user,pass:this.config.smtp.auth.pass}}),console.log(`[EmailChannel] Email transporter initialized for ${this.config.from}`)}).catch(e=>{console.error("[EmailChannel] Failed to initialize nodemailer:",e),console.error("[EmailChannel] Make sure to install nodemailer: npm install nodemailer")})}async send(e){if(!this.transporter)throw new Error("Email transporter not initialized. Did you call listen()?");let t=Array.isArray(this.config.to)?this.config.to:[this.config.to],n=this.config.subject||"Message from Agent",r={from:this.config.from,to:t.join(", "),subject:n,text:e.output,html:this.formatAsHtml(e.output)};try{await this.transporter.sendMail(r)}catch(s){throw console.error("[EmailChannel] Failed to send email:",s),new Error(`Failed to send email: ${s instanceof Error?s.message:String(s)}`)}}normalize(e){throw new Error("EmailChannel is outbound-only. Use WebhookChannel with email webhook events for inbound email.")}formatAsHtml(e){return e.split(`
|
|
32
|
+
Is this answer sufficient? Reply with ONLY "yes" or "no".`,{workflow:{mode:"single-shot"}})).output.toLowerCase().trim().startsWith("yes")}async handlePendingAsk(e,t,n,r){return await this.evaluateAnswer(e.question,t,{simpleValidation:i=>i.trim().length>3})?(await this.resolvePendingAsk(e.id,t),n(t)):e.retries>=e.maxRetries?(await this.resolvePendingAsk(e.id,"__insufficient__"),this._triggeringChannel&&await this.sendTo(this._triggeringChannel,"I was unable to get enough information to proceed. Skipping this step."),r?r():{output:"Step skipped due to insufficient input.",metadata:{skipped:!0,askId:e.id}}):(this._registry?.incrementRetries(e.id),this.ask(`I need a bit more clarity on: "${e.question}". Could you provide more details?`,{context:e.context,maxRetries:e.maxRetries}))}async delegateAndWait(e,t){if(!this._registry)throw new I("Agent not registered - cannot use delegateAndWait()");let n={message:t.message,intent:t.intent,data:t.data,context:{...t.context||{},delegatedBy:this.name},conversationId:t.conversationId||this._conversationId||`delegation-${Date.now()}`};return await this._registry.invoke(e,n)}async onBeforeRun(e){}async onComplete(e){}async onError(e){}_resolveAssemblerOptions(){let e=this.channels.map(r=>r.botUserId).filter(r=>typeof r=="string"&&r.length>0),t=this.assemblerOptions?.agentAliases??[];if(e.length===0&&t.length===0)return this.assemblerOptions;let n=Array.from(new Set([...t,...e]));return{...this.assemblerOptions,agentAliases:n}}_getEffectiveInterceptors(){return this.interceptors.some(t=>t[re]===!0)?this.interceptors:[Y({store:this.conversationHistory}),...this.interceptors]}_bindChannel(e){e.onMessage(async t=>{if(!t.conversationId){console.warn(`[${this.name}] Message received without conversationId \u2014 skipping`);return}let n=await this._acquireConversationLock(t.conversationId);try{this._triggeringChannel=e.name,this._isTriggerChannel=e.isTriggerChannel,this._conversationId=t.conversationId;let r=te(this._getEffectiveInterceptors(),this,e,this._registry??null),s=await ne(r,t);if(s===null)return;let i={output:s.output,metadata:s.metadata};await e.send({output:i.output,metadata:{...i.metadata,conversationId:t.conversationId,...t.context}})}catch(r){let s=r instanceof Error?r.message:"Unknown error occurred";console.error(`[${this.name}] Error in agent invocation: ${s}`);try{await e.send({output:`Error: ${s}`,metadata:{conversationId:t.conversationId,error:!0,...t.context}})}catch(i){console.error(`[${this.name}] Failed to send error to channel: ${i}`)}}finally{n()}})}async _acquireConversationLock(e){for(;this._conversationLocks.has(e);)try{await this._conversationLocks.get(e)}catch{}let t,n=new Promise(r=>{t=r});return this._conversationLocks.set(e,n),()=>{this._conversationLocks.delete(e),t()}}extractSteps(e){let t=e;if(t.plan&&typeof t.plan=="object"){let n=t.plan;if(Array.isArray(n.steps))return n.steps.map(r=>({number:r.number||0,description:r.description||"",status:r.status||"completed",result:r.result}))}if(Array.isArray(t.steps))return t.steps}}});var qn={};nt(qn,{AgentError:()=>I,AgentJsonRpcServer:()=>de,AgentMind:()=>ie,AgentRegistry:()=>Se,BaseAgent:()=>R,BaseChannel:()=>C,BrowserAgent:()=>Me,CodingAgent:()=>Ee,ContainsScorer:()=>ve,CustomScorer:()=>Ae,DataAgent:()=>Pe,DepthExceededError:()=>q,DiscordChannel:()=>Be,EmailChannel:()=>Le,EphemeralAgent:()=>ae,EvalDataset:()=>he,EvalRunner:()=>fe,ExactMatchScorer:()=>ye,HotReloadWatcher:()=>Te,InMemoryConversationStore:()=>Ge.InMemoryConversationStore,IntentClassifierAgent:()=>le,InvocationDepthExceededError:()=>V,JsonRpcTransport:()=>ce,LLMJudgeScorer:()=>we,LocalTransport:()=>z,McpChannel:()=>Ue,OTelSpanStatusCode:()=>ue,ResearchAgent:()=>_e,SKIP_SENTINEL:()=>J,SMSChannel:()=>Fe,ScheduledChannel:()=>$e,SchedulerStore:()=>me,SlackChannel:()=>De,SummarizerAgent:()=>pe,TelegramChannel:()=>je,WebhookChannel:()=>Ne,assemblePrompt:()=>se,compareEvalRuns:()=>kt,composeChain:()=>te,createAddressCheckInterceptor:()=>Ke,createCaptureInterceptor:()=>Y,createConversationSearchTool:()=>wt,createDepthGuardInterceptor:()=>Ye,createEventDedupInterceptor:()=>Je,createIntentClassifierInterceptor:()=>Ve,createNoiseFilterInterceptor:()=>ze,createOTelTracerInterceptor:()=>Qe,createParticipantResolverInterceptor:()=>He,createRateLimitInterceptor:()=>We,createSchedulerTools:()=>Ct,createSelfFilterInterceptor:()=>qe,createTracerInterceptor:()=>Xe,executeChain:()=>ne,formatEvalReport:()=>Rt,isSkipSentinel:()=>j,skip:()=>ee});module.exports=an(qn);d();d();B();xe();d();var Gt=require("crypto");d();var yt=require("crypto");oe();var z=class{constructor(e){this.registry=e}registry;async invoke(e,t){let n=this.registry.getAgent(e);if(!n)throw new I(`Agent "${e}" not found in registry. Available agents: ${this.registry.getAllAgents().map(p=>p.name).join(", ")}`);let r=n.conversationHistory,s=t.conversationId,i=t.context?.delegatedBy;if(r&&s&&i){let p={id:t.context?.messageId??(0,yt.randomUUID)(),conversationId:s,participant:{kind:"agent",id:i,displayName:i},content:t.message??"",timestamp:new Date().toISOString(),scope:"channel",metadata:{}};try{await r.append(p)}catch{}}let c=await n.invokeAgent(t);if(r&&s){let p={id:(0,yt.randomUUID)(),conversationId:s,participant:{kind:"agent",id:e,displayName:e},content:c.output,timestamp:new Date().toISOString(),scope:"channel",metadata:{}};try{await r.append(p)}catch{}}return c}};var Se=class{agentList;instances=new Map;channels=new Map;_transport;pendingAsks=new Map;_started=!1;_restarting=!1;_restartScheduled=!1;_deadlineTimer;constructor(e,t){this.agentList=e,this._transport=t?.transport||new z(this)}async start(){for(let e of this.agentList){await e._ensureToolpack(),e._registry=this,this.instances.set(e.name,e);for(let t of e.channels??[])t.name&&this.channels.set(t.name,t)}for(let e of this.agentList)await e.start();this._started=!0}async addAgent(e){if(this.agentList.push(e),!!this._started){await e._ensureToolpack(),e._registry=this,this.instances.set(e.name,e);for(let t of e.channels??[])t.name&&this.channels.set(t.name,t);await e.start()}}async removeAgent(e){let t=this.instances.get(e);if(t){await t.stop(),this.instances.delete(e),this.agentList=this.agentList.filter(n=>n.name!==e);for(let n of t.channels??[])n.name&&this.channels.delete(n.name)}}isAllIdle(){return this.agentList.every(e=>e.isIdle())}scheduleRestart(e){if(this._restartScheduled)return;this._restartScheduled=!0;let t=(e?.maxWaitMinutes??30)*60*1e3,n=()=>{!this._restarting&&this.isAllIdle()&&this._executeRestart()};if(n(),!this._restarting){for(let r of this.agentList)r.on("agent:complete",n);this._deadlineTimer=setTimeout(()=>{this._executeRestart()},t)}}async _executeRestart(){if(this._restarting)return;this._restarting=!0,this._deadlineTimer&&(clearTimeout(this._deadlineTimer),this._deadlineTimer=void 0),await this.stop();let e=Date.now()+3e4;for(;!this.isAllIdle()&&Date.now()<e;)await new Promise(t=>setTimeout(t,100));this._exit(0)}_exit(e){process.exit(e)}async sendTo(e,t){let n=this.channels.get(e);if(!n)throw new Error(`No channel registered with name "${e}"`);await n.send(t)}getAgent(e){return this.instances.get(e)}getAllAgents(){return Array.from(this.instances.values())}getChannel(e){return this.channels.get(e)}async invoke(e,t){return this._transport.invoke(e,t)}async stop(){for(let e of this.agentList)await e.stop();this.instances.clear(),this.channels.clear(),this.pendingAsks.clear()}getPendingAsk(e){let t=this.pendingAsks.get(e);if(!t||t.length===0)return;let n=new Date;for(;t.length>0;){let r=t[0];if(r.expiresAt&&r.expiresAt<n)t.shift();else break}if(t.length===0){this.pendingAsks.delete(e);return}return t[0]}hasPendingAsks(e){let t=this.pendingAsks.get(e);if(!t||t.length===0)return!1;let n=new Date,r=t.filter(s=>!s.expiresAt||s.expiresAt>=n);return r.length===0?(this.pendingAsks.delete(e),!1):(r.length!==t.length&&this.pendingAsks.set(e,r),r.some(s=>s.status==="pending"))}cleanupExpiredAsks(){let e=0,t=new Date;for(let[n,r]of this.pendingAsks.entries()){let s=r.filter(i=>!i.expiresAt||i.expiresAt>=t);e+=r.length-s.length,s.length===0?this.pendingAsks.delete(n):s.length!==r.length&&this.pendingAsks.set(n,s)}return e}addPendingAsk(e){let t={...e,id:(0,Gt.randomUUID)(),askedAt:new Date,retries:0,status:"pending"},n=this.pendingAsks.get(e.conversationId);return n?n.push(t):this.pendingAsks.set(e.conversationId,[t]),t}incrementRetries(e){for(let t of this.pendingAsks.values()){let n=t.find(r=>r.id===e);if(n)return n.retries+=1,n.retries}}async resolvePendingAsk(e,t){for(let[n,r]of this.pendingAsks.entries()){let s=r.findIndex(i=>i.id===e);if(s!==-1){r[s].status="answered",r[s].answer=t;let i=r[s].channelName;if(r.splice(s,1),r.length>0){let c=r[0];if(i&&i.trim()!=="")try{await this.sendTo(i,{output:c.question})}catch(p){console.error(`[AgentRegistry] Failed to auto-send next ask: ${p instanceof Error?p.message:"Unknown error"}`)}else console.warn(`[AgentRegistry] Cannot auto-send next ask: channelName is empty for conversation ${n}`)}r.length===0&&this.pendingAsks.delete(n);return}}throw new Error(`Pending ask with id "${e}" not found`)}};oe();d();var Jt=require("fs"),zt=require("child_process"),qt=require("path"),Te=class{cwd;debounceMs;onRestartNeeded;onCompileError;spawnFn;watchFn;watchPaths;watchers=[];debounceTimer;constructor(e){this.watchPaths=e.watchPaths,this.cwd=e.cwd??process.cwd(),this.debounceMs=e.debounceMs??3e4,this.onRestartNeeded=e.onRestartNeeded,this.onCompileError=e.onCompileError,this.spawnFn=e.spawnFn??zt.spawn,this.watchFn=e.watchFn??Jt.watch}start(){for(let e of this.watchPaths){let t=this.watchFn(e,{recursive:!0},(n,r)=>{r&&this._handleFileChange(r)});this.watchers.push(t)}}stop(){for(let e of this.watchers)e.close();this.watchers=[],this.debounceTimer!==void 0&&(clearTimeout(this.debounceTimer),this.debounceTimer=void 0)}_handleFileChange(e){this.debounceTimer!==void 0&&clearTimeout(this.debounceTimer),this.debounceTimer=setTimeout(()=>{this.debounceTimer=void 0,(0,qt.basename)(e).startsWith(".env")?this.onRestartNeeded():(e.endsWith(".ts")||e.endsWith(".tsx"))&&this._runCompile()},this.debounceMs)}_runCompile(){return new Promise(e=>{let t="",n=this.spawnFn("npx",["tsc","--build"],{cwd:this.cwd,stdio:["ignore","ignore","pipe"]});n.stderr?.on("data",r=>{t+=r.toString()}),n.on("close",r=>{if(r===0)this.onRestartNeeded();else{let s=t||`tsc --build exited with code ${String(r)}`;this.onCompileError?.(s)}e()}),n.on("error",r=>{let s=r instanceof Error?r.message:String(r);this.onCompileError?.(s),e()})})}};d();B();var Wt=require("toolpack-sdk"),On={...Wt.AGENT_MODE,name:"research-agent-mode",systemPrompt:["You are a research agent specialized in web research and information gathering.","Use web.search to find relevant information, web.fetch to retrieve content, and web.scrape when needed.","Always cite your sources with URLs.","Provide comprehensive, well-structured summaries.","Flag any conflicting information or uncertainty in your findings."].join(" ")},_e=class extends R{name="research-agent";description="Web research agent for summarization, fact-finding, competitive analysis, and trend monitoring";mode=On;constructor(e){super(e)}async invokeAgent(e){let t=await this.run(e.message||"",void 0,{conversationId:e.conversationId});return await this.onComplete(t),t}};d();B();var Ht=require("toolpack-sdk"),Nn={...Ht.CODING_MODE,name:"coding-agent-mode",systemPrompt:["You are a coding agent specialized in software development tasks.","Use coding.* tools for code analysis, fs.* for file operations, and git.* for version control.","Write clean, idiomatic code following best practices.","Always verify your changes and check for potential issues.","Provide clear explanations of your code changes."].join(" ")},Ee=class extends R{name="coding-agent";description="Coding agent for code generation, refactoring, debugging, test writing, and code review";mode=Nn;constructor(e){super(e)}async invokeAgent(e){let t=await this.run(e.message||"",void 0,{conversationId:e.conversationId});return await this.onComplete(t),t}};d();B();var Kt=require("toolpack-sdk"),$n={...Kt.AGENT_MODE,name:"data-agent-mode",systemPrompt:["You are a data agent specialized in database operations and data analysis.","Use db.* tools for database queries, fs.* for file operations, and http.* for API requests.","Generate clear, well-formatted reports and summaries.","Always validate data integrity and handle errors gracefully.","Provide insights and patterns when analyzing data."].join(" ")},Pe=class extends R{name="data-agent";description="Data agent for database queries, CSV generation, data analysis, reporting, and aggregation";mode=$n;constructor(e){super(e)}async invokeAgent(e){let t=await this.run(e.message||"",void 0,{conversationId:e.conversationId});return await this.onComplete(t),t}};d();B();var Vt=require("toolpack-sdk"),jn={...Vt.CHAT_MODE,name:"browser-agent-mode",systemPrompt:["You are a browser agent specialized in web interaction and content extraction.","Use web.fetch to retrieve pages, web.screenshot for visual content, and web.extract_links for navigation.","Follow links intelligently to gather comprehensive information.","Extract structured data from web pages when possible.","Be mindful of rate limits and respectful of website resources."].join(" ")},Me=class extends R{name="browser-agent";description="Browser agent for web browsing, form interaction, page extraction, and link following";mode=jn;constructor(e){super(e)}async invokeAgent(e){let t=await this.run(e.message||"",void 0,{conversationId:e.conversationId});return await this.onComplete(t),t}};d();var C=class{name;_handler;onMessage(e){this._handler=e}async handleMessage(e){this._handler&&await this._handler(e)}};d();var Oe=require("crypto");var De=class extends C{isTriggerChannel=!1;config;server;participantCache=new Map;botUserId;botId;allowedChannels;constructor(e){super(),this.config={port:3e3,...e},this.name=e.name;let t=e.channel;this.allowedChannels=t==null?null:Array.isArray(t)?t:[t]}listen(){typeof process<"u"&&import("http").then(e=>{this.server=e.createServer((t,n)=>{this.handleRequest(t,n)}),this.server.listen(this.config.port,()=>{console.log(`[SlackChannel] Listening on port ${this.config.port}`),this.runStartupCheck().catch(()=>{})})}).catch(e=>{console.error("[SlackChannel] Failed to start HTTP server:",e)})}async runStartupCheck(){try{let t=await(await fetch("https://slack.com/api/auth.test",{method:"POST",headers:{Authorization:`Bearer ${this.config.token}`,"Content-Type":"application/json"}})).json();t.ok?(this.botUserId=t.user_id,this.botId=t.bot_id,console.log(`[SlackChannel] Connected as @${t.user} (${t.user_id}) in workspace "${t.team}" \u2014 ${t.url}`)):console.warn(`[SlackChannel] auth.test failed: ${t.error}. Check your bot token.`)}catch(e){console.warn("[SlackChannel] Startup self-check failed (network error):",e)}}verifySignature(e,t){let n=e["x-slack-request-timestamp"],r=e["x-slack-signature"];if(!n||!r||Array.isArray(n)||Array.isArray(r))return!1;let s=parseInt(n,10),i=Math.floor(Date.now()/1e3);if(isNaN(s)||Math.abs(i-s)>300)return!1;let c=`v0:${n}:${t}`,a=`v0=${(0,Oe.createHmac)("sha256",this.config.signingSecret).update(c).digest("hex")}`;if(a.length!==r.length)return!1;try{return(0,Oe.timingSafeEqual)(Buffer.from(a),Buffer.from(r))}catch{return!1}}async send(e){let t=e.metadata?.threadTs??e.metadata?.thread_ts??e.metadata?.threadId,r=e.metadata?.channelId??(this.allowedChannels&&this.allowedChannels.length>0?this.allowedChannels[0]:void 0);if(!r)throw new Error("[SlackChannel] Cannot send: no channel configured and metadata.channelId is missing. Provide a target via SlackChannelConfig.channel or output.metadata.channelId.");let s={channel:r,text:e.output};t&&(s.thread_ts=t);let i=await fetch("https://slack.com/api/chat.postMessage",{method:"POST",headers:{Authorization:`Bearer ${this.config.token}`,"Content-Type":"application/json"},body:JSON.stringify(s)});if(!i.ok)throw new Error(`Failed to send Slack message: ${i.statusText}`);let c=await i.json();if(!c.ok)throw new Error(`Slack API error: ${c.error}`)}normalize(e){let t=e,r=(t.text||"").replace(/<(https?:\/\/[^|>]+)\|([^>]+)>/g,"$2 ($1)").replace(/<(https?:\/\/[^>]+)>/g,"$1").replace(/<!here>/g,"@here").replace(/<!channel>/g,"@channel").replace(/<!everyone>/g,"@everyone"),s=t.ts,i=t.thread_ts,c=i!==void 0&&i!==s,p=t.user,a=p?{kind:"user",id:p}:void 0,l=/<@([A-Z0-9]+)>/g,m=[],u;for(;(u=l.exec(r))!==null;)m.push(u[1]);let g=t.channel;return{message:r,conversationId:c?i:g||s||"",data:t,participant:a,context:{user:p,channel:g,team:t.team,channelType:t.channel_type,threadId:c?i:void 0,mentions:m.length>0?m:void 0,channelId:g,channelName:typeof this.config.channel=="string"?this.config.channel:g}}}async resolveParticipant(e){let t=e.participant?.id??e.context?.user;if(!t)return;let n=this.participantCache.get(t);if(n)return n;try{let r=await fetch(`https://slack.com/api/users.info?user=${encodeURIComponent(t)}`,{method:"GET",headers:{Authorization:`Bearer ${this.config.token}`}});if(!r.ok)return{kind:"user",id:t};let s=await r.json();if(!s.ok||!s.user){let p={kind:"user",id:t};return this.participantCache.set(t,p),p}let i=s.user.profile?.display_name||s.user.profile?.real_name||s.user.real_name||s.user.name||t,c={kind:"user",id:t,displayName:i,metadata:{slackUser:s.user}};return this.participantCache.set(t,c),c}catch{return{kind:"user",id:t}}}invalidateParticipant(e){this.participantCache.delete(e)}shouldProcessEvent(e){let t=e.type;if(t!=="message"&&t!=="app_mention")return!1;if(this.allowedChannels!==null){let i=e.channel_type;if(!(i==="im"||i==="mpim")){let p=e.channel;if(!p||!this.allowedChannels.includes(p))return!1}}let n=e.user;if(this.botUserId&&n===this.botUserId)return!1;let r=e.bot_id;if(console.log(`[SlackChannel:shouldProcessEvent] subtype=${e.subtype} user=${n} bot_id=${r} this.botUserId=${this.botUserId} this.botId=${this.botId}`),!r)return!0;if(this.botId&&r===this.botId)return!1;let s=this.config.blockedBotIds??[];if(s.includes(r)||n!==void 0&&s.includes(n))return!1;if(this.config.allowedBotIds!==void 0){let i=this.config.allowedBotIds;return i.includes(r)||n!==void 0&&i.includes(n)}return!0}handleRequest(e,t){if(e.method!=="POST"){t.writeHead(405),t.end("Method not allowed");return}let n="";e.on("data",r=>{n+=r.toString()}),e.on("end",()=>{if(!this.verifySignature(e.headers,n)){t.writeHead(401),t.end("Invalid signature");return}try{let r=JSON.parse(n);if(r.type==="url_verification"){t.writeHead(200,{"Content-Type":"application/json"}),t.end(JSON.stringify({challenge:r.challenge}));return}if(r.type==="event_callback"&&r.event){let s=r.event;if(this.shouldProcessEvent(s)){let i=this.normalize(s);this.handleMessage(i)}else s.type==="user_change"&&s.user&&this.invalidateParticipant(s.user.id);t.writeHead(200),t.end("OK");return}t.writeHead(200),t.end("OK")}catch(r){console.error("[SlackChannel] Error handling request:",r),t.writeHead(400),t.end("Bad request")}})}async stop(){if(this.server)return new Promise(e=>{this.server.close(e)})}};d();var Ne=class extends C{isTriggerChannel=!1;config;server;pendingResponses=new Map;constructor(e){super(),this.name=e.name,this.config={port:e.port??3e3,path:e.path??"/webhook"}}listen(){typeof process<"u"&&import("http").then(e=>{this.server=e.createServer((t,n)=>{this.handleRequest(t,n)}),this.server.listen(this.config.port,()=>{console.log(`[WebhookChannel] Listening on port ${this.config.port}${this.config.path}`)})}).catch(e=>{console.error("[WebhookChannel] Failed to start HTTP server:",e)})}async send(e){let t=e.metadata?.conversationId;if(t&&this.pendingResponses.has(t)){let n=this.pendingResponses.get(t);this.pendingResponses.delete(t),n.resolve({output:e.output,metadata:e.metadata})}}normalize(e){let t=e,n=t.headers||{},r=n["x-session-id"]||n["X-Session-Id"]||t.sessionId||t.conversationId||this.generateSessionId();return{message:t.message||t.text||"",intent:t.intent,conversationId:r,data:t,context:{headers:t.headers,method:t.method,sessionId:r}}}handleRequest(e,t){if(e.url!==this.config.path){t.writeHead(404),t.end("Not found");return}if(e.method!=="POST"){t.writeHead(405),t.end("Method not allowed");return}let n="";e.on("data",r=>{n+=r.toString()}),e.on("end",()=>{try{let r=JSON.parse(n),s=this.normalize(r),i=s.conversationId||this.generateSessionId(),c=new Promise((p,a)=>{this.pendingResponses.set(i,{resolve:p,reject:a}),setTimeout(()=>{this.pendingResponses.has(i)&&(this.pendingResponses.delete(i),a(new Error("Agent response timeout")))},3e4)});this.handleMessage({...s,conversationId:i,context:{...s.context,sessionId:i}}),c.then(p=>{t.writeHead(200,{"Content-Type":"application/json"}),t.end(JSON.stringify(p))}).catch(p=>{t.writeHead(500,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:p.message}))})}catch(r){console.error("[WebhookChannel] Error handling request:",r),t.writeHead(400,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Bad request"}))}})}generateSessionId(){return`webhook-${Date.now()}-${Math.random().toString(36).substring(2,9)}`}async stop(){if(this.server)return new Promise(e=>{this.server.close(e)})}};d();var vt=require("cron-parser"),$e=class extends C{isTriggerChannel=!0;config;timer;_stopped=!1;_generation=0;constructor(e){if(super(),!e.cron&&!e.store)throw new Error("ScheduledChannel: provide at least one of `cron` (static schedule) or `store` (dynamic scheduling).");if(e.cron)try{vt.CronExpressionParser.parse(e.cron)}catch(t){throw new Error(`ScheduledChannel: invalid cron expression '${e.cron}': ${t.message}`)}if(e.store&&!e.name&&console.warn("[ScheduledChannel] A `store` was provided without a `name`. All store queries will be unscoped and will pick up jobs from every channel. Set `name` to scope this channel to its own jobs."),e.idlePollMs!==void 0&&e.idlePollMs<1e3)throw new Error(`ScheduledChannel: idlePollMs must be at least 1000ms (got ${e.idlePollMs}). Values below 1 second create a tight polling loop.`);this.config=e,this.name=e.name}listen(){this._generation++,this.timer&&(clearTimeout(this.timer),this.timer=void 0),this._stopped=!1,this.config.store?this._listenWithStore():this._listenStatic()}async stop(){this._stopped=!0,this.timer&&(clearTimeout(this.timer),this.timer=void 0)}async send(e){}normalize(e){let t=e,n=new Date,r=`${n.getFullYear()}-${n.getMonth()+1}-${n.getDate()}`;return{intent:t?.intent??this.config.intent,message:t?.message??this.config.message??`Scheduled task triggered at ${n.toISOString()}`,conversationId:`scheduled:${this.name??"default"}:${r}`,data:{...t?.payload??{},scheduled:!0,jobId:t?.id,cron:t?.cron??this.config.cron,timestamp:n.toISOString()}}}_listenStatic(){this._scheduleNextStatic(this._generation)}_scheduleNextStatic(e){if(this._stopped||e!==this._generation)return;let t=this._nextRunFromCron(this.config.cron),n=t.getTime()-Date.now();if(n<=0){this.timer=setTimeout(()=>this._scheduleNextStatic(e),0);return}console.log(`[ScheduledChannel:${this.name??"default"}] Next run: ${t.toISOString()}`),this.timer=setTimeout(async()=>{this._stopped||e!==this._generation||(await this._triggerStatic(),this._scheduleNextStatic(e))},n)}async _triggerStatic(){if(!this._handler){console.warn(`[ScheduledChannel:${this.name??"default"}] Cron fired but no message handler is registered. Call onMessage() before listen() to avoid silently losing triggers.`);return}let e=this.normalize(null);try{await this.handleMessage(e)}catch(t){console.error(`[ScheduledChannel:${this.name??"default"}] Error on trigger:`,t)}}_listenWithStore(){let e=this.config.store,t=this._generation;if(t===1){let r=e.resetStuck(this.name);r>0&&console.log(`[ScheduledChannel:${this.name??"default"}] Reset ${r} stuck 'running' job(s) to 'pending'.`)}if(this.config.cron){let{duplicate:r}=e.create({channelName:this.name,cron:this.config.cron,intent:this.config.intent,message:this.config.message});r||console.log(`[ScheduledChannel:${this.name??"default"}] Seeded static cron '${this.config.cron}' into store.`)}let n=e.getDue(Date.now(),this.name);n.length>0&&(console.log(`[ScheduledChannel:${this.name??"default"}] Recovering ${n.length} overdue job(s).`),Promise.allSettled(n.map(r=>this._triggerJob(r)))),this._scheduleNextFromStore(t)}_scheduleNextFromStore(e){if(this._stopped||e!==this._generation)return;let t=this.config.store,n=t.getNextPending(this.name);if(!n){let s=this.config.idlePollMs??3e4;this.timer=setTimeout(()=>this._scheduleNextFromStore(e),s);return}let r=Math.max(0,n.nextRunAt-Date.now());console.log(`[ScheduledChannel:${this.name??"default"}] Next store job at ${new Date(n.nextRunAt).toISOString()} (in ${Math.round(r/1e3)}s)`),this.timer=setTimeout(async()=>{if(this._stopped||e!==this._generation)return;let s=t.getDue(Date.now(),this.name);await Promise.allSettled(s.map(i=>this._triggerJob(i))),this._scheduleNextFromStore(e)},r)}async _triggerJob(e){let t=this.config.store;if(!this._handler){console.warn(`[ScheduledChannel:${this.name??"default"}] Job ${e.id} fired but no message handler is registered. Call onMessage() before listen() to avoid silently losing jobs.`),t.markFailed(e.id,"No message handler registered");return}t.markRunning(e.id);let n=this.normalize(e);try{await this.handleMessage(n),t.markCompleted(e.id)}catch(r){let s=r instanceof Error?r.message:String(r);console.error(`[ScheduledChannel:${this.name??"default"}] Job ${e.id} failed:`,r),t.markFailed(e.id,s)}}_nextRunFromCron(e){return vt.CronExpressionParser.parse(e,{currentDate:new Date}).next().toDate()}};d();var je=class extends C{isTriggerChannel=!1;config;offset=0;pollingInterval;server;botUserId;botUsername;constructor(e){super(),this.name=e.name,this.config=e}listen(){this.runStartupCheck().catch(()=>{}),this.config.webhookUrl?this.startWebhook():this.startPolling()}async runStartupCheck(){try{let t=await(await fetch(`https://api.telegram.org/bot${this.config.token}/getMe`)).json();if(t.ok&&t.result){let n=t.result;this.botUserId=n.id!=null?String(n.id):void 0,this.botUsername=n.username,console.log(`[TelegramChannel] Connected as @${n.username} (id: ${n.id}, name: ${n.first_name})`)}else console.warn(`[TelegramChannel] getMe failed: ${t.description??"unknown error"}. Check your bot token.`)}catch(e){console.warn("[TelegramChannel] Startup self-check failed (network error):",e)}}async send(e){let t=e.metadata?.chatId;if(!t)throw new Error("Telegram send requires chatId in metadata");let n=await fetch(`https://api.telegram.org/bot${this.config.token}/sendMessage`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({chat_id:t,text:e.output,parse_mode:"Markdown"})});if(!n.ok)throw new Error(`Failed to send Telegram message: ${n.statusText}`);let r=await n.json();if(!r.ok)throw new Error(`Telegram API error: ${r.description}`)}normalize(e){let t=e,n=t.message||t.edited_message||{},r=n.text||"",s=n.chat||{},i=n.from||{},c=i.id!=null?String(i.id):void 0,p=i.first_name||i.username||c,a=c?{kind:"user",id:c,displayName:p??c}:void 0,l=n.entities??[],m=[];for(let v of l)if(v.type==="text_mention"&&v.user){let f=v.user;f.id!=null&&m.push(String(f.id))}let u=s.type,g=s.id!=null?String(s.id):"";return{message:r,conversationId:g,data:t,participant:a,context:{chatId:s.id,userId:i.id,username:i.username,firstName:i.first_name,lastName:i.last_name,messageId:n.message_id,channelType:u,channelId:g,channelName:s.title,mentions:m.length>0?m:void 0}}}startPolling(){console.log("[TelegramChannel] Starting polling mode"),this.pollingInterval=setInterval(async()=>{try{await this.pollUpdates()}catch(e){console.error("[TelegramChannel] Polling error:",e)}},5e3)}async pollUpdates(){let e=`https://api.telegram.org/bot${this.config.token}/getUpdates?offset=${this.offset}&limit=100`,t=await fetch(e);if(!t.ok)throw new Error(`Telegram getUpdates failed: ${t.statusText}`);let n=await t.json();if(!n.ok)throw new Error("Telegram getUpdates returned not ok");for(let r of n.result){let s=r.update_id;s>=this.offset&&(this.offset=s+1);try{let i=this.normalize(r);await this.handleMessage(i)}catch(i){console.error("[TelegramChannel] Error processing update:",i)}}}startWebhook(){typeof process>"u"||(console.log("[TelegramChannel] Starting webhook mode"),import("http").then(e=>{this.server=e.createServer((r,s)=>{this.handleWebhookRequest(r,s)});let t=new URL(this.config.webhookUrl||"http://localhost:3000"),n=parseInt(t.port,10)||3e3;this.server.listen(n,()=>{console.log(`[TelegramChannel] Webhook server listening on port ${n}`)}),this.setWebhook()}).catch(e=>{console.error("[TelegramChannel] Failed to start webhook server:",e)}))}async setWebhook(){if(!this.config.webhookUrl)return;let e=await fetch(`https://api.telegram.org/bot${this.config.token}/setWebhook`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({url:this.config.webhookUrl})});if(!e.ok){console.error("[TelegramChannel] Failed to set webhook");return}let t=await e.json();t.ok?console.log("[TelegramChannel] Webhook set successfully"):console.error("[TelegramChannel] Failed to set webhook:",t.description)}handleWebhookRequest(e,t){if(e.method!=="POST"){t.writeHead(405),t.end("Method not allowed");return}let n="";e.on("data",r=>{n+=r.toString()}),e.on("end",()=>{try{let r=JSON.parse(n);this.handleMessage(this.normalize(r)).catch(s=>{console.error("[TelegramChannel] Error processing webhook:",s)}),t.writeHead(200),t.end("OK")}catch(r){console.error("[TelegramChannel] Error parsing webhook:",r),t.writeHead(400),t.end("Bad request")}})}async stop(){if(this.pollingInterval&&(clearInterval(this.pollingInterval),this.pollingInterval=void 0),this.server)return new Promise(e=>{this.server.close(e)});if(this.config.webhookUrl)try{await fetch(`https://api.telegram.org/bot${this.config.token}/deleteWebhook`,{method:"POST"})}catch(e){console.error("[TelegramChannel] Failed to delete webhook:",e)}}};d();var Bn=new Set([1,3]),Yt=/<@!?(\d+)>/g,Ln="https://discord.com/api/v10",Be=class extends C{isTriggerChannel=!1;config;allowedChannelIds;botUserId;participantCache=new Map;client;constructor(e){super(),this.config=e,this.name=e.name,e.channelId==null?this.allowedChannelIds=new Set:Array.isArray(e.channelId)?this.allowedChannelIds=new Set(e.channelId):this.allowedChannelIds=new Set([e.channelId])}shouldProcessEvent(e){return!e.author||e.webhookId||this.botUserId&&e.author.id===this.botUserId||this.config.guildId&&e.guildId!==this.config.guildId||this.allowedChannelIds.size>0&&(!e.channelId||!this.allowedChannelIds.has(e.channelId))?!1:e.author.bot||e.author.system?this.config.blockedBotIds?.includes(e.author.id)?!1:this.config.allowedBotIds?this.config.allowedBotIds.includes(e.author.id):!1:!0}normalize(e){let t=e,n=t.channelId,r=(n??"")+(t.thread?.id?`:${t.thread.id}`:""),s=t.channel?.type,i=s!==void 0&&Bn.has(s),c=t.author?.id,p=t.author?.globalName??t.author?.username,a=[];if(t.content){Yt.lastIndex=0;let l;for(;(l=Yt.exec(t.content))!==null;)a.push(l[1])}return{message:t.content,conversationId:r,data:t,participant:c?{kind:"user",id:c,displayName:p??void 0}:void 0,context:{userId:c,username:t.author?.username,channelType:i?"dm":"channel",channelId:n,channelName:t.channel?.name,guildId:t.guildId,threadId:t.thread?.id,messageId:t.id,mentions:a.length>0?a:void 0,isMentioned:this.botUserId?a.includes(this.botUserId):void 0}}}async resolveParticipant(e){let t=e.participant?.id??e.context?.userId;if(!t)return;let n=this.participantCache.get(t);if(n)return n;try{let r=await fetch(`${Ln}/users/${t}`,{headers:{Authorization:`Bot ${this.config.token}`}});if(!r.ok)return console.warn(`[DiscordChannel] Failed to resolve user ${t}: HTTP ${r.status}`),{kind:"user",id:t};let s=await r.json(),i=s.global_name??s.username,c={kind:"user",id:s.id,displayName:i};return this.participantCache.set(t,c),c}catch(r){return console.warn(`[DiscordChannel] resolveParticipant error for ${t}:`,r),{kind:"user",id:t}}}invalidateParticipant(e){this.participantCache.delete(e)}async send(e){if(!this.client)throw new Error("[DiscordChannel] Client not initialized. Did you call listen()?");let t=e.metadata?.threadId;if(t){let s=await this.client.channels.fetch(t);if(s&&"send"in s)try{await s.send({content:e.output});return}catch(i){throw console.error("[DiscordChannel] Failed to send to thread:",i),new Error(`[DiscordChannel] Failed to send Discord message: ${i instanceof Error?i.message:String(i)}`)}console.warn(`[DiscordChannel] Thread ${t} not found or not sendable; falling back to channel send.`)}let n=e.metadata?.channelId??(this.allowedChannelIds.size>0?[...this.allowedChannelIds][0]:void 0);if(!n)throw new Error("[DiscordChannel] No channel ID available for sending. Configure channelId or pass output.metadata.channelId.");let r=await this.client.channels.fetch(n);if(!r||!("send"in r))throw new Error(`[DiscordChannel] Channel ${n} not found or is not a text channel`);try{await r.send({content:e.output})}catch(s){throw console.error("[DiscordChannel] Failed to send to channel:",s),new Error(`[DiscordChannel] Failed to send Discord message: ${s instanceof Error?s.message:String(s)}`)}}listen(){typeof process>"u"||import("discord.js").then(e=>{let{Client:t,GatewayIntentBits:n}=e;this.client=new t({intents:[n.Guilds,n.GuildMessages,n.MessageContent,n.DirectMessages]}),this.client.on("ready",()=>{let r=this.client.user;this.botUserId=r?.id;let s=this.allowedChannelIds.size===0?"all channels":[...this.allowedChannelIds].join(", "),i=this.config.guildId??"all guilds";console.log(`[DiscordChannel] Logged in as ${r?.tag??"unknown"} (botUserId=${this.botUserId??"unknown"}) | guild=${i} | channels=${s}`)}),this.client.on("messageCreate",r=>{let s=r;if(!this.shouldProcessEvent(s))return;let i=this.normalize(s);this.handleMessage(i)}),this.client.on("userUpdate",(r,s)=>{let i=s;i?.id&&this.invalidateParticipant(i.id)}),this.client.login(this.config.token).catch(r=>{console.error("[DiscordChannel] Failed to login to Discord:",r)})}).catch(e=>{console.error("[DiscordChannel] Failed to initialize Discord client:",e),console.error("[DiscordChannel] Make sure discord.js is installed: npm install discord.js")})}async stop(){this.client&&(await this.client.destroy(),this.client=void 0)}};d();var Le=class extends C{isTriggerChannel=!0;config;transporter;constructor(e){super(),this.config=e,this.name=e.name}listen(){typeof process<"u"&&import("nodemailer").then(e=>{this.transporter=e.default.createTransport({host:this.config.smtp.host,port:this.config.smtp.port,secure:this.config.smtp.secure??this.config.smtp.port===465,auth:{user:this.config.smtp.auth.user,pass:this.config.smtp.auth.pass}}),console.log(`[EmailChannel] Email transporter initialized for ${this.config.from}`)}).catch(e=>{console.error("[EmailChannel] Failed to initialize nodemailer:",e),console.error("[EmailChannel] Make sure to install nodemailer: npm install nodemailer")})}async send(e){if(!this.transporter)throw new Error("Email transporter not initialized. Did you call listen()?");let t=Array.isArray(this.config.to)?this.config.to:[this.config.to],n=this.config.subject||"Message from Agent",r={from:this.config.from,to:t.join(", "),subject:n,text:e.output,html:this.formatAsHtml(e.output)};try{await this.transporter.sendMail(r)}catch(s){throw console.error("[EmailChannel] Failed to send email:",s),new Error(`Failed to send email: ${s instanceof Error?s.message:String(s)}`)}}normalize(e){throw new Error("EmailChannel is outbound-only. Use WebhookChannel with email webhook events for inbound email.")}formatAsHtml(e){return e.split(`
|
|
33
33
|
|
|
34
34
|
`).map(t=>`<p>${t.replace(/\n/g,"<br>")}</p>`).join("")}async stop(){this.transporter&&(this.transporter.close(),this.transporter=void 0)}};d();var Fe=class extends C{config;twilioClient;server;constructor(e){super(),this.config={port:3e3,...e},this.name=e.name}get isTriggerChannel(){return!this.config.webhookPath}listen(){typeof process<"u"&&import("twilio").then(e=>{this.twilioClient=e.default(this.config.accountSid,this.config.authToken),console.log("[SMSChannel] Twilio client initialized"),this.config.webhookPath&&this.startWebhookServer()}).catch(e=>{console.error("[SMSChannel] Failed to initialize Twilio client:",e),console.error("[SMSChannel] Make sure to install twilio: npm install twilio")})}async send(e){if(!this.twilioClient)throw new Error("Twilio client not initialized. Did you call listen()?");let t=e.metadata?.from||this.config.to;if(!t)throw new Error('No recipient phone number specified. Set "to" in config or provide in output.metadata.from');try{await this.twilioClient.messages.create({body:e.output,from:this.config.from,to:t})}catch(n){throw console.error("[SMSChannel] Failed to send SMS:",n),new Error(`Failed to send SMS: ${n instanceof Error?n.message:String(n)}`)}}normalize(e){let t=e,n=t.From,r=t.Body,s=t.MessageSid;return{message:r,conversationId:n,data:t,context:{from:n,to:t.To,messageSid:s}}}startWebhookServer(){import("http").then(e=>{this.server=e.createServer((t,n)=>{this.handleWebhookRequest(t,n)}),this.server.listen(this.config.port,()=>{console.log(`[SMSChannel] Webhook server listening on port ${this.config.port} at ${this.config.webhookPath}`)})}).catch(e=>{console.error("[SMSChannel] Failed to start webhook server:",e)})}handleWebhookRequest(e,t){if(e.method!=="POST"||e.url!==this.config.webhookPath){t.writeHead(404),t.end("Not found");return}let n="";e.on("data",r=>{n+=r.toString()}),e.on("end",()=>{try{let r=new URLSearchParams(n),s={};r.forEach((c,p)=>{s[p]=c});let i=this.normalize(s);this.handleMessage(i),t.writeHead(200,{"Content-Type":"text/xml"}),t.end('<?xml version="1.0" encoding="UTF-8"?><Response></Response>')}catch(r){console.error("[SMSChannel] Error handling webhook:",r),t.writeHead(400),t.end("Bad request")}})}async stop(){if(this.server)return new Promise(e=>{this.server.close(e)})}};d();var Ue=class extends C{isTriggerChannel=!1;_timeout;_pendingResolve;constructor(e={}){super(),this._timeout=e.timeout??12e4}listen(){}async send(e){this._pendingResolve?.(e),this._pendingResolve=void 0}normalize(e){let t=e;return{message:typeof t.message=="string"?t.message:JSON.stringify(t),data:t,conversationId:`mcp-${Date.now()}-${Math.random().toString(36).slice(2,7)}`}}async trigger(e){let t=this.normalize(e);return new Promise((n,r)=>{let s=setTimeout(()=>{this._pendingResolve=void 0,r(new Error(`McpChannel: agent did not respond within ${this._timeout}ms`))},this._timeout);this._pendingResolve=i=>{clearTimeout(s),n(i.output)},this.handleMessage(t).catch(i=>{clearTimeout(s),this._pendingResolve=void 0,r(i instanceof Error?i:new Error(String(i)))})})}asAgentDefinition(e,t){return{name:e.name,description:e.description,...t!==void 0&&{inputSchema:t},invoke:n=>this.trigger(n)}}};d();d();oe();var ce=class{agentUrls;constructor(e){this.agentUrls=new Map(Object.entries(e.agents))}async invoke(e,t){let n=this.agentUrls.get(e);if(!n)throw new I(`Agent "${e}" not found in transport configuration. Available agents: ${Array.from(this.agentUrls.keys()).join(", ")}`);let r={jsonrpc:"2.0",method:`agent.invoke:${e}`,params:t,id:Date.now()};try{let s=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)});if(!s.ok)throw new I(`HTTP ${s.status}: ${s.statusText}`);let i=await s.json();if(i.error)throw new I(`JSON-RPC error (${i.error.code}): ${i.error.message}`+(i.error.data?` - ${JSON.stringify(i.error.data)}`:""));if(!i.result)throw new I("No result in JSON-RPC response");return i.result}catch(s){throw s instanceof I?s:new I(`Failed to invoke agent "${e}" at ${n}: ${s instanceof Error?s.message:String(s)}`)}}};d();var Xt=N(require("http"),1),de=class{agents=new Map;server;port;constructor(e){this.port=e.port}registerAgent(e,t){this.agents.set(e,t)}listen(){this.server=Xt.default.createServer(async(e,t)=>{if(e.method!=="POST"){t.writeHead(405,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Method not allowed"}));return}let n="";e.on("data",r=>{n+=r.toString()}),e.on("end",async()=>{try{let r=JSON.parse(n),s=await this.handleRequest(r);t.writeHead(200,{"Content-Type":"application/json"}),t.end(JSON.stringify(s))}catch(r){let s={jsonrpc:"2.0",error:{code:-32700,message:"Parse error",data:r instanceof Error?r.message:String(r)},id:null};t.writeHead(200,{"Content-Type":"application/json"}),t.end(JSON.stringify(s))}})}),this.server.listen(this.port,()=>{console.log(`[AgentJsonRpcServer] Listening on port ${this.port}`),console.log(`[AgentJsonRpcServer] Registered agents: ${Array.from(this.agents.keys()).join(", ")}`)})}async stop(){return new Promise((e,t)=>{if(!this.server){e();return}this.server.close(n=>{n?t(n):(console.log("[AgentJsonRpcServer] Server stopped"),e())})})}async handleRequest(e){if(e.jsonrpc!=="2.0")return{jsonrpc:"2.0",error:{code:-32600,message:"Invalid Request",data:'jsonrpc must be "2.0"'},id:e.id||null};let[t,n]=e.method.split(":");if(t!=="agent.invoke")return{jsonrpc:"2.0",error:{code:-32601,message:"Method not found",data:`Unknown method: ${e.method}`},id:e.id||null};if(!n)return{jsonrpc:"2.0",error:{code:-32602,message:"Invalid params",data:'Agent name required in method (e.g., "agent.invoke:data-agent")'},id:e.id||null};let r=this.agents.get(n);if(!r)return{jsonrpc:"2.0",error:{code:-32602,message:"Invalid params",data:`Agent "${n}" not found. Available: ${Array.from(this.agents.keys()).join(", ")}`},id:e.id||null};if(!e.params)return{jsonrpc:"2.0",error:{code:-32602,message:"Invalid params",data:"params (AgentInput) required"},id:e.id||null};try{return{jsonrpc:"2.0",result:await r.invokeAgent(e.params),id:e.id||null}}catch(s){return{jsonrpc:"2.0",error:{code:-32603,message:"Internal error",data:s instanceof Error?s.message:String(s)},id:e.id||null}}}};d();d();B();var Qt=require("toolpack-sdk"),Fn={...Qt.CHAT_MODE,name:"intent-classifier-mode",systemPrompt:["You classify whether a message is asking an agent to respond.","","Categories:","direct = Message uses @mention, name in greeting, possessive, or commands the agent to act","indirect = Agent is mentioned but unclear if response wanted (talking ABOUT, not TO them)","passive = No addressing detected; agent should only listen, not reply","ignore = Definitely not for this agent (noise, code blocks, other bots)","","Response must start with one of: direct, indirect, passive, ignore"].join(`
|
|
35
35
|
`)},le=class extends R{name="intent-classifier";description="Classifies whether a message is directly addressing an agent for response";mode=Fn;constructor(e){super(e)}async invokeAgent(e){let t=e.data;if(t?.isDirectMessage)return{output:"direct",metadata:{classification:"direct",shortCircuit:"dm"}};if(!t?.message)return{output:"ignore",metadata:{error:"No message provided for classification"}};let n=[];if(n.push(`Context: Public channel #${t.channelName}`),n.push(`Target agent: "${t.agentName}" (ID: ${t.agentId})`),n.push(`Message sender: ${t.senderName}`),t.recentContext&&t.recentContext.length>0){n.push(`
|
package/dist/index.d.cts
CHANGED
|
@@ -4,8 +4,8 @@ import { B as BaseAgent, A as AgentMindConfig } from './base-agent-Dqca3WLY.cjs'
|
|
|
4
4
|
export { a as AgentEvents, C as ConfidenceLevel, G as GoalPriority, b as GoalStatus, M as MindBelief, c as MindEntry, d as MindEntryType, e as MindGoal, f as MindRecallResult, g as MindReflection, h as MindTtlDefaults } from './base-agent-Dqca3WLY.cjs';
|
|
5
5
|
import { ModeConfig, ConversationStore, AssemblerOptions, AssembledPrompt, RequestToolDefinition, ToolProject } from 'toolpack-sdk';
|
|
6
6
|
export { AssembledPrompt, AssemblerOptions, ConversationScope, ConversationStore, GetOptions, InMemoryConversationStore, InMemoryConversationStoreConfig, Participant, PromptMessage, ConversationSearchOptions as SearchOptions, StoredMessage } from 'toolpack-sdk';
|
|
7
|
-
import { S as SchedulerStore } from './index-
|
|
8
|
-
export { B as BaseChannel, C as CreateJobOptions, a as CreateJobResult, D as DiscordChannel, b as DiscordChannelConfig, E as EmailChannel, c as EmailChannelConfig, J as JobStatus, M as McpChannel, d as McpChannelConfig, e as SMSChannel, f as SMSChannelConfig, g as ScheduledChannel, h as ScheduledChannelConfig, i as ScheduledJob, j as SlackChannel, k as SlackChannelConfig, T as TelegramChannel, l as TelegramChannelConfig, W as WebhookChannel, m as WebhookChannelConfig } from './index-
|
|
7
|
+
import { S as SchedulerStore } from './index-CA38tE7C.cjs';
|
|
8
|
+
export { B as BaseChannel, C as CreateJobOptions, a as CreateJobResult, D as DiscordChannel, b as DiscordChannelConfig, E as EmailChannel, c as EmailChannelConfig, J as JobStatus, M as McpChannel, d as McpChannelConfig, e as SMSChannel, f as SMSChannelConfig, g as ScheduledChannel, h as ScheduledChannelConfig, i as ScheduledJob, j as SlackChannel, k as SlackChannelConfig, T as TelegramChannel, l as TelegramChannelConfig, W as WebhookChannel, m as WebhookChannelConfig } from './index-CA38tE7C.cjs';
|
|
9
9
|
export { I as IntentClassification, a as IntentClassifierAgent, b as IntentClassifierInput } from './intent-classifier-agent-CPKmOVJx.cjs';
|
|
10
10
|
import { SummarizerAgent } from './capabilities/index.cjs';
|
|
11
11
|
export { HistoryTurn, SummarizerInput, SummarizerOutput } from './capabilities/index.cjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -4,8 +4,8 @@ import { B as BaseAgent, A as AgentMindConfig } from './base-agent-C4fYjHPu.js';
|
|
|
4
4
|
export { a as AgentEvents, C as ConfidenceLevel, G as GoalPriority, b as GoalStatus, M as MindBelief, c as MindEntry, d as MindEntryType, e as MindGoal, f as MindRecallResult, g as MindReflection, h as MindTtlDefaults } from './base-agent-C4fYjHPu.js';
|
|
5
5
|
import { ModeConfig, ConversationStore, AssemblerOptions, AssembledPrompt, RequestToolDefinition, ToolProject } from 'toolpack-sdk';
|
|
6
6
|
export { AssembledPrompt, AssemblerOptions, ConversationScope, ConversationStore, GetOptions, InMemoryConversationStore, InMemoryConversationStoreConfig, Participant, PromptMessage, ConversationSearchOptions as SearchOptions, StoredMessage } from 'toolpack-sdk';
|
|
7
|
-
import { S as SchedulerStore } from './index-
|
|
8
|
-
export { B as BaseChannel, C as CreateJobOptions, a as CreateJobResult, D as DiscordChannel, b as DiscordChannelConfig, E as EmailChannel, c as EmailChannelConfig, J as JobStatus, M as McpChannel, d as McpChannelConfig, e as SMSChannel, f as SMSChannelConfig, g as ScheduledChannel, h as ScheduledChannelConfig, i as ScheduledJob, j as SlackChannel, k as SlackChannelConfig, T as TelegramChannel, l as TelegramChannelConfig, W as WebhookChannel, m as WebhookChannelConfig } from './index-
|
|
7
|
+
import { S as SchedulerStore } from './index-BCBukKC4.js';
|
|
8
|
+
export { B as BaseChannel, C as CreateJobOptions, a as CreateJobResult, D as DiscordChannel, b as DiscordChannelConfig, E as EmailChannel, c as EmailChannelConfig, J as JobStatus, M as McpChannel, d as McpChannelConfig, e as SMSChannel, f as SMSChannelConfig, g as ScheduledChannel, h as ScheduledChannelConfig, i as ScheduledJob, j as SlackChannel, k as SlackChannelConfig, T as TelegramChannel, l as TelegramChannelConfig, W as WebhookChannel, m as WebhookChannelConfig } from './index-BCBukKC4.js';
|
|
9
9
|
export { I as IntentClassification, a as IntentClassifierAgent, b as IntentClassifierInput } from './intent-classifier-agent-ACQSotfT.js';
|
|
10
10
|
import { SummarizerAgent } from './capabilities/index.js';
|
|
11
11
|
export { HistoryTurn, SummarizerInput, SummarizerOutput } from './capabilities/index.js';
|
package/dist/index.js
CHANGED
|
@@ -29,7 +29,7 @@ ${ht}`:"")+F},U=`${this.name}-replica`,G=this.description,N=this.model}else K={.
|
|
|
29
29
|
Question: "${e}"
|
|
30
30
|
Answer: "${t}"
|
|
31
31
|
|
|
32
|
-
Is this answer sufficient? Reply with ONLY "yes" or "no".`,{workflow:{mode:"single-shot"}})).output.toLowerCase().trim().startsWith("yes")}async handlePendingAsk(e,t,n,r){return await this.evaluateAnswer(e.question,t,{simpleValidation:i=>i.trim().length>3})?(await this.resolvePendingAsk(e.id,t),n(t)):e.retries>=e.maxRetries?(await this.resolvePendingAsk(e.id,"__insufficient__"),this._triggeringChannel&&await this.sendTo(this._triggeringChannel,"I was unable to get enough information to proceed. Skipping this step."),r?r():{output:"Step skipped due to insufficient input.",metadata:{skipped:!0,askId:e.id}}):(this._registry?.incrementRetries(e.id),this.ask(`I need a bit more clarity on: "${e.question}". Could you provide more details?`,{context:e.context,maxRetries:e.maxRetries}))}async delegateAndWait(e,t){if(!this._registry)throw new k("Agent not registered - cannot use delegateAndWait()");let n={message:t.message,intent:t.intent,data:t.data,context:{...t.context||{},delegatedBy:this.name},conversationId:t.conversationId||this._conversationId||`delegation-${Date.now()}`};return await this._registry.invoke(e,n)}async onBeforeRun(e){}async onComplete(e){}async onError(e){}_resolveAssemblerOptions(){let e=this.channels.map(r=>r.botUserId).filter(r=>typeof r=="string"&&r.length>0),t=this.assemblerOptions?.agentAliases??[];if(e.length===0&&t.length===0)return this.assemblerOptions;let n=Array.from(new Set([...t,...e]));return{...this.assemblerOptions,agentAliases:n}}_getEffectiveInterceptors(){return this.interceptors.some(t=>t[X]===!0)?this.interceptors:[Q({store:this.conversationHistory}),...this.interceptors]}_bindChannel(e){e.onMessage(async t=>{if(!t.conversationId){console.warn(`[${this.name}] Message received without conversationId \u2014 skipping`);return}let n=await this._acquireConversationLock(t.conversationId);try{this._triggeringChannel=e.name,this._isTriggerChannel=e.isTriggerChannel,this._conversationId=t.conversationId;let r=se(this._getEffectiveInterceptors(),this,e,this._registry??null),s=await oe(r,t);if(s===null)return;let i={output:s.output,metadata:s.metadata};await e.send({output:i.output,metadata:{...i.metadata,conversationId:t.conversationId,...t.context}})}catch(r){let s=r instanceof Error?r.message:"Unknown error occurred";console.error(`[${this.name}] Error in agent invocation: ${s}`);try{await e.send({output:`Error: ${s}`,metadata:{conversationId:t.conversationId,error:!0,...t.context}})}catch(i){console.error(`[${this.name}] Failed to send error to channel: ${i}`)}}finally{n()}})}async _acquireConversationLock(e){for(;this._conversationLocks.has(e);)try{await this._conversationLocks.get(e)}catch{}let t,n=new Promise(r=>{t=r});return this._conversationLocks.set(e,n),()=>{this._conversationLocks.delete(e),t()}}extractSteps(e){let t=e;if(t.plan&&typeof t.plan=="object"){let n=t.plan;if(Array.isArray(n.steps))return n.steps.map(r=>({number:r.number||0,description:r.description||"",status:r.status||"completed",result:r.result}))}if(Array.isArray(t.steps))return t.steps}}});d();d();j();pe();d();import{randomUUID as hn}from"crypto";d();Z();import{randomUUID as Tt}from"crypto";var W=class{constructor(e){this.registry=e}registry;async invoke(e,t){let n=this.registry.getAgent(e);if(!n)throw new k(`Agent "${e}" not found in registry. Available agents: ${this.registry.getAllAgents().map(p=>p.name).join(", ")}`);let r=n.conversationHistory,s=t.conversationId,i=t.context?.delegatedBy;if(r&&s&&i){let p={id:t.context?.messageId??Tt(),conversationId:s,participant:{kind:"agent",id:i,displayName:i},content:t.message??"",timestamp:new Date().toISOString(),scope:"channel",metadata:{}};try{await r.append(p)}catch{}}let c=await n.invokeAgent(t);if(r&&s){let p={id:Tt(),conversationId:s,participant:{kind:"agent",id:e,displayName:e},content:c.output,timestamp:new Date().toISOString(),scope:"channel",metadata:{}};try{await r.append(p)}catch{}}return c}};var Ue=class{agentList;instances=new Map;channels=new Map;_transport;pendingAsks=new Map;_started=!1;_restarting=!1;_restartScheduled=!1;_deadlineTimer;constructor(e,t){this.agentList=e,this._transport=t?.transport||new W(this)}async start(){for(let e of this.agentList){await e._ensureToolpack(),e._registry=this,this.instances.set(e.name,e);for(let t of e.channels??[])t.name&&this.channels.set(t.name,t)}for(let e of this.agentList)await e.start();this._started=!0}async addAgent(e){if(this.agentList.push(e),!!this._started){await e._ensureToolpack(),e._registry=this,this.instances.set(e.name,e);for(let t of e.channels??[])t.name&&this.channels.set(t.name,t);await e.start()}}async removeAgent(e){let t=this.instances.get(e);if(t){await t.stop(),this.instances.delete(e),this.agentList=this.agentList.filter(n=>n.name!==e);for(let n of t.channels??[])n.name&&this.channels.delete(n.name)}}isAllIdle(){return this.agentList.every(e=>e.isIdle())}scheduleRestart(e){if(this._restartScheduled)return;this._restartScheduled=!0;let t=(e?.maxWaitMinutes??30)*60*1e3,n=()=>{!this._restarting&&this.isAllIdle()&&this._executeRestart()};if(n(),!this._restarting){for(let r of this.agentList)r.on("agent:complete",n);this._deadlineTimer=setTimeout(()=>{this._executeRestart()},t)}}async _executeRestart(){if(this._restarting)return;this._restarting=!0,this._deadlineTimer&&(clearTimeout(this._deadlineTimer),this._deadlineTimer=void 0),await this.stop();let e=Date.now()+3e4;for(;!this.isAllIdle()&&Date.now()<e;)await new Promise(t=>setTimeout(t,100));this._exit(0)}_exit(e){process.exit(e)}async sendTo(e,t){let n=this.channels.get(e);if(!n)throw new Error(`No channel registered with name "${e}"`);await n.send(t)}getAgent(e){return this.instances.get(e)}getAllAgents(){return Array.from(this.instances.values())}getChannel(e){return this.channels.get(e)}async invoke(e,t){return this._transport.invoke(e,t)}async stop(){for(let e of this.agentList)await e.stop();this.instances.clear(),this.channels.clear(),this.pendingAsks.clear()}getPendingAsk(e){let t=this.pendingAsks.get(e);if(!t||t.length===0)return;let n=new Date;for(;t.length>0;){let r=t[0];if(r.expiresAt&&r.expiresAt<n)t.shift();else break}if(t.length===0){this.pendingAsks.delete(e);return}return t[0]}hasPendingAsks(e){let t=this.pendingAsks.get(e);if(!t||t.length===0)return!1;let n=new Date,r=t.filter(s=>!s.expiresAt||s.expiresAt>=n);return r.length===0?(this.pendingAsks.delete(e),!1):(r.length!==t.length&&this.pendingAsks.set(e,r),r.some(s=>s.status==="pending"))}cleanupExpiredAsks(){let e=0,t=new Date;for(let[n,r]of this.pendingAsks.entries()){let s=r.filter(i=>!i.expiresAt||i.expiresAt>=t);e+=r.length-s.length,s.length===0?this.pendingAsks.delete(n):s.length!==r.length&&this.pendingAsks.set(n,s)}return e}addPendingAsk(e){let t={...e,id:hn(),askedAt:new Date,retries:0,status:"pending"},n=this.pendingAsks.get(e.conversationId);return n?n.push(t):this.pendingAsks.set(e.conversationId,[t]),t}incrementRetries(e){for(let t of this.pendingAsks.values()){let n=t.find(r=>r.id===e);if(n)return n.retries+=1,n.retries}}async resolvePendingAsk(e,t){for(let[n,r]of this.pendingAsks.entries()){let s=r.findIndex(i=>i.id===e);if(s!==-1){r[s].status="answered",r[s].answer=t;let i=r[s].channelName;if(r.splice(s,1),r.length>0){let c=r[0];if(i&&i.trim()!=="")try{await this.sendTo(i,{output:c.question})}catch(p){console.error(`[AgentRegistry] Failed to auto-send next ask: ${p instanceof Error?p.message:"Unknown error"}`)}else console.warn(`[AgentRegistry] Cannot auto-send next ask: channelName is empty for conversation ${n}`)}r.length===0&&this.pendingAsks.delete(n);return}}throw new Error(`Pending ask with id "${e}" not found`)}};Z();d();import{watch as fn}from"fs";import{spawn as yn}from"child_process";import{basename as vn}from"path";var Ge=class{cwd;debounceMs;onRestartNeeded;onCompileError;spawnFn;watchFn;watchPaths;watchers=[];debounceTimer;constructor(e){this.watchPaths=e.watchPaths,this.cwd=e.cwd??process.cwd(),this.debounceMs=e.debounceMs??3e4,this.onRestartNeeded=e.onRestartNeeded,this.onCompileError=e.onCompileError,this.spawnFn=e.spawnFn??yn,this.watchFn=e.watchFn??fn}start(){for(let e of this.watchPaths){let t=this.watchFn(e,{recursive:!0},(n,r)=>{r&&this._handleFileChange(r)});this.watchers.push(t)}}stop(){for(let e of this.watchers)e.close();this.watchers=[],this.debounceTimer!==void 0&&(clearTimeout(this.debounceTimer),this.debounceTimer=void 0)}_handleFileChange(e){this.debounceTimer!==void 0&&clearTimeout(this.debounceTimer),this.debounceTimer=setTimeout(()=>{this.debounceTimer=void 0,vn(e).startsWith(".env")?this.onRestartNeeded():(e.endsWith(".ts")||e.endsWith(".tsx"))&&this._runCompile()},this.debounceMs)}_runCompile(){return new Promise(e=>{let t="",n=this.spawnFn("npx",["tsc","--build"],{cwd:this.cwd,stdio:["ignore","ignore","pipe"]});n.stderr?.on("data",r=>{t+=r.toString()}),n.on("close",r=>{if(r===0)this.onRestartNeeded();else{let s=t||`tsc --build exited with code ${String(r)}`;this.onCompileError?.(s)}e()}),n.on("error",r=>{let s=r instanceof Error?r.message:String(r);this.onCompileError?.(s),e()})})}};d();j();import{AGENT_MODE as wn}from"toolpack-sdk";var An={...wn,name:"research-agent-mode",systemPrompt:["You are a research agent specialized in web research and information gathering.","Use web.search to find relevant information, web.fetch to retrieve content, and web.scrape when needed.","Always cite your sources with URLs.","Provide comprehensive, well-structured summaries.","Flag any conflicting information or uncertainty in your findings."].join(" ")},Je=class extends T{name="research-agent";description="Web research agent for summarization, fact-finding, competitive analysis, and trend monitoring";mode=An;constructor(e){super(e)}async invokeAgent(e){let t=await this.run(e.message||"",void 0,{conversationId:e.conversationId});return await this.onComplete(t),t}};d();j();import{CODING_MODE as bn}from"toolpack-sdk";var In={...bn,name:"coding-agent-mode",systemPrompt:["You are a coding agent specialized in software development tasks.","Use coding.* tools for code analysis, fs.* for file operations, and git.* for version control.","Write clean, idiomatic code following best practices.","Always verify your changes and check for potential issues.","Provide clear explanations of your code changes."].join(" ")},ze=class extends T{name="coding-agent";description="Coding agent for code generation, refactoring, debugging, test writing, and code review";mode=In;constructor(e){super(e)}async invokeAgent(e){let t=await this.run(e.message||"",void 0,{conversationId:e.conversationId});return await this.onComplete(t),t}};d();j();import{AGENT_MODE as Cn}from"toolpack-sdk";var kn={...Cn,name:"data-agent-mode",systemPrompt:["You are a data agent specialized in database operations and data analysis.","Use db.* tools for database queries, fs.* for file operations, and http.* for API requests.","Generate clear, well-formatted reports and summaries.","Always validate data integrity and handle errors gracefully.","Provide insights and patterns when analyzing data."].join(" ")},qe=class extends T{name="data-agent";description="Data agent for database queries, CSV generation, data analysis, reporting, and aggregation";mode=kn;constructor(e){super(e)}async invokeAgent(e){let t=await this.run(e.message||"",void 0,{conversationId:e.conversationId});return await this.onComplete(t),t}};d();j();import{CHAT_MODE as Rn}from"toolpack-sdk";var xn={...Rn,name:"browser-agent-mode",systemPrompt:["You are a browser agent specialized in web interaction and content extraction.","Use web.fetch to retrieve pages, web.screenshot for visual content, and web.extract_links for navigation.","Follow links intelligently to gather comprehensive information.","Extract structured data from web pages when possible.","Be mindful of rate limits and respectful of website resources."].join(" ")},We=class extends T{name="browser-agent";description="Browser agent for web browsing, form interaction, page extraction, and link following";mode=xn;constructor(e){super(e)}async invokeAgent(e){let t=await this.run(e.message||"",void 0,{conversationId:e.conversationId});return await this.onComplete(t),t}};d();var R=class{name;_handler;onMessage(e){this._handler=e}async handleMessage(e){this._handler&&await this._handler(e)}};d();import{createHmac as Sn,timingSafeEqual as Tn}from"crypto";var He=class extends R{isTriggerChannel=!1;config;server;participantCache=new Map;botUserId;allowedChannels;constructor(e){super(),this.config={port:3e3,...e},this.name=e.name;let t=e.channel;this.allowedChannels=t==null?null:Array.isArray(t)?t:[t]}listen(){typeof process<"u"&&import("http").then(e=>{this.server=e.createServer((t,n)=>{this.handleRequest(t,n)}),this.server.listen(this.config.port,()=>{console.log(`[SlackChannel] Listening on port ${this.config.port}`),this.runStartupCheck().catch(()=>{})})}).catch(e=>{console.error("[SlackChannel] Failed to start HTTP server:",e)})}async runStartupCheck(){try{let t=await(await fetch("https://slack.com/api/auth.test",{method:"POST",headers:{Authorization:`Bearer ${this.config.token}`,"Content-Type":"application/json"}})).json();t.ok?(this.botUserId=t.user_id,console.log(`[SlackChannel] Connected as @${t.user} (${t.user_id}) in workspace "${t.team}" \u2014 ${t.url}`)):console.warn(`[SlackChannel] auth.test failed: ${t.error}. Check your bot token.`)}catch(e){console.warn("[SlackChannel] Startup self-check failed (network error):",e)}}verifySignature(e,t){let n=e["x-slack-request-timestamp"],r=e["x-slack-signature"];if(!n||!r||Array.isArray(n)||Array.isArray(r))return!1;let s=parseInt(n,10),i=Math.floor(Date.now()/1e3);if(isNaN(s)||Math.abs(i-s)>300)return!1;let c=`v0:${n}:${t}`,a=`v0=${Sn("sha256",this.config.signingSecret).update(c).digest("hex")}`;if(a.length!==r.length)return!1;try{return Tn(Buffer.from(a),Buffer.from(r))}catch{return!1}}async send(e){let t=e.metadata?.threadTs??e.metadata?.thread_ts??e.metadata?.threadId,r=e.metadata?.channelId??(this.allowedChannels&&this.allowedChannels.length>0?this.allowedChannels[0]:void 0);if(!r)throw new Error("[SlackChannel] Cannot send: no channel configured and metadata.channelId is missing. Provide a target via SlackChannelConfig.channel or output.metadata.channelId.");let s={channel:r,text:e.output};t&&(s.thread_ts=t);let i=await fetch("https://slack.com/api/chat.postMessage",{method:"POST",headers:{Authorization:`Bearer ${this.config.token}`,"Content-Type":"application/json"},body:JSON.stringify(s)});if(!i.ok)throw new Error(`Failed to send Slack message: ${i.statusText}`);let c=await i.json();if(!c.ok)throw new Error(`Slack API error: ${c.error}`)}normalize(e){let t=e,r=(t.text||"").replace(/<(https?:\/\/[^|>]+)\|([^>]+)>/g,"$2 ($1)").replace(/<(https?:\/\/[^>]+)>/g,"$1").replace(/<!here>/g,"@here").replace(/<!channel>/g,"@channel").replace(/<!everyone>/g,"@everyone"),s=t.ts,i=t.thread_ts,c=i!==void 0&&i!==s,p=t.user,a=p?{kind:"user",id:p}:void 0,l=/<@([A-Z0-9]+)>/g,m=[],u;for(;(u=l.exec(r))!==null;)m.push(u[1]);let g=t.channel;return{message:r,conversationId:c?i:g||s||"",data:t,participant:a,context:{user:p,channel:g,team:t.team,channelType:t.channel_type,threadId:c?i:void 0,mentions:m.length>0?m:void 0,channelId:g,channelName:typeof this.config.channel=="string"?this.config.channel:g}}}async resolveParticipant(e){let t=e.participant?.id??e.context?.user;if(!t)return;let n=this.participantCache.get(t);if(n)return n;try{let r=await fetch(`https://slack.com/api/users.info?user=${encodeURIComponent(t)}`,{method:"GET",headers:{Authorization:`Bearer ${this.config.token}`}});if(!r.ok)return{kind:"user",id:t};let s=await r.json();if(!s.ok||!s.user){let p={kind:"user",id:t};return this.participantCache.set(t,p),p}let i=s.user.profile?.display_name||s.user.profile?.real_name||s.user.real_name||s.user.name||t,c={kind:"user",id:t,displayName:i,metadata:{slackUser:s.user}};return this.participantCache.set(t,c),c}catch{return{kind:"user",id:t}}}invalidateParticipant(e){this.participantCache.delete(e)}shouldProcessEvent(e){let t=e.type;if(t!=="message"&&t!=="app_mention")return!1;if(this.allowedChannels!==null){let i=e.channel_type;if(!(i==="im"||i==="mpim")){let p=e.channel;if(!p||!this.allowedChannels.includes(p))return!1}}let n=e.user;if(this.botUserId&&n===this.botUserId)return!1;let r=e.bot_id;if(!r)return!0;let s=this.config.blockedBotIds??[];if(s.includes(r)||n!==void 0&&s.includes(n))return!1;if(this.config.allowedBotIds!==void 0){let i=this.config.allowedBotIds;return i.includes(r)||n!==void 0&&i.includes(n)}return!0}handleRequest(e,t){if(e.method!=="POST"){t.writeHead(405),t.end("Method not allowed");return}let n="";e.on("data",r=>{n+=r.toString()}),e.on("end",()=>{if(!this.verifySignature(e.headers,n)){t.writeHead(401),t.end("Invalid signature");return}try{let r=JSON.parse(n);if(r.type==="url_verification"){t.writeHead(200,{"Content-Type":"application/json"}),t.end(JSON.stringify({challenge:r.challenge}));return}if(r.type==="event_callback"&&r.event){let s=r.event;if(this.shouldProcessEvent(s)){let i=this.normalize(s);this.handleMessage(i)}else s.type==="user_change"&&s.user&&this.invalidateParticipant(s.user.id);t.writeHead(200),t.end("OK");return}t.writeHead(200),t.end("OK")}catch(r){console.error("[SlackChannel] Error handling request:",r),t.writeHead(400),t.end("Bad request")}})}async stop(){if(this.server)return new Promise(e=>{this.server.close(e)})}};d();var Ke=class extends R{isTriggerChannel=!1;config;server;pendingResponses=new Map;constructor(e){super(),this.name=e.name,this.config={port:e.port??3e3,path:e.path??"/webhook"}}listen(){typeof process<"u"&&import("http").then(e=>{this.server=e.createServer((t,n)=>{this.handleRequest(t,n)}),this.server.listen(this.config.port,()=>{console.log(`[WebhookChannel] Listening on port ${this.config.port}${this.config.path}`)})}).catch(e=>{console.error("[WebhookChannel] Failed to start HTTP server:",e)})}async send(e){let t=e.metadata?.conversationId;if(t&&this.pendingResponses.has(t)){let n=this.pendingResponses.get(t);this.pendingResponses.delete(t),n.resolve({output:e.output,metadata:e.metadata})}}normalize(e){let t=e,n=t.headers||{},r=n["x-session-id"]||n["X-Session-Id"]||t.sessionId||t.conversationId||this.generateSessionId();return{message:t.message||t.text||"",intent:t.intent,conversationId:r,data:t,context:{headers:t.headers,method:t.method,sessionId:r}}}handleRequest(e,t){if(e.url!==this.config.path){t.writeHead(404),t.end("Not found");return}if(e.method!=="POST"){t.writeHead(405),t.end("Method not allowed");return}let n="";e.on("data",r=>{n+=r.toString()}),e.on("end",()=>{try{let r=JSON.parse(n),s=this.normalize(r),i=s.conversationId||this.generateSessionId(),c=new Promise((p,a)=>{this.pendingResponses.set(i,{resolve:p,reject:a}),setTimeout(()=>{this.pendingResponses.has(i)&&(this.pendingResponses.delete(i),a(new Error("Agent response timeout")))},3e4)});this.handleMessage({...s,conversationId:i,context:{...s.context,sessionId:i}}),c.then(p=>{t.writeHead(200,{"Content-Type":"application/json"}),t.end(JSON.stringify(p))}).catch(p=>{t.writeHead(500,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:p.message}))})}catch(r){console.error("[WebhookChannel] Error handling request:",r),t.writeHead(400,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Bad request"}))}})}generateSessionId(){return`webhook-${Date.now()}-${Math.random().toString(36).substring(2,9)}`}async stop(){if(this.server)return new Promise(e=>{this.server.close(e)})}};d();import{CronExpressionParser as _t}from"cron-parser";var Ve=class extends R{isTriggerChannel=!0;config;timer;_stopped=!1;_generation=0;constructor(e){if(super(),!e.cron&&!e.store)throw new Error("ScheduledChannel: provide at least one of `cron` (static schedule) or `store` (dynamic scheduling).");if(e.cron)try{_t.parse(e.cron)}catch(t){throw new Error(`ScheduledChannel: invalid cron expression '${e.cron}': ${t.message}`)}if(e.store&&!e.name&&console.warn("[ScheduledChannel] A `store` was provided without a `name`. All store queries will be unscoped and will pick up jobs from every channel. Set `name` to scope this channel to its own jobs."),e.idlePollMs!==void 0&&e.idlePollMs<1e3)throw new Error(`ScheduledChannel: idlePollMs must be at least 1000ms (got ${e.idlePollMs}). Values below 1 second create a tight polling loop.`);this.config=e,this.name=e.name}listen(){this._generation++,this.timer&&(clearTimeout(this.timer),this.timer=void 0),this._stopped=!1,this.config.store?this._listenWithStore():this._listenStatic()}async stop(){this._stopped=!0,this.timer&&(clearTimeout(this.timer),this.timer=void 0)}async send(e){}normalize(e){let t=e,n=new Date,r=`${n.getFullYear()}-${n.getMonth()+1}-${n.getDate()}`;return{intent:t?.intent??this.config.intent,message:t?.message??this.config.message??`Scheduled task triggered at ${n.toISOString()}`,conversationId:`scheduled:${this.name??"default"}:${r}`,data:{...t?.payload??{},scheduled:!0,jobId:t?.id,cron:t?.cron??this.config.cron,timestamp:n.toISOString()}}}_listenStatic(){this._scheduleNextStatic(this._generation)}_scheduleNextStatic(e){if(this._stopped||e!==this._generation)return;let t=this._nextRunFromCron(this.config.cron),n=t.getTime()-Date.now();if(n<=0){this.timer=setTimeout(()=>this._scheduleNextStatic(e),0);return}console.log(`[ScheduledChannel:${this.name??"default"}] Next run: ${t.toISOString()}`),this.timer=setTimeout(async()=>{this._stopped||e!==this._generation||(await this._triggerStatic(),this._scheduleNextStatic(e))},n)}async _triggerStatic(){if(!this._handler){console.warn(`[ScheduledChannel:${this.name??"default"}] Cron fired but no message handler is registered. Call onMessage() before listen() to avoid silently losing triggers.`);return}let e=this.normalize(null);try{await this.handleMessage(e)}catch(t){console.error(`[ScheduledChannel:${this.name??"default"}] Error on trigger:`,t)}}_listenWithStore(){let e=this.config.store,t=this._generation;if(t===1){let r=e.resetStuck(this.name);r>0&&console.log(`[ScheduledChannel:${this.name??"default"}] Reset ${r} stuck 'running' job(s) to 'pending'.`)}if(this.config.cron){let{duplicate:r}=e.create({channelName:this.name,cron:this.config.cron,intent:this.config.intent,message:this.config.message});r||console.log(`[ScheduledChannel:${this.name??"default"}] Seeded static cron '${this.config.cron}' into store.`)}let n=e.getDue(Date.now(),this.name);n.length>0&&(console.log(`[ScheduledChannel:${this.name??"default"}] Recovering ${n.length} overdue job(s).`),Promise.allSettled(n.map(r=>this._triggerJob(r)))),this._scheduleNextFromStore(t)}_scheduleNextFromStore(e){if(this._stopped||e!==this._generation)return;let t=this.config.store,n=t.getNextPending(this.name);if(!n){let s=this.config.idlePollMs??3e4;this.timer=setTimeout(()=>this._scheduleNextFromStore(e),s);return}let r=Math.max(0,n.nextRunAt-Date.now());console.log(`[ScheduledChannel:${this.name??"default"}] Next store job at ${new Date(n.nextRunAt).toISOString()} (in ${Math.round(r/1e3)}s)`),this.timer=setTimeout(async()=>{if(this._stopped||e!==this._generation)return;let s=t.getDue(Date.now(),this.name);await Promise.allSettled(s.map(i=>this._triggerJob(i))),this._scheduleNextFromStore(e)},r)}async _triggerJob(e){let t=this.config.store;if(!this._handler){console.warn(`[ScheduledChannel:${this.name??"default"}] Job ${e.id} fired but no message handler is registered. Call onMessage() before listen() to avoid silently losing jobs.`),t.markFailed(e.id,"No message handler registered");return}t.markRunning(e.id);let n=this.normalize(e);try{await this.handleMessage(n),t.markCompleted(e.id)}catch(r){let s=r instanceof Error?r.message:String(r);console.error(`[ScheduledChannel:${this.name??"default"}] Job ${e.id} failed:`,r),t.markFailed(e.id,s)}}_nextRunFromCron(e){return _t.parse(e,{currentDate:new Date}).next().toDate()}};d();var Ye=class extends R{isTriggerChannel=!1;config;offset=0;pollingInterval;server;botUserId;botUsername;constructor(e){super(),this.name=e.name,this.config=e}listen(){this.runStartupCheck().catch(()=>{}),this.config.webhookUrl?this.startWebhook():this.startPolling()}async runStartupCheck(){try{let t=await(await fetch(`https://api.telegram.org/bot${this.config.token}/getMe`)).json();if(t.ok&&t.result){let n=t.result;this.botUserId=n.id!=null?String(n.id):void 0,this.botUsername=n.username,console.log(`[TelegramChannel] Connected as @${n.username} (id: ${n.id}, name: ${n.first_name})`)}else console.warn(`[TelegramChannel] getMe failed: ${t.description??"unknown error"}. Check your bot token.`)}catch(e){console.warn("[TelegramChannel] Startup self-check failed (network error):",e)}}async send(e){let t=e.metadata?.chatId;if(!t)throw new Error("Telegram send requires chatId in metadata");let n=await fetch(`https://api.telegram.org/bot${this.config.token}/sendMessage`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({chat_id:t,text:e.output,parse_mode:"Markdown"})});if(!n.ok)throw new Error(`Failed to send Telegram message: ${n.statusText}`);let r=await n.json();if(!r.ok)throw new Error(`Telegram API error: ${r.description}`)}normalize(e){let t=e,n=t.message||t.edited_message||{},r=n.text||"",s=n.chat||{},i=n.from||{},c=i.id!=null?String(i.id):void 0,p=i.first_name||i.username||c,a=c?{kind:"user",id:c,displayName:p??c}:void 0,l=n.entities??[],m=[];for(let w of l)if(w.type==="text_mention"&&w.user){let f=w.user;f.id!=null&&m.push(String(f.id))}let u=s.type,g=s.id!=null?String(s.id):"";return{message:r,conversationId:g,data:t,participant:a,context:{chatId:s.id,userId:i.id,username:i.username,firstName:i.first_name,lastName:i.last_name,messageId:n.message_id,channelType:u,channelId:g,channelName:s.title,mentions:m.length>0?m:void 0}}}startPolling(){console.log("[TelegramChannel] Starting polling mode"),this.pollingInterval=setInterval(async()=>{try{await this.pollUpdates()}catch(e){console.error("[TelegramChannel] Polling error:",e)}},5e3)}async pollUpdates(){let e=`https://api.telegram.org/bot${this.config.token}/getUpdates?offset=${this.offset}&limit=100`,t=await fetch(e);if(!t.ok)throw new Error(`Telegram getUpdates failed: ${t.statusText}`);let n=await t.json();if(!n.ok)throw new Error("Telegram getUpdates returned not ok");for(let r of n.result){let s=r.update_id;s>=this.offset&&(this.offset=s+1);try{let i=this.normalize(r);await this.handleMessage(i)}catch(i){console.error("[TelegramChannel] Error processing update:",i)}}}startWebhook(){typeof process>"u"||(console.log("[TelegramChannel] Starting webhook mode"),import("http").then(e=>{this.server=e.createServer((r,s)=>{this.handleWebhookRequest(r,s)});let t=new URL(this.config.webhookUrl||"http://localhost:3000"),n=parseInt(t.port,10)||3e3;this.server.listen(n,()=>{console.log(`[TelegramChannel] Webhook server listening on port ${n}`)}),this.setWebhook()}).catch(e=>{console.error("[TelegramChannel] Failed to start webhook server:",e)}))}async setWebhook(){if(!this.config.webhookUrl)return;let e=await fetch(`https://api.telegram.org/bot${this.config.token}/setWebhook`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({url:this.config.webhookUrl})});if(!e.ok){console.error("[TelegramChannel] Failed to set webhook");return}let t=await e.json();t.ok?console.log("[TelegramChannel] Webhook set successfully"):console.error("[TelegramChannel] Failed to set webhook:",t.description)}handleWebhookRequest(e,t){if(e.method!=="POST"){t.writeHead(405),t.end("Method not allowed");return}let n="";e.on("data",r=>{n+=r.toString()}),e.on("end",()=>{try{let r=JSON.parse(n);this.handleMessage(this.normalize(r)).catch(s=>{console.error("[TelegramChannel] Error processing webhook:",s)}),t.writeHead(200),t.end("OK")}catch(r){console.error("[TelegramChannel] Error parsing webhook:",r),t.writeHead(400),t.end("Bad request")}})}async stop(){if(this.pollingInterval&&(clearInterval(this.pollingInterval),this.pollingInterval=void 0),this.server)return new Promise(e=>{this.server.close(e)});if(this.config.webhookUrl)try{await fetch(`https://api.telegram.org/bot${this.config.token}/deleteWebhook`,{method:"POST"})}catch(e){console.error("[TelegramChannel] Failed to delete webhook:",e)}}};d();var _n=new Set([1,3]),Et=/<@!?(\d+)>/g,En="https://discord.com/api/v10",Xe=class extends R{isTriggerChannel=!1;config;allowedChannelIds;botUserId;participantCache=new Map;client;constructor(e){super(),this.config=e,this.name=e.name,e.channelId==null?this.allowedChannelIds=new Set:Array.isArray(e.channelId)?this.allowedChannelIds=new Set(e.channelId):this.allowedChannelIds=new Set([e.channelId])}shouldProcessEvent(e){return!e.author||e.webhookId||this.botUserId&&e.author.id===this.botUserId||this.config.guildId&&e.guildId!==this.config.guildId||this.allowedChannelIds.size>0&&(!e.channelId||!this.allowedChannelIds.has(e.channelId))?!1:e.author.bot||e.author.system?this.config.blockedBotIds?.includes(e.author.id)?!1:this.config.allowedBotIds?this.config.allowedBotIds.includes(e.author.id):!1:!0}normalize(e){let t=e,n=t.channelId,r=(n??"")+(t.thread?.id?`:${t.thread.id}`:""),s=t.channel?.type,i=s!==void 0&&_n.has(s),c=t.author?.id,p=t.author?.globalName??t.author?.username,a=[];if(t.content){Et.lastIndex=0;let l;for(;(l=Et.exec(t.content))!==null;)a.push(l[1])}return{message:t.content,conversationId:r,data:t,participant:c?{kind:"user",id:c,displayName:p??void 0}:void 0,context:{userId:c,username:t.author?.username,channelType:i?"dm":"channel",channelId:n,channelName:t.channel?.name,guildId:t.guildId,threadId:t.thread?.id,messageId:t.id,mentions:a.length>0?a:void 0,isMentioned:this.botUserId?a.includes(this.botUserId):void 0}}}async resolveParticipant(e){let t=e.participant?.id??e.context?.userId;if(!t)return;let n=this.participantCache.get(t);if(n)return n;try{let r=await fetch(`${En}/users/${t}`,{headers:{Authorization:`Bot ${this.config.token}`}});if(!r.ok)return console.warn(`[DiscordChannel] Failed to resolve user ${t}: HTTP ${r.status}`),{kind:"user",id:t};let s=await r.json(),i=s.global_name??s.username,c={kind:"user",id:s.id,displayName:i};return this.participantCache.set(t,c),c}catch(r){return console.warn(`[DiscordChannel] resolveParticipant error for ${t}:`,r),{kind:"user",id:t}}}invalidateParticipant(e){this.participantCache.delete(e)}async send(e){if(!this.client)throw new Error("[DiscordChannel] Client not initialized. Did you call listen()?");let t=e.metadata?.threadId;if(t){let s=await this.client.channels.fetch(t);if(s&&"send"in s)try{await s.send({content:e.output});return}catch(i){throw console.error("[DiscordChannel] Failed to send to thread:",i),new Error(`[DiscordChannel] Failed to send Discord message: ${i instanceof Error?i.message:String(i)}`)}console.warn(`[DiscordChannel] Thread ${t} not found or not sendable; falling back to channel send.`)}let n=e.metadata?.channelId??(this.allowedChannelIds.size>0?[...this.allowedChannelIds][0]:void 0);if(!n)throw new Error("[DiscordChannel] No channel ID available for sending. Configure channelId or pass output.metadata.channelId.");let r=await this.client.channels.fetch(n);if(!r||!("send"in r))throw new Error(`[DiscordChannel] Channel ${n} not found or is not a text channel`);try{await r.send({content:e.output})}catch(s){throw console.error("[DiscordChannel] Failed to send to channel:",s),new Error(`[DiscordChannel] Failed to send Discord message: ${s instanceof Error?s.message:String(s)}`)}}listen(){typeof process>"u"||import("discord.js").then(e=>{let{Client:t,GatewayIntentBits:n}=e;this.client=new t({intents:[n.Guilds,n.GuildMessages,n.MessageContent,n.DirectMessages]}),this.client.on("ready",()=>{let r=this.client.user;this.botUserId=r?.id;let s=this.allowedChannelIds.size===0?"all channels":[...this.allowedChannelIds].join(", "),i=this.config.guildId??"all guilds";console.log(`[DiscordChannel] Logged in as ${r?.tag??"unknown"} (botUserId=${this.botUserId??"unknown"}) | guild=${i} | channels=${s}`)}),this.client.on("messageCreate",r=>{let s=r;if(!this.shouldProcessEvent(s))return;let i=this.normalize(s);this.handleMessage(i)}),this.client.on("userUpdate",(r,s)=>{let i=s;i?.id&&this.invalidateParticipant(i.id)}),this.client.login(this.config.token).catch(r=>{console.error("[DiscordChannel] Failed to login to Discord:",r)})}).catch(e=>{console.error("[DiscordChannel] Failed to initialize Discord client:",e),console.error("[DiscordChannel] Make sure discord.js is installed: npm install discord.js")})}async stop(){this.client&&(await this.client.destroy(),this.client=void 0)}};d();var Qe=class extends R{isTriggerChannel=!0;config;transporter;constructor(e){super(),this.config=e,this.name=e.name}listen(){typeof process<"u"&&import("nodemailer").then(e=>{this.transporter=e.default.createTransport({host:this.config.smtp.host,port:this.config.smtp.port,secure:this.config.smtp.secure??this.config.smtp.port===465,auth:{user:this.config.smtp.auth.user,pass:this.config.smtp.auth.pass}}),console.log(`[EmailChannel] Email transporter initialized for ${this.config.from}`)}).catch(e=>{console.error("[EmailChannel] Failed to initialize nodemailer:",e),console.error("[EmailChannel] Make sure to install nodemailer: npm install nodemailer")})}async send(e){if(!this.transporter)throw new Error("Email transporter not initialized. Did you call listen()?");let t=Array.isArray(this.config.to)?this.config.to:[this.config.to],n=this.config.subject||"Message from Agent",r={from:this.config.from,to:t.join(", "),subject:n,text:e.output,html:this.formatAsHtml(e.output)};try{await this.transporter.sendMail(r)}catch(s){throw console.error("[EmailChannel] Failed to send email:",s),new Error(`Failed to send email: ${s instanceof Error?s.message:String(s)}`)}}normalize(e){throw new Error("EmailChannel is outbound-only. Use WebhookChannel with email webhook events for inbound email.")}formatAsHtml(e){return e.split(`
|
|
32
|
+
Is this answer sufficient? Reply with ONLY "yes" or "no".`,{workflow:{mode:"single-shot"}})).output.toLowerCase().trim().startsWith("yes")}async handlePendingAsk(e,t,n,r){return await this.evaluateAnswer(e.question,t,{simpleValidation:i=>i.trim().length>3})?(await this.resolvePendingAsk(e.id,t),n(t)):e.retries>=e.maxRetries?(await this.resolvePendingAsk(e.id,"__insufficient__"),this._triggeringChannel&&await this.sendTo(this._triggeringChannel,"I was unable to get enough information to proceed. Skipping this step."),r?r():{output:"Step skipped due to insufficient input.",metadata:{skipped:!0,askId:e.id}}):(this._registry?.incrementRetries(e.id),this.ask(`I need a bit more clarity on: "${e.question}". Could you provide more details?`,{context:e.context,maxRetries:e.maxRetries}))}async delegateAndWait(e,t){if(!this._registry)throw new k("Agent not registered - cannot use delegateAndWait()");let n={message:t.message,intent:t.intent,data:t.data,context:{...t.context||{},delegatedBy:this.name},conversationId:t.conversationId||this._conversationId||`delegation-${Date.now()}`};return await this._registry.invoke(e,n)}async onBeforeRun(e){}async onComplete(e){}async onError(e){}_resolveAssemblerOptions(){let e=this.channels.map(r=>r.botUserId).filter(r=>typeof r=="string"&&r.length>0),t=this.assemblerOptions?.agentAliases??[];if(e.length===0&&t.length===0)return this.assemblerOptions;let n=Array.from(new Set([...t,...e]));return{...this.assemblerOptions,agentAliases:n}}_getEffectiveInterceptors(){return this.interceptors.some(t=>t[X]===!0)?this.interceptors:[Q({store:this.conversationHistory}),...this.interceptors]}_bindChannel(e){e.onMessage(async t=>{if(!t.conversationId){console.warn(`[${this.name}] Message received without conversationId \u2014 skipping`);return}let n=await this._acquireConversationLock(t.conversationId);try{this._triggeringChannel=e.name,this._isTriggerChannel=e.isTriggerChannel,this._conversationId=t.conversationId;let r=se(this._getEffectiveInterceptors(),this,e,this._registry??null),s=await oe(r,t);if(s===null)return;let i={output:s.output,metadata:s.metadata};await e.send({output:i.output,metadata:{...i.metadata,conversationId:t.conversationId,...t.context}})}catch(r){let s=r instanceof Error?r.message:"Unknown error occurred";console.error(`[${this.name}] Error in agent invocation: ${s}`);try{await e.send({output:`Error: ${s}`,metadata:{conversationId:t.conversationId,error:!0,...t.context}})}catch(i){console.error(`[${this.name}] Failed to send error to channel: ${i}`)}}finally{n()}})}async _acquireConversationLock(e){for(;this._conversationLocks.has(e);)try{await this._conversationLocks.get(e)}catch{}let t,n=new Promise(r=>{t=r});return this._conversationLocks.set(e,n),()=>{this._conversationLocks.delete(e),t()}}extractSteps(e){let t=e;if(t.plan&&typeof t.plan=="object"){let n=t.plan;if(Array.isArray(n.steps))return n.steps.map(r=>({number:r.number||0,description:r.description||"",status:r.status||"completed",result:r.result}))}if(Array.isArray(t.steps))return t.steps}}});d();d();j();pe();d();import{randomUUID as hn}from"crypto";d();Z();import{randomUUID as Tt}from"crypto";var W=class{constructor(e){this.registry=e}registry;async invoke(e,t){let n=this.registry.getAgent(e);if(!n)throw new k(`Agent "${e}" not found in registry. Available agents: ${this.registry.getAllAgents().map(p=>p.name).join(", ")}`);let r=n.conversationHistory,s=t.conversationId,i=t.context?.delegatedBy;if(r&&s&&i){let p={id:t.context?.messageId??Tt(),conversationId:s,participant:{kind:"agent",id:i,displayName:i},content:t.message??"",timestamp:new Date().toISOString(),scope:"channel",metadata:{}};try{await r.append(p)}catch{}}let c=await n.invokeAgent(t);if(r&&s){let p={id:Tt(),conversationId:s,participant:{kind:"agent",id:e,displayName:e},content:c.output,timestamp:new Date().toISOString(),scope:"channel",metadata:{}};try{await r.append(p)}catch{}}return c}};var Ue=class{agentList;instances=new Map;channels=new Map;_transport;pendingAsks=new Map;_started=!1;_restarting=!1;_restartScheduled=!1;_deadlineTimer;constructor(e,t){this.agentList=e,this._transport=t?.transport||new W(this)}async start(){for(let e of this.agentList){await e._ensureToolpack(),e._registry=this,this.instances.set(e.name,e);for(let t of e.channels??[])t.name&&this.channels.set(t.name,t)}for(let e of this.agentList)await e.start();this._started=!0}async addAgent(e){if(this.agentList.push(e),!!this._started){await e._ensureToolpack(),e._registry=this,this.instances.set(e.name,e);for(let t of e.channels??[])t.name&&this.channels.set(t.name,t);await e.start()}}async removeAgent(e){let t=this.instances.get(e);if(t){await t.stop(),this.instances.delete(e),this.agentList=this.agentList.filter(n=>n.name!==e);for(let n of t.channels??[])n.name&&this.channels.delete(n.name)}}isAllIdle(){return this.agentList.every(e=>e.isIdle())}scheduleRestart(e){if(this._restartScheduled)return;this._restartScheduled=!0;let t=(e?.maxWaitMinutes??30)*60*1e3,n=()=>{!this._restarting&&this.isAllIdle()&&this._executeRestart()};if(n(),!this._restarting){for(let r of this.agentList)r.on("agent:complete",n);this._deadlineTimer=setTimeout(()=>{this._executeRestart()},t)}}async _executeRestart(){if(this._restarting)return;this._restarting=!0,this._deadlineTimer&&(clearTimeout(this._deadlineTimer),this._deadlineTimer=void 0),await this.stop();let e=Date.now()+3e4;for(;!this.isAllIdle()&&Date.now()<e;)await new Promise(t=>setTimeout(t,100));this._exit(0)}_exit(e){process.exit(e)}async sendTo(e,t){let n=this.channels.get(e);if(!n)throw new Error(`No channel registered with name "${e}"`);await n.send(t)}getAgent(e){return this.instances.get(e)}getAllAgents(){return Array.from(this.instances.values())}getChannel(e){return this.channels.get(e)}async invoke(e,t){return this._transport.invoke(e,t)}async stop(){for(let e of this.agentList)await e.stop();this.instances.clear(),this.channels.clear(),this.pendingAsks.clear()}getPendingAsk(e){let t=this.pendingAsks.get(e);if(!t||t.length===0)return;let n=new Date;for(;t.length>0;){let r=t[0];if(r.expiresAt&&r.expiresAt<n)t.shift();else break}if(t.length===0){this.pendingAsks.delete(e);return}return t[0]}hasPendingAsks(e){let t=this.pendingAsks.get(e);if(!t||t.length===0)return!1;let n=new Date,r=t.filter(s=>!s.expiresAt||s.expiresAt>=n);return r.length===0?(this.pendingAsks.delete(e),!1):(r.length!==t.length&&this.pendingAsks.set(e,r),r.some(s=>s.status==="pending"))}cleanupExpiredAsks(){let e=0,t=new Date;for(let[n,r]of this.pendingAsks.entries()){let s=r.filter(i=>!i.expiresAt||i.expiresAt>=t);e+=r.length-s.length,s.length===0?this.pendingAsks.delete(n):s.length!==r.length&&this.pendingAsks.set(n,s)}return e}addPendingAsk(e){let t={...e,id:hn(),askedAt:new Date,retries:0,status:"pending"},n=this.pendingAsks.get(e.conversationId);return n?n.push(t):this.pendingAsks.set(e.conversationId,[t]),t}incrementRetries(e){for(let t of this.pendingAsks.values()){let n=t.find(r=>r.id===e);if(n)return n.retries+=1,n.retries}}async resolvePendingAsk(e,t){for(let[n,r]of this.pendingAsks.entries()){let s=r.findIndex(i=>i.id===e);if(s!==-1){r[s].status="answered",r[s].answer=t;let i=r[s].channelName;if(r.splice(s,1),r.length>0){let c=r[0];if(i&&i.trim()!=="")try{await this.sendTo(i,{output:c.question})}catch(p){console.error(`[AgentRegistry] Failed to auto-send next ask: ${p instanceof Error?p.message:"Unknown error"}`)}else console.warn(`[AgentRegistry] Cannot auto-send next ask: channelName is empty for conversation ${n}`)}r.length===0&&this.pendingAsks.delete(n);return}}throw new Error(`Pending ask with id "${e}" not found`)}};Z();d();import{watch as fn}from"fs";import{spawn as yn}from"child_process";import{basename as vn}from"path";var Ge=class{cwd;debounceMs;onRestartNeeded;onCompileError;spawnFn;watchFn;watchPaths;watchers=[];debounceTimer;constructor(e){this.watchPaths=e.watchPaths,this.cwd=e.cwd??process.cwd(),this.debounceMs=e.debounceMs??3e4,this.onRestartNeeded=e.onRestartNeeded,this.onCompileError=e.onCompileError,this.spawnFn=e.spawnFn??yn,this.watchFn=e.watchFn??fn}start(){for(let e of this.watchPaths){let t=this.watchFn(e,{recursive:!0},(n,r)=>{r&&this._handleFileChange(r)});this.watchers.push(t)}}stop(){for(let e of this.watchers)e.close();this.watchers=[],this.debounceTimer!==void 0&&(clearTimeout(this.debounceTimer),this.debounceTimer=void 0)}_handleFileChange(e){this.debounceTimer!==void 0&&clearTimeout(this.debounceTimer),this.debounceTimer=setTimeout(()=>{this.debounceTimer=void 0,vn(e).startsWith(".env")?this.onRestartNeeded():(e.endsWith(".ts")||e.endsWith(".tsx"))&&this._runCompile()},this.debounceMs)}_runCompile(){return new Promise(e=>{let t="",n=this.spawnFn("npx",["tsc","--build"],{cwd:this.cwd,stdio:["ignore","ignore","pipe"]});n.stderr?.on("data",r=>{t+=r.toString()}),n.on("close",r=>{if(r===0)this.onRestartNeeded();else{let s=t||`tsc --build exited with code ${String(r)}`;this.onCompileError?.(s)}e()}),n.on("error",r=>{let s=r instanceof Error?r.message:String(r);this.onCompileError?.(s),e()})})}};d();j();import{AGENT_MODE as wn}from"toolpack-sdk";var An={...wn,name:"research-agent-mode",systemPrompt:["You are a research agent specialized in web research and information gathering.","Use web.search to find relevant information, web.fetch to retrieve content, and web.scrape when needed.","Always cite your sources with URLs.","Provide comprehensive, well-structured summaries.","Flag any conflicting information or uncertainty in your findings."].join(" ")},Je=class extends T{name="research-agent";description="Web research agent for summarization, fact-finding, competitive analysis, and trend monitoring";mode=An;constructor(e){super(e)}async invokeAgent(e){let t=await this.run(e.message||"",void 0,{conversationId:e.conversationId});return await this.onComplete(t),t}};d();j();import{CODING_MODE as bn}from"toolpack-sdk";var In={...bn,name:"coding-agent-mode",systemPrompt:["You are a coding agent specialized in software development tasks.","Use coding.* tools for code analysis, fs.* for file operations, and git.* for version control.","Write clean, idiomatic code following best practices.","Always verify your changes and check for potential issues.","Provide clear explanations of your code changes."].join(" ")},ze=class extends T{name="coding-agent";description="Coding agent for code generation, refactoring, debugging, test writing, and code review";mode=In;constructor(e){super(e)}async invokeAgent(e){let t=await this.run(e.message||"",void 0,{conversationId:e.conversationId});return await this.onComplete(t),t}};d();j();import{AGENT_MODE as Cn}from"toolpack-sdk";var kn={...Cn,name:"data-agent-mode",systemPrompt:["You are a data agent specialized in database operations and data analysis.","Use db.* tools for database queries, fs.* for file operations, and http.* for API requests.","Generate clear, well-formatted reports and summaries.","Always validate data integrity and handle errors gracefully.","Provide insights and patterns when analyzing data."].join(" ")},qe=class extends T{name="data-agent";description="Data agent for database queries, CSV generation, data analysis, reporting, and aggregation";mode=kn;constructor(e){super(e)}async invokeAgent(e){let t=await this.run(e.message||"",void 0,{conversationId:e.conversationId});return await this.onComplete(t),t}};d();j();import{CHAT_MODE as Rn}from"toolpack-sdk";var xn={...Rn,name:"browser-agent-mode",systemPrompt:["You are a browser agent specialized in web interaction and content extraction.","Use web.fetch to retrieve pages, web.screenshot for visual content, and web.extract_links for navigation.","Follow links intelligently to gather comprehensive information.","Extract structured data from web pages when possible.","Be mindful of rate limits and respectful of website resources."].join(" ")},We=class extends T{name="browser-agent";description="Browser agent for web browsing, form interaction, page extraction, and link following";mode=xn;constructor(e){super(e)}async invokeAgent(e){let t=await this.run(e.message||"",void 0,{conversationId:e.conversationId});return await this.onComplete(t),t}};d();var R=class{name;_handler;onMessage(e){this._handler=e}async handleMessage(e){this._handler&&await this._handler(e)}};d();import{createHmac as Sn,timingSafeEqual as Tn}from"crypto";var He=class extends R{isTriggerChannel=!1;config;server;participantCache=new Map;botUserId;botId;allowedChannels;constructor(e){super(),this.config={port:3e3,...e},this.name=e.name;let t=e.channel;this.allowedChannels=t==null?null:Array.isArray(t)?t:[t]}listen(){typeof process<"u"&&import("http").then(e=>{this.server=e.createServer((t,n)=>{this.handleRequest(t,n)}),this.server.listen(this.config.port,()=>{console.log(`[SlackChannel] Listening on port ${this.config.port}`),this.runStartupCheck().catch(()=>{})})}).catch(e=>{console.error("[SlackChannel] Failed to start HTTP server:",e)})}async runStartupCheck(){try{let t=await(await fetch("https://slack.com/api/auth.test",{method:"POST",headers:{Authorization:`Bearer ${this.config.token}`,"Content-Type":"application/json"}})).json();t.ok?(this.botUserId=t.user_id,this.botId=t.bot_id,console.log(`[SlackChannel] Connected as @${t.user} (${t.user_id}) in workspace "${t.team}" \u2014 ${t.url}`)):console.warn(`[SlackChannel] auth.test failed: ${t.error}. Check your bot token.`)}catch(e){console.warn("[SlackChannel] Startup self-check failed (network error):",e)}}verifySignature(e,t){let n=e["x-slack-request-timestamp"],r=e["x-slack-signature"];if(!n||!r||Array.isArray(n)||Array.isArray(r))return!1;let s=parseInt(n,10),i=Math.floor(Date.now()/1e3);if(isNaN(s)||Math.abs(i-s)>300)return!1;let c=`v0:${n}:${t}`,a=`v0=${Sn("sha256",this.config.signingSecret).update(c).digest("hex")}`;if(a.length!==r.length)return!1;try{return Tn(Buffer.from(a),Buffer.from(r))}catch{return!1}}async send(e){let t=e.metadata?.threadTs??e.metadata?.thread_ts??e.metadata?.threadId,r=e.metadata?.channelId??(this.allowedChannels&&this.allowedChannels.length>0?this.allowedChannels[0]:void 0);if(!r)throw new Error("[SlackChannel] Cannot send: no channel configured and metadata.channelId is missing. Provide a target via SlackChannelConfig.channel or output.metadata.channelId.");let s={channel:r,text:e.output};t&&(s.thread_ts=t);let i=await fetch("https://slack.com/api/chat.postMessage",{method:"POST",headers:{Authorization:`Bearer ${this.config.token}`,"Content-Type":"application/json"},body:JSON.stringify(s)});if(!i.ok)throw new Error(`Failed to send Slack message: ${i.statusText}`);let c=await i.json();if(!c.ok)throw new Error(`Slack API error: ${c.error}`)}normalize(e){let t=e,r=(t.text||"").replace(/<(https?:\/\/[^|>]+)\|([^>]+)>/g,"$2 ($1)").replace(/<(https?:\/\/[^>]+)>/g,"$1").replace(/<!here>/g,"@here").replace(/<!channel>/g,"@channel").replace(/<!everyone>/g,"@everyone"),s=t.ts,i=t.thread_ts,c=i!==void 0&&i!==s,p=t.user,a=p?{kind:"user",id:p}:void 0,l=/<@([A-Z0-9]+)>/g,m=[],u;for(;(u=l.exec(r))!==null;)m.push(u[1]);let g=t.channel;return{message:r,conversationId:c?i:g||s||"",data:t,participant:a,context:{user:p,channel:g,team:t.team,channelType:t.channel_type,threadId:c?i:void 0,mentions:m.length>0?m:void 0,channelId:g,channelName:typeof this.config.channel=="string"?this.config.channel:g}}}async resolveParticipant(e){let t=e.participant?.id??e.context?.user;if(!t)return;let n=this.participantCache.get(t);if(n)return n;try{let r=await fetch(`https://slack.com/api/users.info?user=${encodeURIComponent(t)}`,{method:"GET",headers:{Authorization:`Bearer ${this.config.token}`}});if(!r.ok)return{kind:"user",id:t};let s=await r.json();if(!s.ok||!s.user){let p={kind:"user",id:t};return this.participantCache.set(t,p),p}let i=s.user.profile?.display_name||s.user.profile?.real_name||s.user.real_name||s.user.name||t,c={kind:"user",id:t,displayName:i,metadata:{slackUser:s.user}};return this.participantCache.set(t,c),c}catch{return{kind:"user",id:t}}}invalidateParticipant(e){this.participantCache.delete(e)}shouldProcessEvent(e){let t=e.type;if(t!=="message"&&t!=="app_mention")return!1;if(this.allowedChannels!==null){let i=e.channel_type;if(!(i==="im"||i==="mpim")){let p=e.channel;if(!p||!this.allowedChannels.includes(p))return!1}}let n=e.user;if(this.botUserId&&n===this.botUserId)return!1;let r=e.bot_id;if(console.log(`[SlackChannel:shouldProcessEvent] subtype=${e.subtype} user=${n} bot_id=${r} this.botUserId=${this.botUserId} this.botId=${this.botId}`),!r)return!0;if(this.botId&&r===this.botId)return!1;let s=this.config.blockedBotIds??[];if(s.includes(r)||n!==void 0&&s.includes(n))return!1;if(this.config.allowedBotIds!==void 0){let i=this.config.allowedBotIds;return i.includes(r)||n!==void 0&&i.includes(n)}return!0}handleRequest(e,t){if(e.method!=="POST"){t.writeHead(405),t.end("Method not allowed");return}let n="";e.on("data",r=>{n+=r.toString()}),e.on("end",()=>{if(!this.verifySignature(e.headers,n)){t.writeHead(401),t.end("Invalid signature");return}try{let r=JSON.parse(n);if(r.type==="url_verification"){t.writeHead(200,{"Content-Type":"application/json"}),t.end(JSON.stringify({challenge:r.challenge}));return}if(r.type==="event_callback"&&r.event){let s=r.event;if(this.shouldProcessEvent(s)){let i=this.normalize(s);this.handleMessage(i)}else s.type==="user_change"&&s.user&&this.invalidateParticipant(s.user.id);t.writeHead(200),t.end("OK");return}t.writeHead(200),t.end("OK")}catch(r){console.error("[SlackChannel] Error handling request:",r),t.writeHead(400),t.end("Bad request")}})}async stop(){if(this.server)return new Promise(e=>{this.server.close(e)})}};d();var Ke=class extends R{isTriggerChannel=!1;config;server;pendingResponses=new Map;constructor(e){super(),this.name=e.name,this.config={port:e.port??3e3,path:e.path??"/webhook"}}listen(){typeof process<"u"&&import("http").then(e=>{this.server=e.createServer((t,n)=>{this.handleRequest(t,n)}),this.server.listen(this.config.port,()=>{console.log(`[WebhookChannel] Listening on port ${this.config.port}${this.config.path}`)})}).catch(e=>{console.error("[WebhookChannel] Failed to start HTTP server:",e)})}async send(e){let t=e.metadata?.conversationId;if(t&&this.pendingResponses.has(t)){let n=this.pendingResponses.get(t);this.pendingResponses.delete(t),n.resolve({output:e.output,metadata:e.metadata})}}normalize(e){let t=e,n=t.headers||{},r=n["x-session-id"]||n["X-Session-Id"]||t.sessionId||t.conversationId||this.generateSessionId();return{message:t.message||t.text||"",intent:t.intent,conversationId:r,data:t,context:{headers:t.headers,method:t.method,sessionId:r}}}handleRequest(e,t){if(e.url!==this.config.path){t.writeHead(404),t.end("Not found");return}if(e.method!=="POST"){t.writeHead(405),t.end("Method not allowed");return}let n="";e.on("data",r=>{n+=r.toString()}),e.on("end",()=>{try{let r=JSON.parse(n),s=this.normalize(r),i=s.conversationId||this.generateSessionId(),c=new Promise((p,a)=>{this.pendingResponses.set(i,{resolve:p,reject:a}),setTimeout(()=>{this.pendingResponses.has(i)&&(this.pendingResponses.delete(i),a(new Error("Agent response timeout")))},3e4)});this.handleMessage({...s,conversationId:i,context:{...s.context,sessionId:i}}),c.then(p=>{t.writeHead(200,{"Content-Type":"application/json"}),t.end(JSON.stringify(p))}).catch(p=>{t.writeHead(500,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:p.message}))})}catch(r){console.error("[WebhookChannel] Error handling request:",r),t.writeHead(400,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Bad request"}))}})}generateSessionId(){return`webhook-${Date.now()}-${Math.random().toString(36).substring(2,9)}`}async stop(){if(this.server)return new Promise(e=>{this.server.close(e)})}};d();import{CronExpressionParser as _t}from"cron-parser";var Ve=class extends R{isTriggerChannel=!0;config;timer;_stopped=!1;_generation=0;constructor(e){if(super(),!e.cron&&!e.store)throw new Error("ScheduledChannel: provide at least one of `cron` (static schedule) or `store` (dynamic scheduling).");if(e.cron)try{_t.parse(e.cron)}catch(t){throw new Error(`ScheduledChannel: invalid cron expression '${e.cron}': ${t.message}`)}if(e.store&&!e.name&&console.warn("[ScheduledChannel] A `store` was provided without a `name`. All store queries will be unscoped and will pick up jobs from every channel. Set `name` to scope this channel to its own jobs."),e.idlePollMs!==void 0&&e.idlePollMs<1e3)throw new Error(`ScheduledChannel: idlePollMs must be at least 1000ms (got ${e.idlePollMs}). Values below 1 second create a tight polling loop.`);this.config=e,this.name=e.name}listen(){this._generation++,this.timer&&(clearTimeout(this.timer),this.timer=void 0),this._stopped=!1,this.config.store?this._listenWithStore():this._listenStatic()}async stop(){this._stopped=!0,this.timer&&(clearTimeout(this.timer),this.timer=void 0)}async send(e){}normalize(e){let t=e,n=new Date,r=`${n.getFullYear()}-${n.getMonth()+1}-${n.getDate()}`;return{intent:t?.intent??this.config.intent,message:t?.message??this.config.message??`Scheduled task triggered at ${n.toISOString()}`,conversationId:`scheduled:${this.name??"default"}:${r}`,data:{...t?.payload??{},scheduled:!0,jobId:t?.id,cron:t?.cron??this.config.cron,timestamp:n.toISOString()}}}_listenStatic(){this._scheduleNextStatic(this._generation)}_scheduleNextStatic(e){if(this._stopped||e!==this._generation)return;let t=this._nextRunFromCron(this.config.cron),n=t.getTime()-Date.now();if(n<=0){this.timer=setTimeout(()=>this._scheduleNextStatic(e),0);return}console.log(`[ScheduledChannel:${this.name??"default"}] Next run: ${t.toISOString()}`),this.timer=setTimeout(async()=>{this._stopped||e!==this._generation||(await this._triggerStatic(),this._scheduleNextStatic(e))},n)}async _triggerStatic(){if(!this._handler){console.warn(`[ScheduledChannel:${this.name??"default"}] Cron fired but no message handler is registered. Call onMessage() before listen() to avoid silently losing triggers.`);return}let e=this.normalize(null);try{await this.handleMessage(e)}catch(t){console.error(`[ScheduledChannel:${this.name??"default"}] Error on trigger:`,t)}}_listenWithStore(){let e=this.config.store,t=this._generation;if(t===1){let r=e.resetStuck(this.name);r>0&&console.log(`[ScheduledChannel:${this.name??"default"}] Reset ${r} stuck 'running' job(s) to 'pending'.`)}if(this.config.cron){let{duplicate:r}=e.create({channelName:this.name,cron:this.config.cron,intent:this.config.intent,message:this.config.message});r||console.log(`[ScheduledChannel:${this.name??"default"}] Seeded static cron '${this.config.cron}' into store.`)}let n=e.getDue(Date.now(),this.name);n.length>0&&(console.log(`[ScheduledChannel:${this.name??"default"}] Recovering ${n.length} overdue job(s).`),Promise.allSettled(n.map(r=>this._triggerJob(r)))),this._scheduleNextFromStore(t)}_scheduleNextFromStore(e){if(this._stopped||e!==this._generation)return;let t=this.config.store,n=t.getNextPending(this.name);if(!n){let s=this.config.idlePollMs??3e4;this.timer=setTimeout(()=>this._scheduleNextFromStore(e),s);return}let r=Math.max(0,n.nextRunAt-Date.now());console.log(`[ScheduledChannel:${this.name??"default"}] Next store job at ${new Date(n.nextRunAt).toISOString()} (in ${Math.round(r/1e3)}s)`),this.timer=setTimeout(async()=>{if(this._stopped||e!==this._generation)return;let s=t.getDue(Date.now(),this.name);await Promise.allSettled(s.map(i=>this._triggerJob(i))),this._scheduleNextFromStore(e)},r)}async _triggerJob(e){let t=this.config.store;if(!this._handler){console.warn(`[ScheduledChannel:${this.name??"default"}] Job ${e.id} fired but no message handler is registered. Call onMessage() before listen() to avoid silently losing jobs.`),t.markFailed(e.id,"No message handler registered");return}t.markRunning(e.id);let n=this.normalize(e);try{await this.handleMessage(n),t.markCompleted(e.id)}catch(r){let s=r instanceof Error?r.message:String(r);console.error(`[ScheduledChannel:${this.name??"default"}] Job ${e.id} failed:`,r),t.markFailed(e.id,s)}}_nextRunFromCron(e){return _t.parse(e,{currentDate:new Date}).next().toDate()}};d();var Ye=class extends R{isTriggerChannel=!1;config;offset=0;pollingInterval;server;botUserId;botUsername;constructor(e){super(),this.name=e.name,this.config=e}listen(){this.runStartupCheck().catch(()=>{}),this.config.webhookUrl?this.startWebhook():this.startPolling()}async runStartupCheck(){try{let t=await(await fetch(`https://api.telegram.org/bot${this.config.token}/getMe`)).json();if(t.ok&&t.result){let n=t.result;this.botUserId=n.id!=null?String(n.id):void 0,this.botUsername=n.username,console.log(`[TelegramChannel] Connected as @${n.username} (id: ${n.id}, name: ${n.first_name})`)}else console.warn(`[TelegramChannel] getMe failed: ${t.description??"unknown error"}. Check your bot token.`)}catch(e){console.warn("[TelegramChannel] Startup self-check failed (network error):",e)}}async send(e){let t=e.metadata?.chatId;if(!t)throw new Error("Telegram send requires chatId in metadata");let n=await fetch(`https://api.telegram.org/bot${this.config.token}/sendMessage`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({chat_id:t,text:e.output,parse_mode:"Markdown"})});if(!n.ok)throw new Error(`Failed to send Telegram message: ${n.statusText}`);let r=await n.json();if(!r.ok)throw new Error(`Telegram API error: ${r.description}`)}normalize(e){let t=e,n=t.message||t.edited_message||{},r=n.text||"",s=n.chat||{},i=n.from||{},c=i.id!=null?String(i.id):void 0,p=i.first_name||i.username||c,a=c?{kind:"user",id:c,displayName:p??c}:void 0,l=n.entities??[],m=[];for(let w of l)if(w.type==="text_mention"&&w.user){let f=w.user;f.id!=null&&m.push(String(f.id))}let u=s.type,g=s.id!=null?String(s.id):"";return{message:r,conversationId:g,data:t,participant:a,context:{chatId:s.id,userId:i.id,username:i.username,firstName:i.first_name,lastName:i.last_name,messageId:n.message_id,channelType:u,channelId:g,channelName:s.title,mentions:m.length>0?m:void 0}}}startPolling(){console.log("[TelegramChannel] Starting polling mode"),this.pollingInterval=setInterval(async()=>{try{await this.pollUpdates()}catch(e){console.error("[TelegramChannel] Polling error:",e)}},5e3)}async pollUpdates(){let e=`https://api.telegram.org/bot${this.config.token}/getUpdates?offset=${this.offset}&limit=100`,t=await fetch(e);if(!t.ok)throw new Error(`Telegram getUpdates failed: ${t.statusText}`);let n=await t.json();if(!n.ok)throw new Error("Telegram getUpdates returned not ok");for(let r of n.result){let s=r.update_id;s>=this.offset&&(this.offset=s+1);try{let i=this.normalize(r);await this.handleMessage(i)}catch(i){console.error("[TelegramChannel] Error processing update:",i)}}}startWebhook(){typeof process>"u"||(console.log("[TelegramChannel] Starting webhook mode"),import("http").then(e=>{this.server=e.createServer((r,s)=>{this.handleWebhookRequest(r,s)});let t=new URL(this.config.webhookUrl||"http://localhost:3000"),n=parseInt(t.port,10)||3e3;this.server.listen(n,()=>{console.log(`[TelegramChannel] Webhook server listening on port ${n}`)}),this.setWebhook()}).catch(e=>{console.error("[TelegramChannel] Failed to start webhook server:",e)}))}async setWebhook(){if(!this.config.webhookUrl)return;let e=await fetch(`https://api.telegram.org/bot${this.config.token}/setWebhook`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({url:this.config.webhookUrl})});if(!e.ok){console.error("[TelegramChannel] Failed to set webhook");return}let t=await e.json();t.ok?console.log("[TelegramChannel] Webhook set successfully"):console.error("[TelegramChannel] Failed to set webhook:",t.description)}handleWebhookRequest(e,t){if(e.method!=="POST"){t.writeHead(405),t.end("Method not allowed");return}let n="";e.on("data",r=>{n+=r.toString()}),e.on("end",()=>{try{let r=JSON.parse(n);this.handleMessage(this.normalize(r)).catch(s=>{console.error("[TelegramChannel] Error processing webhook:",s)}),t.writeHead(200),t.end("OK")}catch(r){console.error("[TelegramChannel] Error parsing webhook:",r),t.writeHead(400),t.end("Bad request")}})}async stop(){if(this.pollingInterval&&(clearInterval(this.pollingInterval),this.pollingInterval=void 0),this.server)return new Promise(e=>{this.server.close(e)});if(this.config.webhookUrl)try{await fetch(`https://api.telegram.org/bot${this.config.token}/deleteWebhook`,{method:"POST"})}catch(e){console.error("[TelegramChannel] Failed to delete webhook:",e)}}};d();var _n=new Set([1,3]),Et=/<@!?(\d+)>/g,En="https://discord.com/api/v10",Xe=class extends R{isTriggerChannel=!1;config;allowedChannelIds;botUserId;participantCache=new Map;client;constructor(e){super(),this.config=e,this.name=e.name,e.channelId==null?this.allowedChannelIds=new Set:Array.isArray(e.channelId)?this.allowedChannelIds=new Set(e.channelId):this.allowedChannelIds=new Set([e.channelId])}shouldProcessEvent(e){return!e.author||e.webhookId||this.botUserId&&e.author.id===this.botUserId||this.config.guildId&&e.guildId!==this.config.guildId||this.allowedChannelIds.size>0&&(!e.channelId||!this.allowedChannelIds.has(e.channelId))?!1:e.author.bot||e.author.system?this.config.blockedBotIds?.includes(e.author.id)?!1:this.config.allowedBotIds?this.config.allowedBotIds.includes(e.author.id):!1:!0}normalize(e){let t=e,n=t.channelId,r=(n??"")+(t.thread?.id?`:${t.thread.id}`:""),s=t.channel?.type,i=s!==void 0&&_n.has(s),c=t.author?.id,p=t.author?.globalName??t.author?.username,a=[];if(t.content){Et.lastIndex=0;let l;for(;(l=Et.exec(t.content))!==null;)a.push(l[1])}return{message:t.content,conversationId:r,data:t,participant:c?{kind:"user",id:c,displayName:p??void 0}:void 0,context:{userId:c,username:t.author?.username,channelType:i?"dm":"channel",channelId:n,channelName:t.channel?.name,guildId:t.guildId,threadId:t.thread?.id,messageId:t.id,mentions:a.length>0?a:void 0,isMentioned:this.botUserId?a.includes(this.botUserId):void 0}}}async resolveParticipant(e){let t=e.participant?.id??e.context?.userId;if(!t)return;let n=this.participantCache.get(t);if(n)return n;try{let r=await fetch(`${En}/users/${t}`,{headers:{Authorization:`Bot ${this.config.token}`}});if(!r.ok)return console.warn(`[DiscordChannel] Failed to resolve user ${t}: HTTP ${r.status}`),{kind:"user",id:t};let s=await r.json(),i=s.global_name??s.username,c={kind:"user",id:s.id,displayName:i};return this.participantCache.set(t,c),c}catch(r){return console.warn(`[DiscordChannel] resolveParticipant error for ${t}:`,r),{kind:"user",id:t}}}invalidateParticipant(e){this.participantCache.delete(e)}async send(e){if(!this.client)throw new Error("[DiscordChannel] Client not initialized. Did you call listen()?");let t=e.metadata?.threadId;if(t){let s=await this.client.channels.fetch(t);if(s&&"send"in s)try{await s.send({content:e.output});return}catch(i){throw console.error("[DiscordChannel] Failed to send to thread:",i),new Error(`[DiscordChannel] Failed to send Discord message: ${i instanceof Error?i.message:String(i)}`)}console.warn(`[DiscordChannel] Thread ${t} not found or not sendable; falling back to channel send.`)}let n=e.metadata?.channelId??(this.allowedChannelIds.size>0?[...this.allowedChannelIds][0]:void 0);if(!n)throw new Error("[DiscordChannel] No channel ID available for sending. Configure channelId or pass output.metadata.channelId.");let r=await this.client.channels.fetch(n);if(!r||!("send"in r))throw new Error(`[DiscordChannel] Channel ${n} not found or is not a text channel`);try{await r.send({content:e.output})}catch(s){throw console.error("[DiscordChannel] Failed to send to channel:",s),new Error(`[DiscordChannel] Failed to send Discord message: ${s instanceof Error?s.message:String(s)}`)}}listen(){typeof process>"u"||import("discord.js").then(e=>{let{Client:t,GatewayIntentBits:n}=e;this.client=new t({intents:[n.Guilds,n.GuildMessages,n.MessageContent,n.DirectMessages]}),this.client.on("ready",()=>{let r=this.client.user;this.botUserId=r?.id;let s=this.allowedChannelIds.size===0?"all channels":[...this.allowedChannelIds].join(", "),i=this.config.guildId??"all guilds";console.log(`[DiscordChannel] Logged in as ${r?.tag??"unknown"} (botUserId=${this.botUserId??"unknown"}) | guild=${i} | channels=${s}`)}),this.client.on("messageCreate",r=>{let s=r;if(!this.shouldProcessEvent(s))return;let i=this.normalize(s);this.handleMessage(i)}),this.client.on("userUpdate",(r,s)=>{let i=s;i?.id&&this.invalidateParticipant(i.id)}),this.client.login(this.config.token).catch(r=>{console.error("[DiscordChannel] Failed to login to Discord:",r)})}).catch(e=>{console.error("[DiscordChannel] Failed to initialize Discord client:",e),console.error("[DiscordChannel] Make sure discord.js is installed: npm install discord.js")})}async stop(){this.client&&(await this.client.destroy(),this.client=void 0)}};d();var Qe=class extends R{isTriggerChannel=!0;config;transporter;constructor(e){super(),this.config=e,this.name=e.name}listen(){typeof process<"u"&&import("nodemailer").then(e=>{this.transporter=e.default.createTransport({host:this.config.smtp.host,port:this.config.smtp.port,secure:this.config.smtp.secure??this.config.smtp.port===465,auth:{user:this.config.smtp.auth.user,pass:this.config.smtp.auth.pass}}),console.log(`[EmailChannel] Email transporter initialized for ${this.config.from}`)}).catch(e=>{console.error("[EmailChannel] Failed to initialize nodemailer:",e),console.error("[EmailChannel] Make sure to install nodemailer: npm install nodemailer")})}async send(e){if(!this.transporter)throw new Error("Email transporter not initialized. Did you call listen()?");let t=Array.isArray(this.config.to)?this.config.to:[this.config.to],n=this.config.subject||"Message from Agent",r={from:this.config.from,to:t.join(", "),subject:n,text:e.output,html:this.formatAsHtml(e.output)};try{await this.transporter.sendMail(r)}catch(s){throw console.error("[EmailChannel] Failed to send email:",s),new Error(`Failed to send email: ${s instanceof Error?s.message:String(s)}`)}}normalize(e){throw new Error("EmailChannel is outbound-only. Use WebhookChannel with email webhook events for inbound email.")}formatAsHtml(e){return e.split(`
|
|
33
33
|
|
|
34
34
|
`).map(t=>`<p>${t.replace(/\n/g,"<br>")}</p>`).join("")}async stop(){this.transporter&&(this.transporter.close(),this.transporter=void 0)}};d();var Ze=class extends R{config;twilioClient;server;constructor(e){super(),this.config={port:3e3,...e},this.name=e.name}get isTriggerChannel(){return!this.config.webhookPath}listen(){typeof process<"u"&&import("twilio").then(e=>{this.twilioClient=e.default(this.config.accountSid,this.config.authToken),console.log("[SMSChannel] Twilio client initialized"),this.config.webhookPath&&this.startWebhookServer()}).catch(e=>{console.error("[SMSChannel] Failed to initialize Twilio client:",e),console.error("[SMSChannel] Make sure to install twilio: npm install twilio")})}async send(e){if(!this.twilioClient)throw new Error("Twilio client not initialized. Did you call listen()?");let t=e.metadata?.from||this.config.to;if(!t)throw new Error('No recipient phone number specified. Set "to" in config or provide in output.metadata.from');try{await this.twilioClient.messages.create({body:e.output,from:this.config.from,to:t})}catch(n){throw console.error("[SMSChannel] Failed to send SMS:",n),new Error(`Failed to send SMS: ${n instanceof Error?n.message:String(n)}`)}}normalize(e){let t=e,n=t.From,r=t.Body,s=t.MessageSid;return{message:r,conversationId:n,data:t,context:{from:n,to:t.To,messageSid:s}}}startWebhookServer(){import("http").then(e=>{this.server=e.createServer((t,n)=>{this.handleWebhookRequest(t,n)}),this.server.listen(this.config.port,()=>{console.log(`[SMSChannel] Webhook server listening on port ${this.config.port} at ${this.config.webhookPath}`)})}).catch(e=>{console.error("[SMSChannel] Failed to start webhook server:",e)})}handleWebhookRequest(e,t){if(e.method!=="POST"||e.url!==this.config.webhookPath){t.writeHead(404),t.end("Not found");return}let n="";e.on("data",r=>{n+=r.toString()}),e.on("end",()=>{try{let r=new URLSearchParams(n),s={};r.forEach((c,p)=>{s[p]=c});let i=this.normalize(s);this.handleMessage(i),t.writeHead(200,{"Content-Type":"text/xml"}),t.end('<?xml version="1.0" encoding="UTF-8"?><Response></Response>')}catch(r){console.error("[SMSChannel] Error handling webhook:",r),t.writeHead(400),t.end("Bad request")}})}async stop(){if(this.server)return new Promise(e=>{this.server.close(e)})}};d();var et=class extends R{isTriggerChannel=!1;_timeout;_pendingResolve;constructor(e={}){super(),this._timeout=e.timeout??12e4}listen(){}async send(e){this._pendingResolve?.(e),this._pendingResolve=void 0}normalize(e){let t=e;return{message:typeof t.message=="string"?t.message:JSON.stringify(t),data:t,conversationId:`mcp-${Date.now()}-${Math.random().toString(36).slice(2,7)}`}}async trigger(e){let t=this.normalize(e);return new Promise((n,r)=>{let s=setTimeout(()=>{this._pendingResolve=void 0,r(new Error(`McpChannel: agent did not respond within ${this._timeout}ms`))},this._timeout);this._pendingResolve=i=>{clearTimeout(s),n(i.output)},this.handleMessage(t).catch(i=>{clearTimeout(s),this._pendingResolve=void 0,r(i instanceof Error?i:new Error(String(i)))})})}asAgentDefinition(e,t){return{name:e.name,description:e.description,...t!==void 0&&{inputSchema:t},invoke:n=>this.trigger(n)}}};d();d();Z();var ge=class{agentUrls;constructor(e){this.agentUrls=new Map(Object.entries(e.agents))}async invoke(e,t){let n=this.agentUrls.get(e);if(!n)throw new k(`Agent "${e}" not found in transport configuration. Available agents: ${Array.from(this.agentUrls.keys()).join(", ")}`);let r={jsonrpc:"2.0",method:`agent.invoke:${e}`,params:t,id:Date.now()};try{let s=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)});if(!s.ok)throw new k(`HTTP ${s.status}: ${s.statusText}`);let i=await s.json();if(i.error)throw new k(`JSON-RPC error (${i.error.code}): ${i.error.message}`+(i.error.data?` - ${JSON.stringify(i.error.data)}`:""));if(!i.result)throw new k("No result in JSON-RPC response");return i.result}catch(s){throw s instanceof k?s:new k(`Failed to invoke agent "${e}" at ${n}: ${s instanceof Error?s.message:String(s)}`)}}};d();import Pn from"http";var me=class{agents=new Map;server;port;constructor(e){this.port=e.port}registerAgent(e,t){this.agents.set(e,t)}listen(){this.server=Pn.createServer(async(e,t)=>{if(e.method!=="POST"){t.writeHead(405,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Method not allowed"}));return}let n="";e.on("data",r=>{n+=r.toString()}),e.on("end",async()=>{try{let r=JSON.parse(n),s=await this.handleRequest(r);t.writeHead(200,{"Content-Type":"application/json"}),t.end(JSON.stringify(s))}catch(r){let s={jsonrpc:"2.0",error:{code:-32700,message:"Parse error",data:r instanceof Error?r.message:String(r)},id:null};t.writeHead(200,{"Content-Type":"application/json"}),t.end(JSON.stringify(s))}})}),this.server.listen(this.port,()=>{console.log(`[AgentJsonRpcServer] Listening on port ${this.port}`),console.log(`[AgentJsonRpcServer] Registered agents: ${Array.from(this.agents.keys()).join(", ")}`)})}async stop(){return new Promise((e,t)=>{if(!this.server){e();return}this.server.close(n=>{n?t(n):(console.log("[AgentJsonRpcServer] Server stopped"),e())})})}async handleRequest(e){if(e.jsonrpc!=="2.0")return{jsonrpc:"2.0",error:{code:-32600,message:"Invalid Request",data:'jsonrpc must be "2.0"'},id:e.id||null};let[t,n]=e.method.split(":");if(t!=="agent.invoke")return{jsonrpc:"2.0",error:{code:-32601,message:"Method not found",data:`Unknown method: ${e.method}`},id:e.id||null};if(!n)return{jsonrpc:"2.0",error:{code:-32602,message:"Invalid params",data:'Agent name required in method (e.g., "agent.invoke:data-agent")'},id:e.id||null};let r=this.agents.get(n);if(!r)return{jsonrpc:"2.0",error:{code:-32602,message:"Invalid params",data:`Agent "${n}" not found. Available: ${Array.from(this.agents.keys()).join(", ")}`},id:e.id||null};if(!e.params)return{jsonrpc:"2.0",error:{code:-32602,message:"Invalid params",data:"params (AgentInput) required"},id:e.id||null};try{return{jsonrpc:"2.0",result:await r.invokeAgent(e.params),id:e.id||null}}catch(s){return{jsonrpc:"2.0",error:{code:-32603,message:"Internal error",data:s instanceof Error?s.message:String(s)},id:e.id||null}}}};d();d();j();import{CHAT_MODE as Mn}from"toolpack-sdk";var Dn={...Mn,name:"intent-classifier-mode",systemPrompt:["You classify whether a message is asking an agent to respond.","","Categories:","direct = Message uses @mention, name in greeting, possessive, or commands the agent to act","indirect = Agent is mentioned but unclear if response wanted (talking ABOUT, not TO them)","passive = No addressing detected; agent should only listen, not reply","ignore = Definitely not for this agent (noise, code blocks, other bots)","","Response must start with one of: direct, indirect, passive, ignore"].join(`
|
|
35
35
|
`)},he=class extends T{name="intent-classifier";description="Classifies whether a message is directly addressing an agent for response";mode=Dn;constructor(e){super(e)}async invokeAgent(e){let t=e.data;if(t?.isDirectMessage)return{output:"direct",metadata:{classification:"direct",shortCircuit:"dm"}};if(!t?.message)return{output:"ignore",metadata:{error:"No message provided for classification"}};let n=[];if(n.push(`Context: Public channel #${t.channelName}`),n.push(`Target agent: "${t.agentName}" (ID: ${t.agentId})`),n.push(`Message sender: ${t.senderName}`),t.recentContext&&t.recentContext.length>0){n.push(`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toolpack-sdk/agents",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"description": "Production AI agents for Toolpack SDK — 8 channel integrations (Slack, Discord, Telegram, SMS, Email, Webhook, Scheduled, MCP), AgentMind persistent cognitive layer (goals, beliefs, reflections), interceptors, evals, and multi-agent coordination",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=20"
|
|
@@ -89,11 +89,11 @@
|
|
|
89
89
|
},
|
|
90
90
|
"peerDependencies": {
|
|
91
91
|
"@opentelemetry/api": "^1.x",
|
|
92
|
-
"@toolpack-sdk/knowledge": "^2.
|
|
92
|
+
"@toolpack-sdk/knowledge": "^2.5.0",
|
|
93
93
|
"better-sqlite3": "^12.6.2",
|
|
94
94
|
"discord.js": "^14.x",
|
|
95
95
|
"nodemailer": "^6.x",
|
|
96
|
-
"toolpack-sdk": "^2.
|
|
96
|
+
"toolpack-sdk": "^2.5.0",
|
|
97
97
|
"twilio": "^5.x"
|
|
98
98
|
},
|
|
99
99
|
"peerDependenciesMeta": {
|