clawbee 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,247 @@
1
+ /**
2
+ * ClawBee WhatsApp Integration
3
+ * Real working WhatsApp integration using whatsapp-web.js
4
+ * Connects via QR code scanning
5
+ */
6
+
7
+ const qrcode = require('qrcode-terminal');
8
+ const fs = require('fs');
9
+ const path = require('os').homedir();
10
+
11
+ // Session directory for persistent login
12
+ const SESSION_DIR = `${path}/.local/share/clawbee/integrations/whatsapp`;
13
+
14
+ class WhatsAppBot {
15
+ constructor() {
16
+ this.client = null;
17
+ this.isReady = false;
18
+ this.messageHandler = null;
19
+ this.qrHandler = null;
20
+ this.statusHandler = null;
21
+ }
22
+
23
+ /**
24
+ * Initialize the WhatsApp client
25
+ */
26
+ async initialize() {
27
+ // Dynamic import for whatsapp-web.js (ES module compatibility)
28
+ const { Client, LocalAuth } = await import('whatsapp-web.js');
29
+
30
+ // Ensure session directory exists
31
+ if (!fs.existsSync(SESSION_DIR)) {
32
+ fs.mkdirSync(SESSION_DIR, { recursive: true });
33
+ }
34
+
35
+ this.client = new Client({
36
+ authStrategy: new LocalAuth({
37
+ dataPath: SESSION_DIR
38
+ }),
39
+ puppeteer: {
40
+ headless: true,
41
+ args: [
42
+ '--no-sandbox',
43
+ '--disable-setuid-sandbox',
44
+ '--disable-dev-shm-usage',
45
+ '--disable-accelerated-2d-canvas',
46
+ '--no-first-run',
47
+ '--no-zygote',
48
+ '--disable-gpu'
49
+ ]
50
+ }
51
+ });
52
+
53
+ return this;
54
+ }
55
+
56
+ /**
57
+ * Start the WhatsApp bot
58
+ * @param {Function} messageHandler - Function to handle incoming messages
59
+ * @param {Object} options - Additional options
60
+ */
61
+ async start(messageHandler, options = {}) {
62
+ if (!this.client) {
63
+ await this.initialize();
64
+ }
65
+
66
+ this.messageHandler = messageHandler;
67
+ this.qrHandler = options.onQR || null;
68
+ this.statusHandler = options.onStatus || null;
69
+
70
+ // QR Code event - display for scanning
71
+ this.client.on('qr', (qr) => {
72
+ console.log('\nšŸ Scan this QR code with WhatsApp:\n');
73
+ qrcode.generate(qr, { small: true });
74
+ console.log('\nOpen WhatsApp > Settings > Linked Devices > Link a Device\n');
75
+
76
+ if (this.qrHandler) {
77
+ this.qrHandler(qr);
78
+ }
79
+ });
80
+
81
+ // Ready event - successfully connected
82
+ this.client.on('ready', () => {
83
+ this.isReady = true;
84
+ console.log('šŸ WhatsApp client is ready!');
85
+
86
+ if (this.statusHandler) {
87
+ this.statusHandler('ready', 'WhatsApp connected successfully');
88
+ }
89
+ });
90
+
91
+ // Authentication success
92
+ this.client.on('authenticated', () => {
93
+ console.log('šŸ WhatsApp authenticated');
94
+
95
+ if (this.statusHandler) {
96
+ this.statusHandler('authenticated', 'Authentication successful');
97
+ }
98
+ });
99
+
100
+ // Authentication failure
101
+ this.client.on('auth_failure', (msg) => {
102
+ console.error('šŸ WhatsApp authentication failed:', msg);
103
+
104
+ if (this.statusHandler) {
105
+ this.statusHandler('auth_failure', msg);
106
+ }
107
+ });
108
+
109
+ // Disconnected event
110
+ this.client.on('disconnected', (reason) => {
111
+ this.isReady = false;
112
+ console.log('šŸ WhatsApp disconnected:', reason);
113
+
114
+ if (this.statusHandler) {
115
+ this.statusHandler('disconnected', reason);
116
+ }
117
+ });
118
+
119
+ // Message received event
120
+ this.client.on('message', async (message) => {
121
+ // Skip status updates and own messages
122
+ if (message.isStatus || message.fromMe) return;
123
+
124
+ const chat = await message.getChat();
125
+ const contact = await message.getContact();
126
+
127
+ const context = {
128
+ platform: 'whatsapp',
129
+ chatId: message.from,
130
+ chatName: chat.name || contact.pushname || contact.number,
131
+ username: contact.pushname || contact.name || contact.number,
132
+ isGroup: chat.isGroup,
133
+ messageId: message.id._serialized,
134
+ timestamp: message.timestamp,
135
+ hasMedia: message.hasMedia
136
+ };
137
+
138
+ // Only process text messages for now
139
+ if (message.body && this.messageHandler) {
140
+ try {
141
+ // Show typing indicator
142
+ await chat.sendStateTyping();
143
+
144
+ // Get AI response
145
+ const response = await this.messageHandler(message.body, context);
146
+
147
+ // Send response
148
+ await message.reply(response);
149
+ } catch (error) {
150
+ console.error('WhatsApp message handling error:', error);
151
+ await message.reply(`āŒ Error: ${error.message}`);
152
+ }
153
+ }
154
+ });
155
+
156
+ // Initialize client
157
+ console.log('šŸ Initializing WhatsApp connection...');
158
+ await this.client.initialize();
159
+ }
160
+
161
+ /**
162
+ * Send a message to a specific chat
163
+ * @param {string} chatId - WhatsApp chat ID (number@c.us for contacts, number-id@g.us for groups)
164
+ * @param {string} content - Message content
165
+ */
166
+ async sendMessage(chatId, content) {
167
+ if (!this.isReady) {
168
+ throw new Error('WhatsApp client is not ready');
169
+ }
170
+
171
+ return this.client.sendMessage(chatId, content);
172
+ }
173
+
174
+ /**
175
+ * Get all chats
176
+ */
177
+ async getChats() {
178
+ if (!this.isReady) {
179
+ throw new Error('WhatsApp client is not ready');
180
+ }
181
+
182
+ return this.client.getChats();
183
+ }
184
+
185
+ /**
186
+ * Get contact info
187
+ * @param {string} contactId - Contact ID
188
+ */
189
+ async getContact(contactId) {
190
+ if (!this.isReady) {
191
+ throw new Error('WhatsApp client is not ready');
192
+ }
193
+
194
+ return this.client.getContactById(contactId);
195
+ }
196
+
197
+ /**
198
+ * Get current connection state
199
+ */
200
+ getState() {
201
+ return {
202
+ isReady: this.isReady,
203
+ state: this.client?.info?.wid ? 'connected' : 'disconnected',
204
+ phoneNumber: this.client?.info?.wid?.user || null,
205
+ platform: this.client?.info?.platform || null
206
+ };
207
+ }
208
+
209
+ /**
210
+ * Logout and clear session
211
+ */
212
+ async logout() {
213
+ if (this.client) {
214
+ await this.client.logout();
215
+ this.isReady = false;
216
+
217
+ // Clear session files
218
+ if (fs.existsSync(SESSION_DIR)) {
219
+ fs.rmSync(SESSION_DIR, { recursive: true, force: true });
220
+ }
221
+ }
222
+ }
223
+
224
+ /**
225
+ * Destroy client connection
226
+ */
227
+ async stop() {
228
+ if (this.client) {
229
+ await this.client.destroy();
230
+ this.client = null;
231
+ this.isReady = false;
232
+ }
233
+ }
234
+ }
235
+
236
+ /**
237
+ * Format phone number to WhatsApp ID
238
+ * @param {string} phoneNumber - Phone number with country code
239
+ * @returns {string} WhatsApp chat ID
240
+ */
241
+ function formatWhatsAppId(phoneNumber) {
242
+ // Remove any non-digit characters
243
+ const cleaned = phoneNumber.replace(/\D/g, '');
244
+ return `${cleaned}@c.us`;
245
+ }
246
+
247
+ module.exports = { WhatsAppBot, formatWhatsAppId };
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "clawbee",
3
- "version": "2.1.0",
4
- "description": "ClawBee - Your Personal AI, Endless Possibilities. AI assistant that runs locally and connects to any chat app.",
3
+ "version": "2.2.0",
4
+ "description": "ClawBee - Your Personal AI, Endless Possibilities. AI assistant that runs locally and connects to any chat app. Supports Emergent Universal Key for GPT-5, Claude 4, and Gemini 3.",
5
5
  "main": "lib/index.js",
6
6
  "bin": {
7
7
  "clawbee": "./bin/clawbee.js"
8
8
  },
9
9
  "scripts": {
10
10
  "start": "node bin/clawbee.js start",
11
+ "chat": "node bin/clawbee.js chat",
11
12
  "test": "node bin/clawbee.js status",
12
13
  "postinstall": "echo 'šŸ ClawBee installed! Run: clawbee onboard'"
13
14
  },
@@ -30,12 +31,16 @@
30
31
  "personal-assistant",
31
32
  "openai",
32
33
  "gpt",
34
+ "gpt-5",
33
35
  "claude",
36
+ "claude-4",
34
37
  "anthropic",
35
38
  "gemini",
36
39
  "ollama",
37
40
  "bot",
38
- "local-ai"
41
+ "local-ai",
42
+ "emergent",
43
+ "universal-key"
39
44
  ],
40
45
  "author": "ClawBee Team <hello@clawbee.pro>",
41
46
  "license": "MIT",
@@ -57,11 +62,13 @@
57
62
  "dotenv": "^16.3.1",
58
63
  "inquirer": "^8.2.6",
59
64
  "ora": "^5.4.1",
65
+ "qrcode-terminal": "^0.12.0",
60
66
  "yaml": "^2.3.4"
61
67
  },
62
68
  "optionalDependencies": {
63
69
  "discord.js": "^14.14.1",
64
70
  "@slack/bolt": "^3.17.0",
65
- "puppeteer": "^21.6.0"
71
+ "puppeteer": "^21.6.0",
72
+ "whatsapp-web.js": "^1.34.6"
66
73
  }
67
74
  }