@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 +1 -1
- package/payload/platform/plugins/whatsapp/PLUGIN.md +19 -1
- package/payload/platform/plugins/whatsapp/mcp/dist/index.js +133 -0
- package/payload/platform/plugins/whatsapp/mcp/dist/index.js.map +1 -1
- package/payload/platform/templates/agents/admin/IDENTITY.md +8 -3
- package/payload/platform/templates/agents/admin/LEARNINGS.md +1 -1
- package/payload/server/server.js +352 -87
package/package.json
CHANGED
|
@@ -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
|
|
36
|
+
`agents/admin/LEARNINGS.md` is injected into your system prompt every turn. It captures two categories of standing knowledge:
|
|
37
37
|
|
|
38
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
package/payload/server/server.js
CHANGED
|
@@ -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
|
|
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(`${
|
|
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(`${
|
|
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(`${
|
|
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(`${
|
|
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
|
|
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(`${
|
|
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(`${
|
|
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(`${
|
|
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(`${
|
|
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(`${
|
|
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(`${
|
|
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
|
|
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(`${
|
|
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
|
|
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(`${
|
|
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(`${
|
|
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(`${
|
|
24794
|
+
console.error(`${TAG10} init: no stored WhatsApp credentials found`);
|
|
24610
24795
|
initialized = true;
|
|
24611
24796
|
return;
|
|
24612
24797
|
}
|
|
24613
|
-
console.error(`${
|
|
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(`${
|
|
24803
|
+
console.error(`${TAG10} skipping disabled account=${accountId}`);
|
|
24619
24804
|
continue;
|
|
24620
24805
|
}
|
|
24621
24806
|
startConnection(accountId).catch((err) => {
|
|
24622
|
-
console.error(`${
|
|
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(`${
|
|
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(`${
|
|
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(`${
|
|
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(`${
|
|
24896
|
+
console.error(`${TAG10} presence set to available account=${accountId}`);
|
|
24710
24897
|
} catch (err) {
|
|
24711
|
-
console.error(`${
|
|
24898
|
+
console.error(`${TAG10} presence update failed account=${accountId}: ${String(err)}`);
|
|
24712
24899
|
}
|
|
24713
24900
|
monitorInbound(conn);
|
|
24714
24901
|
watchForDisconnect(conn);
|
|
24715
|
-
console.error(`${
|
|
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(`${
|
|
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(`${
|
|
24924
|
+
console.error(`${TAG10} config validation failed: ${parsed.error.message}`);
|
|
24738
24925
|
whatsAppConfig = {};
|
|
24739
24926
|
}
|
|
24740
24927
|
}
|
|
24741
24928
|
} catch (err) {
|
|
24742
|
-
console.error(`${
|
|
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(`${
|
|
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(`${
|
|
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(`${
|
|
24953
|
+
console.error(`${TAG10} connected account=${conn.accountId} phone=${selfId.e164 ?? "unknown"}`);
|
|
24767
24954
|
try {
|
|
24768
24955
|
await sock.sendPresenceUpdate("available");
|
|
24769
|
-
console.error(`${
|
|
24956
|
+
console.error(`${TAG10} presence set to available account=${conn.accountId}`);
|
|
24770
24957
|
} catch (err) {
|
|
24771
|
-
console.error(`${
|
|
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(`${
|
|
24973
|
+
console.error(`${TAG10} disconnect account=${conn.accountId}: ${classification.kind} \u2014 ${classification.message}`);
|
|
24787
24974
|
if (!classification.shouldRetry) {
|
|
24788
|
-
console.error(`${
|
|
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(`${
|
|
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(`${
|
|
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(`${
|
|
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(`${
|
|
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(`${
|
|
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(`${
|
|
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(`${
|
|
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
|
-
`${
|
|
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
|
-
`${
|
|
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(`${
|
|
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(`${
|
|
25148
|
+
console.error(`${TAG10} drop: status broadcast account=${conn.accountId}`);
|
|
24926
25149
|
return;
|
|
24927
25150
|
}
|
|
24928
25151
|
if (!msg.message) {
|
|
24929
|
-
console.error(`${
|
|
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(`${
|
|
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(`${
|
|
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(`${
|
|
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(`${
|
|
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(`${
|
|
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(`${
|
|
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
|
-
`${
|
|
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
|
|
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(`${
|
|
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(`${
|
|
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(`${
|
|
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
|
-
`${
|
|
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(`${
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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/
|
|
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) =>
|
|
26759
|
-
app.get("/api/admin/claude-info", () =>
|
|
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) =>
|
|
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", () =>
|
|
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", () =>
|
|
27033
|
+
app.get("/api/admin/agents", () => GET8());
|
|
26769
27034
|
app.post("/api/admin/browser/launch", () => POST23());
|
|
26770
|
-
app.get("/api/admin/sessions", (c) =>
|
|
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) =>
|
|
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;
|