@agenticmail/enterprise 0.5.613 → 0.5.614

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/CHANGELOG.md CHANGED
@@ -2,6 +2,18 @@
2
2
 
3
3
  All notable changes to AgenticMail Enterprise are documented here.
4
4
 
5
+ ## [0.5.614] - 2026-05-25
6
+
7
+ ### Fixed — Telegram/WhatsApp "typing…" now stays on for the whole turn
8
+
9
+ The agent sent the chat-action ONCE on inbound, so "typing…" showed for ~5s
10
+ (Telegram's window) then vanished while the agent was still working — unlike
11
+ the open-source bridge, which refreshes it. Added a self-refreshing typing
12
+ indicator in the chat handler: pings every 4s and stops when the session turn
13
+ completes (and on error / a 15-min safety cap). Keyed per-chat so follow-up
14
+ messages don't stack multiple loops. Applies to both Telegram (`sendChatAction`)
15
+ and WhatsApp (`composing` presence).
16
+
5
17
  ## [0.5.613] - 2026-05-25
6
18
 
7
19
  ### Fixed — Agents now always use a PERMANENT workspace, never /tmp
@@ -421,6 +421,33 @@ if (_LOG_THRESHOLD > 2) {
421
421
  console.warn = function() {
422
422
  };
423
423
  }
424
+ var _typingTimers = /* @__PURE__ */ new Map();
425
+ var _TYPING_REFRESH_MS = 4e3;
426
+ var _TYPING_MAX_MS = 15 * 6e4;
427
+ function startTypingIndicator(key, tick) {
428
+ if (!key || _typingTimers.has(key)) return;
429
+ try {
430
+ tick();
431
+ } catch {
432
+ }
433
+ const interval = setInterval(() => {
434
+ try {
435
+ tick();
436
+ } catch {
437
+ }
438
+ }, _TYPING_REFRESH_MS);
439
+ const safety = setTimeout(() => stopTypingIndicator(key), _TYPING_MAX_MS);
440
+ interval.unref?.();
441
+ safety.unref?.();
442
+ _typingTimers.set(key, { interval, safety });
443
+ }
444
+ function stopTypingIndicator(key) {
445
+ const t = _typingTimers.get(key);
446
+ if (!t) return;
447
+ clearInterval(t.interval);
448
+ clearTimeout(t.safety);
449
+ _typingTimers.delete(key);
450
+ }
424
451
  function _stripMd(text) {
425
452
  if (!text) return text;
426
453
  return text.replace(/\*\*(.+?)\*\*/g, "$1").replace(/\*(.+?)\*/g, "$1").replace(/__(.+?)__/g, "$1").replace(/~~(.+?)~~/g, "$1").replace(/^#{1,6}\s+/gm, "").replace(/```[\s\S]*?```/g, (m) => m.replace(/```\w*\n?/g, "").trim()).replace(/`([^`]+)`/g, "$1").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").trim();
@@ -1708,30 +1735,36 @@ Please complete this task now.`,
1708
1735
  }
1709
1736
  });
1710
1737
  app.post("/api/runtime/chat", async (c) => {
1738
+ let typingKey = "";
1711
1739
  try {
1712
1740
  const ctx = await c.req.json();
1713
1741
  if (typeof ctx.messageText !== "string") ctx.messageText = "";
1714
1742
  const isMessagingSource = ["whatsapp", "telegram"].includes(ctx.source);
1715
1743
  console.log(`[chat] Message from ${ctx.senderName} (${ctx.senderEmail}) in ${ctx.source || ctx.spaceName}: "${ctx.messageText.slice(0, 80)}"`);
1744
+ typingKey = ctx.source === "telegram" ? `tg:${ctx.spaceId || ctx.senderEmail}` : ctx.source === "whatsapp" ? `wa:${ctx.senderEmail}` : "";
1716
1745
  if (ctx.source === "telegram") {
1717
- const tgToken = agent.config?.channels?.telegram?.botToken;
1746
+ const tgToken = agent.config?.channels?.telegram?.botToken || agent.config?.messagingChannels?.telegram?.botToken;
1718
1747
  const chatId = ctx.spaceId || ctx.senderEmail;
1719
1748
  if (tgToken && chatId) {
1720
- fetch(`https://api.telegram.org/bot${tgToken}/sendChatAction`, {
1721
- method: "POST",
1722
- headers: { "Content-Type": "application/json" },
1723
- body: JSON.stringify({ chat_id: chatId, action: "typing" })
1724
- }).catch(() => {
1749
+ startTypingIndicator(typingKey, () => {
1750
+ fetch(`https://api.telegram.org/bot${tgToken}/sendChatAction`, {
1751
+ method: "POST",
1752
+ headers: { "Content-Type": "application/json" },
1753
+ body: JSON.stringify({ chat_id: chatId, action: "typing" })
1754
+ }).catch(() => {
1755
+ });
1725
1756
  });
1726
1757
  }
1727
1758
  } else if (ctx.source === "whatsapp") {
1728
- import("./whatsapp-TBOB7TDL.js").then(({ getConnection }) => {
1729
- const conn = getConnection(AGENT_ID);
1730
- if (!conn?.connected) return;
1731
- const jid = ctx.senderEmail.includes("@") ? ctx.senderEmail : ctx.senderEmail.replace(/[^0-9]/g, "") + "@s.whatsapp.net";
1732
- conn.sock.presenceSubscribe(jid).then(() => conn.sock.sendPresenceUpdate("composing", jid)).catch(() => {
1759
+ const jid = ctx.senderEmail.includes("@") ? ctx.senderEmail : ctx.senderEmail.replace(/[^0-9]/g, "") + "@s.whatsapp.net";
1760
+ startTypingIndicator(typingKey, () => {
1761
+ import("./whatsapp-TBOB7TDL.js").then(({ getConnection }) => {
1762
+ const conn = getConnection(AGENT_ID);
1763
+ if (!conn?.connected) return;
1764
+ conn.sock.presenceSubscribe(jid).then(() => conn.sock.sendPresenceUpdate("composing", jid)).catch(() => {
1765
+ });
1766
+ }).catch(() => {
1733
1767
  });
1734
- }).catch(() => {
1735
1768
  });
1736
1769
  }
1737
1770
  const agentDomain = agent.email?.split("@")[1] || "agenticmail.io";
@@ -2032,6 +2065,7 @@ ${ambientContext}` : ""
2032
2065
  }
2033
2066
  });
2034
2067
  runtime.onSessionComplete(session.id, async (result) => {
2068
+ stopTypingIndicator(typingKey);
2035
2069
  sessionRouter?.unregister(agentId, session.id);
2036
2070
  if (taskId) {
2037
2071
  const usage = result?.usage || {};
@@ -2178,6 +2212,10 @@ ${ambientContext}` : ""
2178
2212
  }
2179
2213
  return c.json({ ok: true, sessionId: session.id });
2180
2214
  } catch (err) {
2215
+ try {
2216
+ stopTypingIndicator(typingKey);
2217
+ } catch {
2218
+ }
2181
2219
  console.error(`[chat] Error: ${err.message}`);
2182
2220
  return c.json({ error: err.message }, 500);
2183
2221
  }
package/dist/cli.js CHANGED
@@ -68,7 +68,7 @@ Skill Development:
68
68
  import("./cli-serve-4NLB4RK2.js").then((m) => m.runServe(args.slice(1))).catch(fatal);
69
69
  break;
70
70
  case "agent":
71
- import("./cli-agent-AMA2R4PG.js").then((m) => m.runAgent(args.slice(1))).catch(fatal);
71
+ import("./cli-agent-DOLO7OCU.js").then((m) => m.runAgent(args.slice(1))).catch(fatal);
72
72
  break;
73
73
  case "setup":
74
74
  default:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agenticmail/enterprise",
3
- "version": "0.5.613",
3
+ "version": "0.5.614",
4
4
  "description": "AgenticMail Enterprise — cloud-hosted AI agent identity, email, auth & compliance for organizations",
5
5
  "type": "module",
6
6
  "bin": {