@cereworker/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.
Files changed (41) hide show
  1. package/dist/adapters/discord.d.ts +8 -0
  2. package/dist/adapters/discord.d.ts.map +1 -0
  3. package/dist/adapters/discord.js +99 -0
  4. package/dist/adapters/discord.js.map +1 -0
  5. package/dist/adapters/feishu.d.ts +10 -0
  6. package/dist/adapters/feishu.d.ts.map +1 -0
  7. package/dist/adapters/feishu.js +103 -0
  8. package/dist/adapters/feishu.js.map +1 -0
  9. package/dist/adapters/matrix.d.ts +9 -0
  10. package/dist/adapters/matrix.d.ts.map +1 -0
  11. package/dist/adapters/matrix.js +61 -0
  12. package/dist/adapters/matrix.js.map +1 -0
  13. package/dist/adapters/slack.d.ts +9 -0
  14. package/dist/adapters/slack.d.ts.map +1 -0
  15. package/dist/adapters/slack.js +63 -0
  16. package/dist/adapters/slack.js.map +1 -0
  17. package/dist/adapters/telegram.d.ts +7 -0
  18. package/dist/adapters/telegram.d.ts.map +1 -0
  19. package/dist/adapters/telegram.js +88 -0
  20. package/dist/adapters/telegram.js.map +1 -0
  21. package/dist/adapters/wechat.d.ts +8 -0
  22. package/dist/adapters/wechat.d.ts.map +1 -0
  23. package/dist/adapters/wechat.js +119 -0
  24. package/dist/adapters/wechat.js.map +1 -0
  25. package/dist/factory.d.ts +4 -0
  26. package/dist/factory.d.ts.map +1 -0
  27. package/dist/factory.js +58 -0
  28. package/dist/factory.js.map +1 -0
  29. package/dist/index.d.ts +10 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +9 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/manager.d.ts +24 -0
  34. package/dist/manager.d.ts.map +1 -0
  35. package/dist/manager.js +74 -0
  36. package/dist/manager.js.map +1 -0
  37. package/dist/types.d.ts +42 -0
  38. package/dist/types.d.ts.map +1 -0
  39. package/dist/types.js +2 -0
  40. package/dist/types.js.map +1 -0
  41. package/package.json +37 -0
@@ -0,0 +1,8 @@
1
+ import type { ChannelPlugin } from '../types.js';
2
+ export interface DiscordChannelConfig {
3
+ token: string;
4
+ applicationId?: string;
5
+ allowFrom: string[];
6
+ }
7
+ export declare function createDiscordChannel(config: DiscordChannelConfig): ChannelPlugin;
8
+ //# sourceMappingURL=discord.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discord.d.ts","sourceRoot":"","sources":["../../src/adapters/discord.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAmD,MAAM,aAAa,CAAC;AAElG,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,oBAAoB,GAAG,aAAa,CAqFhF"}
@@ -0,0 +1,99 @@
1
+ import { Client, GatewayIntentBits, Events } from 'discord.js';
2
+ export function createDiscordChannel(config) {
3
+ let client = null;
4
+ let connected = false;
5
+ return {
6
+ id: 'discord',
7
+ meta: { name: 'Discord', emoji: 'D' },
8
+ async start(handler) {
9
+ client = new Client({
10
+ intents: [
11
+ GatewayIntentBits.Guilds,
12
+ GatewayIntentBits.GuildMessages,
13
+ GatewayIntentBits.MessageContent,
14
+ GatewayIntentBits.DirectMessages,
15
+ ],
16
+ });
17
+ client.on(Events.MessageCreate, async (message) => {
18
+ // Ignore bot's own messages
19
+ if (message.author.bot)
20
+ return;
21
+ // Only respond when mentioned or in DMs
22
+ const isDM = !message.guild;
23
+ const isMentioned = client?.user && message.mentions.has(client.user);
24
+ if (!isDM && !isMentioned)
25
+ return;
26
+ // Strip mention from text
27
+ let text = message.content;
28
+ if (client?.user) {
29
+ text = text.replace(new RegExp(`<@!?${client.user.id}>`, 'g'), '').trim();
30
+ }
31
+ if (!text)
32
+ return;
33
+ const inbound = {
34
+ channelId: 'discord',
35
+ senderId: message.author.id,
36
+ senderName: message.author.username,
37
+ text,
38
+ threadId: message.channel.isThread() ? message.channel.id : undefined,
39
+ timestamp: message.createdTimestamp,
40
+ };
41
+ const response = await handler(inbound);
42
+ if (response) {
43
+ // Discord has a 2000 char limit per message
44
+ const chunks = chunkText(response, 2000);
45
+ for (const chunk of chunks) {
46
+ await message.reply(chunk);
47
+ }
48
+ }
49
+ });
50
+ await client.login(config.token);
51
+ connected = true;
52
+ },
53
+ async stop() {
54
+ if (client) {
55
+ await client.destroy();
56
+ connected = false;
57
+ }
58
+ },
59
+ async send(msg) {
60
+ if (!client)
61
+ throw new Error('Discord not started');
62
+ const channel = await client.channels.fetch(msg.to);
63
+ if (channel && 'send' in channel) {
64
+ const chunks = chunkText(msg.text, 2000);
65
+ for (const chunk of chunks) {
66
+ await channel.send(chunk);
67
+ }
68
+ }
69
+ },
70
+ isAllowed(senderId) {
71
+ if (config.allowFrom.length === 0)
72
+ return true;
73
+ return config.allowFrom.includes(senderId);
74
+ },
75
+ isConnected() {
76
+ return connected;
77
+ },
78
+ };
79
+ }
80
+ function chunkText(text, limit) {
81
+ if (text.length <= limit)
82
+ return [text];
83
+ const chunks = [];
84
+ let remaining = text;
85
+ while (remaining.length > 0) {
86
+ if (remaining.length <= limit) {
87
+ chunks.push(remaining);
88
+ break;
89
+ }
90
+ // Try to break at a newline
91
+ let breakAt = remaining.lastIndexOf('\n', limit);
92
+ if (breakAt <= 0)
93
+ breakAt = limit;
94
+ chunks.push(remaining.slice(0, breakAt));
95
+ remaining = remaining.slice(breakAt).trimStart();
96
+ }
97
+ return chunks;
98
+ }
99
+ //# sourceMappingURL=discord.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discord.js","sourceRoot":"","sources":["../../src/adapters/discord.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { ChannelPlugin } from '../types.js';
2
+ export interface FeishuChannelConfig {
3
+ appId: string;
4
+ appSecret: string;
5
+ verificationToken?: string;
6
+ encryptKey?: string;
7
+ allowFrom: string[];
8
+ }
9
+ export declare function createFeishuChannel(config: FeishuChannelConfig): ChannelPlugin;
10
+ //# sourceMappingURL=feishu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feishu.d.ts","sourceRoot":"","sources":["../../src/adapters/feishu.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAmD,MAAM,aAAa,CAAC;AAElG,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,aAAa,CA+G9E"}
@@ -0,0 +1,103 @@
1
+ import * as lark from '@larksuiteoapi/node-sdk';
2
+ export function createFeishuChannel(config) {
3
+ let client = null;
4
+ let eventDispatcher = null;
5
+ let wsClient = null;
6
+ let connected = false;
7
+ let messageHandler = null;
8
+ return {
9
+ id: 'feishu',
10
+ meta: { name: 'Feishu', emoji: 'F' },
11
+ async start(handler) {
12
+ messageHandler = handler;
13
+ client = new lark.Client({
14
+ appId: config.appId,
15
+ appSecret: config.appSecret,
16
+ appType: lark.AppType.SelfBuild,
17
+ });
18
+ eventDispatcher = new lark.EventDispatcher({
19
+ verificationToken: config.verificationToken,
20
+ encryptKey: config.encryptKey,
21
+ });
22
+ // Listen for messages
23
+ eventDispatcher.register({
24
+ 'im.message.receive_v1': async (data) => {
25
+ if (!messageHandler)
26
+ return;
27
+ const message = data.message;
28
+ if (!message)
29
+ return;
30
+ const msgType = message.message_type;
31
+ if (msgType !== 'text')
32
+ return;
33
+ let text = '';
34
+ try {
35
+ const content = JSON.parse(message.content);
36
+ text = content.text ?? '';
37
+ }
38
+ catch {
39
+ return;
40
+ }
41
+ if (!text)
42
+ return;
43
+ const sender = data.sender;
44
+ const senderId = sender?.sender_id?.open_id ?? '';
45
+ const inbound = {
46
+ channelId: 'feishu',
47
+ senderId,
48
+ text,
49
+ threadId: message.root_id,
50
+ timestamp: Number(message.create_time ?? Date.now()),
51
+ };
52
+ const response = await messageHandler(inbound);
53
+ if (response && client) {
54
+ const chatId = message.chat_id;
55
+ await client.im.message.create({
56
+ params: { receive_id_type: 'chat_id' },
57
+ data: {
58
+ receive_id: chatId,
59
+ msg_type: 'text',
60
+ content: JSON.stringify({ text: response }),
61
+ },
62
+ });
63
+ }
64
+ },
65
+ });
66
+ // Use WebSocket client for real-time events
67
+ wsClient = new lark.WSClient({
68
+ appId: config.appId,
69
+ appSecret: config.appSecret,
70
+ loggerLevel: lark.LoggerLevel.warn,
71
+ });
72
+ await wsClient.start({ eventDispatcher });
73
+ connected = true;
74
+ },
75
+ async stop() {
76
+ connected = false;
77
+ wsClient = null;
78
+ eventDispatcher = null;
79
+ client = null;
80
+ },
81
+ async send(msg) {
82
+ if (!client)
83
+ throw new Error('Feishu not started');
84
+ await client.im.message.create({
85
+ params: { receive_id_type: 'chat_id' },
86
+ data: {
87
+ receive_id: msg.to,
88
+ msg_type: 'text',
89
+ content: JSON.stringify({ text: msg.text }),
90
+ },
91
+ });
92
+ },
93
+ isAllowed(senderId) {
94
+ if (config.allowFrom.length === 0)
95
+ return true;
96
+ return config.allowFrom.includes(senderId);
97
+ },
98
+ isConnected() {
99
+ return connected;
100
+ },
101
+ };
102
+ }
103
+ //# sourceMappingURL=feishu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feishu.js","sourceRoot":"","sources":["../../src/adapters/feishu.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { ChannelPlugin } from '../types.js';
2
+ export interface MatrixChannelConfig {
3
+ homeserver: string;
4
+ token: string;
5
+ userId: string;
6
+ allowFrom: string[];
7
+ }
8
+ export declare function createMatrixChannel(config: MatrixChannelConfig): ChannelPlugin;
9
+ //# sourceMappingURL=matrix.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matrix.d.ts","sourceRoot":"","sources":["../../src/adapters/matrix.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAmD,MAAM,aAAa,CAAC;AAElG,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,aAAa,CA+D9E"}
@@ -0,0 +1,61 @@
1
+ import sdk from 'matrix-js-sdk';
2
+ export function createMatrixChannel(config) {
3
+ let client = null;
4
+ let connected = false;
5
+ return {
6
+ id: 'matrix',
7
+ meta: { name: 'Matrix', emoji: 'M' },
8
+ async start(handler) {
9
+ client = sdk.createClient({
10
+ baseUrl: config.homeserver,
11
+ accessToken: config.token,
12
+ userId: config.userId,
13
+ });
14
+ client.on(sdk.RoomEvent.Timeline, async (event, room) => {
15
+ if (!room)
16
+ return;
17
+ if (event.getType() !== 'm.room.message')
18
+ return;
19
+ if (event.getSender() === config.userId)
20
+ return; // ignore own messages
21
+ const content = event.getContent();
22
+ if (content.msgtype !== 'm.text')
23
+ return;
24
+ const senderId = event.getSender() ?? '';
25
+ const inbound = {
26
+ channelId: 'matrix',
27
+ senderId,
28
+ text: content.body ?? '',
29
+ threadId: room.roomId,
30
+ timestamp: event.getTs(),
31
+ };
32
+ const response = await handler(inbound);
33
+ if (response) {
34
+ await client.sendTextMessage(room.roomId, response);
35
+ }
36
+ });
37
+ await client.startClient({ initialSyncLimit: 0 });
38
+ connected = true;
39
+ },
40
+ async stop() {
41
+ if (client) {
42
+ client.stopClient();
43
+ connected = false;
44
+ }
45
+ },
46
+ async send(msg) {
47
+ if (!client)
48
+ throw new Error('Matrix not started');
49
+ await client.sendTextMessage(msg.to, msg.text);
50
+ },
51
+ isAllowed(senderId) {
52
+ if (config.allowFrom.length === 0)
53
+ return true;
54
+ return config.allowFrom.includes(senderId);
55
+ },
56
+ isConnected() {
57
+ return connected;
58
+ },
59
+ };
60
+ }
61
+ //# sourceMappingURL=matrix.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matrix.js","sourceRoot":"","sources":["../../src/adapters/matrix.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,eAAe,CAAC;AAUhC,MAAM,UAAU,mBAAmB,CAAC,MAA2B;IAC7D,IAAI,MAAM,GAA4B,IAAI,CAAC;IAC3C,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,OAAO;QACL,EAAE,EAAE,QAAQ;QACZ,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;QAEpC,KAAK,CAAC,KAAK,CAAC,OAAuB;YACjC,MAAM,GAAG,GAAG,CAAC,YAAY,CAAC;gBACxB,OAAO,EAAE,MAAM,CAAC,UAAU;gBAC1B,WAAW,EAAE,MAAM,CAAC,KAAK;gBACzB,MAAM,EAAE,MAAM,CAAC,MAAM;aACtB,CAAC,CAAC;YAEH,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBACtD,IAAI,CAAC,IAAI;oBAAE,OAAO;gBAClB,IAAI,KAAK,CAAC,OAAO,EAAE,KAAK,gBAAgB;oBAAE,OAAO;gBACjD,IAAI,KAAK,CAAC,SAAS,EAAE,KAAK,MAAM,CAAC,MAAM;oBAAE,OAAO,CAAC,sBAAsB;gBAEvE,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,EAAE,CAAC;gBACnC,IAAI,OAAO,CAAC,OAAO,KAAK,QAAQ;oBAAE,OAAO;gBAEzC,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC;gBACzC,MAAM,OAAO,GAAmB;oBAC9B,SAAS,EAAE,QAAQ;oBACnB,QAAQ;oBACR,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,EAAE;oBACxB,QAAQ,EAAE,IAAI,CAAC,MAAM;oBACrB,SAAS,EAAE,KAAK,CAAC,KAAK,EAAE;iBACzB,CAAC;gBAEF,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;gBACxC,IAAI,QAAQ,EAAE,CAAC;oBACb,MAAM,MAAO,CAAC,eAAe,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;gBACvD,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,MAAM,MAAM,CAAC,WAAW,CAAC,EAAE,gBAAgB,EAAE,CAAC,EAAE,CAAC,CAAC;YAClD,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC;QAED,KAAK,CAAC,IAAI;YACR,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,CAAC,UAAU,EAAE,CAAC;gBACpB,SAAS,GAAG,KAAK,CAAC;YACpB,CAAC;QACH,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,GAAoB;YAC7B,IAAI,CAAC,MAAM;gBAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;YACnD,MAAM,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QACjD,CAAC;QAED,SAAS,CAAC,QAAgB;YACxB,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAC;YAC/C,OAAO,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC7C,CAAC;QAED,WAAW;YACT,OAAO,SAAS,CAAC;QACnB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { ChannelPlugin } from '../types.js';
2
+ export interface SlackChannelConfig {
3
+ botToken: string;
4
+ appToken: string;
5
+ signingSecret?: string;
6
+ allowFrom: string[];
7
+ }
8
+ export declare function createSlackChannel(config: SlackChannelConfig): ChannelPlugin;
9
+ //# sourceMappingURL=slack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slack.d.ts","sourceRoot":"","sources":["../../src/adapters/slack.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAmD,MAAM,aAAa,CAAC;AAElG,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,GAAG,aAAa,CAkE5E"}
@@ -0,0 +1,63 @@
1
+ import { App as SlackApp } from '@slack/bolt';
2
+ export function createSlackChannel(config) {
3
+ let app = null;
4
+ let connected = false;
5
+ return {
6
+ id: 'slack',
7
+ meta: { name: 'Slack', emoji: '#' },
8
+ async start(handler) {
9
+ app = new SlackApp({
10
+ token: config.botToken,
11
+ appToken: config.appToken,
12
+ socketMode: true,
13
+ ...(config.signingSecret ? { signingSecret: config.signingSecret } : {}),
14
+ });
15
+ app.message(async ({ message, say }) => {
16
+ if (message.subtype)
17
+ return; // skip bot messages, edits, etc.
18
+ if (!('text' in message) || !message.text)
19
+ return;
20
+ const inbound = {
21
+ channelId: 'slack',
22
+ senderId: ('user' in message ? message.user : '') ?? '',
23
+ text: message.text,
24
+ threadId: ('thread_ts' in message ? message.thread_ts : undefined),
25
+ timestamp: parseFloat(message.ts) * 1000,
26
+ };
27
+ const response = await handler(inbound);
28
+ if (response) {
29
+ await say({
30
+ text: response,
31
+ thread_ts: inbound.threadId ?? message.ts,
32
+ });
33
+ }
34
+ });
35
+ await app.start();
36
+ connected = true;
37
+ },
38
+ async stop() {
39
+ if (app) {
40
+ await app.stop();
41
+ connected = false;
42
+ }
43
+ },
44
+ async send(msg) {
45
+ if (!app)
46
+ throw new Error('Slack not started');
47
+ await app.client.chat.postMessage({
48
+ channel: msg.to,
49
+ text: msg.text,
50
+ thread_ts: msg.threadId,
51
+ });
52
+ },
53
+ isAllowed(senderId) {
54
+ if (config.allowFrom.length === 0)
55
+ return true;
56
+ return config.allowFrom.includes(senderId);
57
+ },
58
+ isConnected() {
59
+ return connected;
60
+ },
61
+ };
62
+ }
63
+ //# sourceMappingURL=slack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slack.js","sourceRoot":"","sources":["../../src/adapters/slack.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,IAAI,QAAQ,EAAiC,MAAM,aAAa,CAAC;AAU7E,MAAM,UAAU,kBAAkB,CAAC,MAA0B;IAC3D,IAAI,GAAG,GAAoB,IAAI,CAAC;IAChC,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,OAAO;QACL,EAAE,EAAE,OAAO;QACX,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE;QAEnC,KAAK,CAAC,KAAK,CAAC,OAAuB;YACjC,GAAG,GAAG,IAAI,QAAQ,CAAC;gBACjB,KAAK,EAAE,MAAM,CAAC,QAAQ;gBACtB,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,UAAU,EAAE,IAAI;gBAChB,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACzE,CAAC,CAAC;YAEH,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,GAAG,EAA2D,EAAE,EAAE;gBAC9F,IAAI,OAAO,CAAC,OAAO;oBAAE,OAAO,CAAC,iCAAiC;gBAC9D,IAAI,CAAC,CAAC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI;oBAAE,OAAO;gBAElD,MAAM,OAAO,GAAmB;oBAC9B,SAAS,EAAE,OAAO;oBAClB,QAAQ,EAAE,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE;oBACvD,IAAI,EAAE,OAAO,CAAC,IAAI;oBAClB,QAAQ,EAAE,CAAC,WAAW,IAAI,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAuB;oBACxF,SAAS,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,IAAI;iBACzC,CAAC;gBAEF,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;gBACxC,IAAI,QAAQ,EAAE,CAAC;oBACb,MAAM,GAAG,CAAC;wBACR,IAAI,EAAE,QAAQ;wBACd,SAAS,EAAE,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,EAAE;qBAC1C,CAAC,CAAC;gBACL,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;YAClB,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC;QAED,KAAK,CAAC,IAAI;YACR,IAAI,GAAG,EAAE,CAAC;gBACR,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;gBACjB,SAAS,GAAG,KAAK,CAAC;YACpB,CAAC;QACH,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,GAAoB;YAC7B,IAAI,CAAC,GAAG;gBAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;YAC/C,MAAM,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC;gBAChC,OAAO,EAAE,GAAG,CAAC,EAAE;gBACf,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,SAAS,EAAE,GAAG,CAAC,QAAQ;aACxB,CAAC,CAAC;QACL,CAAC;QAED,SAAS,CAAC,QAAgB;YACxB,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAC;YAC/C,OAAO,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC7C,CAAC;QAED,WAAW;YACT,OAAO,SAAS,CAAC;QACnB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { ChannelPlugin } from '../types.js';
2
+ export interface TelegramChannelConfig {
3
+ token: string;
4
+ allowFrom: string[];
5
+ }
6
+ export declare function createTelegramChannel(config: TelegramChannelConfig): ChannelPlugin;
7
+ //# sourceMappingURL=telegram.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telegram.d.ts","sourceRoot":"","sources":["../../src/adapters/telegram.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAmD,MAAM,aAAa,CAAC;AAElG,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,qBAAqB,GAAG,aAAa,CA2ElF"}
@@ -0,0 +1,88 @@
1
+ import { Telegraf } from 'telegraf';
2
+ export function createTelegramChannel(config) {
3
+ let bot = null;
4
+ let connected = false;
5
+ return {
6
+ id: 'telegram',
7
+ meta: { name: 'Telegram', emoji: 'T' },
8
+ async start(handler) {
9
+ bot = new Telegraf(config.token);
10
+ bot.on('text', async (ctx) => {
11
+ const message = ctx.message;
12
+ if (!message || !('text' in message))
13
+ return;
14
+ const senderId = String(message.from?.id ?? '');
15
+ const inbound = {
16
+ channelId: 'telegram',
17
+ senderId,
18
+ senderName: message.from?.username ?? message.from?.first_name,
19
+ text: message.text,
20
+ threadId: message.message_thread_id ? String(message.message_thread_id) : undefined,
21
+ replyToId: message.reply_to_message ? String(message.reply_to_message.message_id) : undefined,
22
+ timestamp: message.date * 1000,
23
+ };
24
+ const response = await handler(inbound);
25
+ if (response) {
26
+ // Telegram has a 4096 char limit per message
27
+ const chunks = chunkText(response, 4096);
28
+ for (const chunk of chunks) {
29
+ await ctx.reply(chunk, {
30
+ reply_parameters: { message_id: message.message_id },
31
+ });
32
+ }
33
+ }
34
+ });
35
+ // Use polling (simpler than webhooks for dev)
36
+ await bot.launch();
37
+ connected = true;
38
+ // Graceful shutdown
39
+ process.once('SIGINT', () => bot?.stop('SIGINT'));
40
+ process.once('SIGTERM', () => bot?.stop('SIGTERM'));
41
+ },
42
+ async stop() {
43
+ if (bot) {
44
+ bot.stop();
45
+ connected = false;
46
+ }
47
+ },
48
+ async send(msg) {
49
+ if (!bot)
50
+ throw new Error('Telegram not started');
51
+ const chunks = chunkText(msg.text, 4096);
52
+ for (const chunk of chunks) {
53
+ await bot.telegram.sendMessage(msg.to, chunk, {
54
+ reply_parameters: msg.replyToId
55
+ ? { message_id: parseInt(msg.replyToId, 10) }
56
+ : undefined,
57
+ });
58
+ }
59
+ },
60
+ isAllowed(senderId) {
61
+ if (config.allowFrom.length === 0)
62
+ return true;
63
+ return config.allowFrom.includes(senderId);
64
+ },
65
+ isConnected() {
66
+ return connected;
67
+ },
68
+ };
69
+ }
70
+ function chunkText(text, limit) {
71
+ if (text.length <= limit)
72
+ return [text];
73
+ const chunks = [];
74
+ let remaining = text;
75
+ while (remaining.length > 0) {
76
+ if (remaining.length <= limit) {
77
+ chunks.push(remaining);
78
+ break;
79
+ }
80
+ let breakAt = remaining.lastIndexOf('\n', limit);
81
+ if (breakAt <= 0)
82
+ breakAt = limit;
83
+ chunks.push(remaining.slice(0, breakAt));
84
+ remaining = remaining.slice(breakAt).trimStart();
85
+ }
86
+ return chunks;
87
+ }
88
+ //# 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,8 @@
1
+ import type { ChannelPlugin } from '../types.js';
2
+ export interface WeChatChannelConfig {
3
+ puppet: string;
4
+ token?: string;
5
+ allowFrom: string[];
6
+ }
7
+ export declare function createWeChatChannel(config: WeChatChannelConfig): ChannelPlugin;
8
+ //# sourceMappingURL=wechat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wechat.d.ts","sourceRoot":"","sources":["../../src/adapters/wechat.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAmD,MAAM,aAAa,CAAC;AAElG,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,aAAa,CA+G9E"}
@@ -0,0 +1,119 @@
1
+ import { WechatyBuilder } from 'wechaty';
2
+ export function createWeChatChannel(config) {
3
+ let bot = null;
4
+ let connected = false;
5
+ return {
6
+ id: 'wechat',
7
+ meta: { name: 'WeChat', emoji: 'W' },
8
+ async start(handler) {
9
+ bot = WechatyBuilder.build({
10
+ name: 'cereworker',
11
+ puppet: config.puppet,
12
+ puppetOptions: config.token ? { token: config.token } : undefined,
13
+ });
14
+ bot.on('message', async (message) => {
15
+ // Skip self messages
16
+ if (message.self())
17
+ return;
18
+ // Only handle text messages
19
+ if (message.type() !== bot.Message.Type.Text)
20
+ return;
21
+ const text = message.text();
22
+ if (!text)
23
+ return;
24
+ const talker = message.talker();
25
+ const senderId = talker.id;
26
+ const room = message.room();
27
+ const inbound = {
28
+ channelId: 'wechat',
29
+ senderId,
30
+ senderName: talker.name(),
31
+ text,
32
+ threadId: room ? room.id : undefined,
33
+ timestamp: message.date().getTime(),
34
+ };
35
+ const response = await handler(inbound);
36
+ if (response) {
37
+ // Chunk long messages (WeChat has ~4096 char limit for text)
38
+ const chunks = chunkText(response, 4096);
39
+ for (const chunk of chunks) {
40
+ if (room) {
41
+ await room.say(chunk);
42
+ }
43
+ else {
44
+ await talker.say(chunk);
45
+ }
46
+ }
47
+ }
48
+ });
49
+ bot.on('login', (user) => {
50
+ console.log(`[WeChat] Logged in as ${user.name()}`);
51
+ connected = true;
52
+ });
53
+ bot.on('logout', () => {
54
+ console.log('[WeChat] Logged out');
55
+ connected = false;
56
+ });
57
+ bot.on('error', (error) => {
58
+ console.error('[WeChat] Error:', error);
59
+ });
60
+ await bot.start();
61
+ },
62
+ async stop() {
63
+ if (bot) {
64
+ await bot.stop();
65
+ connected = false;
66
+ bot = null;
67
+ }
68
+ },
69
+ async send(msg) {
70
+ if (!bot)
71
+ throw new Error('WeChat not started');
72
+ const contact = await bot.Contact.find({ id: msg.to });
73
+ if (contact) {
74
+ const chunks = chunkText(msg.text, 4096);
75
+ for (const chunk of chunks) {
76
+ await contact.say(chunk);
77
+ }
78
+ return;
79
+ }
80
+ // Try as room
81
+ const room = await bot.Room.find({ id: msg.to });
82
+ if (room) {
83
+ const chunks = chunkText(msg.text, 4096);
84
+ for (const chunk of chunks) {
85
+ await room.say(chunk);
86
+ }
87
+ return;
88
+ }
89
+ throw new Error(`WeChat contact/room not found: ${msg.to}`);
90
+ },
91
+ isAllowed(senderId) {
92
+ if (config.allowFrom.length === 0)
93
+ return true;
94
+ return config.allowFrom.includes(senderId);
95
+ },
96
+ isConnected() {
97
+ return connected;
98
+ },
99
+ };
100
+ }
101
+ function chunkText(text, limit) {
102
+ if (text.length <= limit)
103
+ return [text];
104
+ const chunks = [];
105
+ let remaining = text;
106
+ while (remaining.length > 0) {
107
+ if (remaining.length <= limit) {
108
+ chunks.push(remaining);
109
+ break;
110
+ }
111
+ let breakAt = remaining.lastIndexOf('\n', limit);
112
+ if (breakAt <= 0)
113
+ breakAt = limit;
114
+ chunks.push(remaining.slice(0, breakAt));
115
+ remaining = remaining.slice(breakAt).trimStart();
116
+ }
117
+ return chunks;
118
+ }
119
+ //# sourceMappingURL=wechat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wechat.js","sourceRoot":"","sources":["../../src/adapters/wechat.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { CereWorkerConfig } from '@cereworker/config';
2
+ import { ChannelManager } from './manager.js';
3
+ export declare function createChannelManager(config: CereWorkerConfig): ChannelManager;
4
+ //# sourceMappingURL=factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAQ9C,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,gBAAgB,GAAG,cAAc,CAqE7E"}
@@ -0,0 +1,58 @@
1
+ import { ChannelManager } from './manager.js';
2
+ import { createSlackChannel } from './adapters/slack.js';
3
+ import { createDiscordChannel } from './adapters/discord.js';
4
+ import { createTelegramChannel } from './adapters/telegram.js';
5
+ import { createMatrixChannel } from './adapters/matrix.js';
6
+ import { createFeishuChannel } from './adapters/feishu.js';
7
+ import { createWeChatChannel } from './adapters/wechat.js';
8
+ export function createChannelManager(config) {
9
+ const manager = new ChannelManager();
10
+ const { channels } = config;
11
+ if (channels.slack.enabled && channels.slack.botToken && channels.slack.appToken) {
12
+ manager.register(createSlackChannel({
13
+ botToken: channels.slack.botToken,
14
+ appToken: channels.slack.appToken,
15
+ signingSecret: channels.slack.signingSecret,
16
+ allowFrom: channels.slack.allowFrom,
17
+ }));
18
+ }
19
+ if (channels.discord.enabled && channels.discord.token) {
20
+ manager.register(createDiscordChannel({
21
+ token: channels.discord.token,
22
+ applicationId: channels.discord.applicationId,
23
+ allowFrom: channels.discord.allowFrom,
24
+ }));
25
+ }
26
+ if (channels.telegram.enabled && channels.telegram.token) {
27
+ manager.register(createTelegramChannel({
28
+ token: channels.telegram.token,
29
+ allowFrom: channels.telegram.allowFrom,
30
+ }));
31
+ }
32
+ if (channels.matrix.enabled && channels.matrix.token && channels.matrix.userId) {
33
+ manager.register(createMatrixChannel({
34
+ homeserver: channels.matrix.homeserver,
35
+ token: channels.matrix.token,
36
+ userId: channels.matrix.userId,
37
+ allowFrom: channels.matrix.allowFrom,
38
+ }));
39
+ }
40
+ if (channels.feishu.enabled && channels.feishu.appId && channels.feishu.appSecret) {
41
+ manager.register(createFeishuChannel({
42
+ appId: channels.feishu.appId,
43
+ appSecret: channels.feishu.appSecret,
44
+ verificationToken: channels.feishu.verificationToken,
45
+ encryptKey: channels.feishu.encryptKey,
46
+ allowFrom: channels.feishu.allowFrom,
47
+ }));
48
+ }
49
+ if (channels.wechat.enabled) {
50
+ manager.register(createWeChatChannel({
51
+ puppet: channels.wechat.puppet,
52
+ token: channels.wechat.token,
53
+ allowFrom: channels.wechat.allowFrom,
54
+ }));
55
+ }
56
+ return manager;
57
+ }
58
+ //# sourceMappingURL=factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export type { ChannelPlugin, ChannelMeta, ChannelId, ChannelConfig, InboundMessage, OutboundMessage, MessageHandler, } from './types.js';
2
+ export { ChannelManager } from './manager.js';
3
+ export { createChannelManager } from './factory.js';
4
+ export { createSlackChannel, type SlackChannelConfig } from './adapters/slack.js';
5
+ export { createDiscordChannel, type DiscordChannelConfig } from './adapters/discord.js';
6
+ export { createTelegramChannel, type TelegramChannelConfig } from './adapters/telegram.js';
7
+ export { createMatrixChannel, type MatrixChannelConfig } from './adapters/matrix.js';
8
+ export { createFeishuChannel, type FeishuChannelConfig } from './adapters/feishu.js';
9
+ export { createWeChatChannel, type WeChatChannelConfig } from './adapters/wechat.js';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,aAAa,EACb,WAAW,EACX,SAAS,EACT,aAAa,EACb,cAAc,EACd,eAAe,EACf,cAAc,GACf,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAClF,OAAO,EAAE,oBAAoB,EAAE,KAAK,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AACxF,OAAO,EAAE,qBAAqB,EAAE,KAAK,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC3F,OAAO,EAAE,mBAAmB,EAAE,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AACrF,OAAO,EAAE,mBAAmB,EAAE,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AACrF,OAAO,EAAE,mBAAmB,EAAE,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ export { ChannelManager } from './manager.js';
2
+ export { createChannelManager } from './factory.js';
3
+ export { createSlackChannel } from './adapters/slack.js';
4
+ export { createDiscordChannel } from './adapters/discord.js';
5
+ export { createTelegramChannel } from './adapters/telegram.js';
6
+ export { createMatrixChannel } from './adapters/matrix.js';
7
+ export { createFeishuChannel } from './adapters/feishu.js';
8
+ export { createWeChatChannel } from './adapters/wechat.js';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAA2B,MAAM,qBAAqB,CAAC;AAClF,OAAO,EAAE,oBAAoB,EAA6B,MAAM,uBAAuB,CAAC;AACxF,OAAO,EAAE,qBAAqB,EAA8B,MAAM,wBAAwB,CAAC;AAC3F,OAAO,EAAE,mBAAmB,EAA4B,MAAM,sBAAsB,CAAC;AACrF,OAAO,EAAE,mBAAmB,EAA4B,MAAM,sBAAsB,CAAC;AACrF,OAAO,EAAE,mBAAmB,EAA4B,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,24 @@
1
+ import type { ChannelPlugin, MessageHandler, OutboundMessage } from './types.js';
2
+ export declare class ChannelManager {
3
+ private channels;
4
+ private handler;
5
+ /** Set the global message handler (usually wired to the orchestrator) */
6
+ setHandler(handler: MessageHandler): void;
7
+ /** Register a channel plugin */
8
+ register(channel: ChannelPlugin): void;
9
+ /** Get a registered channel by ID */
10
+ get(id: string): ChannelPlugin | undefined;
11
+ /** List all registered channels */
12
+ list(): ChannelPlugin[];
13
+ /** List connected channels */
14
+ listConnected(): ChannelPlugin[];
15
+ /** Start all registered channels */
16
+ startAll(): Promise<void>;
17
+ /** Stop all channels */
18
+ stopAll(): Promise<void>;
19
+ /** Send a message to a specific channel */
20
+ send(channelId: string, msg: OutboundMessage): Promise<void>;
21
+ /** Broadcast a message to all connected channels */
22
+ broadcast(msg: OutboundMessage): Promise<void>;
23
+ }
24
+ //# sourceMappingURL=manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../src/manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,eAAe,EAAa,MAAM,YAAY,CAAC;AAE5F,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAoC;IACpD,OAAO,CAAC,OAAO,CAA+B;IAE9C,yEAAyE;IACzE,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAIzC,gCAAgC;IAChC,QAAQ,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAItC,qCAAqC;IACrC,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAI1C,mCAAmC;IACnC,IAAI,IAAI,aAAa,EAAE;IAIvB,8BAA8B;IAC9B,aAAa,IAAI,aAAa,EAAE;IAIhC,oCAAoC;IAC9B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IA6B/B,wBAAwB;IAClB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAY9B,2CAA2C;IACrC,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAOlE,oDAAoD;IAC9C,SAAS,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;CAKrD"}
@@ -0,0 +1,74 @@
1
+ export class ChannelManager {
2
+ channels = new Map();
3
+ handler = null;
4
+ /** Set the global message handler (usually wired to the orchestrator) */
5
+ setHandler(handler) {
6
+ this.handler = handler;
7
+ }
8
+ /** Register a channel plugin */
9
+ register(channel) {
10
+ this.channels.set(channel.id, channel);
11
+ }
12
+ /** Get a registered channel by ID */
13
+ get(id) {
14
+ return this.channels.get(id);
15
+ }
16
+ /** List all registered channels */
17
+ list() {
18
+ return Array.from(this.channels.values());
19
+ }
20
+ /** List connected channels */
21
+ listConnected() {
22
+ return this.list().filter((ch) => ch.isConnected());
23
+ }
24
+ /** Start all registered channels */
25
+ async startAll() {
26
+ if (!this.handler) {
27
+ throw new Error('No message handler set. Call setHandler() before startAll().');
28
+ }
29
+ const handler = this.handler;
30
+ const results = await Promise.allSettled(this.list().map(async (channel) => {
31
+ try {
32
+ await channel.start(async (msg) => {
33
+ if (!channel.isAllowed(msg.senderId)) {
34
+ return;
35
+ }
36
+ return handler(msg);
37
+ });
38
+ }
39
+ catch (err) {
40
+ console.error(`[ChannelManager] Failed to start ${channel.id}:`, err);
41
+ throw err;
42
+ }
43
+ }));
44
+ const failures = results.filter((r) => r.status === 'rejected');
45
+ if (failures.length > 0) {
46
+ console.warn(`[ChannelManager] ${failures.length} channel(s) failed to start`);
47
+ }
48
+ }
49
+ /** Stop all channels */
50
+ async stopAll() {
51
+ await Promise.allSettled(this.list().map(async (channel) => {
52
+ try {
53
+ await channel.stop();
54
+ }
55
+ catch (err) {
56
+ console.error(`[ChannelManager] Failed to stop ${channel.id}:`, err);
57
+ }
58
+ }));
59
+ }
60
+ /** Send a message to a specific channel */
61
+ async send(channelId, msg) {
62
+ const channel = this.channels.get(channelId);
63
+ if (!channel)
64
+ throw new Error(`Channel not found: ${channelId}`);
65
+ if (!channel.isConnected())
66
+ throw new Error(`Channel not connected: ${channelId}`);
67
+ await channel.send(msg);
68
+ }
69
+ /** Broadcast a message to all connected channels */
70
+ async broadcast(msg) {
71
+ await Promise.allSettled(this.listConnected().map((ch) => ch.send(msg)));
72
+ }
73
+ }
74
+ //# sourceMappingURL=manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../src/manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ export interface ChannelMeta {
2
+ name: string;
3
+ emoji: string;
4
+ }
5
+ export interface InboundMessage {
6
+ channelId: string;
7
+ senderId: string;
8
+ senderName?: string;
9
+ text: string;
10
+ threadId?: string;
11
+ replyToId?: string;
12
+ timestamp: number;
13
+ raw?: unknown;
14
+ }
15
+ export interface OutboundMessage {
16
+ to: string;
17
+ text: string;
18
+ threadId?: string;
19
+ replyToId?: string;
20
+ }
21
+ export type MessageHandler = (msg: InboundMessage) => Promise<string | void>;
22
+ export interface ChannelPlugin {
23
+ id: string;
24
+ meta: ChannelMeta;
25
+ /** Start the channel (connect, listen for events) */
26
+ start(handler: MessageHandler): Promise<void>;
27
+ /** Stop the channel gracefully */
28
+ stop(): Promise<void>;
29
+ /** Send a text message */
30
+ send(msg: OutboundMessage): Promise<void>;
31
+ /** Check if a sender is allowed (security) */
32
+ isAllowed(senderId: string): boolean;
33
+ /** Whether the channel is currently connected */
34
+ isConnected(): boolean;
35
+ }
36
+ export type ChannelId = 'slack' | 'discord' | 'telegram' | 'matrix' | 'feishu' | 'wechat';
37
+ export interface ChannelConfig {
38
+ enabled: boolean;
39
+ allowFrom: string[];
40
+ [key: string]: unknown;
41
+ }
42
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;AAE7E,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,WAAW,CAAC;IAElB,qDAAqD;IACrD,KAAK,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE9C,kCAAkC;IAClC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtB,0BAA0B;IAC1B,IAAI,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1C,8CAA8C;IAC9C,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IAErC,iDAAiD;IACjD,WAAW,IAAI,OAAO,CAAC;CACxB;AAED,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE1F,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@cereworker/channels",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "publishConfig": {
11
+ "access": "public"
12
+ },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://github.com/Producible/CereWorker.git",
16
+ "directory": "packages/channels"
17
+ },
18
+ "dependencies": {
19
+ "@slack/bolt": "^4.2.0",
20
+ "discord.js": "^14.18.0",
21
+ "telegraf": "^4.16.0",
22
+ "matrix-js-sdk": "^36.0.0",
23
+ "@larksuiteoapi/node-sdk": "^1.39.0",
24
+ "wechaty": "^1.20.0",
25
+ "@cereworker/core": "0.1.0",
26
+ "@cereworker/config": "0.1.0"
27
+ },
28
+ "devDependencies": {
29
+ "typescript": "^5.7.3"
30
+ },
31
+ "scripts": {
32
+ "build": "tsc",
33
+ "typecheck": "tsc --noEmit",
34
+ "lint": "eslint src/",
35
+ "clean": "rm -rf dist"
36
+ }
37
+ }