beecork 1.7.0 → 2.0.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 (223) hide show
  1. package/README.md +52 -111
  2. package/dist/index.js +1394 -581
  3. package/package.json +26 -54
  4. package/dist/capabilities/index.d.ts +0 -3
  5. package/dist/capabilities/index.js +0 -2
  6. package/dist/capabilities/manager.d.ts +0 -13
  7. package/dist/capabilities/manager.js +0 -115
  8. package/dist/capabilities/packs.d.ts +0 -2
  9. package/dist/capabilities/packs.js +0 -54
  10. package/dist/capabilities/types.d.ts +0 -21
  11. package/dist/capabilities/types.js +0 -1
  12. package/dist/channels/admin.d.ts +0 -10
  13. package/dist/channels/admin.js +0 -20
  14. package/dist/channels/command-handler.d.ts +0 -19
  15. package/dist/channels/command-handler.js +0 -235
  16. package/dist/channels/discord.d.ts +0 -17
  17. package/dist/channels/discord.js +0 -266
  18. package/dist/channels/index.d.ts +0 -7
  19. package/dist/channels/index.js +0 -6
  20. package/dist/channels/loader.d.ts +0 -7
  21. package/dist/channels/loader.js +0 -87
  22. package/dist/channels/pipeline.d.ts +0 -50
  23. package/dist/channels/pipeline.js +0 -92
  24. package/dist/channels/registry.d.ts +0 -36
  25. package/dist/channels/registry.js +0 -80
  26. package/dist/channels/send-helpers.d.ts +0 -19
  27. package/dist/channels/send-helpers.js +0 -21
  28. package/dist/channels/telegram.d.ts +0 -47
  29. package/dist/channels/telegram.js +0 -649
  30. package/dist/channels/types.d.ts +0 -41
  31. package/dist/channels/types.js +0 -1
  32. package/dist/channels/voice-state.d.ts +0 -29
  33. package/dist/channels/voice-state.js +0 -45
  34. package/dist/channels/webhook.d.ts +0 -16
  35. package/dist/channels/webhook.js +0 -222
  36. package/dist/channels/whatsapp.d.ts +0 -28
  37. package/dist/channels/whatsapp.js +0 -323
  38. package/dist/cli/capabilities.d.ts +0 -3
  39. package/dist/cli/capabilities.js +0 -72
  40. package/dist/cli/channel.d.ts +0 -3
  41. package/dist/cli/channel.js +0 -202
  42. package/dist/cli/commands.d.ts +0 -15
  43. package/dist/cli/commands.js +0 -279
  44. package/dist/cli/doctor.d.ts +0 -1
  45. package/dist/cli/doctor.js +0 -208
  46. package/dist/cli/handoff.d.ts +0 -8
  47. package/dist/cli/handoff.js +0 -33
  48. package/dist/cli/helpers.d.ts +0 -2
  49. package/dist/cli/helpers.js +0 -21
  50. package/dist/cli/mcp.d.ts +0 -3
  51. package/dist/cli/mcp.js +0 -47
  52. package/dist/cli/media.d.ts +0 -2
  53. package/dist/cli/media.js +0 -125
  54. package/dist/cli/setup.d.ts +0 -1
  55. package/dist/cli/setup.js +0 -239
  56. package/dist/cli/store.d.ts +0 -3
  57. package/dist/cli/store.js +0 -108
  58. package/dist/config.d.ts +0 -11
  59. package/dist/config.js +0 -115
  60. package/dist/daemon.d.ts +0 -1
  61. package/dist/daemon.js +0 -345
  62. package/dist/dashboard/html.d.ts +0 -1
  63. package/dist/dashboard/html.js +0 -849
  64. package/dist/dashboard/routes.d.ts +0 -17
  65. package/dist/dashboard/routes.js +0 -623
  66. package/dist/dashboard/server.d.ts +0 -1
  67. package/dist/dashboard/server.js +0 -104
  68. package/dist/db/connection.d.ts +0 -29
  69. package/dist/db/connection.js +0 -37
  70. package/dist/db/index.d.ts +0 -14
  71. package/dist/db/index.js +0 -127
  72. package/dist/db/migrations.d.ts +0 -2
  73. package/dist/db/migrations.js +0 -384
  74. package/dist/delegation/manager.d.ts +0 -18
  75. package/dist/delegation/manager.js +0 -89
  76. package/dist/index.d.ts +0 -2
  77. package/dist/knowledge/index.d.ts +0 -2
  78. package/dist/knowledge/index.js +0 -1
  79. package/dist/knowledge/manager.d.ts +0 -17
  80. package/dist/knowledge/manager.js +0 -160
  81. package/dist/knowledge/types.d.ts +0 -7
  82. package/dist/knowledge/types.js +0 -1
  83. package/dist/mcp/handlers.d.ts +0 -37
  84. package/dist/mcp/handlers.js +0 -520
  85. package/dist/mcp/server.d.ts +0 -2
  86. package/dist/mcp/server.js +0 -86
  87. package/dist/mcp/tool-definitions.d.ts +0 -1225
  88. package/dist/mcp/tool-definitions.js +0 -412
  89. package/dist/mcp/validate.d.ts +0 -23
  90. package/dist/mcp/validate.js +0 -65
  91. package/dist/media/factory.d.ts +0 -6
  92. package/dist/media/factory.js +0 -36
  93. package/dist/media/generators/dall-e.d.ts +0 -10
  94. package/dist/media/generators/dall-e.js +0 -41
  95. package/dist/media/generators/elevenlabs-music.d.ts +0 -9
  96. package/dist/media/generators/elevenlabs-music.js +0 -34
  97. package/dist/media/generators/elevenlabs-sfx.d.ts +0 -9
  98. package/dist/media/generators/elevenlabs-sfx.js +0 -33
  99. package/dist/media/generators/kling.d.ts +0 -9
  100. package/dist/media/generators/kling.js +0 -47
  101. package/dist/media/generators/lyria.d.ts +0 -10
  102. package/dist/media/generators/lyria.js +0 -41
  103. package/dist/media/generators/nano-banana.d.ts +0 -10
  104. package/dist/media/generators/nano-banana.js +0 -45
  105. package/dist/media/generators/poll-util.d.ts +0 -12
  106. package/dist/media/generators/poll-util.js +0 -22
  107. package/dist/media/generators/recraft.d.ts +0 -9
  108. package/dist/media/generators/recraft.js +0 -52
  109. package/dist/media/generators/runway.d.ts +0 -9
  110. package/dist/media/generators/runway.js +0 -49
  111. package/dist/media/generators/stable-diffusion.d.ts +0 -9
  112. package/dist/media/generators/stable-diffusion.js +0 -35
  113. package/dist/media/generators/veo.d.ts +0 -9
  114. package/dist/media/generators/veo.js +0 -32
  115. package/dist/media/index.d.ts +0 -6
  116. package/dist/media/index.js +0 -8
  117. package/dist/media/store.d.ts +0 -17
  118. package/dist/media/store.js +0 -69
  119. package/dist/media/types.d.ts +0 -43
  120. package/dist/media/types.js +0 -1
  121. package/dist/notifications/index.d.ts +0 -4
  122. package/dist/notifications/index.js +0 -21
  123. package/dist/notifications/ntfy.d.ts +0 -9
  124. package/dist/notifications/ntfy.js +0 -25
  125. package/dist/notifications/pushover.d.ts +0 -9
  126. package/dist/notifications/pushover.js +0 -26
  127. package/dist/notifications/types.d.ts +0 -5
  128. package/dist/notifications/types.js +0 -1
  129. package/dist/notifications/webhook-provider.d.ts +0 -9
  130. package/dist/notifications/webhook-provider.js +0 -24
  131. package/dist/observability/analytics.d.ts +0 -30
  132. package/dist/observability/analytics.js +0 -118
  133. package/dist/projects/index.d.ts +0 -4
  134. package/dist/projects/index.js +0 -2
  135. package/dist/projects/manager.d.ts +0 -13
  136. package/dist/projects/manager.js +0 -166
  137. package/dist/projects/router.d.ts +0 -17
  138. package/dist/projects/router.js +0 -246
  139. package/dist/projects/types.d.ts +0 -19
  140. package/dist/projects/types.js +0 -1
  141. package/dist/service/install.d.ts +0 -4
  142. package/dist/service/install.js +0 -146
  143. package/dist/service/templates.d.ts +0 -4
  144. package/dist/service/templates.js +0 -52
  145. package/dist/service/windows.d.ts +0 -8
  146. package/dist/service/windows.js +0 -59
  147. package/dist/session/budget-guard.d.ts +0 -20
  148. package/dist/session/budget-guard.js +0 -31
  149. package/dist/session/circuit-breaker.d.ts +0 -19
  150. package/dist/session/circuit-breaker.js +0 -91
  151. package/dist/session/context-compactor.d.ts +0 -32
  152. package/dist/session/context-compactor.js +0 -45
  153. package/dist/session/context-monitor.d.ts +0 -15
  154. package/dist/session/context-monitor.js +0 -44
  155. package/dist/session/handoff.d.ts +0 -21
  156. package/dist/session/handoff.js +0 -50
  157. package/dist/session/manager.d.ts +0 -60
  158. package/dist/session/manager.js +0 -379
  159. package/dist/session/memory-store.d.ts +0 -29
  160. package/dist/session/memory-store.js +0 -45
  161. package/dist/session/message-queue.d.ts +0 -28
  162. package/dist/session/message-queue.js +0 -52
  163. package/dist/session/pending-dispatcher.d.ts +0 -31
  164. package/dist/session/pending-dispatcher.js +0 -120
  165. package/dist/session/pending-store.d.ts +0 -60
  166. package/dist/session/pending-store.js +0 -118
  167. package/dist/session/stale-session.d.ts +0 -31
  168. package/dist/session/stale-session.js +0 -45
  169. package/dist/session/subprocess.d.ts +0 -25
  170. package/dist/session/subprocess.js +0 -189
  171. package/dist/session/tab-store.d.ts +0 -28
  172. package/dist/session/tab-store.js +0 -78
  173. package/dist/tasks/scheduler.d.ts +0 -45
  174. package/dist/tasks/scheduler.js +0 -329
  175. package/dist/tasks/store.d.ts +0 -11
  176. package/dist/tasks/store.js +0 -103
  177. package/dist/timeline/index.d.ts +0 -3
  178. package/dist/timeline/index.js +0 -2
  179. package/dist/timeline/logger.d.ts +0 -8
  180. package/dist/timeline/logger.js +0 -11
  181. package/dist/timeline/query.d.ts +0 -11
  182. package/dist/timeline/query.js +0 -67
  183. package/dist/timeline/types.d.ts +0 -12
  184. package/dist/timeline/types.js +0 -1
  185. package/dist/types.d.ts +0 -216
  186. package/dist/types.js +0 -3
  187. package/dist/util/auto-heal.d.ts +0 -43
  188. package/dist/util/auto-heal.js +0 -107
  189. package/dist/util/install-info.d.ts +0 -37
  190. package/dist/util/install-info.js +0 -80
  191. package/dist/util/logger.d.ts +0 -18
  192. package/dist/util/logger.js +0 -118
  193. package/dist/util/paths.d.ts +0 -13
  194. package/dist/util/paths.js +0 -55
  195. package/dist/util/platform.d.ts +0 -2
  196. package/dist/util/platform.js +0 -11
  197. package/dist/util/progress.d.ts +0 -34
  198. package/dist/util/progress.js +0 -133
  199. package/dist/util/rate-limiter.d.ts +0 -14
  200. package/dist/util/rate-limiter.js +0 -50
  201. package/dist/util/retry.d.ts +0 -2
  202. package/dist/util/retry.js +0 -18
  203. package/dist/util/text.d.ts +0 -32
  204. package/dist/util/text.js +0 -101
  205. package/dist/version.d.ts +0 -1
  206. package/dist/version.js +0 -4
  207. package/dist/voice/index.d.ts +0 -17
  208. package/dist/voice/index.js +0 -42
  209. package/dist/voice/stt.d.ts +0 -16
  210. package/dist/voice/stt.js +0 -57
  211. package/dist/voice/tts.d.ts +0 -23
  212. package/dist/voice/tts.js +0 -84
  213. package/dist/watchers/evaluator.d.ts +0 -5
  214. package/dist/watchers/evaluator.js +0 -45
  215. package/dist/watchers/index.d.ts +0 -4
  216. package/dist/watchers/index.js +0 -3
  217. package/dist/watchers/scheduler.d.ts +0 -20
  218. package/dist/watchers/scheduler.js +0 -183
  219. package/dist/watchers/store.d.ts +0 -10
  220. package/dist/watchers/store.js +0 -56
  221. package/dist/watchers/types.d.ts +0 -15
  222. package/dist/watchers/types.js +0 -1
  223. package/scripts/postinstall.mjs +0 -50
@@ -1,41 +0,0 @@
1
- import type { TabManager } from '../session/manager.js';
2
- import type { BeecorkConfig, MediaAttachment } from '../types.js';
3
- export type { MediaAttachment };
4
- /**
5
- * Options for sending a message. Currently empty — channels do not honor
6
- * markdown/reply-threading hints. Kept as a placeholder so future per-channel
7
- * options can be added without touching every call site.
8
- */
9
- export type SendOptions = Record<string, never>;
10
- /** The Channel interface — all channels must implement this */
11
- export interface Channel {
12
- /** Unique channel identifier (e.g., 'telegram', 'whatsapp', 'discord') */
13
- readonly id: string;
14
- /** Human-readable name */
15
- readonly name: string;
16
- /** Maximum message length in characters */
17
- readonly maxMessageLength: number;
18
- /** Start the channel (connect, start polling, etc.) */
19
- start(): Promise<void>;
20
- /** Stop the channel gracefully */
21
- stop(): void;
22
- /** Send a text message to a specific peer */
23
- sendMessage(peerId: string, text: string, options?: SendOptions): Promise<void>;
24
- /** Send a media attachment to a peer (optional — channels implement when supported) */
25
- sendMedia?(peerId: string, media: MediaAttachment): Promise<void>;
26
- /** Send a notification to all configured recipients */
27
- sendNotification(message: string, urgent?: boolean): Promise<void>;
28
- /** Set typing indicator for a peer */
29
- setTyping(peerId: string, active: boolean): Promise<void>;
30
- /** Broadcast a media file to every configured recipient — used by the
31
- * pending-message dispatcher to deliver MCP-queued media. Optional; channels
32
- * that don't implement it fall back to sendNotification with a text summary. */
33
- broadcastMedia?(media: MediaAttachment): Promise<void>;
34
- }
35
- /** Context passed to channels during construction */
36
- export interface ChannelContext {
37
- config: BeecorkConfig;
38
- tabManager: TabManager;
39
- /** Broadcast notification to all channels + notification providers */
40
- notifyCallback?: (message: string) => Promise<void>;
41
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,29 +0,0 @@
1
- import type { STTProvider } from '../voice/stt.js';
2
- import type { TTSProvider } from '../voice/tts.js';
3
- import type { VoiceConfig, BeecorkConfig } from '../types.js';
4
- import type { MediaAttachment } from '../types.js';
5
- /**
6
- * Per-channel STT/TTS state. Used to be duplicated across Telegram, WhatsApp,
7
- * and Discord; consolidated here so init + warmup + transcription happen the
8
- * same way across all 3.
9
- *
10
- * Discord historically only called warmup() and did NOT transcribe — preserve
11
- * that behavior unless the caller explicitly asks for transcription.
12
- */
13
- export declare class VoiceState {
14
- private readonly channelId;
15
- stt: STTProvider | null;
16
- tts: TTSProvider | null;
17
- private warmedUp;
18
- constructor(channelId: string);
19
- init(config: BeecorkConfig | {
20
- voice?: VoiceConfig;
21
- }): void;
22
- /** One-shot warmup (no media). Used by Discord today. */
23
- warmup(): Promise<void>;
24
- /**
25
- * Transcribe voice attachments in-place (mutates the caption fields).
26
- * Returns the updated warmed-up flag. No-op if STT isn't configured.
27
- */
28
- transcribe(media: MediaAttachment[]): Promise<void>;
29
- }
@@ -1,45 +0,0 @@
1
- import { initVoiceProviders } from '../voice/index.js';
2
- /**
3
- * Per-channel STT/TTS state. Used to be duplicated across Telegram, WhatsApp,
4
- * and Discord; consolidated here so init + warmup + transcription happen the
5
- * same way across all 3.
6
- *
7
- * Discord historically only called warmup() and did NOT transcribe — preserve
8
- * that behavior unless the caller explicitly asks for transcription.
9
- */
10
- export class VoiceState {
11
- channelId;
12
- stt = null;
13
- tts = null;
14
- warmedUp = false;
15
- constructor(channelId) {
16
- this.channelId = channelId;
17
- }
18
- init(config) {
19
- const { stt, tts } = initVoiceProviders(config.voice);
20
- this.stt = stt;
21
- this.tts = tts;
22
- }
23
- /** One-shot warmup (no media). Used by Discord today. */
24
- async warmup() {
25
- if (this.warmedUp || !this.stt)
26
- return;
27
- try {
28
- this.stt.warmup?.();
29
- }
30
- catch {
31
- /* warmup is best-effort */
32
- }
33
- this.warmedUp = true;
34
- }
35
- /**
36
- * Transcribe voice attachments in-place (mutates the caption fields).
37
- * Returns the updated warmed-up flag. No-op if STT isn't configured.
38
- */
39
- async transcribe(media) {
40
- if (!this.stt)
41
- return;
42
- const { transcribeVoiceMessages } = await import('../voice/index.js');
43
- this.warmedUp = await transcribeVoiceMessages(media, this.stt, this.channelId, this.warmedUp);
44
- }
45
- }
@@ -1,16 +0,0 @@
1
- import type { Channel, ChannelContext, SendOptions } from './types.js';
2
- export declare class WebhookChannel implements Channel {
3
- readonly id = "webhook";
4
- readonly name = "Webhook";
5
- readonly maxMessageLength: 100000;
6
- private server;
7
- private ctx;
8
- constructor(ctx: ChannelContext);
9
- start(): Promise<void>;
10
- stop(): void;
11
- sendMessage(_peerId: string, _text: string, _options?: SendOptions): Promise<void>;
12
- sendNotification(_message: string, _urgent?: boolean): Promise<void>;
13
- setTyping(_peerId: string, _active: boolean): Promise<void>;
14
- private authenticate;
15
- private getConfig;
16
- }
@@ -1,222 +0,0 @@
1
- import http from 'node:http';
2
- import crypto from 'node:crypto';
3
- import { logger } from '../util/logger.js';
4
- import { validateTabNameOrDefault } from '../config.js';
5
- import { inboundLimiter } from '../util/rate-limiter.js';
6
- import { MESSAGE_LIMITS } from '../util/text.js';
7
- import { processInboundMessage } from './pipeline.js';
8
- function safeEqualString(a, b) {
9
- const ab = Buffer.from(a);
10
- const bb = Buffer.from(b);
11
- if (ab.length !== bb.length)
12
- return false;
13
- try {
14
- return crypto.timingSafeEqual(ab, bb);
15
- }
16
- catch {
17
- return false;
18
- }
19
- }
20
- export class WebhookChannel {
21
- id = 'webhook';
22
- name = 'Webhook';
23
- maxMessageLength = MESSAGE_LIMITS.WEBHOOK_PROMPT;
24
- server = null;
25
- ctx;
26
- constructor(ctx) {
27
- this.ctx = ctx;
28
- }
29
- async start() {
30
- const config = this.getConfig();
31
- if (!config?.enabled)
32
- return;
33
- // Fail-secure: a webhook running with no auth turns localhost-injected
34
- // prompts (from any local process or any user on a shared host) into
35
- // arbitrary claude --dangerously-skip-permissions runs. Require either
36
- // an authToken or hmacSecret, OR an explicit allowUnauthLocalhost opt-in.
37
- if (!config.authToken && !config.hmacSecret && !config.allowUnauthLocalhost) {
38
- logger.error('Webhook channel refusing to start: no authToken or hmacSecret configured. ' +
39
- 'Set one in ~/.beecork/config.json under webhook.authToken/hmacSecret, or ' +
40
- 'explicitly opt in with webhook.allowUnauthLocalhost=true (NOT recommended on shared hosts).');
41
- return;
42
- }
43
- const port = config.port || 8374;
44
- this.server = http.createServer(async (req, res) => {
45
- // CORS headers for API clients
46
- res.setHeader('Content-Type', 'application/json');
47
- if (req.method === 'OPTIONS') {
48
- res.writeHead(204);
49
- res.end();
50
- return;
51
- }
52
- if (req.method !== 'POST') {
53
- res.writeHead(405);
54
- res.end(JSON.stringify({ error: 'Method not allowed' }));
55
- return;
56
- }
57
- // Parse URL
58
- const url = new URL(req.url || '/', `http://localhost:${port}`);
59
- const match = url.pathname.match(/^\/webhook\/(.+)$/);
60
- if (!match) {
61
- res.writeHead(404);
62
- res.end(JSON.stringify({ error: 'Use POST /webhook/:tabName' }));
63
- return;
64
- }
65
- const tabName = decodeURIComponent(match[1]);
66
- // Validate tab name (allow "default" — it's a reference, not a creation)
67
- const tabError = validateTabNameOrDefault(tabName);
68
- if (tabError) {
69
- res.writeHead(400);
70
- res.end(JSON.stringify({ error: tabError }));
71
- return;
72
- }
73
- // Read body first (needed for both JSON parsing and HMAC verification)
74
- let body = '';
75
- for await (const chunk of req) {
76
- body += chunk;
77
- if (body.length > MESSAGE_LIMITS.HTTP_BODY) {
78
- res.writeHead(413);
79
- res.end(JSON.stringify({ error: 'Payload too large' }));
80
- req.destroy();
81
- return;
82
- }
83
- }
84
- // Auth check (after body read, so HMAC can verify body)
85
- if (!this.authenticate(req, config, body)) {
86
- res.writeHead(401);
87
- res.end(JSON.stringify({ error: 'Unauthorized' }));
88
- return;
89
- }
90
- // Rate-limit AFTER auth so unauthenticated callers don't burn the budget
91
- if (!inboundLimiter.check(this.id)) {
92
- res.writeHead(429);
93
- res.end(JSON.stringify({ error: 'Rate limit exceeded' }));
94
- return;
95
- }
96
- let payload;
97
- try {
98
- payload = JSON.parse(body);
99
- }
100
- catch {
101
- res.writeHead(400);
102
- res.end(JSON.stringify({ error: 'Invalid JSON' }));
103
- return;
104
- }
105
- const prompt = payload.prompt || payload.message || '';
106
- if (!prompt) {
107
- res.writeHead(400);
108
- res.end(JSON.stringify({ error: 'Missing "prompt" or "message" field' }));
109
- return;
110
- }
111
- const isSync = payload.sync ?? false;
112
- const remote = req.socket.remoteAddress ?? 'webhook';
113
- try {
114
- if (isSync) {
115
- // Sync mode: route through the shared pipeline so routing/enrichment apply.
116
- const result = await processInboundMessage({
117
- text: prompt,
118
- media: [],
119
- channelId: this.id,
120
- tabManager: this.ctx.tabManager,
121
- userId: remote,
122
- sendProgress: () => {
123
- /* webhook has no progress channel */
124
- },
125
- overrideTabName: tabName,
126
- });
127
- res.writeHead(result.isError ? 500 : 200);
128
- res.end(JSON.stringify({
129
- text: result.responseText,
130
- tab: result.tabName,
131
- error: result.isError ? result.responseText : undefined,
132
- }));
133
- }
134
- else {
135
- // Async mode: fire-and-forget through the pipeline.
136
- // Surface failures to the user via broadcastNotify since the HTTP response
137
- // is already 202 and the caller has no other way to learn.
138
- processInboundMessage({
139
- text: prompt,
140
- media: [],
141
- channelId: this.id,
142
- tabManager: this.ctx.tabManager,
143
- userId: remote,
144
- sendProgress: () => {
145
- /* webhook has no progress channel */
146
- },
147
- overrideTabName: tabName,
148
- })
149
- .then((result) => {
150
- if (result.isError && this.ctx.notifyCallback) {
151
- this.ctx
152
- .notifyCallback(`Webhook async failed for "${tabName}": ${result.responseText}`)
153
- .catch(() => { });
154
- }
155
- })
156
- .catch((err) => {
157
- logger.error(`Webhook async processing failed for tab ${tabName}:`, err);
158
- if (this.ctx.notifyCallback) {
159
- this.ctx
160
- .notifyCallback(`Webhook async failed for "${tabName}": ${err instanceof Error ? err.message : String(err)}`)
161
- .catch(() => { });
162
- }
163
- });
164
- res.writeHead(202);
165
- res.end(JSON.stringify({ accepted: true, tab: tabName }));
166
- }
167
- }
168
- catch (err) {
169
- logger.error('Webhook handler error:', err);
170
- res.writeHead(500);
171
- res.end(JSON.stringify({ error: 'Internal error' }));
172
- }
173
- });
174
- this.server.listen(port, '127.0.0.1', () => {
175
- logger.info(`Webhook channel listening on http://127.0.0.1:${port}/webhook/:tabName`);
176
- });
177
- }
178
- stop() {
179
- if (this.server) {
180
- this.server.close();
181
- this.server = null;
182
- }
183
- logger.info('Webhook channel stopped');
184
- }
185
- async sendMessage(_peerId, _text, _options) {
186
- // Webhooks are request-response — responses are sent in the HTTP handler
187
- }
188
- async sendNotification(_message, _urgent) {
189
- // Webhook channel doesn't have persistent connections to send notifications to
190
- }
191
- async setTyping(_peerId, _active) {
192
- // No typing indicators for webhooks
193
- }
194
- authenticate(req, config, body) {
195
- // No auth configured = allow all (localhost only)
196
- if (!config.authToken && !config.hmacSecret)
197
- return true;
198
- // Bearer token auth (constant-time compare)
199
- if (config.authToken) {
200
- const authHeader = req.headers.authorization || '';
201
- if (safeEqualString(authHeader, `Bearer ${config.authToken}`))
202
- return true;
203
- }
204
- // HMAC signature auth (for GitHub-style webhooks)
205
- if (config.hmacSecret) {
206
- const signature = req.headers['x-hub-signature-256'];
207
- if (signature) {
208
- const expected = 'sha256=' + crypto.createHmac('sha256', config.hmacSecret).update(body).digest('hex');
209
- try {
210
- return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
211
- }
212
- catch {
213
- return false; // Length mismatch or encoding error
214
- }
215
- }
216
- }
217
- return false;
218
- }
219
- getConfig() {
220
- return this.ctx.config.webhook;
221
- }
222
- }
@@ -1,28 +0,0 @@
1
- import type { Channel, ChannelContext, SendOptions } from './types.js';
2
- export declare class WhatsAppChannel implements Channel {
3
- readonly id = "whatsapp";
4
- readonly name = "WhatsApp";
5
- readonly maxMessageLength = 8192;
6
- private sock;
7
- private ctx;
8
- private allowedNumbers;
9
- private reconnectAttempts;
10
- private readonly maxReconnectAttempts;
11
- private readonly backoffDelays;
12
- private voice;
13
- constructor(ctx: ChannelContext);
14
- /**
15
- * Schedule the next reconnect with exponential backoff. Unlike the previous
16
- * inline setTimeout, this path retries when `start()` itself rejects (auth
17
- * failure, baileys init throw, etc.) instead of going permanently silent
18
- * after a single failed attempt.
19
- */
20
- private scheduleReconnect;
21
- start(): Promise<void>;
22
- stop(): void;
23
- sendMessage(peerId: string, text: string, _options?: SendOptions): Promise<void>;
24
- sendNotification(message: string, _urgent?: boolean): Promise<void>;
25
- setTyping(peerId: string, active: boolean): Promise<void>;
26
- private sendResponse;
27
- private isAllowed;
28
- }