whatsapp-pi 1.0.24 → 1.0.25

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "whatsapp-pi",
3
- "version": "1.0.24",
3
+ "version": "1.0.25",
4
4
  "type": "module",
5
5
  "description": "WhatsApp integration extension for Pi",
6
6
  "main": "whatsapp-pi.ts",
@@ -242,6 +242,44 @@ export class WhatsAppService {
242
242
  return result;
243
243
  }
244
244
 
245
+ private normalizeRecipientJid(jid: string): string {
246
+ if (jid.includes('@')) return jid;
247
+ const digits = jid.startsWith('+') ? jid.slice(1) : jid;
248
+ return `${digits}@s.whatsapp.net`;
249
+ }
250
+
251
+ async sendMenuMessage(jid: string, text: string) {
252
+ const normalizedJid = this.normalizeRecipientJid(jid);
253
+
254
+ if (!this.socket || this.getStatus() !== 'connected') {
255
+ return {
256
+ success: false,
257
+ error: 'WhatsApp is not connected',
258
+ attempts: 0
259
+ };
260
+ }
261
+
262
+ try {
263
+ await this.sendPresence(normalizedJid, 'composing');
264
+ const response = await this.socket.sendMessage(normalizedJid, { text });
265
+ await this.sendPresence(normalizedJid, 'paused');
266
+
267
+ return {
268
+ success: true,
269
+ messageId: response?.key?.id,
270
+ attempts: 1
271
+ };
272
+ } catch (error: any) {
273
+ await this.sendPresence(normalizedJid, 'paused');
274
+ console.error(`Failed to send menu message to ${normalizedJid}:`, error);
275
+ return {
276
+ success: false,
277
+ error: error?.message || 'Unknown error',
278
+ attempts: 1
279
+ };
280
+ }
281
+ }
282
+
245
283
  async sendPresence(jid: string, presence: 'composing' | 'recording' | 'paused') {
246
284
  if (!this.socket || this.getStatus() !== 'connected') return;
247
285
  try {
@@ -311,7 +311,7 @@ export class MenuHandler {
311
311
  continue;
312
312
  }
313
313
 
314
- const result = await this.whatsappService.sendMessage(this.toJid(conversation.senderNumber), trimmed);
314
+ const result = await this.whatsappService.sendMenuMessage(this.toJid(conversation.senderNumber), trimmed);
315
315
  if (result.success) {
316
316
  await this.recentsService.recordMessage({
317
317
  messageId: result.messageId ?? `${Date.now()}`,
@@ -323,7 +323,7 @@ export class MenuHandler {
323
323
  });
324
324
  ctx.ui.notify(`Sent message to ${displayName}`, 'info');
325
325
  } else {
326
- ctx.ui.notify(`Failed to send message to ${displayName}`, 'error');
326
+ ctx.ui.notify(`Failed to send message to ${displayName}: ${result.error ?? 'Unknown error'}`, 'error');
327
327
  }
328
328
  return;
329
329
  }
@@ -340,7 +340,7 @@ export class MenuHandler {
340
340
  continue;
341
341
  }
342
342
 
343
- const result = await this.whatsappService.sendMessage(this.toJid(contact.number), trimmed);
343
+ const result = await this.whatsappService.sendMenuMessage(this.toJid(contact.number), trimmed);
344
344
  if (result.success) {
345
345
  await this.recentsService.recordMessage({
346
346
  messageId: result.messageId ?? `${Date.now()}`,
@@ -352,7 +352,7 @@ export class MenuHandler {
352
352
  });
353
353
  ctx.ui.notify(`Sent message to ${displayName}`, 'info');
354
354
  } else {
355
- ctx.ui.notify(`Failed to send message to ${displayName}`, 'error');
355
+ ctx.ui.notify(`Failed to send message to ${displayName}: ${result.error ?? 'Unknown error'}`, 'error');
356
356
  }
357
357
  return;
358
358
  }
package/whatsapp-pi.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { ExtensionAPI, ExtensionCommandContext, ExtensionContext } from "@mariozechner/pi-coding-agent";
2
+ import { Type } from "@sinclair/typebox";
2
3
  import { extractMessageContent } from '@whiskeysockets/baileys';
3
4
  import { SessionManager } from './src/services/session.manager.js';
4
5
  import { WhatsAppService } from './src/services/whatsapp.service.js';
@@ -99,7 +100,7 @@ export default function (pi: ExtensionAPI) {
99
100
  .find(entry => entry.type === "custom" && entry.customType === "whatsapp-state");
100
101
 
101
102
  if (savedStateEntry) {
102
- const data = savedStateEntry.data as any;
103
+ const data = (savedStateEntry as { data?: any }).data;
103
104
  if (data.status) await sessionManager.setStatus(data.status);
104
105
  if (Array.isArray(data.allowList)) {
105
106
  for (const n of data.allowList) {
@@ -428,6 +429,45 @@ export default function (pi: ExtensionAPI) {
428
429
 
429
430
  });
430
431
 
432
+ // Register send_wa_message tool (LLM-callable)
433
+ pi.registerTool({
434
+ name: "send_wa_message",
435
+ label: "Send WhatsApp Message",
436
+ description: "Send a WhatsApp message to a contact identified by their JID (e.g. 5511999998888@s.whatsapp.net). Returns a JSON result with success status and messageId or error.",
437
+ promptSnippet: "send_wa_message(jid, message) - Send a WhatsApp message to a contact by JID",
438
+ parameters: Type.Object({
439
+ jid: Type.String({ minLength: 1, description: "WhatsApp JID of the recipient, e.g. 5511999998888@s.whatsapp.net" }),
440
+ message: Type.String({ minLength: 1, description: "Plain-text message content to send" })
441
+ }),
442
+ async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
443
+ if (whatsappService.getStatus() !== 'connected') {
444
+ return {
445
+ isError: true,
446
+ details: undefined,
447
+ content: [{ type: "text" as const, text: JSON.stringify({ success: false, error: "WhatsApp not connected", attempts: 0 }) }]
448
+ };
449
+ }
450
+
451
+ const result = await whatsappService.sendMessage(params.jid, params.message);
452
+
453
+ if (result.success) {
454
+ await recentsService.recordMessage({
455
+ messageId: result.messageId!,
456
+ senderNumber: `+${params.jid.split('@')[0]}`,
457
+ text: params.message,
458
+ direction: 'outgoing',
459
+ timestamp: Date.now()
460
+ });
461
+ }
462
+
463
+ return {
464
+ isError: !result.success,
465
+ details: undefined,
466
+ content: [{ type: "text" as const, text: JSON.stringify({ success: result.success, messageId: result.messageId, error: result.error, attempts: result.attempts }) }]
467
+ };
468
+ }
469
+ });
470
+
431
471
  // Register commands
432
472
  pi.registerCommand("whatsapp", {
433
473
  description: "Manage WhatsApp integration",