@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.
- package/dist/index.js +62 -4
- 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
|
-
|
|
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
|
|
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;
|