@mce-bt/microagents-channels 0.1.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.
@@ -0,0 +1,32 @@
1
+ import { type LogLevel } from '@slack/bolt';
2
+ import { type Channel, type ChannelConfig } from '../channel.js';
3
+ export interface SlackChannelConfig extends ChannelConfig {
4
+ /** Slack Bot Token (xoxb-...) */
5
+ botToken: string;
6
+ /** Slack App-Level Token (xapp-...) for Socket Mode */
7
+ appToken: string;
8
+ /** Slack Signing Secret */
9
+ signingSecret: string;
10
+ /** Port for Slack HTTP receiver (if not using socket mode) */
11
+ port?: number;
12
+ /** Log level for Slack Bolt */
13
+ logLevel?: LogLevel;
14
+ }
15
+ /**
16
+ * Slack channel adapter.
17
+ *
18
+ * Uses Slack Bolt SDK in Socket Mode to receive messages and forward them
19
+ * to the agent via AG-UI. Responses are posted back to the Slack channel/thread.
20
+ */
21
+ export declare class SlackChannel implements Channel {
22
+ readonly type = "slack";
23
+ private app;
24
+ private config;
25
+ /** Map Slack thread_ts → agent session ID */
26
+ private threadSessions;
27
+ constructor(config: SlackChannelConfig);
28
+ private registerHandlers;
29
+ start(): Promise<void>;
30
+ stop(): Promise<void>;
31
+ }
32
+ //# sourceMappingURL=slack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slack.d.ts","sourceRoot":"","sources":["../../src/adapters/slack.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE7D,OAAO,EAAwB,KAAK,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AAEvF,MAAM,WAAW,kBAAmB,SAAQ,aAAa;IACvD,iCAAiC;IACjC,QAAQ,EAAE,MAAM,CAAC;IAEjB,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAC;IAEjB,2BAA2B;IAC3B,aAAa,EAAE,MAAM,CAAC;IAEtB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED;;;;;GAKG;AACH,qBAAa,YAAa,YAAW,OAAO;IAC1C,QAAQ,CAAC,IAAI,WAAW;IAExB,OAAO,CAAC,GAAG,CAAW;IACtB,OAAO,CAAC,MAAM,CAAqB;IAEnC,6CAA6C;IAC7C,OAAO,CAAC,cAAc,CAA6B;gBAEvC,MAAM,EAAE,kBAAkB;IAetC,OAAO,CAAC,gBAAgB;IAqFlB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAItB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAI5B"}
@@ -0,0 +1,108 @@
1
+ import { App as SlackApp } from '@slack/bolt';
2
+ import { randomUUID } from 'node:crypto';
3
+ import { collectAgentResponse } from '../channel.js';
4
+ /**
5
+ * Slack channel adapter.
6
+ *
7
+ * Uses Slack Bolt SDK in Socket Mode to receive messages and forward them
8
+ * to the agent via AG-UI. Responses are posted back to the Slack channel/thread.
9
+ */
10
+ export class SlackChannel {
11
+ type = 'slack';
12
+ app;
13
+ config;
14
+ /** Map Slack thread_ts → agent session ID */
15
+ threadSessions = new Map();
16
+ constructor(config) {
17
+ this.config = config;
18
+ this.app = new SlackApp({
19
+ token: config.botToken,
20
+ appToken: config.appToken,
21
+ signingSecret: config.signingSecret,
22
+ socketMode: true,
23
+ port: config.port,
24
+ logLevel: config.logLevel,
25
+ });
26
+ this.registerHandlers();
27
+ }
28
+ registerHandlers() {
29
+ // Listen for direct messages and @mentions
30
+ this.app.event('message', async ({ event, say }) => {
31
+ // Skip bot messages to prevent loops
32
+ if ('bot_id' in event)
33
+ return;
34
+ if (!('text' in event) || !event.text)
35
+ return;
36
+ const threadTs = ('thread_ts' in event ? event.thread_ts : event.ts);
37
+ const text = event.text;
38
+ // Get or create session for this thread
39
+ let sessionId = this.threadSessions.get(threadTs);
40
+ if (!sessionId) {
41
+ sessionId = randomUUID();
42
+ this.threadSessions.set(threadTs, sessionId);
43
+ }
44
+ try {
45
+ const { text: responseText } = await collectAgentResponse(this.config.agentUrl, {
46
+ threadId: threadTs,
47
+ runId: randomUUID(),
48
+ message: text,
49
+ sessionId,
50
+ }, {
51
+ sharedSecret: this.config.sharedSecret,
52
+ agentId: 'slack-channel',
53
+ });
54
+ if (responseText) {
55
+ await say({ text: responseText, thread_ts: threadTs });
56
+ }
57
+ }
58
+ catch (err) {
59
+ const errorMsg = err instanceof Error ? err.message : String(err);
60
+ await say({
61
+ text: `⚠️ Error: ${errorMsg}`,
62
+ thread_ts: threadTs,
63
+ });
64
+ }
65
+ });
66
+ // Listen for app mentions
67
+ this.app.event('app_mention', async ({ event, say }) => {
68
+ const threadTs = event.thread_ts ?? event.ts;
69
+ const text = event.text.replace(/<@[A-Z0-9]+>/g, '').trim();
70
+ if (!text)
71
+ return;
72
+ let sessionId = this.threadSessions.get(threadTs);
73
+ if (!sessionId) {
74
+ sessionId = randomUUID();
75
+ this.threadSessions.set(threadTs, sessionId);
76
+ }
77
+ try {
78
+ const { text: responseText } = await collectAgentResponse(this.config.agentUrl, {
79
+ threadId: threadTs,
80
+ runId: randomUUID(),
81
+ message: text,
82
+ sessionId,
83
+ }, {
84
+ sharedSecret: this.config.sharedSecret,
85
+ agentId: 'slack-channel',
86
+ });
87
+ if (responseText) {
88
+ await say({ text: responseText, thread_ts: threadTs });
89
+ }
90
+ }
91
+ catch (err) {
92
+ const errorMsg = err instanceof Error ? err.message : String(err);
93
+ await say({
94
+ text: `⚠️ Error: ${errorMsg}`,
95
+ thread_ts: threadTs,
96
+ });
97
+ }
98
+ });
99
+ }
100
+ async start() {
101
+ await this.app.start();
102
+ }
103
+ async stop() {
104
+ await this.app.stop();
105
+ this.threadSessions.clear();
106
+ }
107
+ }
108
+ //# sourceMappingURL=slack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slack.js","sourceRoot":"","sources":["../../src/adapters/slack.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import { type Channel, type ChannelConfig, type MediaPayload } from '../channel.js';
2
+ export interface TelegramChannelConfig extends ChannelConfig {
3
+ /** Telegram Bot API token from @BotFather */
4
+ botToken: string;
5
+ /** Allowed chat IDs (for security). If empty, all chats are allowed. */
6
+ allowedChatIds?: number[];
7
+ }
8
+ /**
9
+ * Telegram channel adapter.
10
+ *
11
+ * Uses Grammy SDK to receive messages and forward them to the agent via AG-UI.
12
+ * Responses are sent back as Telegram messages.
13
+ */
14
+ export declare class TelegramChannel implements Channel {
15
+ readonly type = "telegram";
16
+ private bot;
17
+ private config;
18
+ /** Map Telegram chat ID → agent session ID */
19
+ private chatSessions;
20
+ constructor(config: TelegramChannelConfig);
21
+ private isAllowed;
22
+ private getOrCreateSession;
23
+ /**
24
+ * Download a Telegram file by file_id and return as base64.
25
+ */
26
+ private downloadFile;
27
+ /**
28
+ * Send the agent response back — text in chunks with Markdown fallback.
29
+ */
30
+ private sendReply;
31
+ /**
32
+ * Common handler for forwarding a message (text or multimodal) to the agent.
33
+ */
34
+ private forwardToAgent;
35
+ private registerHandlers;
36
+ start(): Promise<void>;
37
+ stop(): Promise<void>;
38
+ /**
39
+ * Get all known chat IDs (from active sessions + allowedChatIds).
40
+ */
41
+ getActiveChatIds(): number[];
42
+ /**
43
+ * Send a proactive message to all known chat sessions.
44
+ * Falls back to allowedChatIds if no sessions have been started yet.
45
+ */
46
+ sendMessage(text: string): Promise<void>;
47
+ /**
48
+ * Send media to all known chat sessions.
49
+ */
50
+ sendMedia(media: MediaPayload): Promise<void>;
51
+ }
52
+ //# sourceMappingURL=telegram.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telegram.d.ts","sourceRoot":"","sources":["../../src/adapters/telegram.ts"],"names":[],"mappings":"AAEA,OAAO,EAAwB,KAAK,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAM1G,MAAM,WAAW,qBAAsB,SAAQ,aAAa;IAC1D,6CAA6C;IAC7C,QAAQ,EAAE,MAAM,CAAC;IAEjB,wEAAwE;IACxE,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED;;;;;GAKG;AACH,qBAAa,eAAgB,YAAW,OAAO;IAC7C,QAAQ,CAAC,IAAI,cAAc;IAE3B,OAAO,CAAC,GAAG,CAAM;IACjB,OAAO,CAAC,MAAM,CAAwB;IAEtC,8CAA8C;IAC9C,OAAO,CAAC,YAAY,CAA6B;gBAErC,MAAM,EAAE,qBAAqB;IAMzC,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,kBAAkB;IAS1B;;OAEG;YACW,YAAY;IAiB1B;;OAEG;YACW,SAAS;IAYvB;;OAEG;YACW,cAAc;IA4B5B,OAAO,CAAC,gBAAgB;IAmKlB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAStB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAK3B;;OAEG;IACH,gBAAgB,IAAI,MAAM,EAAE;IAa5B;;;OAGG;IACG,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB9C;;OAEG;IACG,SAAS,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;CA6BpD"}
@@ -0,0 +1,317 @@
1
+ import { Bot, InputFile } from 'grammy';
2
+ import { randomUUID } from 'node:crypto';
3
+ import { collectAgentResponse } from '../channel.js';
4
+ /** Max file size for base64 download (10 MB) */
5
+ const MAX_FILE_SIZE = 10 * 1024 * 1024;
6
+ /**
7
+ * Telegram channel adapter.
8
+ *
9
+ * Uses Grammy SDK to receive messages and forward them to the agent via AG-UI.
10
+ * Responses are sent back as Telegram messages.
11
+ */
12
+ export class TelegramChannel {
13
+ type = 'telegram';
14
+ bot;
15
+ config;
16
+ /** Map Telegram chat ID → agent session ID */
17
+ chatSessions = new Map();
18
+ constructor(config) {
19
+ this.config = config;
20
+ this.bot = new Bot(config.botToken);
21
+ this.registerHandlers();
22
+ }
23
+ isAllowed(chatId) {
24
+ if (!this.config.allowedChatIds || this.config.allowedChatIds.length === 0) {
25
+ return true;
26
+ }
27
+ return this.config.allowedChatIds.includes(chatId);
28
+ }
29
+ getOrCreateSession(chatId) {
30
+ let sessionId = this.chatSessions.get(chatId);
31
+ if (!sessionId) {
32
+ sessionId = randomUUID();
33
+ this.chatSessions.set(chatId, sessionId);
34
+ }
35
+ return sessionId;
36
+ }
37
+ /**
38
+ * Download a Telegram file by file_id and return as base64.
39
+ */
40
+ async downloadFile(fileId) {
41
+ const file = await this.bot.api.getFile(fileId);
42
+ const filePath = file.file_path;
43
+ if (!filePath)
44
+ throw new Error('File path not available');
45
+ if (file.file_size && file.file_size > MAX_FILE_SIZE) {
46
+ throw new Error(`File too large (${(file.file_size / 1024 / 1024).toFixed(1)} MB). Max: ${MAX_FILE_SIZE / 1024 / 1024} MB.`);
47
+ }
48
+ const url = `https://api.telegram.org/file/bot${this.config.botToken}/${filePath}`;
49
+ const response = await fetch(url);
50
+ if (!response.ok)
51
+ throw new Error(`Failed to download file: HTTP ${response.status}`);
52
+ const buffer = Buffer.from(await response.arrayBuffer());
53
+ return { data: buffer.toString('base64'), size: buffer.length };
54
+ }
55
+ /**
56
+ * Send the agent response back — text in chunks with Markdown fallback.
57
+ */
58
+ async sendReply(chatId, text, ctx) {
59
+ const maxLen = 4096;
60
+ for (let i = 0; i < text.length; i += maxLen) {
61
+ const chunk = text.slice(i, i + maxLen);
62
+ try {
63
+ await ctx.reply(chunk, { parse_mode: 'Markdown' });
64
+ }
65
+ catch {
66
+ await ctx.reply(chunk);
67
+ }
68
+ }
69
+ }
70
+ /**
71
+ * Common handler for forwarding a message (text or multimodal) to the agent.
72
+ */
73
+ async forwardToAgent(chatId, message, ctx) {
74
+ const sessionId = this.getOrCreateSession(chatId);
75
+ const { text: responseText } = await collectAgentResponse(this.config.agentUrl, {
76
+ threadId: String(chatId),
77
+ runId: randomUUID(),
78
+ message,
79
+ sessionId,
80
+ }, {
81
+ sharedSecret: this.config.sharedSecret,
82
+ agentId: 'telegram-channel',
83
+ });
84
+ if (responseText) {
85
+ await this.sendReply(chatId, responseText, ctx);
86
+ }
87
+ else {
88
+ await ctx.reply('⚠️ No response from agent.');
89
+ }
90
+ }
91
+ registerHandlers() {
92
+ // /start command
93
+ this.bot.command('start', async (ctx) => {
94
+ await ctx.reply('👋 Hello! Send me a message and I\'ll forward it to the agent.');
95
+ });
96
+ // /newsession command — reset thread session
97
+ this.bot.command('newsession', async (ctx) => {
98
+ this.chatSessions.delete(ctx.chat.id);
99
+ await ctx.reply('🔄 New session started.');
100
+ });
101
+ // /chatid command — show the user's chat ID
102
+ this.bot.command('chatid', async (ctx) => {
103
+ await ctx.reply(`Your chat ID is: \`${ctx.chat.id}\``, { parse_mode: 'Markdown' });
104
+ });
105
+ // Handle text messages
106
+ this.bot.on('message:text', async (ctx) => {
107
+ const chatId = ctx.chat.id;
108
+ if (!this.isAllowed(chatId))
109
+ return;
110
+ try {
111
+ await ctx.api.sendChatAction(chatId, 'typing');
112
+ await this.forwardToAgent(chatId, ctx.message.text, ctx);
113
+ }
114
+ catch (err) {
115
+ const errorMsg = err instanceof Error ? err.message : String(err);
116
+ await ctx.reply(`⚠️ Error: ${errorMsg}`);
117
+ }
118
+ });
119
+ // Handle photo messages
120
+ this.bot.on('message:photo', async (ctx) => {
121
+ const chatId = ctx.chat.id;
122
+ if (!this.isAllowed(chatId))
123
+ return;
124
+ try {
125
+ await ctx.api.sendChatAction(chatId, 'typing');
126
+ // Get the largest photo (last in array)
127
+ const photos = ctx.message.photo;
128
+ const largest = photos[photos.length - 1];
129
+ const { data } = await this.downloadFile(largest.file_id);
130
+ const parts = [];
131
+ if (ctx.message.caption) {
132
+ parts.push({ type: 'text', text: ctx.message.caption });
133
+ }
134
+ parts.push({ type: 'image', mimeType: 'image/jpeg', data });
135
+ await this.forwardToAgent(chatId, parts, ctx);
136
+ }
137
+ catch (err) {
138
+ const errorMsg = err instanceof Error ? err.message : String(err);
139
+ await ctx.reply(`⚠️ Error: ${errorMsg}`);
140
+ }
141
+ });
142
+ // Handle document messages
143
+ this.bot.on('message:document', async (ctx) => {
144
+ const chatId = ctx.chat.id;
145
+ if (!this.isAllowed(chatId))
146
+ return;
147
+ try {
148
+ await ctx.api.sendChatAction(chatId, 'upload_document');
149
+ const doc = ctx.message.document;
150
+ const { data } = await this.downloadFile(doc.file_id);
151
+ const mimeType = doc.mime_type ?? 'application/octet-stream';
152
+ const name = doc.file_name ?? 'document';
153
+ const parts = [];
154
+ if (ctx.message.caption) {
155
+ parts.push({ type: 'text', text: ctx.message.caption });
156
+ }
157
+ // If the document is an image, send as image content part
158
+ if (mimeType.startsWith('image/')) {
159
+ parts.push({ type: 'image', mimeType, data });
160
+ }
161
+ else {
162
+ parts.push({ type: 'file', mimeType, data, name });
163
+ }
164
+ await this.forwardToAgent(chatId, parts, ctx);
165
+ }
166
+ catch (err) {
167
+ const errorMsg = err instanceof Error ? err.message : String(err);
168
+ await ctx.reply(`⚠️ Error: ${errorMsg}`);
169
+ }
170
+ });
171
+ // Handle voice messages
172
+ this.bot.on('message:voice', async (ctx) => {
173
+ const chatId = ctx.chat.id;
174
+ if (!this.isAllowed(chatId))
175
+ return;
176
+ try {
177
+ await ctx.api.sendChatAction(chatId, 'typing');
178
+ const voice = ctx.message.voice;
179
+ const { data } = await this.downloadFile(voice.file_id);
180
+ const parts = [];
181
+ if (ctx.message.caption) {
182
+ parts.push({ type: 'text', text: ctx.message.caption });
183
+ }
184
+ parts.push({ type: 'audio', mimeType: voice.mime_type ?? 'audio/ogg', data });
185
+ await this.forwardToAgent(chatId, parts, ctx);
186
+ }
187
+ catch (err) {
188
+ const errorMsg = err instanceof Error ? err.message : String(err);
189
+ await ctx.reply(`⚠️ Error: ${errorMsg}`);
190
+ }
191
+ });
192
+ // Handle audio messages
193
+ this.bot.on('message:audio', async (ctx) => {
194
+ const chatId = ctx.chat.id;
195
+ if (!this.isAllowed(chatId))
196
+ return;
197
+ try {
198
+ await ctx.api.sendChatAction(chatId, 'typing');
199
+ const audio = ctx.message.audio;
200
+ const { data } = await this.downloadFile(audio.file_id);
201
+ const parts = [];
202
+ if (ctx.message.caption) {
203
+ parts.push({ type: 'text', text: ctx.message.caption });
204
+ }
205
+ parts.push({ type: 'audio', mimeType: audio.mime_type ?? 'audio/mpeg', data });
206
+ await this.forwardToAgent(chatId, parts, ctx);
207
+ }
208
+ catch (err) {
209
+ const errorMsg = err instanceof Error ? err.message : String(err);
210
+ await ctx.reply(`⚠️ Error: ${errorMsg}`);
211
+ }
212
+ });
213
+ // Handle video messages
214
+ this.bot.on('message:video', async (ctx) => {
215
+ const chatId = ctx.chat.id;
216
+ if (!this.isAllowed(chatId))
217
+ return;
218
+ try {
219
+ await ctx.api.sendChatAction(chatId, 'upload_video');
220
+ const video = ctx.message.video;
221
+ const { data } = await this.downloadFile(video.file_id);
222
+ const mimeType = video.mime_type ?? 'video/mp4';
223
+ const parts = [];
224
+ if (ctx.message.caption) {
225
+ parts.push({ type: 'text', text: ctx.message.caption });
226
+ }
227
+ parts.push({ type: 'file', mimeType, data, name: `video.${mimeType.split('/')[1] ?? 'mp4'}` });
228
+ await this.forwardToAgent(chatId, parts, ctx);
229
+ }
230
+ catch (err) {
231
+ const errorMsg = err instanceof Error ? err.message : String(err);
232
+ await ctx.reply(`⚠️ Error: ${errorMsg}`);
233
+ }
234
+ });
235
+ }
236
+ async start() {
237
+ // Start long-polling
238
+ void this.bot.start({
239
+ onStart: () => {
240
+ // Bot started
241
+ },
242
+ });
243
+ }
244
+ async stop() {
245
+ this.bot.stop();
246
+ this.chatSessions.clear();
247
+ }
248
+ /**
249
+ * Get all known chat IDs (from active sessions + allowedChatIds).
250
+ */
251
+ getActiveChatIds() {
252
+ const chatIds = new Set();
253
+ for (const chatId of this.chatSessions.keys()) {
254
+ chatIds.add(chatId);
255
+ }
256
+ if (this.config.allowedChatIds) {
257
+ for (const chatId of this.config.allowedChatIds) {
258
+ chatIds.add(chatId);
259
+ }
260
+ }
261
+ return Array.from(chatIds);
262
+ }
263
+ /**
264
+ * Send a proactive message to all known chat sessions.
265
+ * Falls back to allowedChatIds if no sessions have been started yet.
266
+ */
267
+ async sendMessage(text) {
268
+ const chatIds = this.getActiveChatIds();
269
+ const maxLen = 4096;
270
+ for (const chatId of chatIds) {
271
+ for (let i = 0; i < text.length; i += maxLen) {
272
+ const chunk = text.slice(i, i + maxLen);
273
+ try {
274
+ await this.bot.api.sendMessage(chatId, chunk, {
275
+ parse_mode: 'Markdown',
276
+ });
277
+ }
278
+ catch {
279
+ // Markdown parse failed — retry without formatting
280
+ await this.bot.api.sendMessage(chatId, chunk);
281
+ }
282
+ }
283
+ }
284
+ }
285
+ /**
286
+ * Send media to all known chat sessions.
287
+ */
288
+ async sendMedia(media) {
289
+ const chatIds = this.getActiveChatIds();
290
+ const buf = Buffer.from(media.data, 'base64');
291
+ for (const chatId of chatIds) {
292
+ switch (media.type) {
293
+ case 'photo':
294
+ await this.bot.api.sendPhoto(chatId, new InputFile(buf, media.name ?? 'photo.jpg'), {
295
+ caption: media.caption,
296
+ });
297
+ break;
298
+ case 'document':
299
+ await this.bot.api.sendDocument(chatId, new InputFile(buf, media.name ?? 'document'), {
300
+ caption: media.caption,
301
+ });
302
+ break;
303
+ case 'voice':
304
+ await this.bot.api.sendVoice(chatId, new InputFile(buf, media.name ?? 'voice.ogg'), {
305
+ caption: media.caption,
306
+ });
307
+ break;
308
+ case 'audio':
309
+ await this.bot.api.sendAudio(chatId, new InputFile(buf, media.name ?? 'audio.mp3'), {
310
+ caption: media.caption,
311
+ });
312
+ break;
313
+ }
314
+ }
315
+ }
316
+ }
317
+ //# sourceMappingURL=telegram.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telegram.js","sourceRoot":"","sources":["../../src/adapters/telegram.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import { type Channel, type ChannelConfig } from '../channel.js';
2
+ export interface WebhookChannelConfig extends ChannelConfig {
3
+ /** Port to listen on for incoming webhooks */
4
+ port: number;
5
+ /** Host to bind to */
6
+ host?: string;
7
+ /** Optional secret to validate incoming webhook requests */
8
+ webhookSecret?: string;
9
+ /** Path for the webhook endpoint */
10
+ path?: string;
11
+ }
12
+ /**
13
+ * Webhook channel adapter.
14
+ *
15
+ * Exposes an HTTP endpoint that receives messages via POST requests and forwards
16
+ * them to the agent. Useful for custom integrations, n8n, Zapier, etc.
17
+ *
18
+ * Request body: { "message": "...", "threadId"?: "...", "sessionId"?: "...", "metadata"?: {...} }
19
+ * Response body: { "response": "...", "toolCalls": [...], "sessionId": "..." }
20
+ */
21
+ export declare class WebhookChannel implements Channel {
22
+ readonly type = "webhook";
23
+ private server;
24
+ private config;
25
+ /** Map thread IDs → session IDs */
26
+ private threadSessions;
27
+ constructor(config: WebhookChannelConfig);
28
+ start(): Promise<void>;
29
+ stop(): Promise<void>;
30
+ }
31
+ //# sourceMappingURL=webhook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../../src/adapters/webhook.ts"],"names":[],"mappings":"AAEA,OAAO,EAAwB,KAAK,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AAEvF,MAAM,WAAW,oBAAqB,SAAQ,aAAa;IACzD,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAC;IAEb,sBAAsB;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,4DAA4D;IAC5D,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,oCAAoC;IACpC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;GAQG;AACH,qBAAa,cAAe,YAAW,OAAO;IAC5C,QAAQ,CAAC,IAAI,aAAa;IAE1B,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,MAAM,CAAuB;IAErC,mCAAmC;IACnC,OAAO,CAAC,cAAc,CAA6B;gBAEvC,MAAM,EAAE,oBAAoB;IAIlC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAmFtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAS5B"}
@@ -0,0 +1,115 @@
1
+ import { createServer } from 'node:http';
2
+ import { randomUUID } from 'node:crypto';
3
+ import { collectAgentResponse } from '../channel.js';
4
+ /**
5
+ * Webhook channel adapter.
6
+ *
7
+ * Exposes an HTTP endpoint that receives messages via POST requests and forwards
8
+ * them to the agent. Useful for custom integrations, n8n, Zapier, etc.
9
+ *
10
+ * Request body: { "message": "...", "threadId"?: "...", "sessionId"?: "...", "metadata"?: {...} }
11
+ * Response body: { "response": "...", "toolCalls": [...], "sessionId": "..." }
12
+ */
13
+ export class WebhookChannel {
14
+ type = 'webhook';
15
+ server = null;
16
+ config;
17
+ /** Map thread IDs → session IDs */
18
+ threadSessions = new Map();
19
+ constructor(config) {
20
+ this.config = config;
21
+ }
22
+ async start() {
23
+ const webhookPath = this.config.path ?? '/webhook';
24
+ this.server = createServer(async (req, res) => {
25
+ // Only accept POST to the webhook path
26
+ if (req.method !== 'POST' || req.url !== webhookPath) {
27
+ res.writeHead(404, { 'Content-Type': 'application/json' });
28
+ res.end(JSON.stringify({ error: 'Not found' }));
29
+ return;
30
+ }
31
+ // Validate webhook secret
32
+ if (this.config.webhookSecret) {
33
+ const providedSecret = req.headers['x-webhook-secret'];
34
+ if (providedSecret !== this.config.webhookSecret) {
35
+ res.writeHead(401, { 'Content-Type': 'application/json' });
36
+ res.end(JSON.stringify({ error: 'Unauthorized' }));
37
+ return;
38
+ }
39
+ }
40
+ try {
41
+ const body = await readBody(req);
42
+ const parsed = JSON.parse(body);
43
+ if (!parsed.message) {
44
+ res.writeHead(400, { 'Content-Type': 'application/json' });
45
+ res.end(JSON.stringify({ error: 'Missing "message" field' }));
46
+ return;
47
+ }
48
+ const threadId = parsed.threadId ?? randomUUID();
49
+ // Get or create session
50
+ let sessionId = parsed.sessionId;
51
+ if (!sessionId) {
52
+ sessionId = this.threadSessions.get(threadId);
53
+ if (!sessionId) {
54
+ sessionId = randomUUID();
55
+ this.threadSessions.set(threadId, sessionId);
56
+ }
57
+ }
58
+ const result = await collectAgentResponse(this.config.agentUrl, {
59
+ threadId,
60
+ runId: randomUUID(),
61
+ message: parsed.message,
62
+ sessionId,
63
+ }, {
64
+ sharedSecret: this.config.sharedSecret,
65
+ agentId: 'webhook-channel',
66
+ });
67
+ res.writeHead(200, { 'Content-Type': 'application/json' });
68
+ res.end(JSON.stringify({
69
+ response: result.text,
70
+ toolCalls: result.toolCalls,
71
+ threadId,
72
+ sessionId,
73
+ }));
74
+ }
75
+ catch (err) {
76
+ res.writeHead(500, { 'Content-Type': 'application/json' });
77
+ res.end(JSON.stringify({
78
+ error: err instanceof Error ? err.message : String(err),
79
+ }));
80
+ }
81
+ });
82
+ const host = this.config.host ?? '0.0.0.0';
83
+ await new Promise((resolve) => {
84
+ this.server.listen(this.config.port, host, () => resolve());
85
+ });
86
+ }
87
+ async stop() {
88
+ if (this.server) {
89
+ await new Promise((resolve, reject) => {
90
+ this.server.close((err) => (err ? reject(err) : resolve()));
91
+ });
92
+ this.server = null;
93
+ }
94
+ this.threadSessions.clear();
95
+ }
96
+ }
97
+ function readBody(req) {
98
+ return new Promise((resolve, reject) => {
99
+ const chunks = [];
100
+ let size = 0;
101
+ const maxSize = 1024 * 1024; // 1MB limit
102
+ req.on('data', (chunk) => {
103
+ size += chunk.length;
104
+ if (size > maxSize) {
105
+ req.destroy();
106
+ reject(new Error('Request body too large'));
107
+ return;
108
+ }
109
+ chunks.push(chunk);
110
+ });
111
+ req.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
112
+ req.on('error', reject);
113
+ });
114
+ }
115
+ //# sourceMappingURL=webhook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../src/adapters/webhook.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ import type { MessageContent } from '@mce-bt/microagents-core';
2
+ /**
3
+ * Media payload for sending media to a channel.
4
+ */
5
+ export interface MediaPayload {
6
+ type: 'photo' | 'document' | 'voice' | 'audio';
7
+ /** Base64-encoded data or URL */
8
+ data: string;
9
+ mimeType: string;
10
+ /** Filename (for documents) */
11
+ name?: string;
12
+ /** Caption text */
13
+ caption?: string;
14
+ }
15
+ /**
16
+ * Abstract channel interface.
17
+ *
18
+ * A channel bridges an external messaging platform to an agent's AG-UI endpoint.
19
+ * It receives messages from the platform, forwards them to the agent, and streams
20
+ * the agent's response back to the platform.
21
+ */
22
+ export interface Channel {
23
+ /** Unique channel type name (e.g., 'slack', 'telegram', 'webhook') */
24
+ readonly type: string;
25
+ /** Start the channel — connect to the platform and begin listening */
26
+ start(): Promise<void>;
27
+ /** Stop the channel gracefully */
28
+ stop(): Promise<void>;
29
+ /** Send a proactive message to all active chats (optional) */
30
+ sendMessage?(text: string): Promise<void>;
31
+ /** Send media to all active chats (optional) */
32
+ sendMedia?(media: MediaPayload): Promise<void>;
33
+ }
34
+ /**
35
+ * Configuration shared across all channel adapters.
36
+ */
37
+ export interface ChannelConfig {
38
+ /** The agent's HTTP base URL (e.g., http://localhost:3000) */
39
+ agentUrl: string;
40
+ /** Shared secret for agent authentication */
41
+ sharedSecret?: string;
42
+ }
43
+ /**
44
+ * Helper: call the agent's AG-UI endpoint and collect the full text response.
45
+ *
46
+ * Channels typically don't stream to the user (most platforms don't support SSE),
47
+ * so this helper collects the full response text from the AG-UI event stream.
48
+ */
49
+ export declare function collectAgentResponse(agentUrl: string, input: {
50
+ threadId: string;
51
+ runId: string;
52
+ message: MessageContent;
53
+ sessionId?: string;
54
+ }, options?: {
55
+ sharedSecret?: string;
56
+ agentId?: string;
57
+ headers?: Record<string, string>;
58
+ }): Promise<{
59
+ text: string;
60
+ toolCalls: string[];
61
+ }>;
62
+ //# sourceMappingURL=channel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,cAAc,EAAe,MAAM,0BAA0B,CAAC;AAGvF;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,OAAO,GAAG,UAAU,GAAG,OAAO,GAAG,OAAO,CAAC;IAC/C,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,+BAA+B;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mBAAmB;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,OAAO;IACtB,sEAAsE;IACtE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,sEAAsE;IACtE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvB,kCAAkC;IAClC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtB,8DAA8D;IAC9D,WAAW,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1C,gDAAgD;IAChD,SAAS,CAAC,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChD;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,8DAA8D;IAC9D,QAAQ,EAAE,MAAM,CAAC;IAEjB,6CAA6C;IAC7C,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE;IACL,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,cAAc,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,EACD,OAAO,CAAC,EAAE;IACR,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC,GACA,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CA2EhD"}
@@ -0,0 +1,79 @@
1
+ import { createHmac } from 'node:crypto';
2
+ /**
3
+ * Helper: call the agent's AG-UI endpoint and collect the full text response.
4
+ *
5
+ * Channels typically don't stream to the user (most platforms don't support SSE),
6
+ * so this helper collects the full response text from the AG-UI event stream.
7
+ */
8
+ export async function collectAgentResponse(agentUrl, input, options) {
9
+ const url = `${agentUrl}/ag-ui/runs`;
10
+ const body = JSON.stringify(input);
11
+ const headers = {
12
+ 'Content-Type': 'application/json',
13
+ ...options?.headers,
14
+ };
15
+ if (options?.sharedSecret) {
16
+ const timestamp = Date.now().toString();
17
+ const signature = createHmac('sha256', options.sharedSecret)
18
+ .update(`${timestamp}.${body}`)
19
+ .digest('hex');
20
+ headers['X-Agent-Id'] = options.agentId ?? 'channel-client';
21
+ headers['X-Timestamp'] = timestamp;
22
+ headers['X-Signature'] = signature;
23
+ }
24
+ const response = await fetch(url, {
25
+ method: 'POST',
26
+ headers,
27
+ body,
28
+ });
29
+ if (!response.ok) {
30
+ throw new Error(`Agent request failed: HTTP ${response.status}`);
31
+ }
32
+ if (!response.body) {
33
+ throw new Error('No response body');
34
+ }
35
+ let text = '';
36
+ const toolCalls = [];
37
+ const reader = response.body.getReader();
38
+ const decoder = new TextDecoder();
39
+ let buffer = '';
40
+ try {
41
+ for (;;) {
42
+ const { done, value } = await reader.read();
43
+ if (done)
44
+ break;
45
+ buffer += decoder.decode(value, { stream: true });
46
+ const lines = buffer.split('\n');
47
+ buffer = lines.pop() ?? '';
48
+ for (const line of lines) {
49
+ const trimmed = line.trim();
50
+ if (!trimmed || !trimmed.startsWith('data: '))
51
+ continue;
52
+ try {
53
+ const event = JSON.parse(trimmed.slice(6));
54
+ if (event.type === 'TEXT_MESSAGE_CONTENT') {
55
+ text += event.delta;
56
+ }
57
+ else if (event.type === 'TOOL_CALL_START') {
58
+ toolCalls.push(event.toolCallName);
59
+ }
60
+ else if (event.type === 'RUN_ERROR') {
61
+ const errorMsg = event.message ?? 'Unknown agent error';
62
+ throw new Error(`Agent error: ${errorMsg}`);
63
+ }
64
+ }
65
+ catch (parseErr) {
66
+ // Re-throw agent errors, skip parse errors
67
+ if (parseErr instanceof Error && parseErr.message.startsWith('Agent error:')) {
68
+ throw parseErr;
69
+ }
70
+ }
71
+ }
72
+ }
73
+ }
74
+ finally {
75
+ reader.releaseLock();
76
+ }
77
+ return { text, toolCalls };
78
+ }
79
+ //# sourceMappingURL=channel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel.js","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { type Channel, type ChannelConfig, type MediaPayload, collectAgentResponse, } from './channel.js';
2
+ export { SlackChannel, type SlackChannelConfig, } from './adapters/slack.js';
3
+ export { TelegramChannel, type TelegramChannelConfig, } from './adapters/telegram.js';
4
+ export { WebhookChannel, type WebhookChannelConfig, } from './adapters/webhook.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,oBAAoB,GACrB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,YAAY,EACZ,KAAK,kBAAkB,GACxB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,eAAe,EACf,KAAK,qBAAqB,GAC3B,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,cAAc,EACd,KAAK,oBAAoB,GAC1B,MAAM,uBAAuB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export { collectAgentResponse, } from './channel.js';
2
+ export { SlackChannel, } from './adapters/slack.js';
3
+ export { TelegramChannel, } from './adapters/telegram.js';
4
+ export { WebhookChannel, } from './adapters/webhook.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,oBAAoB,GACrB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,YAAY,GAEb,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,eAAe,GAEhB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,cAAc,GAEf,MAAM,uBAAuB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@mce-bt/microagents-channels",
3
+ "version": "0.1.0",
4
+ "description": "Channel integrations — Slack, Telegram, Webhook",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "scripts": {
9
+ "build": "tsc --build",
10
+ "clean": "rm -rf dist tsconfig.tsbuildinfo",
11
+ "test": "vitest run --passWithNoTests"
12
+ },
13
+ "dependencies": {
14
+ "@mce-bt/microagents-core": "^0.1.0",
15
+ "@slack/bolt": "^4.3.0",
16
+ "grammy": "^1.35.0"
17
+ },
18
+ "license": "MIT",
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "git+https://github.com/cavillo/microagents.git",
28
+ "directory": "packages/channels"
29
+ },
30
+ "homepage": "https://github.com/cavillo/microagents#readme",
31
+ "bugs": {
32
+ "url": "https://github.com/cavillo/microagents/issues"
33
+ },
34
+ "engines": {
35
+ "node": ">=20.0.0"
36
+ },
37
+ "exports": {
38
+ ".": {
39
+ "types": "./dist/index.d.ts",
40
+ "import": "./dist/index.js"
41
+ }
42
+ }
43
+ }