beecork 0.3.2 → 1.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 (285) hide show
  1. package/dist/channels/discord.d.ts +23 -0
  2. package/dist/channels/discord.d.ts.map +1 -0
  3. package/dist/channels/discord.js +352 -0
  4. package/dist/channels/discord.js.map +1 -0
  5. package/dist/channels/index.d.ts +8 -0
  6. package/dist/channels/index.d.ts.map +1 -0
  7. package/dist/channels/index.js +7 -0
  8. package/dist/channels/index.js.map +1 -0
  9. package/dist/channels/loader.d.ts +8 -0
  10. package/dist/channels/loader.d.ts.map +1 -0
  11. package/dist/channels/loader.js +72 -0
  12. package/dist/channels/loader.js.map +1 -0
  13. package/dist/channels/registry.d.ts +24 -0
  14. package/dist/channels/registry.d.ts.map +1 -0
  15. package/dist/channels/registry.js +65 -0
  16. package/dist/channels/registry.js.map +1 -0
  17. package/dist/channels/telegram.d.ts +41 -0
  18. package/dist/channels/telegram.d.ts.map +1 -0
  19. package/dist/channels/telegram.js +720 -0
  20. package/dist/channels/telegram.js.map +1 -0
  21. package/dist/channels/types.d.ts +67 -0
  22. package/dist/channels/types.d.ts.map +1 -0
  23. package/dist/channels/types.js +2 -0
  24. package/dist/channels/types.js.map +1 -0
  25. package/dist/channels/webhook.d.ts +28 -0
  26. package/dist/channels/webhook.d.ts.map +1 -0
  27. package/dist/channels/webhook.js +164 -0
  28. package/dist/channels/webhook.js.map +1 -0
  29. package/dist/channels/whatsapp.d.ts +27 -0
  30. package/dist/channels/whatsapp.d.ts.map +1 -0
  31. package/dist/channels/whatsapp.js +373 -0
  32. package/dist/channels/whatsapp.js.map +1 -0
  33. package/dist/cli/channel.d.ts +4 -0
  34. package/dist/cli/channel.d.ts.map +1 -0
  35. package/dist/cli/channel.js +194 -0
  36. package/dist/cli/channel.js.map +1 -0
  37. package/dist/cli/doctor.d.ts +2 -0
  38. package/dist/cli/doctor.d.ts.map +1 -0
  39. package/dist/cli/doctor.js +150 -0
  40. package/dist/cli/doctor.js.map +1 -0
  41. package/dist/cli/handoff.d.ts +16 -0
  42. package/dist/cli/handoff.d.ts.map +1 -0
  43. package/dist/cli/handoff.js +69 -0
  44. package/dist/cli/handoff.js.map +1 -0
  45. package/dist/cli/mcp.d.ts +4 -0
  46. package/dist/cli/mcp.d.ts.map +1 -0
  47. package/dist/cli/mcp.js +48 -0
  48. package/dist/cli/mcp.js.map +1 -0
  49. package/dist/cli/media.d.ts +3 -0
  50. package/dist/cli/media.d.ts.map +1 -0
  51. package/dist/cli/media.js +113 -0
  52. package/dist/cli/media.js.map +1 -0
  53. package/dist/cli/setup.d.ts.map +1 -1
  54. package/dist/cli/setup.js +249 -19
  55. package/dist/cli/setup.js.map +1 -1
  56. package/dist/config.d.ts.map +1 -1
  57. package/dist/config.js +10 -1
  58. package/dist/config.js.map +1 -1
  59. package/dist/cron/scheduler.d.ts +2 -0
  60. package/dist/cron/scheduler.d.ts.map +1 -1
  61. package/dist/cron/scheduler.js +32 -10
  62. package/dist/cron/scheduler.js.map +1 -1
  63. package/dist/daemon.js +87 -25
  64. package/dist/daemon.js.map +1 -1
  65. package/dist/dashboard/html.d.ts +1 -1
  66. package/dist/dashboard/html.d.ts.map +1 -1
  67. package/dist/dashboard/html.js +396 -111
  68. package/dist/dashboard/html.js.map +1 -1
  69. package/dist/dashboard/server.d.ts.map +1 -1
  70. package/dist/dashboard/server.js +176 -16
  71. package/dist/dashboard/server.js.map +1 -1
  72. package/dist/db/index.d.ts.map +1 -1
  73. package/dist/db/index.js +15 -0
  74. package/dist/db/index.js.map +1 -1
  75. package/dist/db/migrations.d.ts.map +1 -1
  76. package/dist/db/migrations.js +94 -0
  77. package/dist/db/migrations.js.map +1 -1
  78. package/dist/delegation/manager.d.ts +21 -0
  79. package/dist/delegation/manager.d.ts.map +1 -0
  80. package/dist/delegation/manager.js +88 -0
  81. package/dist/delegation/manager.js.map +1 -0
  82. package/dist/index.js +283 -0
  83. package/dist/index.js.map +1 -1
  84. package/dist/machines/forwarder.d.ts +7 -0
  85. package/dist/machines/forwarder.d.ts.map +1 -0
  86. package/dist/machines/forwarder.js +25 -0
  87. package/dist/machines/forwarder.js.map +1 -0
  88. package/dist/machines/index.d.ts +3 -0
  89. package/dist/machines/index.d.ts.map +1 -0
  90. package/dist/machines/index.js +3 -0
  91. package/dist/machines/index.js.map +1 -0
  92. package/dist/machines/registry.d.ts +22 -0
  93. package/dist/machines/registry.d.ts.map +1 -0
  94. package/dist/machines/registry.js +71 -0
  95. package/dist/machines/registry.js.map +1 -0
  96. package/dist/mcp/server.js +418 -32
  97. package/dist/mcp/server.js.map +1 -1
  98. package/dist/media/factory.d.ts +7 -0
  99. package/dist/media/factory.d.ts.map +1 -0
  100. package/dist/media/factory.js +33 -0
  101. package/dist/media/factory.js.map +1 -0
  102. package/dist/media/generators/dall-e.d.ts +11 -0
  103. package/dist/media/generators/dall-e.d.ts.map +1 -0
  104. package/dist/media/generators/dall-e.js +42 -0
  105. package/dist/media/generators/dall-e.js.map +1 -0
  106. package/dist/media/generators/elevenlabs-music.d.ts +10 -0
  107. package/dist/media/generators/elevenlabs-music.d.ts.map +1 -0
  108. package/dist/media/generators/elevenlabs-music.js +35 -0
  109. package/dist/media/generators/elevenlabs-music.js.map +1 -0
  110. package/dist/media/generators/elevenlabs-sfx.d.ts +10 -0
  111. package/dist/media/generators/elevenlabs-sfx.d.ts.map +1 -0
  112. package/dist/media/generators/elevenlabs-sfx.js +34 -0
  113. package/dist/media/generators/elevenlabs-sfx.js.map +1 -0
  114. package/dist/media/generators/kling.d.ts +10 -0
  115. package/dist/media/generators/kling.d.ts.map +1 -0
  116. package/dist/media/generators/kling.js +53 -0
  117. package/dist/media/generators/kling.js.map +1 -0
  118. package/dist/media/generators/lyria.d.ts +11 -0
  119. package/dist/media/generators/lyria.d.ts.map +1 -0
  120. package/dist/media/generators/lyria.js +42 -0
  121. package/dist/media/generators/lyria.js.map +1 -0
  122. package/dist/media/generators/nano-banana.d.ts +11 -0
  123. package/dist/media/generators/nano-banana.d.ts.map +1 -0
  124. package/dist/media/generators/nano-banana.js +46 -0
  125. package/dist/media/generators/nano-banana.js.map +1 -0
  126. package/dist/media/generators/recraft.d.ts +10 -0
  127. package/dist/media/generators/recraft.d.ts.map +1 -0
  128. package/dist/media/generators/recraft.js +53 -0
  129. package/dist/media/generators/recraft.js.map +1 -0
  130. package/dist/media/generators/runway.d.ts +10 -0
  131. package/dist/media/generators/runway.d.ts.map +1 -0
  132. package/dist/media/generators/runway.js +58 -0
  133. package/dist/media/generators/runway.js.map +1 -0
  134. package/dist/media/generators/stable-diffusion.d.ts +10 -0
  135. package/dist/media/generators/stable-diffusion.d.ts.map +1 -0
  136. package/dist/media/generators/stable-diffusion.js +36 -0
  137. package/dist/media/generators/stable-diffusion.js.map +1 -0
  138. package/dist/media/generators/veo.d.ts +10 -0
  139. package/dist/media/generators/veo.d.ts.map +1 -0
  140. package/dist/media/generators/veo.js +33 -0
  141. package/dist/media/generators/veo.js.map +1 -0
  142. package/dist/media/index.d.ts +13 -0
  143. package/dist/media/index.d.ts.map +1 -0
  144. package/dist/media/index.js +10 -0
  145. package/dist/media/index.js.map +1 -0
  146. package/dist/media/loader.d.ts +8 -0
  147. package/dist/media/loader.d.ts.map +1 -0
  148. package/dist/media/loader.js +46 -0
  149. package/dist/media/loader.js.map +1 -0
  150. package/dist/media/store.d.ts +11 -0
  151. package/dist/media/store.d.ts.map +1 -0
  152. package/dist/media/store.js +53 -0
  153. package/dist/media/store.js.map +1 -0
  154. package/dist/media/types.d.ts +22 -0
  155. package/dist/media/types.d.ts.map +1 -0
  156. package/dist/media/types.js +2 -0
  157. package/dist/media/types.js.map +1 -0
  158. package/dist/memory/extractor.js +1 -1
  159. package/dist/memory/extractor.js.map +1 -1
  160. package/dist/notifications/index.d.ts +7 -0
  161. package/dist/notifications/index.d.ts.map +1 -0
  162. package/dist/notifications/index.js +35 -0
  163. package/dist/notifications/index.js.map +1 -0
  164. package/dist/notifications/ntfy.d.ts +10 -0
  165. package/dist/notifications/ntfy.d.ts.map +1 -0
  166. package/dist/notifications/ntfy.js +26 -0
  167. package/dist/notifications/ntfy.js.map +1 -0
  168. package/dist/notifications/pushover.d.ts +10 -0
  169. package/dist/notifications/pushover.d.ts.map +1 -0
  170. package/dist/notifications/pushover.js +27 -0
  171. package/dist/notifications/pushover.js.map +1 -0
  172. package/dist/notifications/types.d.ts +6 -0
  173. package/dist/notifications/types.d.ts.map +1 -0
  174. package/dist/notifications/types.js +2 -0
  175. package/dist/notifications/types.js.map +1 -0
  176. package/dist/notifications/webhook-provider.d.ts +10 -0
  177. package/dist/notifications/webhook-provider.d.ts.map +1 -0
  178. package/dist/notifications/webhook-provider.js +25 -0
  179. package/dist/notifications/webhook-provider.js.map +1 -0
  180. package/dist/observability/analytics.d.ts +26 -0
  181. package/dist/observability/analytics.d.ts.map +1 -0
  182. package/dist/observability/analytics.js +94 -0
  183. package/dist/observability/analytics.js.map +1 -0
  184. package/dist/pipe/memory-store.d.ts +1 -6
  185. package/dist/pipe/memory-store.d.ts.map +1 -1
  186. package/dist/pipe/memory-store.js +0 -24
  187. package/dist/pipe/memory-store.js.map +1 -1
  188. package/dist/pipe/types.d.ts +0 -9
  189. package/dist/pipe/types.d.ts.map +1 -1
  190. package/dist/projects/index.d.ts +4 -0
  191. package/dist/projects/index.d.ts.map +1 -0
  192. package/dist/projects/index.js +3 -0
  193. package/dist/projects/index.js.map +1 -0
  194. package/dist/projects/manager.d.ts +20 -0
  195. package/dist/projects/manager.d.ts.map +1 -0
  196. package/dist/projects/manager.js +135 -0
  197. package/dist/projects/manager.js.map +1 -0
  198. package/dist/projects/router.d.ts +6 -0
  199. package/dist/projects/router.d.ts.map +1 -0
  200. package/dist/projects/router.js +177 -0
  201. package/dist/projects/router.js.map +1 -0
  202. package/dist/projects/types.d.ts +26 -0
  203. package/dist/projects/types.d.ts.map +1 -0
  204. package/dist/projects/types.js +2 -0
  205. package/dist/projects/types.js.map +1 -0
  206. package/dist/service/install.d.ts.map +1 -1
  207. package/dist/service/install.js +26 -7
  208. package/dist/service/install.js.map +1 -1
  209. package/dist/service/windows.d.ts +11 -0
  210. package/dist/service/windows.d.ts.map +1 -0
  211. package/dist/service/windows.js +70 -0
  212. package/dist/service/windows.js.map +1 -0
  213. package/dist/session/manager.d.ts +3 -1
  214. package/dist/session/manager.d.ts.map +1 -1
  215. package/dist/session/manager.js +46 -9
  216. package/dist/session/manager.js.map +1 -1
  217. package/dist/session/subprocess.d.ts +2 -1
  218. package/dist/session/subprocess.d.ts.map +1 -1
  219. package/dist/session/subprocess.js +8 -2
  220. package/dist/session/subprocess.js.map +1 -1
  221. package/dist/types.d.ts +54 -2
  222. package/dist/types.d.ts.map +1 -1
  223. package/dist/types.js +1 -3
  224. package/dist/types.js.map +1 -1
  225. package/dist/users/index.d.ts +3 -0
  226. package/dist/users/index.d.ts.map +1 -0
  227. package/dist/users/index.js +2 -0
  228. package/dist/users/index.js.map +1 -0
  229. package/dist/users/service.d.ts +25 -0
  230. package/dist/users/service.d.ts.map +1 -0
  231. package/dist/users/service.js +65 -0
  232. package/dist/users/service.js.map +1 -0
  233. package/dist/util/logger.d.ts +2 -0
  234. package/dist/util/logger.d.ts.map +1 -1
  235. package/dist/util/logger.js +24 -0
  236. package/dist/util/logger.js.map +1 -1
  237. package/dist/util/platform.d.ts +1 -1
  238. package/dist/util/platform.d.ts.map +1 -1
  239. package/dist/util/platform.js +3 -1
  240. package/dist/util/platform.js.map +1 -1
  241. package/dist/util/progress.d.ts +35 -0
  242. package/dist/util/progress.d.ts.map +1 -0
  243. package/dist/util/progress.js +134 -0
  244. package/dist/util/progress.js.map +1 -0
  245. package/dist/util/rate-limiter.d.ts +15 -0
  246. package/dist/util/rate-limiter.d.ts.map +1 -0
  247. package/dist/util/rate-limiter.js +43 -0
  248. package/dist/util/rate-limiter.js.map +1 -0
  249. package/dist/util/text.d.ts +3 -0
  250. package/dist/util/text.d.ts.map +1 -1
  251. package/dist/util/text.js +19 -0
  252. package/dist/util/text.js.map +1 -1
  253. package/dist/voice/index.d.ts +10 -0
  254. package/dist/voice/index.d.ts.map +1 -0
  255. package/dist/voice/index.js +16 -0
  256. package/dist/voice/index.js.map +1 -0
  257. package/dist/voice/stt.d.ts +15 -0
  258. package/dist/voice/stt.d.ts.map +1 -0
  259. package/dist/voice/stt.js +40 -0
  260. package/dist/voice/stt.js.map +1 -0
  261. package/dist/voice/tts.d.ts +24 -0
  262. package/dist/voice/tts.d.ts.map +1 -0
  263. package/dist/voice/tts.js +85 -0
  264. package/dist/voice/tts.js.map +1 -0
  265. package/package.json +2 -1
  266. package/dist/session/approval.d.ts +0 -20
  267. package/dist/session/approval.d.ts.map +0 -1
  268. package/dist/session/approval.js +0 -59
  269. package/dist/session/approval.js.map +0 -1
  270. package/dist/telegram/bot.d.ts +0 -25
  271. package/dist/telegram/bot.d.ts.map +0 -1
  272. package/dist/telegram/bot.js +0 -307
  273. package/dist/telegram/bot.js.map +0 -1
  274. package/dist/telegram/formatter.d.ts +0 -9
  275. package/dist/telegram/formatter.d.ts.map +0 -1
  276. package/dist/telegram/formatter.js +0 -13
  277. package/dist/telegram/formatter.js.map +0 -1
  278. package/dist/whatsapp/client.d.ts +0 -26
  279. package/dist/whatsapp/client.d.ts.map +0 -1
  280. package/dist/whatsapp/client.js +0 -145
  281. package/dist/whatsapp/client.js.map +0 -1
  282. package/dist/whatsapp/formatter.d.ts +0 -3
  283. package/dist/whatsapp/formatter.d.ts.map +0 -1
  284. package/dist/whatsapp/formatter.js +0 -7
  285. package/dist/whatsapp/formatter.js.map +0 -1
@@ -0,0 +1,23 @@
1
+ import type { Channel, ChannelContext, InboundMessageHandler, SendOptions } from './types.js';
2
+ export declare class DiscordChannel implements Channel {
3
+ readonly id = "discord";
4
+ readonly name = "Discord";
5
+ readonly maxMessageLength = 2000;
6
+ readonly supportsStreaming = false;
7
+ readonly supportsMedia = true;
8
+ private client;
9
+ private ctx;
10
+ private handler;
11
+ private allowedUserIds;
12
+ private sttProvider;
13
+ private ttsProvider;
14
+ constructor(ctx: ChannelContext);
15
+ start(): Promise<void>;
16
+ stop(): void;
17
+ onMessage(handler: InboundMessageHandler): void;
18
+ sendMessage(peerId: string, text: string, options?: SendOptions): Promise<void>;
19
+ sendNotification(message: string, urgent?: boolean): Promise<void>;
20
+ setTyping(peerId: string, active: boolean): Promise<void>;
21
+ private sendResponse;
22
+ }
23
+ //# sourceMappingURL=discord.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discord.d.ts","sourceRoot":"","sources":["../../src/channels/discord.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAmB,WAAW,EAAE,MAAM,YAAY,CAAC;AAE/G,qBAAa,cAAe,YAAW,OAAO;IAC5C,QAAQ,CAAC,EAAE,aAAa;IACxB,QAAQ,CAAC,IAAI,aAAa;IAC1B,QAAQ,CAAC,gBAAgB,QAAQ;IACjC,QAAQ,CAAC,iBAAiB,SAAS;IACnC,QAAQ,CAAC,aAAa,QAAQ;IAE9B,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,GAAG,CAAiB;IAC5B,OAAO,CAAC,OAAO,CAAsC;IACrD,OAAO,CAAC,cAAc,CAAc;IACpC,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,WAAW,CAA4B;gBAEnC,GAAG,EAAE,cAAc;IAOzB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAwR5B,IAAI,IAAI,IAAI;IAQZ,SAAS,CAAC,OAAO,EAAE,qBAAqB,GAAG,IAAI;IAIzC,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB/E,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAelE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;YAUjD,YAAY;CAqB3B"}
@@ -0,0 +1,352 @@
1
+ import { logger } from '../util/logger.js';
2
+ import { chunkText, parseTabMessage, buildMediaPrompt } from '../util/text.js';
3
+ import { retryWithBackoff } from '../util/retry.js';
4
+ import { inboundLimiter } from '../util/rate-limiter.js';
5
+ import { saveMedia, isOversized } from '../media/store.js';
6
+ import { initVoiceProviders } from '../voice/index.js';
7
+ import { ProgressTracker } from '../util/progress.js';
8
+ export class DiscordChannel {
9
+ id = 'discord';
10
+ name = 'Discord';
11
+ maxMessageLength = 2000;
12
+ supportsStreaming = false; // Discord message editing is rate-limited
13
+ supportsMedia = true;
14
+ client = null; // Discord.js Client
15
+ ctx;
16
+ handler = null;
17
+ allowedUserIds;
18
+ sttProvider = null;
19
+ ttsProvider = null;
20
+ constructor(ctx) {
21
+ this.ctx = ctx;
22
+ this.allowedUserIds = new Set((ctx.config.discord?.allowedUserIds ?? []).map(String));
23
+ }
24
+ async start() {
25
+ const discordConfig = this.ctx.config.discord;
26
+ if (!discordConfig?.token) {
27
+ logger.warn('No Discord token configured');
28
+ return;
29
+ }
30
+ // Dynamic import since discord.js might not be installed
31
+ const { Client, GatewayIntentBits, Events } = await import('discord.js');
32
+ this.client = new Client({
33
+ intents: [
34
+ GatewayIntentBits.Guilds,
35
+ GatewayIntentBits.GuildMessages,
36
+ GatewayIntentBits.DirectMessages,
37
+ GatewayIntentBits.MessageContent,
38
+ ],
39
+ });
40
+ // Voice providers
41
+ const { stt, tts } = initVoiceProviders(this.ctx.config.voice);
42
+ this.sttProvider = stt;
43
+ this.ttsProvider = tts;
44
+ this.client.on(Events.MessageCreate, async (message) => {
45
+ // Ignore bot messages
46
+ if (message.author.bot)
47
+ return;
48
+ const isDM = !message.guild;
49
+ const isMentioned = message.mentions.has(this.client.user);
50
+ // In DMs: allow if user is in allowlist (or allowlist is empty = allow all)
51
+ // In servers: only respond if @mentioned
52
+ if (isDM) {
53
+ if (this.allowedUserIds.size > 0 && !this.allowedUserIds.has(message.author.id))
54
+ return;
55
+ }
56
+ else {
57
+ if (!isMentioned)
58
+ return;
59
+ }
60
+ // Rate limit
61
+ if (!inboundLimiter.check(this.id)) {
62
+ await message.reply("I'm receiving too many messages right now. Please wait a moment.").catch(() => { });
63
+ return;
64
+ }
65
+ const text = message.content
66
+ .replace(/<@!?\d+>/g, '') // Remove mentions
67
+ .trim();
68
+ // Download attachments
69
+ const media = [];
70
+ for (const attachment of message.attachments.values()) {
71
+ try {
72
+ if (isOversized(attachment.size)) {
73
+ logger.warn(`Skipping oversized Discord attachment: ${attachment.size} bytes`);
74
+ continue;
75
+ }
76
+ const response = await fetch(attachment.url, { signal: AbortSignal.timeout(30000) });
77
+ if (!response.ok)
78
+ continue;
79
+ const buffer = Buffer.from(await response.arrayBuffer());
80
+ const ext = attachment.name?.split('.').pop() || 'bin';
81
+ const filePath = saveMedia(buffer, ext, attachment.name);
82
+ let type = 'document';
83
+ if (attachment.contentType?.startsWith('image/'))
84
+ type = 'image';
85
+ else if (attachment.contentType?.startsWith('video/'))
86
+ type = 'video';
87
+ else if (attachment.contentType?.startsWith('audio/'))
88
+ type = 'audio';
89
+ media.push({
90
+ type,
91
+ mimeType: attachment.contentType || 'application/octet-stream',
92
+ filePath,
93
+ fileName: attachment.name,
94
+ });
95
+ }
96
+ catch (err) {
97
+ logger.warn('Failed to download Discord attachment:', err);
98
+ }
99
+ }
100
+ if (!text && media.length === 0)
101
+ return;
102
+ try {
103
+ // Show typing
104
+ await message.channel.sendTyping().catch(() => { });
105
+ // Parse tab name
106
+ const { tabName, prompt } = parseTabMessage(text || '');
107
+ if (!prompt && media.length === 0)
108
+ return;
109
+ // Handle commands
110
+ if (text.startsWith('/tabs')) {
111
+ const tabs = this.ctx.tabManager.listTabs();
112
+ if (tabs.length === 0) {
113
+ await message.reply('No tabs.');
114
+ }
115
+ else {
116
+ const list = tabs.map(t => `• **${t.name}** [${t.status}]`).join('\n');
117
+ await message.reply(list);
118
+ }
119
+ return;
120
+ }
121
+ if (text.startsWith('/stop ')) {
122
+ const name = text.slice(6).trim();
123
+ this.ctx.tabManager.stopTab(name);
124
+ await message.reply(`Stopped tab: ${name}`);
125
+ return;
126
+ }
127
+ // /projects — list all projects
128
+ if (text === '/projects') {
129
+ const { listProjects } = await import('../projects/index.js');
130
+ const projects = listProjects();
131
+ if (projects.length === 0) {
132
+ await message.reply('No projects found. Create one with /newproject <name>');
133
+ return;
134
+ }
135
+ const userProjects = projects.filter((p) => p.type === 'user-project');
136
+ const categories = projects.filter((p) => p.type === 'category');
137
+ let msg2 = '📦 **Projects:**\n';
138
+ if (userProjects.length > 0) {
139
+ msg2 += userProjects.map((p) => ` • ${p.name} — ${p.path}`).join('\n');
140
+ }
141
+ if (categories.length > 0) {
142
+ msg2 += '\n\n📁 **Categories:**\n';
143
+ msg2 += categories.map((p) => ` • ${p.name}`).join('\n');
144
+ }
145
+ await message.reply(msg2);
146
+ return;
147
+ }
148
+ // /project <name> — switch to a project
149
+ if (text.startsWith('/project ') && !text.startsWith('/projects')) {
150
+ const pname = text.slice(9).trim();
151
+ const { getProject, setUserContext } = await import('../projects/index.js');
152
+ const project = getProject(pname);
153
+ if (!project) {
154
+ await message.reply(`Project "${pname}" not found. Use /projects to list or /newproject to create.`);
155
+ return;
156
+ }
157
+ setUserContext(message.author.id, project.name, project.name);
158
+ await message.reply(`Switched to project: ${project.name}\nPath: ${project.path}\n\nNext messages will work in this project.`);
159
+ return;
160
+ }
161
+ // /newproject <name> [path] — create a new project
162
+ if (text.startsWith('/newproject ')) {
163
+ const parts = text.slice(12).trim().split(/\s+/);
164
+ const pname = parts[0];
165
+ const customPath = parts[1] || undefined;
166
+ if (!pname) {
167
+ await message.reply('Usage: /newproject <name> [path]');
168
+ return;
169
+ }
170
+ const { createProject, setUserContext } = await import('../projects/index.js');
171
+ const project = createProject(pname, customPath);
172
+ setUserContext(message.author.id, project.name, project.name);
173
+ await message.reply(`✓ Project "${pname}" created at ${project.path}\nSwitched to this project.`);
174
+ return;
175
+ }
176
+ // /close <tab> — permanently close a tab
177
+ if (text.startsWith('/close ')) {
178
+ const tabToClose = text.slice(7).trim();
179
+ if (!tabToClose) {
180
+ await message.reply('Usage: /close <tabname>');
181
+ return;
182
+ }
183
+ const { closeTab } = await import('../projects/index.js');
184
+ const closed = closeTab(tabToClose);
185
+ if (closed) {
186
+ await message.reply(`Tab "${tabToClose}" permanently closed. History deleted.`);
187
+ }
188
+ else {
189
+ await message.reply(`Tab "${tabToClose}" not found.`);
190
+ }
191
+ return;
192
+ }
193
+ // /fresh <project> — start a new tab in a project
194
+ if (text.startsWith('/fresh ')) {
195
+ const projectName = text.slice(7).trim();
196
+ const { getProject, setUserContext } = await import('../projects/index.js');
197
+ const project = getProject(projectName);
198
+ if (!project) {
199
+ await message.reply(`Project "${projectName}" not found.`);
200
+ return;
201
+ }
202
+ const freshTab = `${projectName}-${Date.now().toString(36).slice(-4)}`;
203
+ setUserContext(message.author.id, project.name, freshTab);
204
+ await message.reply(`Fresh start in "${projectName}" (tab: ${freshTab})\nSend your message now.`);
205
+ return;
206
+ }
207
+ // Build prompt with media
208
+ const fullPrompt = buildMediaPrompt(media, prompt || '');
209
+ // Smart project routing (if no explicit /tab command)
210
+ let effectiveTab = tabName;
211
+ let projectPath;
212
+ // Use thread name as tab if in a thread
213
+ if (message.channel.isThread?.()) {
214
+ effectiveTab = message.channel.name || tabName;
215
+ }
216
+ if (effectiveTab === 'default' && !text.startsWith('/tab ')) {
217
+ try {
218
+ const { routeMessage, setUserContext } = await import('../projects/index.js');
219
+ const decision = routeMessage(prompt || '', {
220
+ userId: message.author.id,
221
+ });
222
+ if (decision.needsConfirmation) {
223
+ const { listProjects } = await import('../projects/index.js');
224
+ const projects = listProjects().filter((p) => p.type === 'user-project');
225
+ const options = projects.map((p, i) => `${i + 1}) ${p.name}`).join('\n');
226
+ await message.reply(`Which project?\n${options}\n\nReply with the number, or just send your message with /project <name> first.`);
227
+ return;
228
+ }
229
+ effectiveTab = decision.tabName;
230
+ projectPath = decision.project.path;
231
+ setUserContext(message.author.id, decision.project.name, decision.tabName);
232
+ }
233
+ catch (err) {
234
+ logger.warn('Project routing failed, using default:', err);
235
+ }
236
+ }
237
+ // Typing indicator refresh
238
+ const typingInterval = setInterval(() => {
239
+ message.channel.sendTyping().catch(() => { });
240
+ }, 8000); // Discord typing lasts 10s
241
+ try {
242
+ // Progress updates for long tasks (every 30 seconds)
243
+ const progressTracker = new ProgressTracker(effectiveTab, (msg) => {
244
+ message.channel.send(msg).catch(() => { });
245
+ });
246
+ const result = await this.ctx.tabManager.sendMessage(effectiveTab, fullPrompt, {
247
+ onToolUse: (name, input) => progressTracker.record(name, input),
248
+ projectPath,
249
+ });
250
+ progressTracker.stop();
251
+ clearInterval(typingInterval);
252
+ const responseText = result.error
253
+ ? `Error: ${result.text}`
254
+ : result.text || '(empty response)';
255
+ // Voice reply if configured
256
+ const voiceMode = this.ctx.config.voice?.replyMode;
257
+ if (this.ttsProvider && (voiceMode === 'voice' || voiceMode === 'both')) {
258
+ try {
259
+ const audioPath = await this.ttsProvider.synthesize(responseText);
260
+ await message.reply({ files: [audioPath] });
261
+ if (voiceMode === 'voice')
262
+ return;
263
+ }
264
+ catch (err) {
265
+ logger.warn('Discord TTS failed:', err);
266
+ }
267
+ }
268
+ // Send text response
269
+ await this.sendResponse(message, responseText, effectiveTab);
270
+ }
271
+ catch (err) {
272
+ clearInterval(typingInterval);
273
+ throw err;
274
+ }
275
+ }
276
+ catch (err) {
277
+ logger.error('Discord message handler error:', err);
278
+ await message.reply('Something went wrong processing your message.').catch(() => { });
279
+ }
280
+ });
281
+ this.client.on(Events.ClientReady, () => {
282
+ logger.info(`Discord bot ready as ${this.client.user?.tag}`);
283
+ });
284
+ await this.client.login(discordConfig.token);
285
+ }
286
+ stop() {
287
+ if (this.client) {
288
+ this.client.destroy();
289
+ this.client = null;
290
+ }
291
+ logger.info('Discord bot stopped');
292
+ }
293
+ onMessage(handler) {
294
+ this.handler = handler;
295
+ }
296
+ async sendMessage(peerId, text, options) {
297
+ if (!this.client)
298
+ return;
299
+ try {
300
+ const channel = await this.client.channels.fetch(peerId);
301
+ if (!channel?.isTextBased())
302
+ return;
303
+ const chunks = chunkText(text, this.maxMessageLength);
304
+ for (const chunk of chunks) {
305
+ await retryWithBackoff(() => channel.send(chunk), [1000, 5000, 15000], 'discord-send');
306
+ }
307
+ }
308
+ catch (err) {
309
+ logger.error(`Discord send failed for ${peerId}:`, err);
310
+ }
311
+ }
312
+ async sendNotification(message, urgent) {
313
+ if (!this.client)
314
+ return;
315
+ // Send to all allowed users via DM
316
+ for (const userId of this.allowedUserIds) {
317
+ try {
318
+ const user = await this.client.users.fetch(userId);
319
+ if (user) {
320
+ await user.send(message);
321
+ }
322
+ }
323
+ catch (err) {
324
+ logger.error(`Discord notification failed for ${userId}:`, err);
325
+ }
326
+ }
327
+ }
328
+ async setTyping(peerId, active) {
329
+ if (!this.client || !active)
330
+ return;
331
+ try {
332
+ const channel = await this.client.channels.fetch(peerId);
333
+ if (channel?.isTextBased()) {
334
+ await channel.sendTyping();
335
+ }
336
+ }
337
+ catch { }
338
+ }
339
+ async sendResponse(message, text, tabName) {
340
+ const prefix = tabName && tabName !== 'default' ? `[${tabName}] ` : '';
341
+ const fullText = prefix + text;
342
+ const chunks = chunkText(fullText, this.maxMessageLength);
343
+ // First chunk as reply, rest as follow-ups
344
+ if (chunks.length > 0) {
345
+ await retryWithBackoff(() => message.reply(chunks[0]), [1000, 5000], 'discord-reply');
346
+ }
347
+ for (let i = 1; i < chunks.length; i++) {
348
+ await retryWithBackoff(() => message.channel.send(chunks[i]), [1000, 5000], 'discord-send');
349
+ }
350
+ }
351
+ }
352
+ //# sourceMappingURL=discord.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discord.js","sourceRoot":"","sources":["../../src/channels/discord.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export { ChannelRegistry } from './registry.js';
2
+ export { TelegramChannel } from './telegram.js';
3
+ export { WhatsAppChannel } from './whatsapp.js';
4
+ export { WebhookChannel } from './webhook.js';
5
+ export { DiscordChannel } from './discord.js';
6
+ export { loadCommunityChannels } from './loader.js';
7
+ export type { Channel, ChannelContext, InboundMessage, InboundMessageHandler, MediaAttachment, SendOptions } from './types.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/channels/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,qBAAqB,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,7 @@
1
+ export { ChannelRegistry } from './registry.js';
2
+ export { TelegramChannel } from './telegram.js';
3
+ export { WhatsAppChannel } from './whatsapp.js';
4
+ export { WebhookChannel } from './webhook.js';
5
+ export { DiscordChannel } from './discord.js';
6
+ export { loadCommunityChannels } from './loader.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/channels/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { Channel, ChannelContext } from './types.js';
2
+ /**
3
+ * Discover and load community channel packages from node_modules.
4
+ * Convention: packages named `beecork-channel-<name>` must export a default
5
+ * class implementing the Channel interface.
6
+ */
7
+ export declare function loadCommunityChannels(ctx: ChannelContext): Promise<Channel[]>;
8
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/channels/loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAI1D;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAqEnF"}
@@ -0,0 +1,72 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { logger } from '../util/logger.js';
4
+ const CHANNEL_PREFIX = 'beecork-channel-';
5
+ /**
6
+ * Discover and load community channel packages from node_modules.
7
+ * Convention: packages named `beecork-channel-<name>` must export a default
8
+ * class implementing the Channel interface.
9
+ */
10
+ export async function loadCommunityChannels(ctx) {
11
+ const channels = [];
12
+ // Look in global and local node_modules
13
+ const searchPaths = [
14
+ path.join(process.cwd(), 'node_modules'),
15
+ // Global npm modules path varies by OS — try common locations
16
+ ];
17
+ // Also check if beecork is installed globally
18
+ try {
19
+ const globalPath = path.dirname(require.resolve('beecork/package.json'));
20
+ const globalNodeModules = path.join(globalPath, '..');
21
+ if (fs.existsSync(globalNodeModules)) {
22
+ searchPaths.push(globalNodeModules);
23
+ }
24
+ }
25
+ catch { }
26
+ for (const searchPath of searchPaths) {
27
+ if (!fs.existsSync(searchPath))
28
+ continue;
29
+ try {
30
+ const dirs = fs.readdirSync(searchPath);
31
+ for (const dir of dirs) {
32
+ if (!dir.startsWith(CHANNEL_PREFIX))
33
+ continue;
34
+ const channelName = dir.slice(CHANNEL_PREFIX.length);
35
+ const pkgPath = path.join(searchPath, dir);
36
+ try {
37
+ // Read package.json to find the main entry
38
+ const pkgJson = JSON.parse(fs.readFileSync(path.join(pkgPath, 'package.json'), 'utf-8'));
39
+ const main = pkgJson.main || 'index.js';
40
+ const entryPath = path.join(pkgPath, main);
41
+ if (!fs.existsSync(entryPath)) {
42
+ logger.warn(`Community channel ${dir}: entry point not found at ${entryPath}`);
43
+ continue;
44
+ }
45
+ // Dynamic import
46
+ const module = await import(entryPath);
47
+ const ChannelClass = module.default || module[Object.keys(module)[0]];
48
+ if (!ChannelClass || typeof ChannelClass !== 'function') {
49
+ logger.warn(`Community channel ${dir}: no default export found`);
50
+ continue;
51
+ }
52
+ const instance = new ChannelClass(ctx);
53
+ // Validate it implements Channel interface (duck typing)
54
+ if (!instance.id || !instance.name || typeof instance.start !== 'function' || typeof instance.stop !== 'function') {
55
+ logger.warn(`Community channel ${dir}: does not implement Channel interface`);
56
+ continue;
57
+ }
58
+ channels.push(instance);
59
+ logger.info(`Community channel loaded: ${instance.name} (${instance.id}) from ${dir}`);
60
+ }
61
+ catch (err) {
62
+ logger.warn(`Failed to load community channel ${dir}:`, err);
63
+ }
64
+ }
65
+ }
66
+ catch (err) {
67
+ logger.warn(`Failed to scan ${searchPath}:`, err);
68
+ }
69
+ }
70
+ return channels;
71
+ }
72
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/channels/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAG3C,MAAM,cAAc,GAAG,kBAAkB,CAAC;AAE1C;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,GAAmB;IAC7D,MAAM,QAAQ,GAAc,EAAE,CAAC;IAE/B,wCAAwC;IACxC,MAAM,WAAW,GAAG;QAClB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,CAAC;QACxC,8DAA8D;KAC/D,CAAC;IAEF,8CAA8C;IAC9C,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC,CAAC;QACzE,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACtD,IAAI,EAAE,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC;YACrC,WAAW,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IAEV,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC;YAAE,SAAS;QAEzC,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,EAAE,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;YACxC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,cAAc,CAAC;oBAAE,SAAS;gBAE9C,MAAM,WAAW,GAAG,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;gBACrD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;gBAE3C,IAAI,CAAC;oBACH,2CAA2C;oBAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;oBACzF,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,UAAU,CAAC;oBACxC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;oBAE3C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;wBAC9B,MAAM,CAAC,IAAI,CAAC,qBAAqB,GAAG,8BAA8B,SAAS,EAAE,CAAC,CAAC;wBAC/E,SAAS;oBACX,CAAC;oBAED,iBAAiB;oBACjB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;oBACvC,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;oBAEtE,IAAI,CAAC,YAAY,IAAI,OAAO,YAAY,KAAK,UAAU,EAAE,CAAC;wBACxD,MAAM,CAAC,IAAI,CAAC,qBAAqB,GAAG,2BAA2B,CAAC,CAAC;wBACjE,SAAS;oBACX,CAAC;oBAED,MAAM,QAAQ,GAAG,IAAI,YAAY,CAAC,GAAG,CAAY,CAAC;oBAElD,yDAAyD;oBACzD,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,OAAO,QAAQ,CAAC,KAAK,KAAK,UAAU,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;wBAClH,MAAM,CAAC,IAAI,CAAC,qBAAqB,GAAG,wCAAwC,CAAC,CAAC;wBAC9E,SAAS;oBACX,CAAC;oBAED,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;oBACxB,MAAM,CAAC,IAAI,CAAC,6BAA6B,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,EAAE,UAAU,GAAG,EAAE,CAAC,CAAC;gBACzF,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,MAAM,CAAC,IAAI,CAAC,oCAAoC,GAAG,GAAG,EAAE,GAAG,CAAC,CAAC;gBAC/D,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,IAAI,CAAC,kBAAkB,UAAU,GAAG,EAAE,GAAG,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,24 @@
1
+ import type { Channel, InboundMessageHandler } from './types.js';
2
+ /**
3
+ * ChannelRegistry manages the lifecycle of all channels.
4
+ * Channels register themselves, and the registry handles start/stop/broadcast.
5
+ */
6
+ export declare class ChannelRegistry {
7
+ private channels;
8
+ private messageHandler;
9
+ /** Register a channel */
10
+ register(channel: Channel): void;
11
+ /** Set the handler that processes all inbound messages from all channels */
12
+ setMessageHandler(handler: InboundMessageHandler): void;
13
+ /** Start all registered channels */
14
+ start(): Promise<void>;
15
+ /** Stop all channels */
16
+ stop(): void;
17
+ /** Get a channel by ID */
18
+ get(id: string): Channel | undefined;
19
+ /** Get all registered channels */
20
+ getAll(): Channel[];
21
+ /** Broadcast a notification to all channels */
22
+ broadcastNotify(text: string, urgent?: boolean): Promise<void>;
23
+ }
24
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/channels/registry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEjE;;;GAGG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAA8B;IAC9C,OAAO,CAAC,cAAc,CAAsC;IAE5D,yBAAyB;IACzB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAYhC,4EAA4E;IAC5E,iBAAiB,CAAC,OAAO,EAAE,qBAAqB,GAAG,IAAI;IAQvD,oCAAoC;IAC9B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAW5B,wBAAwB;IACxB,IAAI,IAAI,IAAI;IAUZ,0BAA0B;IAC1B,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAIpC,kCAAkC;IAClC,MAAM,IAAI,OAAO,EAAE;IAInB,+CAA+C;IACzC,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CASrE"}
@@ -0,0 +1,65 @@
1
+ import { logger } from '../util/logger.js';
2
+ /**
3
+ * ChannelRegistry manages the lifecycle of all channels.
4
+ * Channels register themselves, and the registry handles start/stop/broadcast.
5
+ */
6
+ export class ChannelRegistry {
7
+ channels = new Map();
8
+ messageHandler = null;
9
+ /** Register a channel */
10
+ register(channel) {
11
+ if (this.channels.has(channel.id)) {
12
+ throw new Error(`Channel "${channel.id}" is already registered`);
13
+ }
14
+ this.channels.set(channel.id, channel);
15
+ // Wire up the message handler if one is already set
16
+ if (this.messageHandler) {
17
+ channel.onMessage(this.messageHandler);
18
+ }
19
+ logger.info(`Channel registered: ${channel.name} (${channel.id})`);
20
+ }
21
+ /** Set the handler that processes all inbound messages from all channels */
22
+ setMessageHandler(handler) {
23
+ this.messageHandler = handler;
24
+ // Wire to all already-registered channels
25
+ for (const channel of this.channels.values()) {
26
+ channel.onMessage(handler);
27
+ }
28
+ }
29
+ /** Start all registered channels */
30
+ async start() {
31
+ for (const [id, channel] of this.channels) {
32
+ try {
33
+ await channel.start();
34
+ logger.info(`Channel started: ${channel.name}`);
35
+ }
36
+ catch (err) {
37
+ logger.error(`Failed to start channel ${id}:`, err);
38
+ }
39
+ }
40
+ }
41
+ /** Stop all channels */
42
+ stop() {
43
+ for (const [id, channel] of this.channels) {
44
+ try {
45
+ channel.stop();
46
+ }
47
+ catch (err) {
48
+ logger.error(`Failed to stop channel ${id}:`, err);
49
+ }
50
+ }
51
+ }
52
+ /** Get a channel by ID */
53
+ get(id) {
54
+ return this.channels.get(id);
55
+ }
56
+ /** Get all registered channels */
57
+ getAll() {
58
+ return Array.from(this.channels.values());
59
+ }
60
+ /** Broadcast a notification to all channels */
61
+ async broadcastNotify(text, urgent) {
62
+ await Promise.all(Array.from(this.channels.values()).map(channel => channel.sendNotification(text, urgent).catch(err => logger.warn(`${channel.name} notify failed:`, err))));
63
+ }
64
+ }
65
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/channels/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAG3C;;;GAGG;AACH,MAAM,OAAO,eAAe;IAClB,QAAQ,GAAG,IAAI,GAAG,EAAmB,CAAC;IACtC,cAAc,GAAiC,IAAI,CAAC;IAE5D,yBAAyB;IACzB,QAAQ,CAAC,OAAgB;QACvB,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,YAAY,OAAO,CAAC,EAAE,yBAAyB,CAAC,CAAC;QACnE,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QACvC,oDAAoD;QACpD,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACzC,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,uBAAuB,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC;IACrE,CAAC;IAED,4EAA4E;IAC5E,iBAAiB,CAAC,OAA8B;QAC9C,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC;QAC9B,0CAA0C;QAC1C,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YAC7C,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,oCAAoC;IACpC,KAAK,CAAC,KAAK;QACT,KAAK,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC1C,IAAI,CAAC;gBACH,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;gBACtB,MAAM,CAAC,IAAI,CAAC,oBAAoB,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;YAClD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,CAAC,KAAK,CAAC,2BAA2B,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YACtD,CAAC;QACH,CAAC;IACH,CAAC;IAED,wBAAwB;IACxB,IAAI;QACF,KAAK,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC1C,IAAI,CAAC;gBACH,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,CAAC,KAAK,CAAC,0BAA0B,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YACrD,CAAC;QACH,CAAC;IACH,CAAC;IAED,0BAA0B;IAC1B,GAAG,CAAC,EAAU;QACZ,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC/B,CAAC;IAED,kCAAkC;IAClC,MAAM;QACJ,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAC5C,CAAC;IAED,+CAA+C;IAC/C,KAAK,CAAC,eAAe,CAAC,IAAY,EAAE,MAAgB;QAClD,MAAM,OAAO,CAAC,GAAG,CACf,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAC/C,OAAO,CAAC,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CACjD,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,iBAAiB,EAAE,GAAG,CAAC,CACnD,CACF,CACF,CAAC;IACJ,CAAC;CACF"}