@chamade/mcp-server 1.1.3 → 1.1.5

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 -17
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -597,26 +597,20 @@ server.resource("call-transcript", transcriptTemplate, {
597
597
  // ---------------------------------------------------------------------------
598
598
  const _callWatchers = new Map();
599
599
  const _closedWatchers = new Set();
600
- const _typingIntervals = new Map();
600
+ const _typingActive = new Set();
601
601
  /**
602
- * Start repeating typing indicator for a conversation.
603
- * Sends immediately then every 2s. Stops after 30s max.
602
+ * Start typing indicator for a conversation.
603
+ * Sends a single POST Maquisard manages the repeat loop internally
604
+ * and stops it automatically when a message is sent.
604
605
  */
605
606
  function channelStartTyping(conversationId) {
606
- channelStopTyping(conversationId);
607
- const send = () => chamadePost("/api/typing", { conversation_id: conversationId }).catch(() => { });
608
- send();
609
- const interval = setInterval(send, 2000);
610
- _typingIntervals.set(conversationId, interval);
611
- // Safety: stop after 30s even if chamade_send is never called
612
- setTimeout(() => channelStopTyping(conversationId), 30_000);
607
+ if (_typingActive.has(conversationId))
608
+ return;
609
+ _typingActive.add(conversationId);
610
+ chamadePost("/api/typing", { conversation_id: conversationId }).catch(() => { });
613
611
  }
614
612
  function channelStopTyping(conversationId) {
615
- const interval = _typingIntervals.get(conversationId);
616
- if (interval) {
617
- clearInterval(interval);
618
- _typingIntervals.delete(conversationId);
619
- }
613
+ _typingActive.delete(conversationId);
620
614
  }
621
615
  /**
622
616
  * Push a channel notification to Claude Code.
@@ -730,12 +724,23 @@ function channelUnwatchCall(callId) {
730
724
  */
731
725
  function channelWatchInbox() {
732
726
  let retryDelay = 1000;
727
+ let retryCount = 0;
728
+ let wasConnected = false;
729
+ const WARN_AFTER = 3; // warn agent after 3 consecutive failures
733
730
  function connect() {
734
731
  const url = `${CHAMADE_WS_URL}/api/inbox/stream?api_key=${API_KEY}`;
735
732
  const ws = new WebSocket(url);
736
733
  ws.on("open", () => {
734
+ if (retryCount > 0) {
735
+ console.error(`[chamade-channel] Inbox WS reconnected after ${retryCount} retries`);
736
+ channelPush("Inbox connection restored. Messages received during the outage may have been lost.", { type: "inbox_reconnected" });
737
+ }
738
+ else {
739
+ console.error("[chamade-channel] Inbox WS connected");
740
+ }
737
741
  retryDelay = 1000;
738
- console.error("[chamade-channel] Inbox WS connected");
742
+ retryCount = 0;
743
+ wasConnected = true;
739
744
  });
740
745
  ws.on("message", async (raw) => {
741
746
  try {
@@ -789,10 +794,17 @@ function channelWatchInbox() {
789
794
  }
790
795
  });
791
796
  ws.on("close", () => {
797
+ retryCount++;
798
+ if (retryCount === WARN_AFTER && wasConnected) {
799
+ console.error(`[chamade-channel] Inbox WS: ${retryCount} reconnect attempts failed`);
800
+ channelPush(`Inbox connection lost. ${retryCount} reconnect attempts failed — messages may be missed until connection is restored.`, { type: "inbox_disconnected" });
801
+ }
802
+ console.error(`[chamade-channel] Inbox WS reconnecting in ${retryDelay / 1000}s (attempt ${retryCount})`);
792
803
  setTimeout(connect, retryDelay);
793
804
  retryDelay = Math.min(retryDelay * 2, 30_000);
794
805
  });
795
- ws.on("error", () => {
806
+ ws.on("error", (err) => {
807
+ console.error(`[chamade-channel] Inbox WS error: ${err.message || err}`);
796
808
  // Close handler will fire next and handle reconnection
797
809
  });
798
810
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chamade/mcp-server",
3
- "version": "1.1.3",
3
+ "version": "1.1.5",
4
4
  "description": "MCP server for Chamade — voice gateway for AI agents. Join Discord, Teams, Meet, Telegram, SIP, Zoom meetings and interact via speech and text. Supports Claude Code channel mode for push events.",
5
5
  "type": "module",
6
6
  "bin": {