@rubytech/create-maxy 1.0.475 → 1.0.477

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rubytech/create-maxy",
3
- "version": "1.0.475",
3
+ "version": "1.0.477",
4
4
  "description": "Install Maxy — AI for Productive People",
5
5
  "bin": {
6
6
  "create-maxy": "./dist/index.js"
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: whatsapp
3
- description: WhatsApp messaging channel — Baileys QR pairing, DM/group policy enforcement, inbound routing, outbound messaging, document sending.
3
+ description: WhatsApp messaging channel — Baileys QR pairing, DM/group policy enforcement, inbound routing, business hours gating, outbound messaging, document sending, conversation browsing.
4
4
  tools:
5
5
  - whatsapp-login-start
6
6
  - whatsapp-login-wait
@@ -9,6 +9,10 @@ tools:
9
9
  - whatsapp-send
10
10
  - whatsapp-send-document
11
11
  - whatsapp-config
12
+ - whatsapp-activity
13
+ - whatsapp-conversations
14
+ - whatsapp-messages
15
+ - whatsapp-group-info
12
16
  metadata: {"platform":{"embed":["admin"]}}
13
17
  ---
14
18
 
@@ -23,8 +27,22 @@ Activate when the user asks about WhatsApp — connecting, linking, checking sta
23
27
  - Inbound message routing (admin phone → admin agent, public → public agent)
24
28
  - Group messaging with mention gating and per-group activation
25
29
  - DM policy enforcement (open, allowlist, disabled)
30
+ - Conversation browsing — list active conversations, read message history, inspect group metadata
26
31
  - Voice note normalization (OGG Opus via ffmpeg)
27
32
  - Auto-reconnection with exponential backoff
33
+ - Business hours gating — public messages gated by `OpeningHoursSpecification` from Neo4j, with optional after-hours auto-reply via the `afterHoursMessage` config field
34
+
35
+ ## Conversation Browsing
36
+
37
+ Three tools for reading WhatsApp conversation context. Messages come from the in-memory store — they accumulate while the server is running and clear on restart.
38
+
39
+ | Tool | Returns |
40
+ |------|---------|
41
+ | `whatsapp-conversations` | JIDs with recent message activity, conversation type (group/DM), last message timestamp, message count |
42
+ | `whatsapp-messages` | Stored messages for a specific JID — sender, body, timestamp, reply context. Supports optional `limit` for most recent N messages |
43
+ | `whatsapp-group-info` | Group metadata from WhatsApp servers — subject, description, participants with admin flags, creation date. Requires active connection |
44
+
45
+ **Limitations:** In-memory only (Phase 0). Store clears on server restart. Inbound messages only — outbound messages sent by the agent are not stored.
28
46
 
29
47
  ## Skills
30
48
 
@@ -99,6 +99,44 @@ server.tool("whatsapp-status", "Get WhatsApp connection status for all linked ac
99
99
  return textResult(`Status check failed: ${err instanceof Error ? err.message : String(err)}`, true);
100
100
  }
101
101
  });
102
+ // ─── whatsapp-activity ────────────────────────────────────────────────
103
+ server.tool("whatsapp-activity", "Get WhatsApp channel activity — message counts (inbound and outbound) and recent events since last restart. Shows per-account usage metrics so you can report on channel activity when asked. Counters reset on server restart.", {
104
+ accountId: z.string().optional().describe('Filter to a specific account (default: all accounts)'),
105
+ }, async ({ accountId }) => {
106
+ try {
107
+ const query = accountId ? `?accountId=${encodeURIComponent(accountId)}` : "";
108
+ const result = await callApi(`/api/whatsapp/activity${query}`, "GET");
109
+ if (result.error)
110
+ return textResult(`Activity check failed: ${result.error}`, true);
111
+ const accounts = result.accounts ?? [];
112
+ if (accounts.length === 0) {
113
+ return textResult("No WhatsApp activity recorded since last restart.");
114
+ }
115
+ const lines = [];
116
+ for (const a of accounts) {
117
+ const lastAt = a.lastEventAt ? new Date(a.lastEventAt).toISOString() : "never";
118
+ lines.push(`${a.accountId}: ${a.total} messages (${a.inbound} inbound, ${a.outbound} outbound) — last activity: ${lastAt}`);
119
+ }
120
+ const events = result.recentEvents ?? [];
121
+ if (events.length > 0) {
122
+ lines.push("");
123
+ lines.push(`Recent events (${events.length}):`);
124
+ // Show last 10 for readability
125
+ const recent = events.slice(-10);
126
+ for (const e of recent) {
127
+ const ts = new Date(e.timestamp).toISOString();
128
+ lines.push(` ${ts} ${e.direction} account=${e.accountId} jid=${e.jid}${e.messageType ? ` type=${e.messageType}` : ""}`);
129
+ }
130
+ if (events.length > 10) {
131
+ lines.push(` ... and ${events.length - 10} more events`);
132
+ }
133
+ }
134
+ return textResult(lines.join("\n"));
135
+ }
136
+ catch (err) {
137
+ return textResult(`Activity check failed: ${err instanceof Error ? err.message : String(err)}`, true);
138
+ }
139
+ });
102
140
  // ─── whatsapp-disconnect ───────────────────────────────────────────────
103
141
  server.tool("whatsapp-disconnect", "Disconnect a WhatsApp account. Closes the Baileys WebSocket connection cleanly.", {
104
142
  accountId: z.string().optional().describe('Account ID to disconnect (default: "default")'),
@@ -211,6 +249,101 @@ server.tool("whatsapp-send-document", "Send a file as a WhatsApp document messag
211
249
  return textResult(`Send failed: ${err instanceof Error ? err.message : String(err)}`, true);
212
250
  }
213
251
  });
252
+ // ─── whatsapp-conversations ──────────────────────────────────────────
253
+ server.tool("whatsapp-conversations", "List WhatsApp conversations with recent message activity. Returns each conversation's JID, type (group or DM), last message timestamp, and message count. Messages are from the in-memory store (clears on server restart). Use this to see which conversations have recent activity before retrieving specific messages with whatsapp-messages.", {
254
+ accountId: z.string().optional().describe('Account ID (default: "default")'),
255
+ }, async ({ accountId }) => {
256
+ try {
257
+ const id = accountId ?? "default";
258
+ console.error(`[whatsapp-mcp] whatsapp-conversations called for account ${id}`);
259
+ const result = await callApi(`/api/whatsapp/conversations?accountId=${encodeURIComponent(id)}`, "GET");
260
+ if (result.error)
261
+ return textResult(`Failed to list conversations: ${result.error}`, true);
262
+ const conversations = result.conversations ?? [];
263
+ if (conversations.length === 0) {
264
+ return textResult("No conversations with stored messages. Messages are stored when they arrive while the server is running.");
265
+ }
266
+ const lines = conversations.map((c) => {
267
+ const type = c.type === "group" ? "[group]" : "[DM]";
268
+ const ts = c.lastMessageTimestamp
269
+ ? new Date(c.lastMessageTimestamp * 1000).toISOString()
270
+ : "unknown";
271
+ return `${type} ${c.jid} — ${c.messageCount} messages, last: ${ts}`;
272
+ });
273
+ return textResult(`Conversations (${conversations.length}):\n${lines.join("\n")}`);
274
+ }
275
+ catch (err) {
276
+ console.error(`[whatsapp-mcp] whatsapp-conversations error: ${err instanceof Error ? err.message : String(err)}`);
277
+ return textResult(`Failed to list conversations: ${err instanceof Error ? err.message : String(err)}`, true);
278
+ }
279
+ });
280
+ // ─── whatsapp-messages ───────────────────────────────────────────────
281
+ server.tool("whatsapp-messages", "Retrieve stored WhatsApp messages for a specific conversation. Returns messages in chronological order (oldest first) with sender, body, timestamp, and reply context. Messages are from the in-memory store (clears on server restart). Use whatsapp-conversations first to see available JIDs.", {
282
+ jid: z.string().describe("Conversation JID (phone@s.whatsapp.net for DMs, id@g.us for groups)"),
283
+ accountId: z.string().optional().describe('Account ID (default: "default")'),
284
+ limit: z.number().optional().describe("Max number of most recent messages to return (default: all)"),
285
+ }, async ({ jid, accountId, limit }) => {
286
+ try {
287
+ const id = accountId ?? "default";
288
+ console.error(`[whatsapp-mcp] whatsapp-messages called for account ${id} jid=${jid} limit=${limit ?? "all"}`);
289
+ const params = new URLSearchParams({ accountId: id, jid });
290
+ if (limit !== undefined)
291
+ params.set("limit", String(limit));
292
+ const result = await callApi(`/api/whatsapp/messages?${params}`, "GET");
293
+ if (result.error)
294
+ return textResult(`Failed to get messages: ${result.error}`, true);
295
+ const messages = result.messages ?? [];
296
+ if (messages.length === 0) {
297
+ return textResult(`No stored messages for ${jid}. Messages appear when they arrive while the server is running.`);
298
+ }
299
+ const lines = messages.map((m) => {
300
+ const ts = new Date(m.timestamp * 1000).toISOString();
301
+ const direction = m.fromMe ? "→" : "←";
302
+ const sender = m.senderName ? `${m.senderName} (${m.sender})` : m.sender;
303
+ let line = `[${ts}] ${direction} ${sender}: ${m.body}`;
304
+ if (m.quoted?.body) {
305
+ line += `\n ↳ replying to: "${m.quoted.body}"`;
306
+ }
307
+ return line;
308
+ });
309
+ return textResult(`Messages for ${jid} (${messages.length}):\n${lines.join("\n")}`);
310
+ }
311
+ catch (err) {
312
+ console.error(`[whatsapp-mcp] whatsapp-messages error: ${err instanceof Error ? err.message : String(err)}`);
313
+ return textResult(`Failed to get messages: ${err instanceof Error ? err.message : String(err)}`, true);
314
+ }
315
+ });
316
+ // ─── whatsapp-group-info ─────────────────────────────────────────────
317
+ server.tool("whatsapp-group-info", "Get metadata for a WhatsApp group: subject (name), description, participant list with admin flags, creation date, and owner. Queries WhatsApp servers directly (requires active connection). The JID must be a group JID ending in @g.us — use whatsapp-conversations or whatsapp-config action list-groups to find group JIDs.", {
318
+ jid: z.string().describe("Group JID (must end with @g.us)"),
319
+ accountId: z.string().optional().describe('Account ID (default: "default")'),
320
+ }, async ({ jid, accountId }) => {
321
+ try {
322
+ const id = accountId ?? "default";
323
+ console.error(`[whatsapp-mcp] whatsapp-group-info called for account ${id} jid=${jid}`);
324
+ const params = new URLSearchParams({ accountId: id, jid });
325
+ const result = await callApi(`/api/whatsapp/group-info?${params}`, "GET");
326
+ if (result.error)
327
+ return textResult(`Failed to get group info: ${result.error}`, true);
328
+ const parts = (result.participants ?? []).map((p) => {
329
+ const role = p.admin === "superadmin" ? " (super admin)" : p.admin === "admin" ? " (admin)" : "";
330
+ return ` ${p.jid}${role}`;
331
+ });
332
+ const lines = [
333
+ `Group: ${result.subject}`,
334
+ result.description ? `Description: ${result.description}` : null,
335
+ result.owner ? `Owner: ${result.owner}` : null,
336
+ result.creation ? `Created: ${new Date(result.creation * 1000).toISOString()}` : null,
337
+ `Participants (${result.participantCount}):`,
338
+ ...parts,
339
+ ].filter(Boolean);
340
+ return textResult(lines.join("\n"));
341
+ }
342
+ catch (err) {
343
+ console.error(`[whatsapp-mcp] whatsapp-group-info error: ${err instanceof Error ? err.message : String(err)}`);
344
+ return textResult(`Failed to get group info: ${err instanceof Error ? err.message : String(err)}`, true);
345
+ }
346
+ });
214
347
  // ─── Start server ──────────────────────────────────────────────────────
215
348
  const transport = new StdioServerTransport();
216
349
  await server.connect(transport);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -33,11 +33,16 @@ Scheduling, reminders, and recurring triggers are handled exclusively by the sch
33
33
 
34
34
  ## Self-Correction
35
35
 
36
- `agents/admin/LEARNINGS.md` is injected into your system prompt every turn. It captures idiosyncratic tool-call patterns specific to this account — parameter formats, auth quirks, data-shape issues discovered through use. Consult it before repeating an approach that failed.
36
+ `agents/admin/LEARNINGS.md` is injected into your system prompt every turn. It captures two categories of standing knowledge:
37
37
 
38
- Fundamental tool routingwhich tool to use for which domain does not belong in LEARNINGS.md. That works from the plugin manifest descriptions and the Tool Routing principle above.
38
+ 1. **Tool-call patterns**parameter formats, auth quirks, schema requirements, data-shape issues discovered through use. Write trigger: a tool call returns an error that reveals a reusable correction.
39
+ 2. **Working-relationship learnings** — the owner's stated working philosophy, communication preferences, and approach patterns that should shape every interaction. Write trigger: the owner reveals a working principle or preference that needs to be present unconditionally, not just when searched for.
39
40
 
40
- When a tool call returns an error, check whether the mistake matches an existing entry. If not, append a concise entry: what went wrong, why, and what to do instead. One entry per distinct mistake pattern do not duplicate.
41
+ The dividing line between LEARNINGS.md and `profile-update`: if the agent needs to *remember to look for it* at the right moment, it belongs in LEARNINGS.md (auto-injected every turn). If it enriches a response when the topic arises naturally, `profile-update` suffices (retrieved on demand).
42
+
43
+ LEARNINGS.md does not contain business knowledge (graph data), personality or tone (SOUL.md), domain knowledge (KNOWLEDGE.md), or fundamental tool routing (plugin manifest + Tool Routing above).
44
+
45
+ Consult LEARNINGS.md before repeating an approach that failed or interacting in a way that contradicts a recorded working-relationship entry. When adding an entry, check whether it matches an existing one. One entry per distinct pattern — do not duplicate.
41
46
 
42
47
  ## Capabilities
43
48
 
@@ -1,3 +1,3 @@
1
1
  # Learnings
2
2
 
3
- Accumulated tool-call patterns. Each entry records a mistake and the correct approach. Consult before calling unfamiliar tools.
3
+ Accumulated tool-call patterns and working-relationship learnings. Tool-call entries record a mistake and the correct approach. Working-relationship entries record the owner's stated working principles and preferences that shape every interaction. Consult before repeating a known mistake or interacting in a way that contradicts a recorded preference.
@@ -5211,6 +5211,10 @@ var ADMIN_CORE_TOOLS = [
5211
5211
  "mcp__whatsapp__whatsapp-send",
5212
5212
  "mcp__whatsapp__whatsapp-send-document",
5213
5213
  "mcp__whatsapp__whatsapp-config",
5214
+ "mcp__whatsapp__whatsapp-activity",
5215
+ "mcp__whatsapp__whatsapp-conversations",
5216
+ "mcp__whatsapp__whatsapp-messages",
5217
+ "mcp__whatsapp__whatsapp-group-info",
5214
5218
  "mcp__admin__system-status",
5215
5219
  "mcp__admin__brand-settings",
5216
5220
  "mcp__admin__account-manage",
@@ -23724,7 +23728,8 @@ var WhatsAppAccountSchema = external_exports.object({
23724
23728
  group: external_exports.enum(["always", "mentions", "never"]).optional().default("mentions")
23725
23729
  }).strict().optional().describe("React to incoming messages with an emoji to acknowledge receipt before the agent responds."),
23726
23730
  debounceMs: external_exports.number().int().nonnegative().optional().default(2e3).describe("Wait this many milliseconds after the last message before processing, to batch rapid multi-message input into a single agent turn. Default 2000ms catches most multi-message bursts. 0 means process each message immediately."),
23727
- publicAgent: external_exports.string().optional().describe("Slug of the public agent that handles WhatsApp inbound from non-admin phones for this account. Overrides the top-level publicAgent when set.")
23731
+ publicAgent: external_exports.string().optional().describe("Slug of the public agent that handles WhatsApp inbound from non-admin phones for this account. Overrides the top-level publicAgent when set."),
23732
+ afterHoursMessage: external_exports.string().optional().describe("Auto-reply text sent to public senders when the business is closed (outside opening hours). If not set, messages received outside business hours are silently skipped with no reply.")
23728
23733
  }).strict().superRefine((value, ctx) => {
23729
23734
  if (value.dmPolicy !== "open") return;
23730
23735
  const allow = (value.allowFrom ?? []).map((v) => String(v).trim()).filter(Boolean);
@@ -23746,7 +23751,8 @@ var WhatsAppConfigSchema = external_exports.object({
23746
23751
  mediaMaxMb: external_exports.number().int().positive().optional().default(50).describe("Maximum file size in MB for media the agent will download and process."),
23747
23752
  textChunkLimit: external_exports.number().int().positive().optional().default(4e3).describe("Maximum characters per outbound message. Longer replies are split into multiple messages."),
23748
23753
  debounceMs: external_exports.number().int().nonnegative().optional().default(2e3).describe("Wait this many milliseconds after the last message before processing, to batch rapid multi-message input into a single agent turn. Default 2000ms catches most multi-message bursts. 0 means process each message immediately."),
23749
- publicAgent: external_exports.string().optional().describe("Slug of the public agent that handles WhatsApp inbound from non-admin phones. Per-account overrides take precedence.")
23754
+ publicAgent: external_exports.string().optional().describe("Slug of the public agent that handles WhatsApp inbound from non-admin phones. Per-account overrides take precedence."),
23755
+ afterHoursMessage: external_exports.string().optional().describe("Default auto-reply text sent to public senders when the business is closed (outside opening hours). Per-account overrides take precedence. If not set, messages received outside business hours are silently skipped.")
23750
23756
  }).strict().superRefine((value, ctx) => {
23751
23757
  if (value.dmPolicy !== "open") return;
23752
23758
  const allow = (value.allowFrom ?? []).map((v) => String(v).trim()).filter(Boolean);
@@ -24318,8 +24324,60 @@ function isDuplicateInbound(key) {
24318
24324
  return true;
24319
24325
  }
24320
24326
 
24327
+ // app/lib/whatsapp/activity.ts
24328
+ var TAG5 = "[whatsapp:activity]";
24329
+ var RECENT_EVENTS_MAX = 200;
24330
+ var counters = /* @__PURE__ */ new Map();
24331
+ var recentEvents = [];
24332
+ function recordActivity(event) {
24333
+ try {
24334
+ const now = Date.now();
24335
+ const { accountId, direction, jid, messageType } = event;
24336
+ let acct = counters.get(accountId);
24337
+ if (!acct) {
24338
+ acct = { inbound: 0, outbound: 0, firstEventAt: now, lastEventAt: now };
24339
+ counters.set(accountId, acct);
24340
+ }
24341
+ acct[direction]++;
24342
+ acct.lastEventAt = now;
24343
+ const entry = {
24344
+ channel: "whatsapp",
24345
+ accountId,
24346
+ direction,
24347
+ jid,
24348
+ timestamp: now,
24349
+ messageType
24350
+ };
24351
+ recentEvents.push(entry);
24352
+ if (recentEvents.length > RECENT_EVENTS_MAX) {
24353
+ recentEvents.splice(0, recentEvents.length - RECENT_EVENTS_MAX);
24354
+ }
24355
+ console.error(
24356
+ `${TAG5} channel-activity: direction=${direction} account=${accountId} jid=${jid}` + (messageType ? ` type=${messageType}` : "")
24357
+ );
24358
+ } catch (err) {
24359
+ console.error(`${TAG5} recording failed: ${String(err)}`);
24360
+ }
24361
+ }
24362
+ function getChannelActivity(accountId) {
24363
+ const accounts = [];
24364
+ for (const [id, acct] of counters) {
24365
+ if (accountId && id !== accountId) continue;
24366
+ accounts.push({
24367
+ accountId: id,
24368
+ inbound: acct.inbound,
24369
+ outbound: acct.outbound,
24370
+ total: acct.inbound + acct.outbound,
24371
+ firstEventAt: acct.firstEventAt,
24372
+ lastEventAt: acct.lastEventAt
24373
+ });
24374
+ }
24375
+ const events = accountId ? recentEvents.filter((e) => e.accountId === accountId) : [...recentEvents];
24376
+ return { accounts, recentEvents: events };
24377
+ }
24378
+
24321
24379
  // app/lib/whatsapp/outbound/send.ts
24322
- var TAG5 = "[whatsapp:outbound]";
24380
+ var TAG6 = "[whatsapp:outbound]";
24323
24381
  async function sendTextMessage(sock, to, text, opts) {
24324
24382
  try {
24325
24383
  const jid = to.includes("@") ? to : toWhatsappJid(to);
@@ -24331,11 +24389,14 @@ async function sendTextMessage(sock, to, text, opts) {
24331
24389
  const messageId = result?.key?.id;
24332
24390
  if (messageId) {
24333
24391
  trackAgentSentMessage(messageId);
24334
- console.error(`${TAG5} sent text to=${jid} id=${messageId}`);
24392
+ console.error(`${TAG6} sent text to=${jid} id=${messageId}`);
24393
+ }
24394
+ if (opts?.accountId) {
24395
+ recordActivity({ accountId: opts.accountId, direction: "outbound", jid, messageType: "text" });
24335
24396
  }
24336
24397
  return { success: true, messageId: messageId ?? void 0 };
24337
24398
  } catch (err) {
24338
- console.error(`${TAG5} send failed to=${to}: ${String(err)}`);
24399
+ console.error(`${TAG6} send failed to=${to}: ${String(err)}`);
24339
24400
  return { success: false, error: String(err) };
24340
24401
  }
24341
24402
  }
@@ -24351,7 +24412,7 @@ async function sendReadReceipt(sock, chatJid, messageIds, participant) {
24351
24412
  } catch {
24352
24413
  }
24353
24414
  }
24354
- async function sendMediaMessage(sock, to, media) {
24415
+ async function sendMediaMessage(sock, to, media, opts) {
24355
24416
  try {
24356
24417
  const jid = to.includes("@") ? to : toWhatsappJid(to);
24357
24418
  let payload;
@@ -24390,11 +24451,14 @@ async function sendMediaMessage(sock, to, media) {
24390
24451
  const messageId = result?.key?.id;
24391
24452
  if (messageId) {
24392
24453
  trackAgentSentMessage(messageId);
24393
- console.error(`${TAG5} sent ${media.type} to=${jid} id=${messageId}`);
24454
+ console.error(`${TAG6} sent ${media.type} to=${jid} id=${messageId}`);
24455
+ }
24456
+ if (opts?.accountId) {
24457
+ recordActivity({ accountId: opts.accountId, direction: "outbound", jid, messageType: media.type });
24394
24458
  }
24395
24459
  return { success: true, messageId: messageId ?? void 0 };
24396
24460
  } catch (err) {
24397
- console.error(`${TAG5} send media failed to=${to}: ${String(err)}`);
24461
+ console.error(`${TAG6} send media failed to=${to}: ${String(err)}`);
24398
24462
  return { success: false, error: String(err) };
24399
24463
  }
24400
24464
  }
@@ -24408,7 +24472,7 @@ import {
24408
24472
  downloadContentFromMessage,
24409
24473
  normalizeMessageContent as normalizeMessageContent2
24410
24474
  } from "@whiskeysockets/baileys";
24411
- var TAG6 = "[whatsapp:media]";
24475
+ var TAG7 = "[whatsapp:media]";
24412
24476
  var MEDIA_DIR = "/tmp/maxy-media";
24413
24477
  function mimeToExt(mimetype) {
24414
24478
  const map2 = {
@@ -24464,25 +24528,25 @@ async function downloadInboundMedia(msg, sock, opts) {
24464
24528
  }
24465
24529
  );
24466
24530
  if (!buffer || buffer.length === 0) {
24467
- console.error(`${TAG6} primary download returned empty, trying direct fallback`);
24531
+ console.error(`${TAG7} primary download returned empty, trying direct fallback`);
24468
24532
  const downloadable = getDownloadableContent(content);
24469
24533
  if (downloadable) {
24470
24534
  try {
24471
24535
  const stream = await downloadContentFromMessage(downloadable.downloadable, downloadable.mediaType);
24472
24536
  buffer = await streamToBuffer(stream);
24473
24537
  } catch (fallbackErr) {
24474
- console.error(`${TAG6} direct download fallback failed: ${String(fallbackErr)}`);
24538
+ console.error(`${TAG7} direct download fallback failed: ${String(fallbackErr)}`);
24475
24539
  }
24476
24540
  }
24477
24541
  }
24478
24542
  if (!buffer || buffer.length === 0) {
24479
- console.error(`${TAG6} download failed: empty buffer for ${mimetype ?? "unknown"}`);
24543
+ console.error(`${TAG7} download failed: empty buffer for ${mimetype ?? "unknown"}`);
24480
24544
  return void 0;
24481
24545
  }
24482
24546
  if (buffer.length > maxBytes) {
24483
24547
  const sizeMB = (buffer.length / (1024 * 1024)).toFixed(1);
24484
24548
  const limitMB = (maxBytes / (1024 * 1024)).toFixed(0);
24485
- console.error(`${TAG6} media too large type=${mimetype ?? "unknown"} size=${sizeMB}MB limit=${limitMB}MB`);
24549
+ console.error(`${TAG7} media too large type=${mimetype ?? "unknown"} size=${sizeMB}MB limit=${limitMB}MB`);
24486
24550
  return void 0;
24487
24551
  }
24488
24552
  await mkdir2(MEDIA_DIR, { recursive: true });
@@ -24491,20 +24555,20 @@ async function downloadInboundMedia(msg, sock, opts) {
24491
24555
  const filePath = join6(MEDIA_DIR, filename);
24492
24556
  await writeFile2(filePath, buffer);
24493
24557
  const sizeKB = (buffer.length / 1024).toFixed(0);
24494
- console.error(`${TAG6} media downloaded type=${mimetype ?? "unknown"} size=${sizeKB}KB path=${filePath}`);
24558
+ console.error(`${TAG7} media downloaded type=${mimetype ?? "unknown"} size=${sizeKB}KB path=${filePath}`);
24495
24559
  return {
24496
24560
  path: filePath,
24497
24561
  mimetype: mimetype ?? "application/octet-stream",
24498
24562
  size: buffer.length
24499
24563
  };
24500
24564
  } catch (err) {
24501
- console.error(`${TAG6} media download failed type=${mimetype ?? "unknown"} error=${String(err)}`);
24565
+ console.error(`${TAG7} media download failed type=${mimetype ?? "unknown"} error=${String(err)}`);
24502
24566
  return void 0;
24503
24567
  }
24504
24568
  }
24505
24569
 
24506
24570
  // app/lib/whatsapp/inbound/debounce.ts
24507
- var TAG7 = "[whatsapp:debounce]";
24571
+ var TAG8 = "[whatsapp:debounce]";
24508
24572
  function createInboundDebouncer(opts) {
24509
24573
  const { debounceMs, buildKey, onFlush, onError } = opts;
24510
24574
  const pending = /* @__PURE__ */ new Map();
@@ -24516,7 +24580,7 @@ function createInboundDebouncer(opts) {
24516
24580
  pending.delete(key);
24517
24581
  const batchSize = batch.entries.length;
24518
24582
  try {
24519
- console.error(`${TAG7} debounce flush key=${key} batchSize=${batchSize}`);
24583
+ console.error(`${TAG8} debounce flush key=${key} batchSize=${batchSize}`);
24520
24584
  const result = onFlush(batch.entries);
24521
24585
  if (result && typeof result.catch === "function") {
24522
24586
  result.catch(onError);
@@ -24573,10 +24637,131 @@ function createInboundDebouncer(opts) {
24573
24637
  return { enqueue, flush, destroy };
24574
24638
  }
24575
24639
 
24640
+ // app/lib/whatsapp/opening-hours.ts
24641
+ var TAG9 = "[whatsapp:hours]";
24642
+ async function isBusinessOpen(accountId) {
24643
+ try {
24644
+ const timezone = await resolveTimezone(accountId);
24645
+ const now = /* @__PURE__ */ new Date();
24646
+ const dayOfWeek = getDayOfWeek(now, timezone);
24647
+ const previousDayOfWeek = getPreviousDayOfWeek(now, timezone);
24648
+ const currentTime = getCurrentTime(now, timezone);
24649
+ const session = getSession();
24650
+ try {
24651
+ const result = await session.run(
24652
+ `MATCH (b:LocalBusiness {accountId: $accountId})
24653
+ OPTIONAL MATCH (b)-[:HAS_HOURS]->(hours:OpeningHoursSpecification)
24654
+ WHERE hours.dayOfWeek IN [$dayOfWeek, $previousDayOfWeek]
24655
+ RETURN hours.dayOfWeek AS dayOfWeek, hours.opens AS opens, hours.closes AS closes`,
24656
+ { accountId, dayOfWeek, previousDayOfWeek }
24657
+ );
24658
+ if (result.records.length === 0) {
24659
+ console.error(`${TAG9} [${accountId}] business hours check: no opening hours configured, treating as open`);
24660
+ return { open: true, reason: "no opening hours configured" };
24661
+ }
24662
+ const specs = result.records.filter((r) => r.get("opens") != null && r.get("closes") != null).map((r) => ({
24663
+ day: String(r.get("dayOfWeek")).trim(),
24664
+ opens: String(r.get("opens")).trim(),
24665
+ closes: String(r.get("closes")).trim()
24666
+ }));
24667
+ if (specs.length === 0) {
24668
+ console.error(`${TAG9} [${accountId}] business hours check: no opening hours configured, treating as open`);
24669
+ return { open: true, reason: "no opening hours configured" };
24670
+ }
24671
+ for (const spec of specs) {
24672
+ if (!spec.opens || !spec.closes || spec.opens === spec.closes) continue;
24673
+ const isYesterday = spec.day === previousDayOfWeek;
24674
+ if (isYesterday) {
24675
+ if (spec.opens > spec.closes && currentTime < spec.closes) {
24676
+ const hoursStr = `${spec.opens}-${spec.closes} (${spec.day})`;
24677
+ console.error(
24678
+ `${TAG9} [${accountId}] business hours check: open (day=${dayOfWeek}, time=${currentTime}, hours=${hoursStr})`
24679
+ );
24680
+ return {
24681
+ open: true,
24682
+ reason: "within business hours",
24683
+ dayOfWeek,
24684
+ currentTime,
24685
+ matchedHours: hoursStr
24686
+ };
24687
+ }
24688
+ } else if (isTimeInRange(currentTime, spec.opens, spec.closes)) {
24689
+ const hoursStr = `${spec.opens}-${spec.closes}`;
24690
+ console.error(
24691
+ `${TAG9} [${accountId}] business hours check: open (day=${dayOfWeek}, time=${currentTime}, hours=${hoursStr})`
24692
+ );
24693
+ return {
24694
+ open: true,
24695
+ reason: "within business hours",
24696
+ dayOfWeek,
24697
+ currentTime,
24698
+ matchedHours: hoursStr
24699
+ };
24700
+ }
24701
+ }
24702
+ const todaySpecs = specs.filter((s) => s.day === dayOfWeek);
24703
+ const allHours = todaySpecs.map((s) => `${s.opens}-${s.closes}`).join(", ") || "none today";
24704
+ console.error(
24705
+ `${TAG9} [${accountId}] business hours check: closed (day=${dayOfWeek}, time=${currentTime}, hours=${allHours})`
24706
+ );
24707
+ return {
24708
+ open: false,
24709
+ reason: "outside business hours",
24710
+ dayOfWeek,
24711
+ currentTime,
24712
+ matchedHours: allHours
24713
+ };
24714
+ } finally {
24715
+ await session.close();
24716
+ }
24717
+ } catch (err) {
24718
+ console.error(
24719
+ `${TAG9} [${accountId}] business hours check failed, treating as open: ${err instanceof Error ? err.message : String(err)}`
24720
+ );
24721
+ return { open: true, reason: "hours check failed (treating as open)" };
24722
+ }
24723
+ }
24724
+ async function resolveTimezone(accountId) {
24725
+ try {
24726
+ const tz = await getUserTimezone(accountId);
24727
+ if (tz) {
24728
+ Intl.DateTimeFormat("en-US", { timeZone: tz });
24729
+ return tz;
24730
+ }
24731
+ } catch {
24732
+ }
24733
+ return Intl.DateTimeFormat().resolvedOptions().timeZone;
24734
+ }
24735
+ function getDayOfWeek(date5, timezone) {
24736
+ return new Intl.DateTimeFormat("en-US", { weekday: "long", timeZone: timezone }).format(date5);
24737
+ }
24738
+ function getPreviousDayOfWeek(date5, timezone) {
24739
+ const yesterday = new Date(date5.getTime() - 24 * 60 * 60 * 1e3);
24740
+ return getDayOfWeek(yesterday, timezone);
24741
+ }
24742
+ function getCurrentTime(date5, timezone) {
24743
+ const parts = new Intl.DateTimeFormat("en-US", {
24744
+ hour: "2-digit",
24745
+ minute: "2-digit",
24746
+ hour12: false,
24747
+ timeZone: timezone
24748
+ }).formatToParts(date5);
24749
+ const hour = parts.find((p) => p.type === "hour")?.value ?? "00";
24750
+ const minute = parts.find((p) => p.type === "minute")?.value ?? "00";
24751
+ return `${hour}:${minute}`;
24752
+ }
24753
+ function isTimeInRange(time3, opens, closes) {
24754
+ if (opens <= closes) {
24755
+ return time3 >= opens && time3 < closes;
24756
+ }
24757
+ return time3 >= opens || time3 < closes;
24758
+ }
24759
+
24576
24760
  // app/lib/whatsapp/manager.ts
24577
- var TAG8 = "[whatsapp:manager]";
24761
+ var TAG10 = "[whatsapp:manager]";
24578
24762
  var MAX_RECONNECT_ATTEMPTS = 10;
24579
24763
  var MESSAGE_STORE_MAX = 500;
24764
+ var GROUP_META_TTL = 5 * 60 * 1e3;
24580
24765
  var connections = /* @__PURE__ */ new Map();
24581
24766
  var configDir = null;
24582
24767
  var whatsAppConfig = {};
@@ -24593,12 +24778,12 @@ function storeMessage(storeKey, entry) {
24593
24778
  if (entries.length > MESSAGE_STORE_MAX) {
24594
24779
  const trimmed = entries.length - MESSAGE_STORE_MAX;
24595
24780
  entries.splice(0, trimmed);
24596
- console.error(`${TAG8} message store trimmed for ${storeKey}: ${trimmed} oldest messages removed`);
24781
+ console.error(`${TAG10} message store trimmed for ${storeKey}: ${trimmed} oldest messages removed`);
24597
24782
  }
24598
24783
  }
24599
24784
  async function init(opts) {
24600
24785
  if (initialized) {
24601
- console.error(`${TAG8} already initialized`);
24786
+ console.error(`${TAG10} already initialized`);
24602
24787
  return;
24603
24788
  }
24604
24789
  configDir = opts.configDir;
@@ -24606,20 +24791,20 @@ async function init(opts) {
24606
24791
  loadConfig(opts.accountConfig);
24607
24792
  const accountIds = listCredentialAccountIds(configDir);
24608
24793
  if (accountIds.length === 0) {
24609
- console.error(`${TAG8} init: no stored WhatsApp credentials found`);
24794
+ console.error(`${TAG10} init: no stored WhatsApp credentials found`);
24610
24795
  initialized = true;
24611
24796
  return;
24612
24797
  }
24613
- console.error(`${TAG8} init: found ${accountIds.length} credentialed account(s): ${accountIds.join(", ")}`);
24798
+ console.error(`${TAG10} init: found ${accountIds.length} credentialed account(s): ${accountIds.join(", ")}`);
24614
24799
  initialized = true;
24615
24800
  for (const accountId of accountIds) {
24616
24801
  const accountCfg = whatsAppConfig.accounts?.[accountId];
24617
24802
  if (accountCfg?.enabled === false) {
24618
- console.error(`${TAG8} skipping disabled account=${accountId}`);
24803
+ console.error(`${TAG10} skipping disabled account=${accountId}`);
24619
24804
  continue;
24620
24805
  }
24621
24806
  startConnection(accountId).catch((err) => {
24622
- console.error(`${TAG8} failed to auto-start account=${accountId}: ${formatError(err)}`);
24807
+ console.error(`${TAG10} failed to auto-start account=${accountId}: ${formatError(err)}`);
24623
24808
  });
24624
24809
  }
24625
24810
  }
@@ -24628,7 +24813,7 @@ async function startConnection(accountId) {
24628
24813
  const authDir = resolveAuthDir(configDir, accountId);
24629
24814
  const hasAuth = await authExists(authDir);
24630
24815
  if (!hasAuth) {
24631
- console.error(`${TAG8} no credentials for account=${accountId}`);
24816
+ console.error(`${TAG10} no credentials for account=${accountId}`);
24632
24817
  return;
24633
24818
  }
24634
24819
  await stopConnection(accountId);
@@ -24643,7 +24828,8 @@ async function startConnection(accountId) {
24643
24828
  reconnectAttempts: 0,
24644
24829
  abortController: new AbortController(),
24645
24830
  debouncer: null,
24646
- lidMapping: null
24831
+ lidMapping: null,
24832
+ groupMetaCache: /* @__PURE__ */ new Map()
24647
24833
  };
24648
24834
  connections.set(accountId, conn);
24649
24835
  await connectWithReconnect(conn);
@@ -24663,11 +24849,11 @@ async function stopConnection(accountId) {
24663
24849
  conn.sock.ev.removeAllListeners("creds.update");
24664
24850
  conn.sock.ws?.close?.();
24665
24851
  } catch (err) {
24666
- console.warn(`${TAG8} socket cleanup error during stop account=${accountId}: ${String(err)}`);
24852
+ console.warn(`${TAG10} socket cleanup error during stop account=${accountId}: ${String(err)}`);
24667
24853
  }
24668
24854
  }
24669
24855
  connections.delete(accountId);
24670
- console.error(`${TAG8} stopped account=${accountId}`);
24856
+ console.error(`${TAG10} stopped account=${accountId}`);
24671
24857
  }
24672
24858
  function getStatus() {
24673
24859
  return Array.from(connections.values()).map((conn) => ({
@@ -24701,18 +24887,19 @@ async function registerLoginSocket(accountId, sock, authDir) {
24701
24887
  lastConnectedAt: Date.now(),
24702
24888
  abortController: new AbortController(),
24703
24889
  debouncer: null,
24704
- lidMapping
24890
+ lidMapping,
24891
+ groupMetaCache: /* @__PURE__ */ new Map()
24705
24892
  };
24706
24893
  connections.set(accountId, conn);
24707
24894
  try {
24708
24895
  await sock.sendPresenceUpdate("available");
24709
- console.error(`${TAG8} presence set to available account=${accountId}`);
24896
+ console.error(`${TAG10} presence set to available account=${accountId}`);
24710
24897
  } catch (err) {
24711
- console.error(`${TAG8} presence update failed account=${accountId}: ${String(err)}`);
24898
+ console.error(`${TAG10} presence update failed account=${accountId}: ${String(err)}`);
24712
24899
  }
24713
24900
  monitorInbound(conn);
24714
24901
  watchForDisconnect(conn);
24715
- console.error(`${TAG8} registered login socket for account=${accountId} phone=${selfId.e164 ?? "unknown"}`);
24902
+ console.error(`${TAG10} registered login socket for account=${accountId} phone=${selfId.e164 ?? "unknown"}`);
24716
24903
  }
24717
24904
  function reloadConfig(accountConfig) {
24718
24905
  loadConfig(accountConfig);
@@ -24722,7 +24909,7 @@ async function shutdown() {
24722
24909
  const ids = Array.from(connections.keys());
24723
24910
  await Promise.all(ids.map((id) => stopConnection(id)));
24724
24911
  initialized = false;
24725
- console.error(`${TAG8} shutdown complete`);
24912
+ console.error(`${TAG10} shutdown complete`);
24726
24913
  }
24727
24914
  function loadConfig(accountConfig) {
24728
24915
  try {
@@ -24734,12 +24921,12 @@ function loadConfig(accountConfig) {
24734
24921
  if (parsed.success) {
24735
24922
  whatsAppConfig = parsed.data;
24736
24923
  } else {
24737
- console.error(`${TAG8} config validation failed: ${parsed.error.message}`);
24924
+ console.error(`${TAG10} config validation failed: ${parsed.error.message}`);
24738
24925
  whatsAppConfig = {};
24739
24926
  }
24740
24927
  }
24741
24928
  } catch (err) {
24742
- console.error(`${TAG8} config load error: ${String(err)}`);
24929
+ console.error(`${TAG10} config load error: ${String(err)}`);
24743
24930
  whatsAppConfig = {};
24744
24931
  }
24745
24932
  }
@@ -24747,13 +24934,13 @@ async function connectWithReconnect(conn) {
24747
24934
  const maxAttempts = MAX_RECONNECT_ATTEMPTS;
24748
24935
  while (!conn.abortController.signal.aborted) {
24749
24936
  try {
24750
- console.error(`${TAG8} connecting account=${conn.accountId} attempt=${conn.reconnectAttempts}`);
24937
+ console.error(`${TAG10} connecting account=${conn.accountId} attempt=${conn.reconnectAttempts}`);
24751
24938
  const sock = await createWaSocket({
24752
24939
  authDir: conn.authDir,
24753
24940
  silent: true
24754
24941
  });
24755
24942
  conn.sock = sock;
24756
- console.error(`${TAG8} socket created account=${conn.accountId} \u2014 waiting for connection`);
24943
+ console.error(`${TAG10} socket created account=${conn.accountId} \u2014 waiting for connection`);
24757
24944
  await waitForConnection(sock);
24758
24945
  const selfId = readSelfId(conn.authDir);
24759
24946
  conn.connected = true;
@@ -24763,12 +24950,12 @@ async function connectWithReconnect(conn) {
24763
24950
  conn.reconnectAttempts = 0;
24764
24951
  conn.lastError = void 0;
24765
24952
  conn.lidMapping = sock.signalRepository?.lidMapping ?? null;
24766
- console.error(`${TAG8} connected account=${conn.accountId} phone=${selfId.e164 ?? "unknown"}`);
24953
+ console.error(`${TAG10} connected account=${conn.accountId} phone=${selfId.e164 ?? "unknown"}`);
24767
24954
  try {
24768
24955
  await sock.sendPresenceUpdate("available");
24769
- console.error(`${TAG8} presence set to available account=${conn.accountId}`);
24956
+ console.error(`${TAG10} presence set to available account=${conn.accountId}`);
24770
24957
  } catch (err) {
24771
- console.error(`${TAG8} presence update failed account=${conn.accountId}: ${String(err)}`);
24958
+ console.error(`${TAG10} presence update failed account=${conn.accountId}: ${String(err)}`);
24772
24959
  }
24773
24960
  if (conn.debouncer) {
24774
24961
  conn.debouncer.destroy();
@@ -24783,19 +24970,19 @@ async function connectWithReconnect(conn) {
24783
24970
  conn.sock = null;
24784
24971
  const classification = classifyDisconnect(err);
24785
24972
  conn.lastError = classification.message;
24786
- console.error(`${TAG8} disconnect account=${conn.accountId}: ${classification.kind} \u2014 ${classification.message}`);
24973
+ console.error(`${TAG10} disconnect account=${conn.accountId}: ${classification.kind} \u2014 ${classification.message}`);
24787
24974
  if (!classification.shouldRetry) {
24788
- console.error(`${TAG8} terminal disconnect for account=${conn.accountId}, stopping reconnection`);
24975
+ console.error(`${TAG10} terminal disconnect for account=${conn.accountId}, stopping reconnection`);
24789
24976
  return;
24790
24977
  }
24791
24978
  conn.reconnectAttempts++;
24792
24979
  if (conn.reconnectAttempts > maxAttempts) {
24793
- console.error(`${TAG8} max retries exceeded for account=${conn.accountId}`);
24980
+ console.error(`${TAG10} max retries exceeded for account=${conn.accountId}`);
24794
24981
  conn.lastError = `Max reconnect attempts (${maxAttempts}) exceeded`;
24795
24982
  return;
24796
24983
  }
24797
24984
  const delay = computeBackoff(conn.reconnectAttempts);
24798
- console.error(`${TAG8} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${conn.reconnectAttempts}/${maxAttempts})`);
24985
+ console.error(`${TAG10} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${conn.reconnectAttempts}/${maxAttempts})`);
24799
24986
  await new Promise((resolve19) => {
24800
24987
  const timer = setTimeout(resolve19, delay);
24801
24988
  conn.abortController.signal.addEventListener("abort", () => {
@@ -24825,20 +25012,51 @@ function watchForDisconnect(conn) {
24825
25012
  conn.sock.ev.on("connection.update", (update) => {
24826
25013
  if (update.connection === "close") {
24827
25014
  if (connections.get(conn.accountId) !== conn) return;
24828
- console.error(`${TAG8} socket disconnected for account=${conn.accountId}`);
25015
+ console.error(`${TAG10} socket disconnected for account=${conn.accountId}`);
24829
25016
  conn.connected = false;
24830
25017
  conn.sock = null;
24831
25018
  connectWithReconnect(conn).catch((err) => {
24832
- console.error(`${TAG8} reconnection failed for account=${conn.accountId}: ${formatError(err)}`);
25019
+ console.error(`${TAG10} reconnection failed for account=${conn.accountId}: ${formatError(err)}`);
24833
25020
  });
24834
25021
  }
24835
25022
  });
24836
25023
  }
25024
+ async function getGroupMeta(conn, jid) {
25025
+ const cached2 = conn.groupMetaCache.get(jid);
25026
+ if (cached2 && cached2.expires > Date.now()) return cached2;
25027
+ if (!conn.sock) return null;
25028
+ console.error(`${TAG10} group metadata cache miss for ${jid}, fetching from Baileys account=${conn.accountId}`);
25029
+ try {
25030
+ const meta3 = await conn.sock.groupMetadata(jid);
25031
+ const participants = await Promise.all(
25032
+ (meta3.participants ?? []).map(async (p) => {
25033
+ return await resolveJidToE164(p.id, conn.lidMapping) ?? p.id;
25034
+ })
25035
+ );
25036
+ const entry = {
25037
+ subject: meta3.subject,
25038
+ participants,
25039
+ expires: Date.now() + GROUP_META_TTL
25040
+ };
25041
+ conn.groupMetaCache.set(jid, entry);
25042
+ console.error(
25043
+ `${TAG10} group metadata cached for ${jid}: "${meta3.subject}", ${participants.length} participants, expires in ${GROUP_META_TTL}ms account=${conn.accountId}`
25044
+ );
25045
+ return entry;
25046
+ } catch (err) {
25047
+ console.error(
25048
+ `${TAG10} group metadata fetch failed for ${jid}: ${err instanceof Error ? err.message : String(err)}, caching empty entry for ${GROUP_META_TTL}ms account=${conn.accountId}`
25049
+ );
25050
+ const emptyEntry = { expires: Date.now() + GROUP_META_TTL };
25051
+ conn.groupMetaCache.set(jid, emptyEntry);
25052
+ return null;
25053
+ }
25054
+ }
24837
25055
  function monitorInbound(conn) {
24838
25056
  if (!conn.sock || !onInboundMessage) return;
24839
25057
  const sock = conn.sock;
24840
25058
  const debounceMs = whatsAppConfig.accounts?.[conn.accountId]?.debounceMs ?? whatsAppConfig.debounceMs ?? 0;
24841
- console.error(`${TAG8} monitorInbound started account=${conn.accountId} debounceMs=${debounceMs}`);
25059
+ console.error(`${TAG10} monitorInbound started account=${conn.accountId} debounceMs=${debounceMs}`);
24842
25060
  conn.debouncer = createInboundDebouncer({
24843
25061
  debounceMs,
24844
25062
  buildKey: (payload) => {
@@ -24851,7 +25069,7 @@ function monitorInbound(conn) {
24851
25069
  onInboundMessage(entries[0]);
24852
25070
  return;
24853
25071
  }
24854
- console.error(`${TAG8} debounce: combining ${entries.length} messages account=${conn.accountId} from=${entries[0].senderPhone}`);
25072
+ console.error(`${TAG10} debounce: combining ${entries.length} messages account=${conn.accountId} from=${entries[0].senderPhone}`);
24855
25073
  const last = entries[entries.length - 1];
24856
25074
  const mediaEntry = entries.find((e) => e.mediaPath);
24857
25075
  const combinedText = entries.map((e) => e.text).filter(Boolean).join("\n");
@@ -24864,7 +25082,7 @@ function monitorInbound(conn) {
24864
25082
  });
24865
25083
  },
24866
25084
  onError: (err) => {
24867
- console.error(`${TAG8} debounce flush error account=${conn.accountId}: ${String(err)}`);
25085
+ console.error(`${TAG10} debounce flush error account=${conn.accountId}: ${String(err)}`);
24868
25086
  }
24869
25087
  });
24870
25088
  sock.ev.on("messages.upsert", async (upsert) => {
@@ -24892,8 +25110,13 @@ function monitorInbound(conn) {
24892
25110
  });
24893
25111
  const entries = messageStore.get(storeKey);
24894
25112
  console.error(
24895
- `${TAG8} stored message ${msg.key.id ?? "?"} for ${remoteJid} (type: ${upsert.type}, store size: ${entries?.length ?? 0}/${MESSAGE_STORE_MAX}) account=${conn.accountId}`
25113
+ `${TAG10} stored message ${msg.key.id ?? "?"} for ${remoteJid} (type: ${upsert.type}, store size: ${entries?.length ?? 0}/${MESSAGE_STORE_MAX}) account=${conn.accountId}`
24896
25114
  );
25115
+ recordActivity({
25116
+ accountId: conn.accountId,
25117
+ direction: "inbound",
25118
+ jid: remoteJid
25119
+ });
24897
25120
  }
24898
25121
  if (upsert.type === "append") {
24899
25122
  const sendReceipts = whatsAppConfig.accounts?.[conn.accountId]?.sendReadReceipts ?? whatsAppConfig.sendReadReceipts ?? true;
@@ -24906,13 +25129,13 @@ function monitorInbound(conn) {
24906
25129
  );
24907
25130
  }
24908
25131
  console.error(
24909
- `${TAG8} append-type message ${msg.key.id ?? "?"} stored, dispatch skipped account=${conn.accountId}`
25132
+ `${TAG10} append-type message ${msg.key.id ?? "?"} stored, dispatch skipped account=${conn.accountId}`
24910
25133
  );
24911
25134
  continue;
24912
25135
  }
24913
25136
  await handleInboundMessage(conn, msg);
24914
25137
  } catch (err) {
24915
- console.error(`${TAG8} inbound handler error account=${conn.accountId}: ${String(err)}`);
25138
+ console.error(`${TAG10} inbound handler error account=${conn.accountId}: ${String(err)}`);
24916
25139
  }
24917
25140
  }
24918
25141
  });
@@ -24922,35 +25145,35 @@ async function handleInboundMessage(conn, msg) {
24922
25145
  const remoteJid = msg.key.remoteJid;
24923
25146
  if (!remoteJid) return;
24924
25147
  if (remoteJid === "status@broadcast") {
24925
- console.error(`${TAG8} drop: status broadcast account=${conn.accountId}`);
25148
+ console.error(`${TAG10} drop: status broadcast account=${conn.accountId}`);
24926
25149
  return;
24927
25150
  }
24928
25151
  if (!msg.message) {
24929
- console.error(`${TAG8} drop: empty message account=${conn.accountId} from=${remoteJid}`);
25152
+ console.error(`${TAG10} drop: empty message account=${conn.accountId} from=${remoteJid}`);
24930
25153
  return;
24931
25154
  }
24932
25155
  const dedupKey = `${conn.accountId}:${remoteJid}:${msg.key.id}`;
24933
25156
  if (isDuplicateInbound(dedupKey)) {
24934
- console.error(`${TAG8} drop: duplicate account=${conn.accountId} key=${dedupKey}`);
25157
+ console.error(`${TAG10} drop: duplicate account=${conn.accountId} key=${dedupKey}`);
24935
25158
  return;
24936
25159
  }
24937
25160
  if (msg.key.fromMe) {
24938
25161
  if (msg.key.id && isAgentSentMessage(msg.key.id)) {
24939
- console.error(`${TAG8} drop: echo suppression account=${conn.accountId} msgId=${msg.key.id}`);
25162
+ console.error(`${TAG10} drop: echo suppression account=${conn.accountId} msgId=${msg.key.id}`);
24940
25163
  return;
24941
25164
  }
24942
25165
  const extracted2 = extractMessage(msg);
24943
25166
  if (!extracted2.text) {
24944
- console.error(`${TAG8} owner reply skipped \u2014 no text content account=${conn.accountId}`);
25167
+ console.error(`${TAG10} owner reply skipped \u2014 no text content account=${conn.accountId}`);
24945
25168
  return;
24946
25169
  }
24947
25170
  const isGroup2 = isGroupJid(remoteJid);
24948
25171
  const senderPhone2 = conn.selfPhone ?? "owner";
24949
- console.error(`${TAG8} owner reply mirrored to session from=${senderPhone2} account=${conn.accountId}`);
25172
+ console.error(`${TAG10} owner reply mirrored to session from=${senderPhone2} account=${conn.accountId}`);
24950
25173
  const reply2 = async (text) => {
24951
25174
  const currentSock = conn.sock;
24952
25175
  if (!currentSock) throw new Error("WhatsApp disconnected \u2014 cannot reply");
24953
- await sendTextMessage(currentSock, remoteJid, text);
25176
+ await sendTextMessage(currentSock, remoteJid, text, { accountId: conn.accountId });
24954
25177
  };
24955
25178
  onInboundMessage({
24956
25179
  accountId: conn.accountId,
@@ -24967,7 +25190,7 @@ async function handleInboundMessage(conn, msg) {
24967
25190
  }
24968
25191
  const extracted = extractMessage(msg);
24969
25192
  if (!extracted.text && !extracted.mediaType) {
24970
- console.error(`${TAG8} drop: no text or media account=${conn.accountId} from=${remoteJid}`);
25193
+ console.error(`${TAG10} drop: no text or media account=${conn.accountId} from=${remoteJid}`);
24971
25194
  return;
24972
25195
  }
24973
25196
  let mediaResult;
@@ -24977,7 +25200,7 @@ async function handleInboundMessage(conn, msg) {
24977
25200
  maxBytes: maxMb * 1024 * 1024
24978
25201
  });
24979
25202
  if (!mediaResult) {
24980
- console.error(`${TAG8} media download returned undefined account=${conn.accountId} type=${extracted.mediaType} from=${remoteJid}`);
25203
+ console.error(`${TAG10} media download returned undefined account=${conn.accountId} type=${extracted.mediaType} from=${remoteJid}`);
24981
25204
  }
24982
25205
  }
24983
25206
  const isGroup = isGroupJid(remoteJid);
@@ -25005,9 +25228,14 @@ async function handleInboundMessage(conn, msg) {
25005
25228
  });
25006
25229
  }
25007
25230
  console.error(
25008
- `${TAG8} inbound account=${conn.accountId} from=${senderPhone} group=${isGroup} access=${accessResult.allowed ? "allowed" : "blocked"}(${accessResult.reason}) agent=${accessResult.agentType}` + (extracted.mediaType ? ` media=${extracted.mediaType}` : "") + (mediaResult ? ` mediaPath=${mediaResult.path}` : "") + (extracted.quotedMessage ? ` replyTo=${extracted.quotedMessage.id}` : "")
25231
+ `${TAG10} inbound account=${conn.accountId} from=${senderPhone} group=${isGroup} access=${accessResult.allowed ? "allowed" : "blocked"}(${accessResult.reason}) agent=${accessResult.agentType}` + (extracted.mediaType ? ` media=${extracted.mediaType}` : "") + (mediaResult ? ` mediaPath=${mediaResult.path}` : "") + (extracted.quotedMessage ? ` replyTo=${extracted.quotedMessage.id}` : "")
25009
25232
  );
25010
25233
  if (!accessResult.allowed) return;
25234
+ let groupSubject;
25235
+ if (isGroup) {
25236
+ const groupMeta = await getGroupMeta(conn, remoteJid);
25237
+ groupSubject = groupMeta?.subject;
25238
+ }
25011
25239
  const sendReceipts = whatsAppConfig.accounts?.[conn.accountId]?.sendReadReceipts ?? whatsAppConfig.sendReadReceipts ?? true;
25012
25240
  if (sendReceipts && msg.key.id) {
25013
25241
  sendReadReceipt(conn.sock, remoteJid, [msg.key.id], isGroup ? senderJid : void 0);
@@ -25015,7 +25243,7 @@ async function handleInboundMessage(conn, msg) {
25015
25243
  const reply = async (text) => {
25016
25244
  const currentSock = conn.sock;
25017
25245
  if (!currentSock) throw new Error("WhatsApp disconnected \u2014 cannot reply");
25018
- await sendTextMessage(currentSock, remoteJid, text);
25246
+ await sendTextMessage(currentSock, remoteJid, text, { accountId: conn.accountId });
25019
25247
  };
25020
25248
  const sessionKey = accessResult.agentType === "admin" ? `whatsapp:${conn.accountId}` : void 0;
25021
25249
  conn.lastMessageAt = Date.now();
@@ -25026,6 +25254,7 @@ async function handleInboundMessage(conn, msg) {
25026
25254
  text: extracted.text,
25027
25255
  isGroup,
25028
25256
  groupJid: isGroup ? remoteJid : void 0,
25257
+ groupSubject,
25029
25258
  reply,
25030
25259
  sessionKey,
25031
25260
  mediaPath: mediaResult?.path,
@@ -25033,6 +25262,24 @@ async function handleInboundMessage(conn, msg) {
25033
25262
  mediaType: extracted.mediaType,
25034
25263
  replyContext: extracted.quotedMessage
25035
25264
  };
25265
+ if (accessResult.agentType === "public") {
25266
+ const hoursResult = await isBusinessOpen(conn.accountId);
25267
+ if (!hoursResult.open) {
25268
+ console.error(`${TAG10} [${conn.accountId}] dispatch skipped: business closed`);
25269
+ const afterHoursMessage = whatsAppConfig.accounts?.[conn.accountId]?.afterHoursMessage ?? whatsAppConfig.afterHoursMessage;
25270
+ if (afterHoursMessage) {
25271
+ try {
25272
+ await reply(afterHoursMessage);
25273
+ console.error(`${TAG10} [${conn.accountId}] after-hours auto-reply sent to ${remoteJid}`);
25274
+ } catch (err) {
25275
+ console.error(
25276
+ `${TAG10} [${conn.accountId}] after-hours auto-reply failed: ${err instanceof Error ? err.message : String(err)}`
25277
+ );
25278
+ }
25279
+ }
25280
+ return;
25281
+ }
25282
+ }
25036
25283
  if (conn.debouncer) {
25037
25284
  conn.debouncer.enqueue(payload);
25038
25285
  } else {
@@ -25137,7 +25384,7 @@ async function POST13(req) {
25137
25384
  { status: 503 }
25138
25385
  );
25139
25386
  }
25140
- const result = await sendTextMessage(sock, to, text);
25387
+ const result = await sendTextMessage(sock, to, text, { accountId });
25141
25388
  return Response.json(result);
25142
25389
  } catch (err) {
25143
25390
  console.error(`[whatsapp:api] send error: ${String(err)}`);
@@ -25371,7 +25618,7 @@ async function POST14(req) {
25371
25618
  import { readFile as readFile2, stat as stat2 } from "fs/promises";
25372
25619
  import { realpathSync as realpathSync2 } from "fs";
25373
25620
  import { resolve as resolve11, basename as basename2 } from "path";
25374
- var TAG9 = "[whatsapp:api]";
25621
+ var TAG11 = "[whatsapp:api]";
25375
25622
  var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT || "";
25376
25623
  async function POST15(req) {
25377
25624
  try {
@@ -25394,16 +25641,16 @@ async function POST15(req) {
25394
25641
  const accountResolved = realpathSync2(accountDir);
25395
25642
  if (!resolvedPath.startsWith(accountResolved + "/")) {
25396
25643
  const sanitised = filePath.replace(accountDir, "<account>/");
25397
- console.error(`${TAG9} send-document REJECTED path=${sanitised} reason=outside_account_directory`);
25644
+ console.error(`${TAG11} send-document REJECTED path=${sanitised} reason=outside_account_directory`);
25398
25645
  return Response.json({ error: "Access denied: file is outside the account directory" }, { status: 403 });
25399
25646
  }
25400
25647
  } catch (err) {
25401
25648
  const code = err.code;
25402
25649
  if (code === "ENOENT") {
25403
- console.error(`${TAG9} send-document ENOENT path=${filePath}`);
25650
+ console.error(`${TAG11} send-document ENOENT path=${filePath}`);
25404
25651
  return Response.json({ error: `File not found: ${filePath}` }, { status: 404 });
25405
25652
  }
25406
- console.error(`${TAG9} send-document path error: ${String(err)}`);
25653
+ console.error(`${TAG11} send-document path error: ${String(err)}`);
25407
25654
  return Response.json({ error: String(err) }, { status: 500 });
25408
25655
  }
25409
25656
  const fileStat = await stat2(resolvedPath);
@@ -25429,13 +25676,30 @@ async function POST15(req) {
25429
25676
  mimetype,
25430
25677
  filename,
25431
25678
  caption
25432
- });
25679
+ }, { accountId });
25433
25680
  console.error(
25434
- `${TAG9} send-document to=${to} size=${fileStat.size} mime=${mimetype} ok=${result.success}` + (result.messageId ? ` id=${result.messageId}` : "")
25681
+ `${TAG11} send-document to=${to} size=${fileStat.size} mime=${mimetype} ok=${result.success}` + (result.messageId ? ` id=${result.messageId}` : "")
25435
25682
  );
25436
25683
  return Response.json(result);
25437
25684
  } catch (err) {
25438
- console.error(`${TAG9} send-document error: ${String(err)}`);
25685
+ console.error(`${TAG11} send-document error: ${String(err)}`);
25686
+ return Response.json({ error: String(err) }, { status: 500 });
25687
+ }
25688
+ }
25689
+
25690
+ // app/api/whatsapp/activity/route.ts
25691
+ async function GET3(req) {
25692
+ try {
25693
+ const url2 = new URL(req.url);
25694
+ const accountId = url2.searchParams.get("accountId") ?? void 0;
25695
+ const result = getChannelActivity(accountId);
25696
+ const total = result.accounts.reduce((sum, a) => sum + a.total, 0);
25697
+ console.error(
25698
+ `[whatsapp:api] activity accounts=${result.accounts.length} total=${total} recentEvents=${result.recentEvents.length}` + (accountId ? ` filter=${accountId}` : "")
25699
+ );
25700
+ return Response.json(result);
25701
+ } catch (err) {
25702
+ console.error(`[whatsapp:api] activity error: ${String(err)}`);
25439
25703
  return Response.json({ error: String(err) }, { status: 500 });
25440
25704
  }
25441
25705
  }
@@ -25495,7 +25759,7 @@ async function waitForAuthPage(timeoutMs = 2e4) {
25495
25759
  }
25496
25760
  return false;
25497
25761
  }
25498
- async function GET3() {
25762
+ async function GET4() {
25499
25763
  return Response.json({ authenticated: checkAuthStatus() });
25500
25764
  }
25501
25765
  async function POST17(req) {
@@ -25949,7 +26213,7 @@ async function POST21(req) {
25949
26213
  import { existsSync as existsSync14, readdirSync as readdirSync3, readFileSync as readFileSync14, statSync as statSync3 } from "fs";
25950
26214
  import { resolve as resolve12, basename as basename3 } from "path";
25951
26215
  var TAIL_BYTES = 8192;
25952
- async function GET4(request) {
26216
+ async function GET5(request) {
25953
26217
  const { searchParams } = new URL(request.url);
25954
26218
  const fileParam = searchParams.get("file");
25955
26219
  const typeParam = searchParams.get("type");
@@ -26023,7 +26287,7 @@ async function GET4(request) {
26023
26287
 
26024
26288
  // app/api/admin/claude-info/route.ts
26025
26289
  import { execFileSync as execFileSync3 } from "child_process";
26026
- async function GET5() {
26290
+ async function GET6() {
26027
26291
  let version2 = "unknown";
26028
26292
  try {
26029
26293
  const raw2 = execFileSync3("claude", ["--version"], { encoding: "utf-8", timeout: 5e3 });
@@ -26047,7 +26311,7 @@ async function GET5() {
26047
26311
  import { readFile as readFile3, readdir } from "fs/promises";
26048
26312
  import { existsSync as existsSync15 } from "fs";
26049
26313
  import { resolve as resolve13 } from "path";
26050
- async function GET6(req, attachmentId) {
26314
+ async function GET7(req, attachmentId) {
26051
26315
  const sessionKey = new URL(req.url).searchParams.get("session_key") ?? "";
26052
26316
  if (!validateSession(sessionKey, "admin")) {
26053
26317
  return new Response("Unauthorized", { status: 401 });
@@ -26131,7 +26395,7 @@ async function PATCH(req) {
26131
26395
  // app/api/admin/agents/route.ts
26132
26396
  import { resolve as resolve15 } from "path";
26133
26397
  import { readdirSync as readdirSync4, readFileSync as readFileSync16, existsSync as existsSync16 } from "fs";
26134
- async function GET7() {
26398
+ async function GET8() {
26135
26399
  const account = resolveAccount();
26136
26400
  if (!account) {
26137
26401
  return Response.json({ agents: [] });
@@ -26234,7 +26498,7 @@ function isNewer(latest, installed) {
26234
26498
  function invalidateVersionCache() {
26235
26499
  latestCache = null;
26236
26500
  }
26237
- async function GET8() {
26501
+ async function GET9() {
26238
26502
  const installed = readInstalled();
26239
26503
  const latest = await fetchLatest();
26240
26504
  const updateAvailable = installed !== "unknown" && latest !== null && isNewer(latest, installed);
@@ -26314,7 +26578,7 @@ async function POST22(req) {
26314
26578
  }
26315
26579
 
26316
26580
  // app/api/admin/sessions/route.ts
26317
- async function GET9(req) {
26581
+ async function GET10(req) {
26318
26582
  const url2 = new URL(req.url);
26319
26583
  const sessionKey = url2.searchParams.get("session_key");
26320
26584
  if (!sessionKey) {
@@ -26365,7 +26629,7 @@ async function DELETE2(req, { params }) {
26365
26629
  }
26366
26630
 
26367
26631
  // app/api/admin/sessions/[id]/messages/route.ts
26368
- async function GET10(req, { params }) {
26632
+ async function GET11(req, { params }) {
26369
26633
  const { id: conversationId } = await params;
26370
26634
  const url2 = new URL(req.url);
26371
26635
  const sessionKey = url2.searchParams.get("session_key");
@@ -26748,33 +27012,34 @@ app.post("/api/whatsapp/reconnect", (c) => POST12(c.req.raw));
26748
27012
  app.post("/api/whatsapp/send", (c) => POST13(c.req.raw));
26749
27013
  app.post("/api/whatsapp/config", (c) => POST14(c.req.raw));
26750
27014
  app.post("/api/whatsapp/send-document", (c) => POST15(c.req.raw));
26751
- app.get("/api/onboarding/claude-auth", () => GET3());
27015
+ app.get("/api/whatsapp/activity", (c) => GET3(c.req.raw));
27016
+ app.get("/api/onboarding/claude-auth", () => GET4());
26752
27017
  app.post("/api/onboarding/claude-auth", (c) => POST17(c.req.raw));
26753
27018
  app.post("/api/onboarding/set-pin", (c) => POST18(c.req.raw));
26754
27019
  app.delete("/api/onboarding/set-pin", (c) => DELETE(c.req.raw));
26755
27020
  app.post("/api/admin/session", (c) => POST19(c.req.raw));
26756
27021
  app.post("/api/admin/chat", (c) => POST20(c.req.raw));
26757
27022
  app.post("/api/admin/compact", (c) => POST21(c.req.raw));
26758
- app.get("/api/admin/logs", (c) => GET4(c.req.raw));
26759
- app.get("/api/admin/claude-info", () => GET5());
27023
+ app.get("/api/admin/logs", (c) => GET5(c.req.raw));
27024
+ app.get("/api/admin/claude-info", () => GET6());
26760
27025
  app.patch("/api/admin/account", (c) => PATCH(c.req.raw));
26761
27026
  app.get(
26762
27027
  "/api/admin/attachment/:attachmentId",
26763
- (c) => GET6(c.req.raw, c.req.param("attachmentId"))
27028
+ (c) => GET7(c.req.raw, c.req.param("attachmentId"))
26764
27029
  );
26765
27030
  app.post("/api/admin/file-attach", (c) => POST16(c.req.raw));
26766
- app.get("/api/admin/version", () => GET8());
27031
+ app.get("/api/admin/version", () => GET9());
26767
27032
  app.post("/api/admin/version/upgrade", (c) => POST22(c.req.raw));
26768
- app.get("/api/admin/agents", () => GET7());
27033
+ app.get("/api/admin/agents", () => GET8());
26769
27034
  app.post("/api/admin/browser/launch", () => POST23());
26770
- app.get("/api/admin/sessions", (c) => GET9(c.req.raw));
27035
+ app.get("/api/admin/sessions", (c) => GET10(c.req.raw));
26771
27036
  app.delete(
26772
27037
  "/api/admin/sessions/:id",
26773
27038
  (c) => DELETE2(c.req.raw, { params: Promise.resolve({ id: c.req.param("id") }) })
26774
27039
  );
26775
27040
  app.get(
26776
27041
  "/api/admin/sessions/:id/messages",
26777
- (c) => GET10(c.req.raw, { params: Promise.resolve({ id: c.req.param("id") }) })
27042
+ (c) => GET11(c.req.raw, { params: Promise.resolve({ id: c.req.param("id") }) })
26778
27043
  );
26779
27044
  var SAFE_SLUG_RE = /^[a-z][a-z0-9-]{2,49}$/;
26780
27045
  var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;