@wahooks/channel 0.8.0 → 0.9.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 (2) hide show
  1. package/dist/index.js +29 -2
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -315,9 +315,13 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
315
315
  switch (req.params.name) {
316
316
  case "wahooks_reply":
317
317
  case "wahooks_send": {
318
+ const chatId = toChatId(args.to);
319
+ // Start typing, then send with skipPresence to avoid double seen/typing
320
+ api("POST", `/connections/${connectionId}/typing`, { chatId }).catch(() => { });
318
321
  await api("POST", `/connections/${connectionId}/send`, {
319
- chatId: toChatId(args.to),
322
+ chatId,
320
323
  text: args.text,
324
+ skipPresence: true,
321
325
  });
322
326
  return { content: [{ type: "text", text: `Sent to ${args.to}` }] };
323
327
  }
@@ -385,8 +389,25 @@ function connectWebSocket() {
385
389
  const wsUrl = `${wsHost}/api/ws?token=${encodeURIComponent(API_KEY)}`;
386
390
  console.error("[wahooks-channel] Connecting to event stream...");
387
391
  const ws = new WebSocket(wsUrl);
392
+ let alive = false;
393
+ let heartbeat;
388
394
  ws.on("open", () => {
389
395
  console.error("[wahooks-channel] Connected to event stream");
396
+ alive = true;
397
+ // Heartbeat: ping every 30s, if no pong within 10s, force reconnect
398
+ heartbeat = setInterval(() => {
399
+ if (!alive) {
400
+ console.error("[wahooks-channel] Heartbeat timeout, reconnecting...");
401
+ clearInterval(heartbeat);
402
+ ws.terminate();
403
+ return;
404
+ }
405
+ alive = false;
406
+ ws.ping();
407
+ }, 30000);
408
+ });
409
+ ws.on("pong", () => {
410
+ alive = true;
390
411
  });
391
412
  ws.on("message", async (data) => {
392
413
  try {
@@ -401,7 +422,11 @@ function connectWebSocket() {
401
422
  return;
402
423
  const chatId = payload.from ?? "";
403
424
  const isGroup = chatId.includes("@g.us");
404
- const sender = payload.participant ?? chatId; // participant for groups, from for DMs
425
+ const sender = payload.participant ?? chatId;
426
+ // Send read receipt immediately
427
+ if (chatId && connectionId) {
428
+ api("POST", `/connections/${connectionId}/mark-read`, { chatId }).catch(() => { });
429
+ }
405
430
  const text = payload.body ?? payload.text ?? "";
406
431
  const hasMedia = payload.hasMedia === true;
407
432
  const media = payload.media;
@@ -477,6 +502,8 @@ function connectWebSocket() {
477
502
  }
478
503
  });
479
504
  ws.on("close", (code) => {
505
+ if (heartbeat)
506
+ clearInterval(heartbeat);
480
507
  console.error(`[wahooks-channel] Connection closed (${code}), reconnecting in 5s...`);
481
508
  setTimeout(connectWebSocket, 5000);
482
509
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wahooks/channel",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "WhatsApp channel for Claude Code — chat with Claude via WhatsApp",
5
5
  "type": "module",
6
6
  "bin": {