@0xmaxma/claude-gateway 1.8.10 → 1.8.12
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/README.md +14 -1
- package/config.template.json +2 -1
- package/dist/agent/runner.d.ts +72 -0
- package/dist/agent/runner.d.ts.map +1 -1
- package/dist/agent/runner.js +300 -6
- package/dist/agent/runner.js.map +1 -1
- package/dist/api/router.d.ts.map +1 -1
- package/dist/api/router.js +1001 -4
- package/dist/api/router.js.map +1 -1
- package/dist/api/webhooks-router.d.ts +2 -0
- package/dist/api/webhooks-router.d.ts.map +1 -1
- package/dist/api/webhooks-router.js +2 -0
- package/dist/api/webhooks-router.js.map +1 -1
- package/dist/api/whatsapp-access.d.ts +123 -0
- package/dist/api/whatsapp-access.d.ts.map +1 -0
- package/dist/api/whatsapp-access.js +135 -0
- package/dist/api/whatsapp-access.js.map +1 -0
- package/dist/api/whatsapp-cloud-access.d.ts +48 -0
- package/dist/api/whatsapp-cloud-access.d.ts.map +1 -0
- package/dist/api/whatsapp-cloud-access.js +58 -0
- package/dist/api/whatsapp-cloud-access.js.map +1 -0
- package/dist/api/whatsapp-cloud-client.d.ts +143 -0
- package/dist/api/whatsapp-cloud-client.d.ts.map +1 -0
- package/dist/api/whatsapp-cloud-client.js +298 -0
- package/dist/api/whatsapp-cloud-client.js.map +1 -0
- package/dist/api/whatsapp-cloud-webhook-router.d.ts +132 -0
- package/dist/api/whatsapp-cloud-webhook-router.d.ts.map +1 -0
- package/dist/api/whatsapp-cloud-webhook-router.js +494 -0
- package/dist/api/whatsapp-cloud-webhook-router.js.map +1 -0
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +7 -0
- package/dist/config/loader.js.map +1 -1
- package/dist/config/whatsapp-accounts.d.ts +77 -0
- package/dist/config/whatsapp-accounts.d.ts.map +1 -0
- package/dist/config/whatsapp-accounts.js +218 -0
- package/dist/config/whatsapp-accounts.js.map +1 -0
- package/dist/history/db.d.ts.map +1 -1
- package/dist/history/db.js +43 -11
- package/dist/history/db.js.map +1 -1
- package/dist/history/types.d.ts +18 -1
- package/dist/history/types.d.ts.map +1 -1
- package/dist/history/types.js +1 -1
- package/dist/history/types.js.map +1 -1
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -1
- package/dist/session/process.d.ts.map +1 -1
- package/dist/session/process.js +37 -0
- package/dist/session/process.js.map +1 -1
- package/dist/shared/image-optimize.d.ts +32 -0
- package/dist/shared/image-optimize.d.ts.map +1 -0
- package/dist/shared/image-optimize.js +197 -0
- package/dist/shared/image-optimize.js.map +1 -0
- package/dist/shared/image-sniff.d.ts +9 -0
- package/dist/shared/image-sniff.d.ts.map +1 -1
- package/dist/shared/image-sniff.js +13 -0
- package/dist/shared/image-sniff.js.map +1 -1
- package/dist/shared/text-chunk.d.ts +37 -0
- package/dist/shared/text-chunk.d.ts.map +1 -0
- package/dist/shared/text-chunk.js +105 -0
- package/dist/shared/text-chunk.js.map +1 -0
- package/dist/shared/whatsapp-ack.d.ts +13 -0
- package/dist/shared/whatsapp-ack.d.ts.map +1 -0
- package/dist/shared/whatsapp-ack.js +16 -0
- package/dist/shared/whatsapp-ack.js.map +1 -0
- package/dist/types.d.ts +158 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/whatsapp/manager.d.ts +173 -0
- package/dist/whatsapp/manager.d.ts.map +1 -0
- package/dist/whatsapp/manager.js +838 -0
- package/dist/whatsapp/manager.js.map +1 -0
- package/mcp/server.ts +4 -0
- package/mcp/tools/whatsapp/module.ts +162 -0
- package/mcp/tools/whatsapp-cloud/module.ts +536 -0
- package/package.json +9 -4
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ A self-hosted multi-agent gateway for Claude Code — with agents that improve t
|
|
|
15
15
|
- 📚 **Knowledge base (two-lane memory)** — per-agent SQLite/FTS5 searchable archive exposed through `memory_search` / `memory_get` MCP tools, so agents recall notes that don't fit the always-injected core; chunks carry fail-closed provenance and the index is refreshed off the gateway event loop. See [`gateway.knowledge`](#gatewayknowledge)
|
|
16
16
|
- 🌙 **Nightly dreaming** — background consolidation of long-term memory: a print-only reviewer proposes ops that a safe applier writes to `MEMORY.md` / `USER.md` (backup, bounded-loss, net-negative when over budget). Deterministic compaction, budget-scaled pruning, and staleness GC keep memory near budget without forgetting — archived entries stay searchable. See [`gateway.dreaming`](#gatewaydreaming)
|
|
17
17
|
- 🤖 **Multi-agent** — run multiple bots from a single gateway, each with isolated sessions
|
|
18
|
-
- 🔌 **Multi-channel MCP** — modular tool system per channel (Telegram, Discord, LINE, Slack, Cron, Skills, extensible to more)
|
|
18
|
+
- 🔌 **Multi-channel MCP** — modular tool system per channel (Telegram, Discord, LINE, Slack, WhatsApp, Cron, Skills, extensible to more)
|
|
19
19
|
- 🧩 **Agent skills** — extensible skill system via SKILL.md files; agents can create, delete, and install skills from URLs at runtime with hot-reload
|
|
20
20
|
- 🎭 **Agent identity** — define personality, tone, and rules via workspace markdown files
|
|
21
21
|
- 📡 **Live status messages** — real-time status updates showing tool usage, thinking, and progress
|
|
@@ -772,6 +772,8 @@ Tokens are stored per-agent at `~/.claude-gateway/agents/<id>/.env` and auto-loa
|
|
|
772
772
|
|
|
773
773
|
A variable you exported yourself always wins over the `.env` file and is never replaced by a reload. A token the gateway did read from a `.env` is refreshed when that file changes, so **rotating a token takes effect on the next config reload** rather than at the next restart. Note that only `config.json` is watched — editing a `.env` by hand applies on the following reload, while the MCP `agent_create` / `agent_update` tools write both files and so take effect immediately. If a `${VAR}` cannot be resolved from anywhere, that one agent is skipped — the rest of the gateway starts normally — and the skip is logged to `logs/gateway.log` with the name of the missing variable.
|
|
774
774
|
|
|
775
|
+
WhatsApp Cloud's credentials (`accessToken`, `phoneNumberId`, `appSecret`, `verifyToken`) are plain fields under the agent's `whatsapp_cloud` config block, not a dedicated "bot token" field — but they resolve through the exact same mechanism as Telegram/Discord bot tokens: reference them as `${VAR}` in `config.json` and put the value in the agent's `.env` (or export it as a shell variable), same as above.
|
|
776
|
+
|
|
775
777
|
---
|
|
776
778
|
|
|
777
779
|
## Architecture
|
|
@@ -1383,6 +1385,9 @@ sees a message. If those aren't met the bot looks online but stays silent.
|
|
|
1383
1385
|
| | Guild | **Message Content Intent** + **View Channel** + **Read Message History** | `groupPolicy` + `guildAllowlist` (+ optional `channelAllowlist`/`roleAllowlist`) | `requireMention` false, or @mentioned/replied |
|
|
1384
1386
|
| **LINE** | 1:1 | webhook delivered (valid signature) | `dmPolicy` | — |
|
|
1385
1387
|
| | Group/Room | webhook delivered + bot is a member | `groupPolicy` + `groupAllowlist` | `requireMention` false, or **native** @mention |
|
|
1388
|
+
| **WhatsApp (Baileys)** | DM | number is linked (QR/pairing-code device link) | `dmPolicy` + `pairing` → `dmAllowlist` (per account) | — |
|
|
1389
|
+
| | Group | number is linked and is a member of the group | `groupPolicy` + `groupAllowlist` (per account) | `requireMention` false, or @mentioned |
|
|
1390
|
+
| **WhatsApp (Cloud API)** | DM | webhook delivered (valid `X-Hub-Signature-256`) | `dmPolicy` + `pairing` → `dmAllowlist` | — (DM-only, no group concept) |
|
|
1386
1391
|
|
|
1387
1392
|
**Telegram limits**
|
|
1388
1393
|
- Exactly one process may poll a bot token — a second poller causes `409 Conflict`.
|
|
@@ -1402,6 +1407,14 @@ sees a message. If those aren't met the bot looks online but stays silent.
|
|
|
1402
1407
|
- Delivery is **reply-token-first (free) → push fallback (metered)**. The single-use reply token lives only ~1 min; after that, replies consume the OA's monthly push quota.
|
|
1403
1408
|
- Max **5 message objects** per reply/push request (the gateway auto-chunks to fit).
|
|
1404
1409
|
|
|
1410
|
+
**WhatsApp limits**
|
|
1411
|
+
- Two independent modes, configured separately: the **Baileys** device-link bridge (`whatsapp` config block) and the **Cloud API** (`whatsapp_cloud` config block).
|
|
1412
|
+
- **Baileys** requires linking a device per number — QR code or a text pairing code, the same one-time handshake as WhatsApp Web. Multi-account: an agent can hold several linked numbers at once (`whatsapp.accounts[]`), each with its own DM/group policy and allowlist.
|
|
1413
|
+
- **Cloud API is DM-only** — a WhatsApp Business number has no group concept, so there's no `groupPolicy`/`groupAllowlist`/`requireMention` for it.
|
|
1414
|
+
- **Cloud API's inbound webhook requires a valid `X-Hub-Signature-256`** (HMAC-SHA256 of the raw body against `appSecret`); a bad or missing signature is rejected with `401` before the payload is parsed.
|
|
1415
|
+
- **Cloud API's 24-hour customer-service window**: free-form text replies only work within 24h of the user's last inbound message; outside that window only a pre-approved message template can reach them, and template sending is off by default (`templatesEnabled: false`) since it's the one send that can reach a user outside that window.
|
|
1416
|
+
- Inbound media cap is **20 MB** on both modes (same `MediaStore` cap LINE's file uploads use).
|
|
1417
|
+
|
|
1405
1418
|
---
|
|
1406
1419
|
|
|
1407
1420
|
## Telegram Groups
|
package/config.template.json
CHANGED
package/dist/agent/runner.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { EventEmitter } from 'events';
|
|
2
2
|
import { AgentConfig, CustomConnectorEntry, GatewayConfig, Logger, ModelConfig, ApiAttachment, ImageParams, VideoParams } from '../types';
|
|
3
3
|
import { SessionProcess } from '../session/process';
|
|
4
|
+
import { type WhatsAppStatus } from '../whatsapp/manager';
|
|
4
5
|
import { type SkillRegistry } from '../skills';
|
|
5
6
|
import { type ApiStreamCallbacks, type TurnSink } from './turn-stream';
|
|
6
7
|
import { type CliChannel } from '../cli-viewer/pairing-store';
|
|
@@ -9,6 +10,14 @@ import type { ChatChannel } from '../history/types';
|
|
|
9
10
|
import type { SkillLearningManager } from './skill-learning';
|
|
10
11
|
export declare const MAX_IMAGE_SIZE_BYTES: number;
|
|
11
12
|
export declare const DEFAULT_MODELS: ModelConfig[];
|
|
13
|
+
/**
|
|
14
|
+
* One-line reminder injected into every `whatsapp_cloud` turn's <channel>
|
|
15
|
+
* block (see buildChannelXml) — the 24h customer-service window is a
|
|
16
|
+
* WhatsApp-Business-only rule the agent cannot infer from the turn itself.
|
|
17
|
+
*
|
|
18
|
+
* Must stay free of `--` so it remains a well-formed XML comment.
|
|
19
|
+
*/
|
|
20
|
+
export declare const WHATSAPP_CLOUD_WINDOW_NOTE: string;
|
|
12
21
|
export declare const CHANNEL_COALESCE_WINDOW_MS = 1200;
|
|
13
22
|
/**
|
|
14
23
|
* Convert absolute file paths (e.g. from a reply tool's `files` input) into
|
|
@@ -42,6 +51,10 @@ export declare class AgentRunner extends EventEmitter {
|
|
|
42
51
|
private discordReceiver;
|
|
43
52
|
private lineReply;
|
|
44
53
|
private slackOutbound;
|
|
54
|
+
private whatsAppCloudOutbound;
|
|
55
|
+
private readonly whatsappAccounts;
|
|
56
|
+
private whatsappConfigSnapshot;
|
|
57
|
+
private readonly whatsappAccountForChat;
|
|
45
58
|
private readonly sessionStore;
|
|
46
59
|
private readonly idleTimeoutMs;
|
|
47
60
|
private readonly maxConcurrent;
|
|
@@ -475,8 +488,67 @@ export declare class AgentRunner extends EventEmitter {
|
|
|
475
488
|
*/
|
|
476
489
|
private sweepStaleSessionDirs;
|
|
477
490
|
updateAgentConfig(newConfig: AgentConfig): void;
|
|
491
|
+
/**
|
|
492
|
+
* Reconcile `this.whatsappAccounts` with `agentConfig.whatsapp.accounts`.
|
|
493
|
+
*
|
|
494
|
+
* Diffing (rather than teardown+recreate) is load-bearing here: a manager
|
|
495
|
+
* holds a live, authenticated Baileys socket that can take tens of seconds
|
|
496
|
+
* to re-establish, so an edit to account "sales" must not drop account
|
|
497
|
+
* "default"'s connection. Accounts that survive the diff only get the new
|
|
498
|
+
* AgentConfig pushed into them — their socket is untouched.
|
|
499
|
+
*
|
|
500
|
+
* Removal uses stop() (socket teardown), never unlink(): dropping an
|
|
501
|
+
* account from config must not silently wipe its on-disk session. The
|
|
502
|
+
* DELETE .../whatsapp/accounts/:id route unlinks explicitly before it
|
|
503
|
+
* rewrites config.
|
|
504
|
+
*/
|
|
505
|
+
private syncWhatsAppAccounts;
|
|
506
|
+
/** Live managers, in configured order. */
|
|
507
|
+
private whatsAppManagers;
|
|
508
|
+
/**
|
|
509
|
+
* Pick the manager a call should use.
|
|
510
|
+
*
|
|
511
|
+
* An EXPLICIT accountId must exist — silently falling back would send a
|
|
512
|
+
* reply from the wrong number, which on WhatsApp is visible to the
|
|
513
|
+
* recipient and unrecoverable. Without one, prefer the account the chat's
|
|
514
|
+
* last inbound message arrived on (so a reply leaves on the number the user
|
|
515
|
+
* actually wrote to), then 'default', then — for an agent whose only
|
|
516
|
+
* account is named something else — its single account.
|
|
517
|
+
*/
|
|
518
|
+
private whatsAppManagerFor;
|
|
519
|
+
/**
|
|
520
|
+
* Which account id a send to `chatId` (with an optional explicit
|
|
521
|
+
* `accountId`) would actually use — the same resolution
|
|
522
|
+
* `sendWhatsAppMessage` applies internally, exposed read-only so a caller
|
|
523
|
+
* (the `/whatsapp/send` route) can run access-control/path-confinement
|
|
524
|
+
* checks against the REAL target account without duplicating or
|
|
525
|
+
* second-guessing this resolution logic. Throws the same errors
|
|
526
|
+
* `whatsAppManagerFor` would (unknown account / agent not started).
|
|
527
|
+
*/
|
|
528
|
+
resolveWhatsAppAccountId(chatId: string | undefined, accountId?: string): string;
|
|
529
|
+
/** Live link status for one account (defaults to 'default'). */
|
|
530
|
+
getWhatsAppStatus(accountId?: string): WhatsAppStatus | undefined;
|
|
531
|
+
/** Configured account ids that currently have a live manager. */
|
|
532
|
+
getWhatsAppAccountIds(): string[];
|
|
533
|
+
startWhatsAppLinking(accountId?: string): Promise<void>;
|
|
534
|
+
requestWhatsAppPairingCode(phoneNumber: string, accountId?: string): Promise<string>;
|
|
535
|
+
unlinkWhatsApp(accountId?: string): Promise<void>;
|
|
536
|
+
sendWhatsAppMessage(jid: string, text: string, imagePath?: string, accountId?: string,
|
|
537
|
+
/**
|
|
538
|
+
* Phase 2 extras, all optional so existing callers (auto-forward, older
|
|
539
|
+
* MCP builds) are unaffected: quote an inbound message, send the image
|
|
540
|
+
* uncompressed as a document, and clear the ⏳ ack left on the inbound
|
|
541
|
+
* message once the send lands.
|
|
542
|
+
*/
|
|
543
|
+
opts?: {
|
|
544
|
+
quotedMessageId?: string;
|
|
545
|
+
asDocument?: boolean;
|
|
546
|
+
ackMessageId?: string;
|
|
547
|
+
}): Promise<void>;
|
|
478
548
|
startSlackOutbound(): void;
|
|
479
549
|
stopSlackOutbound(): void;
|
|
550
|
+
startWhatsAppCloudOutbound(): void;
|
|
551
|
+
stopWhatsAppCloudOutbound(): void;
|
|
480
552
|
startLineReply(): void;
|
|
481
553
|
stopLineReply(): void;
|
|
482
554
|
getAgentConfig(): AgentConfig;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/agent/runner.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/agent/runner.ts"],"names":[],"mappings":"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"}
|
package/dist/agent/runner.js
CHANGED
|
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.AgentRunner = exports.CHANNEL_COALESCE_WINDOW_MS = exports.DEFAULT_MODELS = exports.MAX_IMAGE_SIZE_BYTES = void 0;
|
|
36
|
+
exports.AgentRunner = exports.CHANNEL_COALESCE_WINDOW_MS = exports.WHATSAPP_CLOUD_WINDOW_NOTE = exports.DEFAULT_MODELS = exports.MAX_IMAGE_SIZE_BYTES = void 0;
|
|
37
37
|
exports.toRelMediaFiles = toRelMediaFiles;
|
|
38
38
|
const crypto_1 = require("crypto");
|
|
39
39
|
const events_1 = require("events");
|
|
@@ -51,6 +51,9 @@ const receiver_1 = require("../telegram/receiver");
|
|
|
51
51
|
const receiver_2 = require("../discord/receiver");
|
|
52
52
|
const line_reply_manager_1 = require("./line-reply-manager");
|
|
53
53
|
const slack_client_1 = require("../api/slack-client");
|
|
54
|
+
const whatsapp_cloud_client_1 = require("../api/whatsapp-cloud-client");
|
|
55
|
+
const manager_1 = require("../whatsapp/manager");
|
|
56
|
+
const whatsapp_accounts_1 = require("../config/whatsapp-accounts");
|
|
54
57
|
const markdown_1 = require("../telegram/markdown");
|
|
55
58
|
const skills_1 = require("../skills");
|
|
56
59
|
const builtin_commands_1 = require("./builtin-commands");
|
|
@@ -125,6 +128,15 @@ const PROTECTED_WORKSPACE_FILES = [
|
|
|
125
128
|
'AGENTS.md', 'SOUL.md', 'MEMORY.md', 'CLAUDE.md',
|
|
126
129
|
'IDENTITY.md', 'USER.md', 'HEARTBEAT.md',
|
|
127
130
|
];
|
|
131
|
+
/**
|
|
132
|
+
* One-line reminder injected into every `whatsapp_cloud` turn's <channel>
|
|
133
|
+
* block (see buildChannelXml) — the 24h customer-service window is a
|
|
134
|
+
* WhatsApp-Business-only rule the agent cannot infer from the turn itself.
|
|
135
|
+
*
|
|
136
|
+
* Must stay free of `--` so it remains a well-formed XML comment.
|
|
137
|
+
*/
|
|
138
|
+
exports.WHATSAPP_CLOUD_WINDOW_NOTE = '[WhatsApp Business: free-form replies only work within 24h of the user\'s last message. ' +
|
|
139
|
+
'Outside that window, whatsapp_cloud_reply requires template_name + template_language (see templatesEnabled).]';
|
|
128
140
|
const MAX_API_IMAGES = 5;
|
|
129
141
|
/** Extra time an api turn may keep running AFTER its soft timeout already
|
|
130
142
|
* answered the caller (#75). The soft timeout only abandons the WAIT — the
|
|
@@ -236,6 +248,29 @@ class AgentRunner extends events_1.EventEmitter {
|
|
|
236
248
|
// it exists only so writeAutoForward's fallback/command-reply path (below) has
|
|
237
249
|
// somewhere to actually deliver Slack messages instead of silently dropping them.
|
|
238
250
|
this.slackOutbound = null;
|
|
251
|
+
// WhatsApp Cloud mirrors Slack exactly: webhook-based, real credentials, no
|
|
252
|
+
// reply-token TTL to work around — a plain client so writeAutoForward's
|
|
253
|
+
// fallback/command-reply path has somewhere to deliver messages instead of
|
|
254
|
+
// silently dropping them (see the Slack comment just above).
|
|
255
|
+
this.whatsAppCloudOutbound = null;
|
|
256
|
+
// One live Baileys socket per linked WhatsApp account, keyed by account id
|
|
257
|
+
// (Phase 1 of the WhatsApp feature-parity plan — this used to be a single
|
|
258
|
+
// `whatsapp: WhatsAppManager | null`). Populated in start() (needs
|
|
259
|
+
// this.callbackPort, only resolved once startCallbackServer() runs — same
|
|
260
|
+
// reason DiscordReceiver/TelegramReceiver are built there too) and then
|
|
261
|
+
// DIFFED, never rebuilt wholesale, by syncWhatsAppAccounts(): unlike
|
|
262
|
+
// SlackClient/DiscordReceiver there is no credential to re-read on a config
|
|
263
|
+
// change, since the credential IS the on-disk session (see
|
|
264
|
+
// WhatsAppAccountConfig's doc comment), so tearing a linked socket down on
|
|
265
|
+
// an unrelated config edit would be pure downtime. Each manager decides for
|
|
266
|
+
// itself whether there's anything to do on start (resumeIfLinked() no-ops
|
|
267
|
+
// if that account was never linked).
|
|
268
|
+
this.whatsappAccounts = new Map();
|
|
269
|
+
// chatId → the account id its last inbound message arrived on. Mirrors
|
|
270
|
+
// slackThreadTs above: it lets writeAutoForward (and a whatsapp_reply call
|
|
271
|
+
// that omits account_id) answer on the SAME number the user wrote to
|
|
272
|
+
// instead of guessing 'default' and replying from the wrong line.
|
|
273
|
+
this.whatsappAccountForChat = new Map();
|
|
239
274
|
this.idleCleanerTimer = null;
|
|
240
275
|
// Tracks session IDs with an in-flight API request (prevents concurrent turns)
|
|
241
276
|
this.pendingApiSessions = new Set();
|
|
@@ -439,7 +474,11 @@ class AgentRunner extends events_1.EventEmitter {
|
|
|
439
474
|
? 'line'
|
|
440
475
|
: meta['source'] === 'slack'
|
|
441
476
|
? 'slack'
|
|
442
|
-
: '
|
|
477
|
+
: meta['source'] === 'whatsapp'
|
|
478
|
+
? 'whatsapp'
|
|
479
|
+
: meta['source'] === 'whatsapp_cloud'
|
|
480
|
+
? 'whatsapp_cloud'
|
|
481
|
+
: 'telegram');
|
|
443
482
|
this.channelSourceMap.set(chatId, channelSource);
|
|
444
483
|
// Slack: remember the current message's thread context so the
|
|
445
484
|
// auto-forward fallback (writeAutoForward) can stay in-thread. A
|
|
@@ -452,6 +491,14 @@ class AgentRunner extends events_1.EventEmitter {
|
|
|
452
491
|
else
|
|
453
492
|
this.slackThreadTs.delete(chatId);
|
|
454
493
|
}
|
|
494
|
+
// WhatsApp: remember which linked number this chat last came in on,
|
|
495
|
+
// so a reply that doesn't name an account_id (the auto-forward
|
|
496
|
+
// fallback, or a whatsapp_reply call that omitted it) still goes out
|
|
497
|
+
// on the number the user actually wrote to. Same shape as the Slack
|
|
498
|
+
// thread-context stash just above.
|
|
499
|
+
if (channelSource === 'whatsapp' && meta['account_id']) {
|
|
500
|
+
this.whatsappAccountForChat.set(chatId, meta['account_id']);
|
|
501
|
+
}
|
|
455
502
|
// LINE slow-LLM postback: stash this turn's reply token + arm the
|
|
456
503
|
// button timer before the token expires. In groups/rooms the shared
|
|
457
504
|
// button is disabled (armButton:false) — the token is still stashed so
|
|
@@ -1027,7 +1074,7 @@ class AgentRunner extends events_1.EventEmitter {
|
|
|
1027
1074
|
for (const entry of entries) {
|
|
1028
1075
|
const meta = entry.meta ?? {};
|
|
1029
1076
|
const content = entry.content ?? '';
|
|
1030
|
-
const userContent = content || (meta['attachment_file_id'] || meta['image_path'] ? '(photo)' : '');
|
|
1077
|
+
const userContent = content || (meta['attachment_file_id'] || meta['image_path'] ? '(photo)' : meta['document_path'] ? '(document)' : meta['sticker_path'] ? '(sticker)' : '');
|
|
1031
1078
|
const userTs = Date.now();
|
|
1032
1079
|
await this.sessionStore.appendTelegramMessage(this.agentConfig.id, chatId, sessionId, {
|
|
1033
1080
|
role: 'user',
|
|
@@ -1058,6 +1105,33 @@ class AgentRunner extends events_1.EventEmitter {
|
|
|
1058
1105
|
// Non-fatal — leave the original path so host agents still read it
|
|
1059
1106
|
}
|
|
1060
1107
|
}
|
|
1108
|
+
// WhatsApp Cloud documents (PDF today — see MediaStore.isAllowedMime):
|
|
1109
|
+
// same MediaStore copy + path-rewrite as image_path above, parallel
|
|
1110
|
+
// key so an inbound document doesn't collide with an inbound image
|
|
1111
|
+
// in the same turn.
|
|
1112
|
+
if (meta['document_path']) {
|
|
1113
|
+
try {
|
|
1114
|
+
const rel = media_store_1.MediaStore.copyToMedia(this.agentsBaseDir, this.agentConfig.id, `${channelSource}-${chatId}`, meta['document_path']);
|
|
1115
|
+
mediaFiles.push(rel);
|
|
1116
|
+
meta['document_path'] = media_store_1.MediaStore.resolvePath(this.agentsBaseDir, this.agentConfig.id, rel);
|
|
1117
|
+
}
|
|
1118
|
+
catch {
|
|
1119
|
+
// Non-fatal — leave the original path so host agents still read it
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
// WhatsApp stickers (both channels — image/webp): same MediaStore
|
|
1123
|
+
// copy + path-rewrite as image_path above, on its own key so an
|
|
1124
|
+
// inbound sticker never masquerades as a photo.
|
|
1125
|
+
if (meta['sticker_path']) {
|
|
1126
|
+
try {
|
|
1127
|
+
const rel = media_store_1.MediaStore.copyToMedia(this.agentsBaseDir, this.agentConfig.id, `${channelSource}-${chatId}`, meta['sticker_path']);
|
|
1128
|
+
mediaFiles.push(rel);
|
|
1129
|
+
meta['sticker_path'] = media_store_1.MediaStore.resolvePath(this.agentsBaseDir, this.agentConfig.id, rel);
|
|
1130
|
+
}
|
|
1131
|
+
catch {
|
|
1132
|
+
// Non-fatal — leave the original path so host agents still read it
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1061
1135
|
this.historyDb.insertMessage({
|
|
1062
1136
|
chatId: `${channelSource}-${chatId}`,
|
|
1063
1137
|
sessionId,
|
|
@@ -1068,6 +1142,14 @@ class AgentRunner extends events_1.EventEmitter {
|
|
|
1068
1142
|
senderId: meta['user_id'] ?? meta['chat_id'] ?? undefined,
|
|
1069
1143
|
platformMessageId: meta['message_id'] ?? undefined,
|
|
1070
1144
|
mediaFiles: mediaFiles.length > 0 ? mediaFiles : undefined,
|
|
1145
|
+
// Reply context (WhatsApp Phase 2) — the same meta keys buildChannelXml
|
|
1146
|
+
// renders into <replied> for the agent, persisted so the web dashboard
|
|
1147
|
+
// can show "in reply to X" instead of losing it after the turn.
|
|
1148
|
+
// whatsapp_cloud only ever sets replied_message_id (its webhook reports
|
|
1149
|
+
// the quoted id and nothing else), so the other two stay undefined there.
|
|
1150
|
+
repliedToMessageId: meta['replied_message_id'] ?? undefined,
|
|
1151
|
+
repliedToText: meta['replied_text'] ?? undefined,
|
|
1152
|
+
repliedToUser: meta['replied_user'] ?? undefined,
|
|
1071
1153
|
ts: userTs,
|
|
1072
1154
|
});
|
|
1073
1155
|
}
|
|
@@ -1330,6 +1412,11 @@ class AgentRunner extends events_1.EventEmitter {
|
|
|
1330
1412
|
const meta = params.meta ?? {};
|
|
1331
1413
|
const optionalAttrs = [
|
|
1332
1414
|
'image_path',
|
|
1415
|
+
'document_path', // WhatsApp Cloud: inbound PDF document (see MediaStore.isAllowedMime)
|
|
1416
|
+
'sticker_path', // WhatsApp (both channels): inbound sticker — kept distinct from image_path so the agent can tell a sticker from a photo
|
|
1417
|
+
'location_lat', // WhatsApp (both channels): inbound location pin
|
|
1418
|
+
'location_lng',
|
|
1419
|
+
'vcard', // WhatsApp: inbound contact card — raw vCard on Baileys, synthesized from Meta's structured payload on Cloud
|
|
1333
1420
|
'attachment_file_id',
|
|
1334
1421
|
'attachment_kind',
|
|
1335
1422
|
'attachment_mime',
|
|
@@ -1337,6 +1424,8 @@ class AgentRunner extends events_1.EventEmitter {
|
|
|
1337
1424
|
'user_id', // LINE: the userId the session passes back to line_reply
|
|
1338
1425
|
'reply_token', // LINE: single-use reply token (push is preferred; surfaced for completeness)
|
|
1339
1426
|
'thread_ts', // Slack: set when the inbound message is inside a thread — pass back as thread_id to slack_reply to reply in-thread
|
|
1427
|
+
'account_id', // WhatsApp: which linked number this arrived on — pass back to whatsapp_reply to answer on the same one
|
|
1428
|
+
'interactive_id', // WhatsApp Cloud: the id of the tapped button / picked list row (content already carries its title)
|
|
1340
1429
|
// NOTE: message_id is NOT listed here — the base <channel> template below
|
|
1341
1430
|
// already unconditionally emits it; adding it here would duplicate the
|
|
1342
1431
|
// attribute in the XML whenever meta.message_id is set (any channel).
|
|
@@ -1364,9 +1453,18 @@ class AgentRunner extends events_1.EventEmitter {
|
|
|
1364
1453
|
`</replied>`;
|
|
1365
1454
|
}
|
|
1366
1455
|
const source = meta['source'] ?? 'telegram';
|
|
1456
|
+
// Per-turn channel note (Phase 3). WhatsApp Business enforces a 24h
|
|
1457
|
+
// customer-service window that no other channel here has, and the agent
|
|
1458
|
+
// cannot discover it from the turn itself — it only shows up as an opaque
|
|
1459
|
+
// Meta error at send time. Emitted as an XML COMMENT so it can never be
|
|
1460
|
+
// mistaken for part of the user's message, and kept to ONE short line
|
|
1461
|
+
// because it repeats on every single whatsapp_cloud turn. (A frozen,
|
|
1462
|
+
// system-prompt-level injection would be new infra for one warning; the
|
|
1463
|
+
// per-turn wrapper is the existing seam.)
|
|
1464
|
+
const channelNote = source === 'whatsapp_cloud' ? `<!-- ${exports.WHATSAPP_CLOUD_WINDOW_NOTE} -->` : '';
|
|
1367
1465
|
return (`<channel source="${source}" chat_id="${meta['chat_id'] ?? ''}" ` +
|
|
1368
1466
|
`message_id="${meta['message_id'] ?? ''}" user="${AgentRunner.escapeXmlAttr(meta['user'] ?? '')}" ` +
|
|
1369
|
-
`ts="${meta['ts'] ?? new Date().toISOString()}"${optionalAttrs}>${repliedBlock}${params.content ?? ''}</channel>`);
|
|
1467
|
+
`ts="${meta['ts'] ?? new Date().toISOString()}"${optionalAttrs}>${channelNote}${repliedBlock}${params.content ?? ''}</channel>`);
|
|
1370
1468
|
}
|
|
1371
1469
|
/**
|
|
1372
1470
|
* Await a SessionProcess's in-flight crash-triggered auto-restart
|
|
@@ -1625,7 +1723,11 @@ class AgentRunner extends events_1.EventEmitter {
|
|
|
1625
1723
|
? 'mcp__gateway__line_reply'
|
|
1626
1724
|
: source === 'slack'
|
|
1627
1725
|
? 'mcp__gateway__slack_reply'
|
|
1628
|
-
: '
|
|
1726
|
+
: source === 'whatsapp'
|
|
1727
|
+
? 'mcp__gateway__whatsapp_reply'
|
|
1728
|
+
: source === 'whatsapp_cloud'
|
|
1729
|
+
? 'mcp__gateway__whatsapp_cloud_reply'
|
|
1730
|
+
: 'mcp__gateway__telegram_reply';
|
|
1629
1731
|
proc.on('output', (line) => {
|
|
1630
1732
|
try {
|
|
1631
1733
|
const obj = JSON.parse(line);
|
|
@@ -1938,10 +2040,15 @@ class AgentRunner extends events_1.EventEmitter {
|
|
|
1938
2040
|
}
|
|
1939
2041
|
else if (channelSrcForResult !== 'discord' &&
|
|
1940
2042
|
channelSrcForResult !== 'slack' &&
|
|
2043
|
+
channelSrcForResult !== 'whatsapp' &&
|
|
2044
|
+
channelSrcForResult !== 'whatsapp_cloud' &&
|
|
1941
2045
|
((0, markdown_1.hasMarkdown)(channelText) || (0, markdown_1.containsTelegramHtml)(channelText))) {
|
|
1942
2046
|
// Telegram HTML entities — Slack has its own mrkdwn format and
|
|
1943
2047
|
// would display these tags literally, so Slack skips this and
|
|
1944
|
-
// falls through to the plain-text branch below.
|
|
2048
|
+
// falls through to the plain-text branch below. WhatsApp (and
|
|
2049
|
+
// WhatsApp Cloud, same lightweight markup) has
|
|
2050
|
+
// its own lightweight markup (*bold*/_italic_/~strike~, not
|
|
2051
|
+
// HTML), same reasoning.
|
|
1945
2052
|
this.writeAutoForward(mapKey, (0, markdown_1.toTelegramHtml)(channelText), 'html', replySendFailed);
|
|
1946
2053
|
}
|
|
1947
2054
|
else {
|
|
@@ -2798,6 +2905,36 @@ class AgentRunner extends events_1.EventEmitter {
|
|
|
2798
2905
|
}
|
|
2799
2906
|
return;
|
|
2800
2907
|
}
|
|
2908
|
+
// WhatsApp likewise has no .forward consumer, and — unlike Slack/SMS's
|
|
2909
|
+
// outbound REST clients — cannot open a fresh connection per call either
|
|
2910
|
+
// (see WhatsAppManager's doc comment): reach the live socket this
|
|
2911
|
+
// process already holds directly.
|
|
2912
|
+
if (this.channelFor(chatId) === 'whatsapp') {
|
|
2913
|
+
// No account_id to go on here (this is the fallback path, not a tool
|
|
2914
|
+
// call), so whatsAppManagerFor falls back to the account this chat's
|
|
2915
|
+
// last inbound message arrived on — the number the user wrote to.
|
|
2916
|
+
void this.sendWhatsAppMessage(chatId, text).catch((err) => {
|
|
2917
|
+
this.logger.warn('WhatsApp auto-forward failed', {
|
|
2918
|
+
chatId,
|
|
2919
|
+
error: err instanceof Error ? err.message : String(err),
|
|
2920
|
+
});
|
|
2921
|
+
});
|
|
2922
|
+
return;
|
|
2923
|
+
}
|
|
2924
|
+
// WhatsApp Cloud mirrors Slack exactly (no .forward consumer, a real REST
|
|
2925
|
+
// client that can open a fresh connection per call — unlike Baileys'
|
|
2926
|
+
// `whatsapp` above, there's no live socket to reuse or reason to).
|
|
2927
|
+
if (this.channelFor(chatId) === 'whatsapp_cloud') {
|
|
2928
|
+
if (this.whatsAppCloudOutbound) {
|
|
2929
|
+
void this.whatsAppCloudOutbound.sendText(chatId, text).catch((err) => {
|
|
2930
|
+
this.logger.warn('WhatsApp Cloud auto-forward failed', {
|
|
2931
|
+
chatId,
|
|
2932
|
+
error: err instanceof Error ? err.message : String(err),
|
|
2933
|
+
});
|
|
2934
|
+
});
|
|
2935
|
+
}
|
|
2936
|
+
return;
|
|
2937
|
+
}
|
|
2801
2938
|
const typingDir = this.getTypingDir(chatId);
|
|
2802
2939
|
const forwardPath = path.join(typingDir, `${chatId}.forward`);
|
|
2803
2940
|
try {
|
|
@@ -2897,6 +3034,15 @@ class AgentRunner extends events_1.EventEmitter {
|
|
|
2897
3034
|
// line_reply tool keeps the plain reply-first → push-fallback path).
|
|
2898
3035
|
this.startLineReply();
|
|
2899
3036
|
this.startSlackOutbound();
|
|
3037
|
+
this.startWhatsAppCloudOutbound();
|
|
3038
|
+
// Unconditional (unlike every credential-gated channel above) — each
|
|
3039
|
+
// WhatsAppManager checks disk for a previously-linked session itself;
|
|
3040
|
+
// there's no config field to gate on, and an agent with no `whatsapp`
|
|
3041
|
+
// block still gets the implicit 'default' account (see
|
|
3042
|
+
// resolveWhatsAppAccounts). A brand-new agent that's never linked just
|
|
3043
|
+
// no-ops here and stays 'unlinked' until the user starts a QR/pairing
|
|
3044
|
+
// flow via the API.
|
|
3045
|
+
this.syncWhatsAppAccounts();
|
|
2900
3046
|
this.startIdleCleaner();
|
|
2901
3047
|
this._startCleanupScheduler();
|
|
2902
3048
|
this.logger.info('AgentRunner started', { agentId: this.agentConfig.id });
|
|
@@ -2950,6 +3096,129 @@ class AgentRunner extends events_1.EventEmitter {
|
|
|
2950
3096
|
// it up, same reasoning as LineReplyManager above.
|
|
2951
3097
|
this.stopSlackOutbound();
|
|
2952
3098
|
this.startSlackOutbound();
|
|
3099
|
+
// WhatsApp Cloud credentials may have changed (or been cleared) — rebuild
|
|
3100
|
+
// to pick it up, same reasoning as Slack above.
|
|
3101
|
+
this.stopWhatsAppCloudOutbound();
|
|
3102
|
+
this.startWhatsAppCloudOutbound();
|
|
3103
|
+
// WhatsApp has no credential to rebuild on — push the new config
|
|
3104
|
+
// (access-control fields) into every already-running manager, and
|
|
3105
|
+
// add/remove managers only if the set of configured accounts changed.
|
|
3106
|
+
this.syncWhatsAppAccounts();
|
|
3107
|
+
}
|
|
3108
|
+
/**
|
|
3109
|
+
* Reconcile `this.whatsappAccounts` with `agentConfig.whatsapp.accounts`.
|
|
3110
|
+
*
|
|
3111
|
+
* Diffing (rather than teardown+recreate) is load-bearing here: a manager
|
|
3112
|
+
* holds a live, authenticated Baileys socket that can take tens of seconds
|
|
3113
|
+
* to re-establish, so an edit to account "sales" must not drop account
|
|
3114
|
+
* "default"'s connection. Accounts that survive the diff only get the new
|
|
3115
|
+
* AgentConfig pushed into them — their socket is untouched.
|
|
3116
|
+
*
|
|
3117
|
+
* Removal uses stop() (socket teardown), never unlink(): dropping an
|
|
3118
|
+
* account from config must not silently wipe its on-disk session. The
|
|
3119
|
+
* DELETE .../whatsapp/accounts/:id route unlinks explicitly before it
|
|
3120
|
+
* rewrites config.
|
|
3121
|
+
*/
|
|
3122
|
+
syncWhatsAppAccounts() {
|
|
3123
|
+
const snapshot = JSON.stringify(this.agentConfig.whatsapp ?? null);
|
|
3124
|
+
const accounts = (0, whatsapp_accounts_1.resolveWhatsAppAccounts)(this.agentConfig.whatsapp);
|
|
3125
|
+
// Always push the fresh config into live managers — access-control fields
|
|
3126
|
+
// are read live off it on every inbound message.
|
|
3127
|
+
for (const manager of this.whatsappAccounts.values()) {
|
|
3128
|
+
manager.updateAgentConfig(this.agentConfig);
|
|
3129
|
+
}
|
|
3130
|
+
// Nothing about the WhatsApp block moved ⇒ the account SET can't have
|
|
3131
|
+
// changed either, so skip the diff entirely.
|
|
3132
|
+
if (this.whatsappConfigSnapshot === snapshot && this.whatsappAccounts.size > 0)
|
|
3133
|
+
return;
|
|
3134
|
+
this.whatsappConfigSnapshot = snapshot;
|
|
3135
|
+
const wanted = new Set(accounts.map((a) => a.id));
|
|
3136
|
+
for (const [accountId, manager] of [...this.whatsappAccounts]) {
|
|
3137
|
+
if (wanted.has(accountId))
|
|
3138
|
+
continue;
|
|
3139
|
+
manager.stop();
|
|
3140
|
+
this.whatsappAccounts.delete(accountId);
|
|
3141
|
+
this.logger.info('WhatsApp account removed', { agentId: this.agentConfig.id, accountId });
|
|
3142
|
+
}
|
|
3143
|
+
for (const account of accounts) {
|
|
3144
|
+
if (this.whatsappAccounts.has(account.id))
|
|
3145
|
+
continue;
|
|
3146
|
+
const manager = new manager_1.WhatsAppManager(this.agentConfig, account.id, this.callbackPort, this.gatewayConfig.gateway.logDir);
|
|
3147
|
+
this.whatsappAccounts.set(account.id, manager);
|
|
3148
|
+
void manager.resumeIfLinked();
|
|
3149
|
+
this.logger.info('WhatsApp account started', { agentId: this.agentConfig.id, accountId: account.id });
|
|
3150
|
+
}
|
|
3151
|
+
}
|
|
3152
|
+
/** Live managers, in configured order. */
|
|
3153
|
+
whatsAppManagers() {
|
|
3154
|
+
return (0, whatsapp_accounts_1.resolveWhatsAppAccounts)(this.agentConfig.whatsapp)
|
|
3155
|
+
.map((a) => this.whatsappAccounts.get(a.id))
|
|
3156
|
+
.filter((m) => !!m);
|
|
3157
|
+
}
|
|
3158
|
+
/**
|
|
3159
|
+
* Pick the manager a call should use.
|
|
3160
|
+
*
|
|
3161
|
+
* An EXPLICIT accountId must exist — silently falling back would send a
|
|
3162
|
+
* reply from the wrong number, which on WhatsApp is visible to the
|
|
3163
|
+
* recipient and unrecoverable. Without one, prefer the account the chat's
|
|
3164
|
+
* last inbound message arrived on (so a reply leaves on the number the user
|
|
3165
|
+
* actually wrote to), then 'default', then — for an agent whose only
|
|
3166
|
+
* account is named something else — its single account.
|
|
3167
|
+
*/
|
|
3168
|
+
whatsAppManagerFor(chatId, accountId) {
|
|
3169
|
+
if (accountId) {
|
|
3170
|
+
const explicit = this.whatsappAccounts.get(accountId);
|
|
3171
|
+
if (!explicit)
|
|
3172
|
+
throw new Error(`Unknown WhatsApp account '${accountId}'`);
|
|
3173
|
+
return explicit;
|
|
3174
|
+
}
|
|
3175
|
+
const remembered = chatId ? this.whatsappAccountForChat.get(chatId) : undefined;
|
|
3176
|
+
const managers = this.whatsAppManagers();
|
|
3177
|
+
const picked = (remembered ? this.whatsappAccounts.get(remembered) : undefined) ??
|
|
3178
|
+
this.whatsappAccounts.get(whatsapp_accounts_1.DEFAULT_WHATSAPP_ACCOUNT_ID) ??
|
|
3179
|
+
managers[0];
|
|
3180
|
+
if (!picked)
|
|
3181
|
+
throw new Error('Agent not started');
|
|
3182
|
+
return picked;
|
|
3183
|
+
}
|
|
3184
|
+
/**
|
|
3185
|
+
* Which account id a send to `chatId` (with an optional explicit
|
|
3186
|
+
* `accountId`) would actually use — the same resolution
|
|
3187
|
+
* `sendWhatsAppMessage` applies internally, exposed read-only so a caller
|
|
3188
|
+
* (the `/whatsapp/send` route) can run access-control/path-confinement
|
|
3189
|
+
* checks against the REAL target account without duplicating or
|
|
3190
|
+
* second-guessing this resolution logic. Throws the same errors
|
|
3191
|
+
* `whatsAppManagerFor` would (unknown account / agent not started).
|
|
3192
|
+
*/
|
|
3193
|
+
resolveWhatsAppAccountId(chatId, accountId) {
|
|
3194
|
+
return this.whatsAppManagerFor(chatId, accountId).accountId;
|
|
3195
|
+
}
|
|
3196
|
+
/** Live link status for one account (defaults to 'default'). */
|
|
3197
|
+
getWhatsAppStatus(accountId = whatsapp_accounts_1.DEFAULT_WHATSAPP_ACCOUNT_ID) {
|
|
3198
|
+
return this.whatsappAccounts.get(accountId)?.getStatus();
|
|
3199
|
+
}
|
|
3200
|
+
/** Configured account ids that currently have a live manager. */
|
|
3201
|
+
getWhatsAppAccountIds() {
|
|
3202
|
+
return this.whatsAppManagers().map((m) => m.accountId);
|
|
3203
|
+
}
|
|
3204
|
+
async startWhatsAppLinking(accountId) {
|
|
3205
|
+
await this.whatsAppManagerFor(undefined, accountId).startLinking();
|
|
3206
|
+
}
|
|
3207
|
+
async requestWhatsAppPairingCode(phoneNumber, accountId) {
|
|
3208
|
+
return this.whatsAppManagerFor(undefined, accountId).requestPairingCode(phoneNumber);
|
|
3209
|
+
}
|
|
3210
|
+
async unlinkWhatsApp(accountId) {
|
|
3211
|
+
await this.whatsAppManagerFor(undefined, accountId).unlink();
|
|
3212
|
+
}
|
|
3213
|
+
async sendWhatsAppMessage(jid, text, imagePath, accountId,
|
|
3214
|
+
/**
|
|
3215
|
+
* Phase 2 extras, all optional so existing callers (auto-forward, older
|
|
3216
|
+
* MCP builds) are unaffected: quote an inbound message, send the image
|
|
3217
|
+
* uncompressed as a document, and clear the ⏳ ack left on the inbound
|
|
3218
|
+
* message once the send lands.
|
|
3219
|
+
*/
|
|
3220
|
+
opts) {
|
|
3221
|
+
await this.whatsAppManagerFor(jid, accountId).sendMessage(jid, text, imagePath, opts);
|
|
2953
3222
|
}
|
|
2954
3223
|
startSlackOutbound() {
|
|
2955
3224
|
if (!this.agentConfig.slack?.botToken || !this.agentConfig.slack?.signingSecret)
|
|
@@ -2964,6 +3233,21 @@ class AgentRunner extends events_1.EventEmitter {
|
|
|
2964
3233
|
stopSlackOutbound() {
|
|
2965
3234
|
this.slackOutbound = null;
|
|
2966
3235
|
}
|
|
3236
|
+
startWhatsAppCloudOutbound() {
|
|
3237
|
+
const cfg = this.agentConfig.whatsapp_cloud;
|
|
3238
|
+
if (!cfg?.accessToken || !cfg?.phoneNumberId || !cfg?.appSecret || !cfg?.verifyToken)
|
|
3239
|
+
return;
|
|
3240
|
+
if (this.whatsAppCloudOutbound)
|
|
3241
|
+
return; // already running
|
|
3242
|
+
this.whatsAppCloudOutbound = new whatsapp_cloud_client_1.WhatsAppCloudClient({
|
|
3243
|
+
accessToken: cfg.accessToken,
|
|
3244
|
+
phoneNumberId: cfg.phoneNumberId,
|
|
3245
|
+
logDir: this.gatewayConfig.gateway.logDir,
|
|
3246
|
+
});
|
|
3247
|
+
}
|
|
3248
|
+
stopWhatsAppCloudOutbound() {
|
|
3249
|
+
this.whatsAppCloudOutbound = null;
|
|
3250
|
+
}
|
|
2967
3251
|
startLineReply() {
|
|
2968
3252
|
const lineThreshold = this.agentConfig.line?.slowResponseThreshold ?? 45;
|
|
2969
3253
|
if (!this.agentConfig.line?.channelSecret || !this.agentConfig.line?.channelAccessToken || lineThreshold <= 0)
|
|
@@ -3060,6 +3344,16 @@ class AgentRunner extends events_1.EventEmitter {
|
|
|
3060
3344
|
// teardown rather than serially — both are bounded, neither depends on the
|
|
3061
3345
|
// other, and shutdown latency is user-visible.
|
|
3062
3346
|
const receiversStopped = [this.receiver?.stop(), this.discordReceiver?.stop()];
|
|
3347
|
+
// stop(), not unlink() — gateway shutdown should NOT wipe a linked
|
|
3348
|
+
// session; resumeIfLinked() picks each account back up on next boot.
|
|
3349
|
+
// Synchronous (no socket-close promise to await), unlike the receivers above.
|
|
3350
|
+
for (const manager of this.whatsappAccounts.values())
|
|
3351
|
+
manager.stop();
|
|
3352
|
+
this.whatsappAccounts.clear();
|
|
3353
|
+
this.whatsappAccountForChat.clear();
|
|
3354
|
+
// Force syncWhatsAppAccounts() to rebuild from scratch if this runner is
|
|
3355
|
+
// started again, rather than short-circuiting on a stale snapshot.
|
|
3356
|
+
this.whatsappConfigSnapshot = undefined;
|
|
3063
3357
|
this.stopLineReply();
|
|
3064
3358
|
await Promise.all([
|
|
3065
3359
|
...receiversStopped,
|