visionclaw 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 (158) hide show
  1. package/README.md +116 -0
  2. package/dist/agent/context.d.ts +56 -0
  3. package/dist/agent/context.d.ts.map +1 -0
  4. package/dist/agent/context.js +142 -0
  5. package/dist/agent/context.js.map +1 -0
  6. package/dist/agent/loop.d.ts +18 -0
  7. package/dist/agent/loop.d.ts.map +1 -0
  8. package/dist/agent/loop.js +323 -0
  9. package/dist/agent/loop.js.map +1 -0
  10. package/dist/agent/session.d.ts +49 -0
  11. package/dist/agent/session.d.ts.map +1 -0
  12. package/dist/agent/session.js +200 -0
  13. package/dist/agent/session.js.map +1 -0
  14. package/dist/agent/system-prompt.d.ts +10 -0
  15. package/dist/agent/system-prompt.d.ts.map +1 -0
  16. package/dist/agent/system-prompt.js +167 -0
  17. package/dist/agent/system-prompt.js.map +1 -0
  18. package/dist/calendar/google-calendar.d.ts +46 -0
  19. package/dist/calendar/google-calendar.d.ts.map +1 -0
  20. package/dist/calendar/google-calendar.js +132 -0
  21. package/dist/calendar/google-calendar.js.map +1 -0
  22. package/dist/calendar/scheduler.d.ts +7 -0
  23. package/dist/calendar/scheduler.d.ts.map +1 -0
  24. package/dist/calendar/scheduler.js +33 -0
  25. package/dist/calendar/scheduler.js.map +1 -0
  26. package/dist/channels/discord.d.ts +19 -0
  27. package/dist/channels/discord.d.ts.map +1 -0
  28. package/dist/channels/discord.js +169 -0
  29. package/dist/channels/discord.js.map +1 -0
  30. package/dist/channels/gmail.d.ts +31 -0
  31. package/dist/channels/gmail.d.ts.map +1 -0
  32. package/dist/channels/gmail.js +300 -0
  33. package/dist/channels/gmail.js.map +1 -0
  34. package/dist/channels/interface.d.ts +45 -0
  35. package/dist/channels/interface.d.ts.map +1 -0
  36. package/dist/channels/interface.js +2 -0
  37. package/dist/channels/interface.js.map +1 -0
  38. package/dist/channels/manager.d.ts +36 -0
  39. package/dist/channels/manager.d.ts.map +1 -0
  40. package/dist/channels/manager.js +108 -0
  41. package/dist/channels/manager.js.map +1 -0
  42. package/dist/channels/queue.d.ts +17 -0
  43. package/dist/channels/queue.d.ts.map +1 -0
  44. package/dist/channels/queue.js +85 -0
  45. package/dist/channels/queue.js.map +1 -0
  46. package/dist/channels/slack.d.ts +17 -0
  47. package/dist/channels/slack.d.ts.map +1 -0
  48. package/dist/channels/slack.js +142 -0
  49. package/dist/channels/slack.js.map +1 -0
  50. package/dist/channels/sms.d.ts +19 -0
  51. package/dist/channels/sms.d.ts.map +1 -0
  52. package/dist/channels/sms.js +111 -0
  53. package/dist/channels/sms.js.map +1 -0
  54. package/dist/channels/telegram.d.ts +28 -0
  55. package/dist/channels/telegram.d.ts.map +1 -0
  56. package/dist/channels/telegram.js +246 -0
  57. package/dist/channels/telegram.js.map +1 -0
  58. package/dist/channels/whatsapp.d.ts +28 -0
  59. package/dist/channels/whatsapp.d.ts.map +1 -0
  60. package/dist/channels/whatsapp.js +292 -0
  61. package/dist/channels/whatsapp.js.map +1 -0
  62. package/dist/config/index.d.ts +24 -0
  63. package/dist/config/index.d.ts.map +1 -0
  64. package/dist/config/index.js +104 -0
  65. package/dist/config/index.js.map +1 -0
  66. package/dist/config/types.d.ts +227 -0
  67. package/dist/config/types.d.ts.map +1 -0
  68. package/dist/config/types.js +45 -0
  69. package/dist/config/types.js.map +1 -0
  70. package/dist/files.d.ts +20 -0
  71. package/dist/files.d.ts.map +1 -0
  72. package/dist/files.js +82 -0
  73. package/dist/files.js.map +1 -0
  74. package/dist/index.d.ts +3 -0
  75. package/dist/index.d.ts.map +1 -0
  76. package/dist/index.js +54 -0
  77. package/dist/index.js.map +1 -0
  78. package/dist/logger.d.ts +76 -0
  79. package/dist/logger.d.ts.map +1 -0
  80. package/dist/logger.js +384 -0
  81. package/dist/logger.js.map +1 -0
  82. package/dist/memory/store.d.ts +24 -0
  83. package/dist/memory/store.d.ts.map +1 -0
  84. package/dist/memory/store.js +71 -0
  85. package/dist/memory/store.js.map +1 -0
  86. package/dist/obs/server.d.ts +10 -0
  87. package/dist/obs/server.d.ts.map +1 -0
  88. package/dist/obs/server.js +406 -0
  89. package/dist/obs/server.js.map +1 -0
  90. package/dist/onboarding/google-auth.d.ts +11 -0
  91. package/dist/onboarding/google-auth.d.ts.map +1 -0
  92. package/dist/onboarding/google-auth.js +113 -0
  93. package/dist/onboarding/google-auth.js.map +1 -0
  94. package/dist/onboarding/index.d.ts +2 -0
  95. package/dist/onboarding/index.d.ts.map +1 -0
  96. package/dist/onboarding/index.js +213 -0
  97. package/dist/onboarding/index.js.map +1 -0
  98. package/dist/onboarding/macos-permissions.d.ts +37 -0
  99. package/dist/onboarding/macos-permissions.d.ts.map +1 -0
  100. package/dist/onboarding/macos-permissions.js +207 -0
  101. package/dist/onboarding/macos-permissions.js.map +1 -0
  102. package/dist/skills/install.d.ts +7 -0
  103. package/dist/skills/install.d.ts.map +1 -0
  104. package/dist/skills/install.js +63 -0
  105. package/dist/skills/install.js.map +1 -0
  106. package/dist/tools/browser.d.ts +7 -0
  107. package/dist/tools/browser.d.ts.map +1 -0
  108. package/dist/tools/browser.js +202 -0
  109. package/dist/tools/browser.js.map +1 -0
  110. package/dist/tools/calendar.d.ts +12 -0
  111. package/dist/tools/calendar.d.ts.map +1 -0
  112. package/dist/tools/calendar.js +210 -0
  113. package/dist/tools/calendar.js.map +1 -0
  114. package/dist/tools/computer-use.d.ts +28 -0
  115. package/dist/tools/computer-use.d.ts.map +1 -0
  116. package/dist/tools/computer-use.js +311 -0
  117. package/dist/tools/computer-use.js.map +1 -0
  118. package/dist/tools/coordinate-resolver.d.ts +26 -0
  119. package/dist/tools/coordinate-resolver.d.ts.map +1 -0
  120. package/dist/tools/coordinate-resolver.js +157 -0
  121. package/dist/tools/coordinate-resolver.js.map +1 -0
  122. package/dist/tools/desktop-executor.d.ts +52 -0
  123. package/dist/tools/desktop-executor.d.ts.map +1 -0
  124. package/dist/tools/desktop-executor.js +202 -0
  125. package/dist/tools/desktop-executor.js.map +1 -0
  126. package/dist/tools/finish.d.ts +5 -0
  127. package/dist/tools/finish.d.ts.map +1 -0
  128. package/dist/tools/finish.js +18 -0
  129. package/dist/tools/finish.js.map +1 -0
  130. package/dist/tools/index.d.ts +7 -0
  131. package/dist/tools/index.d.ts.map +1 -0
  132. package/dist/tools/index.js +37 -0
  133. package/dist/tools/index.js.map +1 -0
  134. package/dist/tools/memory.d.ts +14 -0
  135. package/dist/tools/memory.d.ts.map +1 -0
  136. package/dist/tools/memory.js +269 -0
  137. package/dist/tools/memory.js.map +1 -0
  138. package/dist/tools/notify.d.ts +12 -0
  139. package/dist/tools/notify.d.ts.map +1 -0
  140. package/dist/tools/notify.js +108 -0
  141. package/dist/tools/notify.js.map +1 -0
  142. package/dist/tools/screenshot.d.ts +7 -0
  143. package/dist/tools/screenshot.d.ts.map +1 -0
  144. package/dist/tools/screenshot.js +189 -0
  145. package/dist/tools/screenshot.js.map +1 -0
  146. package/dist/tools/skill.d.ts +8 -0
  147. package/dist/tools/skill.d.ts.map +1 -0
  148. package/dist/tools/skill.js +133 -0
  149. package/dist/tools/skill.js.map +1 -0
  150. package/dist/tools/upgrade.d.ts +5 -0
  151. package/dist/tools/upgrade.d.ts.map +1 -0
  152. package/dist/tools/upgrade.js +89 -0
  153. package/dist/tools/upgrade.js.map +1 -0
  154. package/dist/tools/wait.d.ts +5 -0
  155. package/dist/tools/wait.d.ts.map +1 -0
  156. package/dist/tools/wait.js +21 -0
  157. package/dist/tools/wait.js.map +1 -0
  158. package/package.json +61 -0
@@ -0,0 +1,28 @@
1
+ import { EventEmitter } from "node:events";
2
+ import type { VisionClawConfig } from "../config/types.js";
3
+ import type { ChannelAdapter, MessageAttachment } from "./interface.js";
4
+ /**
5
+ * Telegram channel adapter.
6
+ * Supports multimodal inbound (photos, documents, voice) and
7
+ * outbound (photos, documents) messages.
8
+ */
9
+ export declare class TelegramAdapter extends EventEmitter implements ChannelAdapter {
10
+ readonly name = "telegram";
11
+ private config;
12
+ private bot;
13
+ constructor(config: VisionClawConfig);
14
+ start(): Promise<void>;
15
+ stop(): Promise<void>;
16
+ sendMessage(to: string, message: string, attachments?: MessageAttachment[]): Promise<void>;
17
+ /**
18
+ * Process an inbound Telegram message, downloading any media
19
+ * and uploading to S3 before emitting the CommandMessage.
20
+ */
21
+ private processInboundMessage;
22
+ /**
23
+ * Download a file from Telegram and upload to S3.
24
+ * Returns the S3 public URL, or null on failure.
25
+ */
26
+ private downloadAndUpload;
27
+ }
28
+ //# sourceMappingURL=telegram.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telegram.d.ts","sourceRoot":"","sources":["../../src/channels/telegram.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAK3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAkB,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAOxF;;;;GAIG;AACH,qBAAa,eAAgB,SAAQ,YAAa,YAAW,cAAc;IACzE,QAAQ,CAAC,IAAI,cAAc;IAC3B,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,GAAG,CAA4B;gBAE3B,MAAM,EAAE,gBAAgB;IAKpC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA2BhB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAOrB,WAAW,CACf,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,EACf,WAAW,CAAC,EAAE,iBAAiB,EAAE,GAChC,OAAO,CAAC,IAAI,CAAC;IAuFhB;;;OAGG;YACW,qBAAqB;IAiHnC;;;OAGG;YACW,iBAAiB;CA8BhC"}
@@ -0,0 +1,246 @@
1
+ import { EventEmitter } from "node:events";
2
+ import fs from "node:fs";
3
+ import TelegramBot from "node-telegram-bot-api";
4
+ import { logger } from "../logger.js";
5
+ import { uploadMedia } from "../files.js";
6
+ // Enable proper fileOptions (filename, contentType) handling in node-telegram-bot-api.
7
+ // Without this, the library ignores the fileOptions argument and emits a deprecation warning.
8
+ // See: https://github.com/yagop/node-telegram-bot-api/blob/master/doc/usage.md#file-options-metadata
9
+ process.env.NTBA_FIX_350 = "1";
10
+ /**
11
+ * Telegram channel adapter.
12
+ * Supports multimodal inbound (photos, documents, voice) and
13
+ * outbound (photos, documents) messages.
14
+ */
15
+ export class TelegramAdapter extends EventEmitter {
16
+ name = "telegram";
17
+ config;
18
+ bot = null;
19
+ constructor(config) {
20
+ super();
21
+ this.config = config;
22
+ }
23
+ start() {
24
+ const botToken = this.config.channels.telegram?.botToken;
25
+ if (!botToken) {
26
+ throw new Error("Telegram bot token not configured");
27
+ }
28
+ this.bot = new TelegramBot(botToken, { polling: true });
29
+ this.bot.on("message", (msg) => {
30
+ // Optionally filter by allowed chat IDs
31
+ const allowedChats = this.config.channels.telegram?.allowedChatIds ?? [];
32
+ if (allowedChats.length > 0 && !allowedChats.includes(msg.chat.id)) {
33
+ return;
34
+ }
35
+ // Process message asynchronously (to allow media downloads)
36
+ void this.processInboundMessage(msg);
37
+ });
38
+ this.bot.on("polling_error", (err) => {
39
+ this.emit("error", err);
40
+ });
41
+ return Promise.resolve();
42
+ }
43
+ async stop() {
44
+ if (this.bot) {
45
+ await this.bot.stopPolling();
46
+ this.bot = null;
47
+ }
48
+ }
49
+ async sendMessage(to, message, attachments) {
50
+ if (!this.bot) {
51
+ throw new Error("Telegram bot not started");
52
+ }
53
+ // Extract numeric chat ID from sender string like "Name (12345)" or plain "12345"
54
+ const match = /\((\d+)\)/.exec(to) ?? /^(\d+)$/.exec(to);
55
+ const chatId = match ? Number(match[1]) : NaN;
56
+ if (isNaN(chatId)) {
57
+ throw new Error(`Invalid Telegram chat ID: ${to}`);
58
+ }
59
+ // Send attachments first
60
+ if (attachments && attachments.length > 0) {
61
+ for (const att of attachments) {
62
+ // Resolve the source: prefer local file path, then URL
63
+ let source;
64
+ if (att.localPath) {
65
+ source = att.localPath;
66
+ }
67
+ else if (att.url) {
68
+ // Validate URL has a proper host before sending to Telegram
69
+ try {
70
+ const parsed = new URL(att.url);
71
+ if (!parsed.host) {
72
+ logger.warn(`Telegram: Skipping attachment with empty URL host: ${att.url}`);
73
+ continue;
74
+ }
75
+ source = att.url;
76
+ }
77
+ catch {
78
+ // Not a valid URL — treat as local file path if it looks like one
79
+ if (att.url.startsWith("/")) {
80
+ source = att.url;
81
+ }
82
+ else {
83
+ logger.warn(`Telegram: Skipping attachment with invalid URL: ${att.url}`);
84
+ continue;
85
+ }
86
+ }
87
+ }
88
+ if (!source)
89
+ continue;
90
+ // For local files, use a read stream so node-telegram-bot-api
91
+ // sends the file content directly with the correct content type
92
+ // (avoids the deprecated auto-detect behaviour).
93
+ const isLocal = source.startsWith("/");
94
+ const fileSource = isLocal ? fs.createReadStream(source) : source;
95
+ const fileOpts = {
96
+ filename: att.filename ?? (isLocal ? source.split("/").pop() : undefined),
97
+ contentType: att.mimeType ?? "application/octet-stream",
98
+ };
99
+ try {
100
+ switch (att.type) {
101
+ case "image":
102
+ await this.bot.sendPhoto(chatId, fileSource, { caption: att.filename }, fileOpts);
103
+ break;
104
+ case "audio":
105
+ await this.bot.sendVoice(chatId, fileSource, {}, fileOpts);
106
+ break;
107
+ case "video":
108
+ await this.bot.sendVideo(chatId, fileSource, { caption: att.filename }, fileOpts);
109
+ break;
110
+ case "file":
111
+ await this.bot.sendDocument(chatId, fileSource, { caption: att.filename }, fileOpts);
112
+ break;
113
+ }
114
+ }
115
+ catch (err) {
116
+ logger.warn(`Telegram: Failed to send ${att.type}: ${err instanceof Error ? err.message : String(err)}`);
117
+ }
118
+ }
119
+ }
120
+ // Send text message
121
+ if (message.trim()) {
122
+ const MAX_LENGTH = 4096;
123
+ if (message.length <= MAX_LENGTH) {
124
+ await this.bot.sendMessage(chatId, message);
125
+ }
126
+ else {
127
+ for (let i = 0; i < message.length; i += MAX_LENGTH) {
128
+ await this.bot.sendMessage(chatId, message.substring(i, i + MAX_LENGTH));
129
+ }
130
+ }
131
+ }
132
+ }
133
+ /**
134
+ * Process an inbound Telegram message, downloading any media
135
+ * and uploading to S3 before emitting the CommandMessage.
136
+ */
137
+ async processInboundMessage(msg) {
138
+ try {
139
+ const fromName = [msg.from?.first_name, msg.from?.last_name]
140
+ .filter(Boolean)
141
+ .join(" ");
142
+ const senderDisplay = fromName
143
+ ? `${fromName} (${msg.chat.id})`
144
+ : String(msg.chat.id);
145
+ const commandMessage = {
146
+ id: `telegram-${msg.message_id}-${msg.chat.id}`,
147
+ channel: "telegram",
148
+ sender: senderDisplay,
149
+ text: msg.text ?? msg.caption ?? "",
150
+ attachments: [],
151
+ timestamp: new Date(msg.date * 1000).toISOString(),
152
+ meta: {
153
+ chatId: msg.chat.id,
154
+ messageId: msg.message_id,
155
+ from: msg.from,
156
+ chatType: msg.chat.type,
157
+ username: msg.from?.username,
158
+ },
159
+ };
160
+ // Handle photos -- download and upload to S3
161
+ if (msg.photo && msg.photo.length > 0) {
162
+ const largestPhoto = msg.photo[msg.photo.length - 1];
163
+ const url = await this.downloadAndUpload(largestPhoto.file_id, "photo.jpg", "image/jpeg");
164
+ commandMessage.attachments.push({
165
+ type: "image",
166
+ url: url ?? largestPhoto.file_id,
167
+ mimeType: "image/jpeg",
168
+ });
169
+ }
170
+ // Handle documents
171
+ if (msg.document) {
172
+ const filename = msg.document.file_name ?? "document";
173
+ const mimeType = msg.document.mime_type ?? "application/octet-stream";
174
+ const url = await this.downloadAndUpload(msg.document.file_id, filename, mimeType);
175
+ commandMessage.attachments.push({
176
+ type: mimeType.startsWith("image/") ? "image" : "file",
177
+ url: url ?? msg.document.file_id,
178
+ filename,
179
+ mimeType,
180
+ });
181
+ }
182
+ // Handle voice messages
183
+ if (msg.voice) {
184
+ const mimeType = msg.voice.mime_type ?? "audio/ogg";
185
+ const url = await this.downloadAndUpload(msg.voice.file_id, "voice.ogg", mimeType);
186
+ commandMessage.attachments.push({
187
+ type: "audio",
188
+ url: url ?? msg.voice.file_id,
189
+ mimeType,
190
+ });
191
+ }
192
+ // Handle video
193
+ if (msg.video) {
194
+ const mimeType = msg.video.mime_type ?? "video/mp4";
195
+ const url = await this.downloadAndUpload(msg.video.file_id, "video.mp4", mimeType);
196
+ commandMessage.attachments.push({
197
+ type: "video",
198
+ url: url ?? msg.video.file_id,
199
+ mimeType,
200
+ });
201
+ }
202
+ // Handle stickers as images
203
+ if (msg.sticker) {
204
+ const url = await this.downloadAndUpload(msg.sticker.file_id, "sticker.webp", "image/webp");
205
+ commandMessage.attachments.push({
206
+ type: "image",
207
+ url: url ?? msg.sticker.file_id,
208
+ mimeType: "image/webp",
209
+ });
210
+ }
211
+ if (commandMessage.text || commandMessage.attachments.length > 0) {
212
+ this.emit("message", commandMessage);
213
+ }
214
+ }
215
+ catch (err) {
216
+ logger.warn(`Telegram: Error processing message: ${err instanceof Error ? err.message : String(err)}`);
217
+ }
218
+ }
219
+ /**
220
+ * Download a file from Telegram and upload to S3.
221
+ * Returns the S3 public URL, or null on failure.
222
+ */
223
+ async downloadAndUpload(fileId, filename, contentType) {
224
+ if (!this.bot)
225
+ return null;
226
+ try {
227
+ // Get download URL from Telegram
228
+ const fileLink = await this.bot.getFileLink(fileId);
229
+ // Download the file
230
+ const response = await fetch(fileLink);
231
+ if (!response.ok) {
232
+ logger.warn(`Telegram: Failed to download file: ${response.status}`);
233
+ return null;
234
+ }
235
+ const arrayBuffer = await response.arrayBuffer();
236
+ const buffer = Buffer.from(arrayBuffer);
237
+ // Upload to S3
238
+ return await uploadMedia(buffer, filename, contentType);
239
+ }
240
+ catch (err) {
241
+ logger.warn(`Telegram: Failed to download/upload media: ${err instanceof Error ? err.message : String(err)}`);
242
+ return null;
243
+ }
244
+ }
245
+ }
246
+ //# sourceMappingURL=telegram.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telegram.js","sourceRoot":"","sources":["../../src/channels/telegram.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { EventEmitter } from "node:events";
2
+ import type { VisionClawConfig } from "../config/types.js";
3
+ import type { ChannelAdapter, MessageAttachment } from "./interface.js";
4
+ /**
5
+ * WhatsApp channel adapter using the WhatsApp Cloud API.
6
+ * Supports multimodal inbound (images, audio, video, documents) and
7
+ * outbound (images, documents) messages.
8
+ */
9
+ export declare class WhatsAppAdapter extends EventEmitter implements ChannelAdapter {
10
+ readonly name = "whatsapp";
11
+ private config;
12
+ private server;
13
+ private port;
14
+ constructor(config: VisionClawConfig);
15
+ start(): Promise<void>;
16
+ stop(): Promise<void>;
17
+ sendMessage(to: string, message: string, attachments?: MessageAttachment[]): Promise<void>;
18
+ /**
19
+ * Process inbound webhook payload. Downloads media attachments
20
+ * and uploads to S3 before emitting the CommandMessage.
21
+ */
22
+ private processWebhookPayload;
23
+ /**
24
+ * Download media from WhatsApp and upload to S3.
25
+ */
26
+ private downloadAndUploadWhatsAppMedia;
27
+ }
28
+ //# sourceMappingURL=whatsapp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whatsapp.d.ts","sourceRoot":"","sources":["../../src/channels/whatsapp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAG3D,OAAO,KAAK,EAAE,cAAc,EAAkB,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAExF;;;;GAIG;AACH,qBAAa,eAAgB,SAAQ,YAAa,YAAW,cAAc;IACzE,QAAQ,CAAC,IAAI,cAAc;IAC3B,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,IAAI,CAAQ;gBAER,MAAM,EAAE,gBAAgB;IAK9B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA8DtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAWrB,WAAW,CACf,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,EACf,WAAW,CAAC,EAAE,iBAAiB,EAAE,GAChC,OAAO,CAAC,IAAI,CAAC;IA+FhB;;;OAGG;YACW,qBAAqB;IA0GnC;;OAEG;YACW,8BAA8B;CAqC7C"}
@@ -0,0 +1,292 @@
1
+ import { EventEmitter } from "node:events";
2
+ import http from "node:http";
3
+ import { URL } from "node:url";
4
+ import { logger } from "../logger.js";
5
+ import { uploadMedia } from "../files.js";
6
+ /**
7
+ * WhatsApp channel adapter using the WhatsApp Cloud API.
8
+ * Supports multimodal inbound (images, audio, video, documents) and
9
+ * outbound (images, documents) messages.
10
+ */
11
+ export class WhatsAppAdapter extends EventEmitter {
12
+ name = "whatsapp";
13
+ config;
14
+ server = null;
15
+ port = 3001;
16
+ constructor(config) {
17
+ super();
18
+ this.config = config;
19
+ }
20
+ async start() {
21
+ const whatsappConfig = this.config.channels.whatsapp;
22
+ if (!whatsappConfig)
23
+ throw new Error("WhatsApp channel not configured");
24
+ if (!whatsappConfig.phoneNumberId || !whatsappConfig.accessToken) {
25
+ throw new Error("WhatsApp phoneNumberId and accessToken are required");
26
+ }
27
+ this.server = http.createServer((req, res) => {
28
+ const url = new URL(req.url ?? "/", `http://localhost:${this.port}`);
29
+ // Webhook verification
30
+ if (req.method === "GET" && url.pathname === "/webhook") {
31
+ const mode = url.searchParams.get("hub.mode");
32
+ const token = url.searchParams.get("hub.verify_token");
33
+ const challenge = url.searchParams.get("hub.challenge");
34
+ if (mode === "subscribe" && token === whatsappConfig.verifyToken) {
35
+ res.writeHead(200);
36
+ res.end(challenge);
37
+ }
38
+ else {
39
+ res.writeHead(403);
40
+ res.end("Forbidden");
41
+ }
42
+ return;
43
+ }
44
+ // Webhook messages
45
+ if (req.method === "POST" && url.pathname === "/webhook") {
46
+ let body = "";
47
+ req.on("data", (chunk) => (body += String(chunk)));
48
+ req.on("end", () => {
49
+ try {
50
+ const data = JSON.parse(body);
51
+ void this.processWebhookPayload(data);
52
+ }
53
+ catch (err) {
54
+ logger.warn(`WhatsApp: Error parsing webhook: ${err instanceof Error ? err.message : String(err)}`);
55
+ }
56
+ res.writeHead(200);
57
+ res.end("OK");
58
+ });
59
+ return;
60
+ }
61
+ res.writeHead(404);
62
+ res.end("Not found");
63
+ });
64
+ return new Promise((resolve) => {
65
+ const server = this.server;
66
+ if (server) {
67
+ server.listen(this.port, () => {
68
+ logger.channel("whatsapp", `Webhook listening on port ${this.port}`);
69
+ resolve();
70
+ });
71
+ }
72
+ else {
73
+ resolve();
74
+ }
75
+ });
76
+ }
77
+ async stop() {
78
+ return new Promise((resolve) => {
79
+ if (this.server) {
80
+ this.server.close(() => resolve());
81
+ this.server = null;
82
+ }
83
+ else {
84
+ resolve();
85
+ }
86
+ });
87
+ }
88
+ async sendMessage(to, message, attachments) {
89
+ const whatsappConfig = this.config.channels.whatsapp;
90
+ if (!whatsappConfig)
91
+ throw new Error("WhatsApp not configured");
92
+ if (!whatsappConfig.phoneNumberId || !whatsappConfig.accessToken) {
93
+ throw new Error("WhatsApp configuration incomplete");
94
+ }
95
+ const apiUrl = `https://graph.facebook.com/v18.0/${whatsappConfig.phoneNumberId}/messages`;
96
+ const headers = {
97
+ Authorization: `Bearer ${whatsappConfig.accessToken}`,
98
+ "Content-Type": "application/json",
99
+ };
100
+ // Send attachments first
101
+ if (attachments && attachments.length > 0) {
102
+ for (const att of attachments) {
103
+ const mediaUrl = att.url ?? att.localPath;
104
+ if (!mediaUrl)
105
+ continue;
106
+ try {
107
+ // For local files, we need to upload to WhatsApp media first
108
+ // For URLs, we can send directly via link
109
+ let body;
110
+ if (att.type === "image") {
111
+ body = {
112
+ messaging_product: "whatsapp",
113
+ to,
114
+ type: "image",
115
+ image: { link: mediaUrl },
116
+ };
117
+ }
118
+ else if (att.type === "audio") {
119
+ body = {
120
+ messaging_product: "whatsapp",
121
+ to,
122
+ type: "audio",
123
+ audio: { link: mediaUrl },
124
+ };
125
+ }
126
+ else if (att.type === "video") {
127
+ body = {
128
+ messaging_product: "whatsapp",
129
+ to,
130
+ type: "video",
131
+ video: { link: mediaUrl },
132
+ };
133
+ }
134
+ else {
135
+ body = {
136
+ messaging_product: "whatsapp",
137
+ to,
138
+ type: "document",
139
+ document: {
140
+ link: mediaUrl,
141
+ filename: att.filename ?? "document",
142
+ },
143
+ };
144
+ }
145
+ const response = await fetch(apiUrl, {
146
+ method: "POST",
147
+ headers,
148
+ body: JSON.stringify(body),
149
+ });
150
+ if (!response.ok) {
151
+ const text = await response.text();
152
+ logger.warn(`WhatsApp: Failed to send ${att.type}: ${response.status} ${text}`);
153
+ }
154
+ }
155
+ catch (err) {
156
+ logger.warn(`WhatsApp: Failed to send ${att.type}: ${err instanceof Error ? err.message : String(err)}`);
157
+ }
158
+ }
159
+ }
160
+ // Send text message
161
+ if (message.trim()) {
162
+ const response = await fetch(apiUrl, {
163
+ method: "POST",
164
+ headers,
165
+ body: JSON.stringify({
166
+ messaging_product: "whatsapp",
167
+ to,
168
+ type: "text",
169
+ text: { body: message },
170
+ }),
171
+ });
172
+ if (!response.ok) {
173
+ const text = await response.text();
174
+ throw new Error(`WhatsApp API error: ${response.status} ${text}`);
175
+ }
176
+ }
177
+ }
178
+ /**
179
+ * Process inbound webhook payload. Downloads media attachments
180
+ * and uploads to S3 before emitting the CommandMessage.
181
+ */
182
+ async processWebhookPayload(data) {
183
+ try {
184
+ const whatsappConfig = this.config.channels.whatsapp;
185
+ const accessToken = whatsappConfig?.accessToken ?? "";
186
+ const entry = data.entry ?? [];
187
+ for (const e of entry) {
188
+ const changes = e.changes ?? [];
189
+ for (const change of changes) {
190
+ const value = change.value;
191
+ if (typeof value !== "object" || value === null)
192
+ continue;
193
+ const valueObj = value;
194
+ const messages = valueObj.messages ?? [];
195
+ for (const msg of messages) {
196
+ const msgType = typeof msg.type === "string" ? msg.type : "text";
197
+ const msgId = typeof msg.id === "string" || typeof msg.id === "number"
198
+ ? String(msg.id)
199
+ : String(Date.now());
200
+ const sender = typeof msg.from === "string" || typeof msg.from === "number"
201
+ ? String(msg.from)
202
+ : "unknown";
203
+ // Extract text
204
+ let textBody = "";
205
+ if (msgType === "text") {
206
+ const textObj = msg.text;
207
+ if (typeof textObj === "object" && textObj !== null && "body" in textObj) {
208
+ const bodyVal = textObj.body;
209
+ textBody = typeof bodyVal === "string" ? bodyVal : "";
210
+ }
211
+ }
212
+ const commandMessage = {
213
+ id: `whatsapp-${msgId}`,
214
+ channel: "whatsapp",
215
+ sender,
216
+ text: textBody,
217
+ attachments: [],
218
+ timestamp: new Date(Number(msg.timestamp ?? 0) * 1000).toISOString(),
219
+ meta: { waMessageId: msg.id, type: msgType },
220
+ };
221
+ // Handle media messages (image, audio, video, document)
222
+ const mediaTypes = ["image", "audio", "video", "document"];
223
+ for (const mediaType of mediaTypes) {
224
+ if (msgType !== mediaType)
225
+ continue;
226
+ const mediaObj = msg[mediaType];
227
+ if (typeof mediaObj !== "object" || mediaObj === null)
228
+ continue;
229
+ const mediaData = mediaObj;
230
+ const mediaId = typeof mediaData.id === "string" ? mediaData.id : null;
231
+ const mimeType = typeof mediaData.mime_type === "string"
232
+ ? mediaData.mime_type
233
+ : "application/octet-stream";
234
+ if (mediaId) {
235
+ const url = await this.downloadAndUploadWhatsAppMedia(mediaId, accessToken, `${mediaType}-${msgId}`, mimeType);
236
+ const attType = mediaType === "document" ? "file" : mediaType;
237
+ commandMessage.attachments.push({
238
+ type: attType,
239
+ url: url ?? undefined,
240
+ mimeType,
241
+ filename: typeof mediaData.filename === "string"
242
+ ? mediaData.filename
243
+ : undefined,
244
+ });
245
+ }
246
+ // Use caption as text if available
247
+ if (typeof mediaData.caption === "string" && !textBody) {
248
+ commandMessage.text = mediaData.caption;
249
+ }
250
+ }
251
+ if (commandMessage.text.length > 0 || commandMessage.attachments.length > 0) {
252
+ this.emit("message", commandMessage);
253
+ }
254
+ }
255
+ }
256
+ }
257
+ }
258
+ catch (err) {
259
+ logger.warn(`WhatsApp: Error processing payload: ${err instanceof Error ? err.message : String(err)}`);
260
+ }
261
+ }
262
+ /**
263
+ * Download media from WhatsApp and upload to S3.
264
+ */
265
+ async downloadAndUploadWhatsAppMedia(mediaId, accessToken, filename, contentType) {
266
+ try {
267
+ // Step 1: Get media URL from WhatsApp
268
+ const mediaInfoRes = await fetch(`https://graph.facebook.com/v18.0/${mediaId}`, { headers: { Authorization: `Bearer ${accessToken}` } });
269
+ if (!mediaInfoRes.ok)
270
+ return null;
271
+ const mediaInfo = (await mediaInfoRes.json());
272
+ const mediaUrl = typeof mediaInfo.url === "string" ? mediaInfo.url : null;
273
+ if (!mediaUrl)
274
+ return null;
275
+ // Step 2: Download the media
276
+ const downloadRes = await fetch(mediaUrl, {
277
+ headers: { Authorization: `Bearer ${accessToken}` },
278
+ });
279
+ if (!downloadRes.ok)
280
+ return null;
281
+ const arrayBuffer = await downloadRes.arrayBuffer();
282
+ const buffer = Buffer.from(arrayBuffer);
283
+ // Step 3: Upload to S3
284
+ return await uploadMedia(buffer, filename, contentType);
285
+ }
286
+ catch (err) {
287
+ logger.warn(`WhatsApp: Failed to download/upload media: ${err instanceof Error ? err.message : String(err)}`);
288
+ return null;
289
+ }
290
+ }
291
+ }
292
+ //# sourceMappingURL=whatsapp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whatsapp.js","sourceRoot":"","sources":["../../src/channels/whatsapp.ts"],"names":[],"mappings":"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"}