@daolmedo/openclaw-twilio-whatsapp 1.1.5 → 1.1.7

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 (2) hide show
  1. package/dist/index.js +62 -4
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -176,9 +176,8 @@ var twilioWhatsappPlugin = {
176
176
 
177
177
  // src/http-routes.ts
178
178
  import { dispatchInboundDirectDmWithRuntime } from "openclaw/plugin-sdk/direct-dm";
179
- import {
180
- saveMediaBuffer
181
- } from "openclaw/plugin-sdk/media-runtime";
179
+ import { saveMediaBuffer } from "openclaw/plugin-sdk/media-runtime";
180
+ import { transcribeFirstAudio } from "openclaw/plugin-sdk/media-understanding";
182
181
 
183
182
  // src/webhook.ts
184
183
  import twilio2 from "twilio";
@@ -209,6 +208,39 @@ function parseTwilioWebhook(rawBody) {
209
208
  };
210
209
  }
211
210
 
211
+ // src/typing.ts
212
+ async function sendWhatsappTypingIndicator(opts) {
213
+ const auth = Buffer.from(`${opts.accountSid}:${opts.authToken}`).toString("base64");
214
+ const body = new URLSearchParams({ messageId: opts.messageId, channel: "whatsapp" });
215
+ const response = await fetch("https://messaging.twilio.com/v2/Indicators/Typing.json", {
216
+ method: "POST",
217
+ headers: {
218
+ Authorization: `Basic ${auth}`,
219
+ "Content-Type": "application/x-www-form-urlencoded"
220
+ },
221
+ body: body.toString(),
222
+ signal: AbortSignal.timeout(1e4)
223
+ });
224
+ if (!response.ok) {
225
+ throw new Error(`Typing indicator failed: HTTP ${response.status}`);
226
+ }
227
+ }
228
+ function startTypingKeepalive(opts) {
229
+ const { intervalMs = 2e4 } = opts;
230
+ let stopped = false;
231
+ void sendWhatsappTypingIndicator(opts).catch(() => {
232
+ });
233
+ const timer = setInterval(() => {
234
+ if (stopped) return;
235
+ void sendWhatsappTypingIndicator(opts).catch(() => {
236
+ });
237
+ }, intervalMs);
238
+ return () => {
239
+ stopped = true;
240
+ clearInterval(timer);
241
+ };
242
+ }
243
+
212
244
  // src/http-routes.ts
213
245
  var MEDIA_MAX_BYTES = 16 * 1024 * 1024;
214
246
  async function readBody(req) {
@@ -321,6 +353,29 @@ function registerTwilioWhatsappHttpRoutes(api) {
321
353
  MediaUrls: resolvedMedia.map((m) => m.path),
322
354
  MediaTypes: resolvedMedia.map((m) => m.contentType)
323
355
  } : {};
356
+ let bodyForAgent = messageText || void 0;
357
+ const hasAudio = resolvedMedia.some((m) => m.contentType.startsWith("audio/"));
358
+ if (hasAudio) {
359
+ try {
360
+ const transcript = await transcribeFirstAudio({
361
+ ctx: {
362
+ MediaPaths: resolvedMedia.map((m) => m.path),
363
+ MediaTypes: resolvedMedia.map((m) => m.contentType)
364
+ },
365
+ cfg: stored.cfg
366
+ });
367
+ bodyForAgent = transcript || messageText || "<media:audio>";
368
+ } catch (err) {
369
+ console.error("[twilio-whatsapp] Audio transcription failed:", err);
370
+ bodyForAgent = messageText || "<media:audio>";
371
+ }
372
+ }
373
+ const stopTyping = fields.messageSid ? startTypingKeepalive({
374
+ accountSid: account.accountSid,
375
+ authToken: account.authToken,
376
+ messageId: fields.messageSid
377
+ }) : () => {
378
+ };
324
379
  dispatchInboundDirectDmWithRuntime({
325
380
  cfg: stored.cfg,
326
381
  runtime: { channel: stored.channelRuntime },
@@ -333,12 +388,13 @@ function registerTwilioWhatsappHttpRoutes(api) {
333
388
  recipientAddress,
334
389
  conversationLabel,
335
390
  rawBody: messageText,
336
- bodyForAgent: messageText || void 0,
391
+ bodyForAgent,
337
392
  messageId: fields.messageSid,
338
393
  timestamp: Date.now(),
339
394
  commandAuthorized: true,
340
395
  extraContext: mediaContext,
341
396
  deliver: async (payload) => {
397
+ stopTyping();
342
398
  const text = payload.text ?? "";
343
399
  const mediaUrl = payload.mediaUrl ?? payload.mediaUrls?.[0];
344
400
  if (!text && !mediaUrl) return;
@@ -355,9 +411,11 @@ function registerTwilioWhatsappHttpRoutes(api) {
355
411
  console.error("[twilio-whatsapp] Session record error:", err);
356
412
  },
357
413
  onDispatchError: (err, info) => {
414
+ stopTyping();
358
415
  console.error(`[twilio-whatsapp] Dispatch error (${info.kind}):`, err);
359
416
  }
360
417
  }).catch((err) => {
418
+ stopTyping();
361
419
  console.error("[twilio-whatsapp] Unhandled dispatch error:", err);
362
420
  });
363
421
  return true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@daolmedo/openclaw-twilio-whatsapp",
3
- "version": "1.1.5",
3
+ "version": "1.1.7",
4
4
  "description": "Twilio WhatsApp channel plugin for OpenClaw (Cody ISV)",
5
5
  "type": "module",
6
6
  "exports": {