@elizaos/plugin-whatsapp 2.0.0-alpha.5 → 2.0.0-alpha.537
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 +278 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/index.js +2298 -0
- package/dist/index.js.map +26 -0
- package/dist/src/accounts.d.ts +217 -0
- package/dist/src/accounts.d.ts.map +1 -0
- package/dist/src/actions/index.d.ts +6 -0
- package/dist/src/actions/index.d.ts.map +1 -0
- package/dist/src/actions/sendMessage.d.ts +4 -0
- package/dist/src/actions/sendMessage.d.ts.map +1 -0
- package/dist/src/actions/sendReaction.d.ts +4 -0
- package/dist/src/actions/sendReaction.d.ts.map +1 -0
- package/dist/src/baileys/auth.d.ts +10 -0
- package/dist/src/baileys/auth.d.ts.map +1 -0
- package/dist/src/baileys/connection.d.ts +19 -0
- package/dist/src/baileys/connection.d.ts.map +1 -0
- package/dist/src/baileys/index.d.ts +5 -0
- package/dist/src/baileys/index.d.ts.map +1 -0
- package/dist/src/baileys/message-adapter.d.ts +14 -0
- package/dist/src/baileys/message-adapter.d.ts.map +1 -0
- package/dist/src/baileys/qr-code.d.ts +6 -0
- package/dist/src/baileys/qr-code.d.ts.map +1 -0
- package/dist/src/client.d.ts +139 -0
- package/dist/src/client.d.ts.map +1 -0
- package/dist/src/clients/baileys-client.d.ts +26 -0
- package/dist/src/clients/baileys-client.d.ts.map +1 -0
- package/dist/src/clients/factory.d.ts +6 -0
- package/dist/src/clients/factory.d.ts.map +1 -0
- package/dist/src/clients/index.d.ts +4 -0
- package/dist/src/clients/index.d.ts.map +1 -0
- package/dist/src/clients/interface.d.ts +10 -0
- package/dist/src/clients/interface.d.ts.map +1 -0
- package/dist/src/config.d.ts +144 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/handlers/index.d.ts +3 -0
- package/dist/src/handlers/index.d.ts.map +1 -0
- package/dist/src/handlers/message.handler.d.ts +8 -0
- package/dist/src/handlers/message.handler.d.ts.map +1 -0
- package/dist/src/handlers/webhook.handler.d.ts +7 -0
- package/dist/src/handlers/webhook.handler.d.ts.map +1 -0
- package/dist/src/index.d.ts +62 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/normalize.d.ts +72 -0
- package/dist/src/normalize.d.ts.map +1 -0
- package/dist/src/pairing-service.d.ts +54 -0
- package/dist/src/pairing-service.d.ts.map +1 -0
- package/dist/src/runtime-service.d.ts +50 -0
- package/dist/src/runtime-service.d.ts.map +1 -0
- package/dist/src/service.d.ts +157 -0
- package/dist/src/service.d.ts.map +1 -0
- package/dist/src/setup-routes.d.ts +26 -0
- package/dist/src/setup-routes.d.ts.map +1 -0
- package/dist/src/types.d.ts +396 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/utils/config-detector.d.ts +5 -0
- package/dist/src/utils/config-detector.d.ts.map +1 -0
- package/dist/src/utils/index.d.ts +3 -0
- package/dist/src/utils/index.d.ts.map +1 -0
- package/dist/src/utils/validators.d.ts +14 -0
- package/dist/src/utils/validators.d.ts.map +1 -0
- package/package.json +41 -17
- package/dist/index.d.ts +0 -2
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/actions/sendMessage.ts", "../src/actions/sendReaction.ts", "../src/runtime-service.ts", "../src/accounts.ts", "../src/client.ts", "../src/clients/baileys-client.ts", "../src/baileys/auth.ts", "../src/baileys/connection.ts", "../src/baileys/message-adapter.ts", "../src/baileys/qr-code.ts", "../src/normalize.ts", "../src/setup-routes.ts", "../src/pairing-service.ts", "../src/utils/config-detector.ts", "../src/clients/factory.ts", "../src/types.ts", "../src/index.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type {\n Action,\n ActionExample,\n ActionResult,\n HandlerCallback,\n HandlerOptions,\n IAgentRuntime,\n Memory,\n State,\n} from \"@elizaos/core\";\nimport { composePromptFromState, ModelType, parseJSONObjectFromText } from \"@elizaos/core\";\n\nexport const WHATSAPP_SEND_MESSAGE_ACTION = \"WHATSAPP_SEND_MESSAGE\";\n\nconst SEND_MESSAGE_TEMPLATE = `\nYou are extracting WhatsApp message parameters from a conversation.\n\nThe user wants to send a WhatsApp message. Extract the following:\n1. to: The phone number to send to (E.164 format, e.g., +14155552671)\n2. text: The message text to send\n\n{{recentMessages}}\n\nBased on the conversation, extract the message parameters.\n\nRespond with a JSON object:\n{\n \"to\": \"+14155552671\",\n \"text\": \"Hello from WhatsApp!\"\n}\n`;\n\ninterface SendMessageParams {\n to: string;\n text: string;\n}\n\nexport const sendMessageAction: Action = {\n name: WHATSAPP_SEND_MESSAGE_ACTION,\n similes: [\"SEND_WHATSAPP\", \"WHATSAPP_MESSAGE\", \"TEXT_WHATSAPP\", \"SEND_WHATSAPP_MESSAGE\"],\n description: \"Send a text message via WhatsApp\",\n descriptionCompressed: \"Send WhatsApp text message.\",\n suppressPostActionContinuation: true,\n\n validate: async (\n _runtime: IAgentRuntime,\n message: Memory,\n _state?: State,\n _options?: HandlerOptions\n ): Promise<boolean> => {\n const text = message.content?.text?.toLowerCase() ?? \"\";\n const hasIntent =\n [\"whatsapp\", \"send\", \"message\"].some((keyword) => text.includes(keyword)) &&\n /\\b(?:whatsapp|send|message)\\b/i.test(text);\n return hasIntent && message.content?.source === \"whatsapp\";\n },\n\n handler: async (\n runtime: IAgentRuntime,\n message: Memory,\n state: State | undefined,\n _options?: HandlerOptions,\n callback?: HandlerCallback\n ): Promise<ActionResult> => {\n // Get WhatsApp settings\n const accessToken = runtime.getSetting(\"WHATSAPP_ACCESS_TOKEN\") as string;\n const phoneNumberId = runtime.getSetting(\"WHATSAPP_PHONE_NUMBER_ID\") as string;\n const apiVersion = (runtime.getSetting(\"WHATSAPP_API_VERSION\") as string) || \"v24.0\";\n\n if (!accessToken || !phoneNumberId) {\n if (callback) {\n await callback({\n text: \"WhatsApp is not configured. Missing access token or phone number ID.\",\n });\n }\n return { success: false, error: \"WhatsApp not configured\" };\n }\n\n const currentState = state ?? (await runtime.composeState(message));\n\n // Extract message parameters using LLM\n const prompt = composePromptFromState({\n state: currentState,\n template: SEND_MESSAGE_TEMPLATE,\n });\n\n let params: SendMessageParams;\n try {\n const response = await runtime.useModel(ModelType.TEXT_SMALL, {\n prompt,\n });\n\n const parsed = parseJSONObjectFromText(response) as unknown as SendMessageParams | null;\n if (!parsed?.to || !parsed.text) {\n // Try to use context from message\n const to = message.content?.from as string;\n const text = currentState.values?.response?.toString() || \"\";\n\n if (!to) {\n if (callback) {\n await callback({\n text: \"Could not determine who to send the message to\",\n });\n }\n return { success: false, error: \"Missing recipient\" };\n }\n\n // Validate text is not empty\n if (!text || text.trim() === \"\") {\n if (callback) {\n await callback({\n text: \"Cannot send an empty message. Please provide message content.\",\n });\n }\n return { success: false, error: \"Empty message text\" };\n }\n\n params = { to, text };\n } else {\n // Also validate that parsed text is not empty\n if (!parsed.text.trim()) {\n if (callback) {\n await callback({\n text: \"Cannot send an empty message. Please provide message content.\",\n });\n }\n return { success: false, error: \"Empty message text\" };\n }\n params = parsed;\n }\n } catch {\n if (callback) {\n await callback({\n text: \"Failed to parse message parameters\",\n });\n }\n return { success: false, error: \"Failed to parse message parameters\" };\n }\n\n // Send the message via WhatsApp Cloud API\n try {\n const url = `https://graph.facebook.com/${apiVersion}/${phoneNumberId}/messages`;\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${accessToken}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n messaging_product: \"whatsapp\",\n recipient_type: \"individual\",\n to: params.to,\n type: \"text\",\n text: {\n preview_url: false,\n body: params.text,\n },\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json();\n throw new Error(errorData.error?.message || `HTTP ${response.status}`);\n }\n\n const data = (await response.json()) as {\n messages: Array<{ id: string }>;\n };\n const messageId = data.messages?.[0]?.id;\n\n return {\n success: true,\n data: {\n action: WHATSAPP_SEND_MESSAGE_ACTION,\n to: params.to,\n messageId,\n suppressVisibleCallback: true,\n suppressActionResultClipboard: true,\n },\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n if (callback) {\n await callback({\n text: `Failed to send WhatsApp message: ${errorMessage}`,\n });\n }\n return { success: false, error: errorMessage };\n }\n },\n\n examples: [\n [\n {\n name: \"{{name1}}\",\n content: {\n text: \"Send a WhatsApp message to +14155552671 saying hello\",\n },\n },\n {\n name: \"{{agentName}}\",\n content: {\n text: \"I'll send that WhatsApp message now.\",\n actions: [WHATSAPP_SEND_MESSAGE_ACTION],\n },\n },\n ],\n ] as ActionExample[][],\n};\n",
|
|
6
|
+
"import type {\n Action,\n ActionExample,\n ActionResult,\n HandlerCallback,\n HandlerOptions,\n IAgentRuntime,\n Memory,\n State,\n} from \"@elizaos/core\";\nimport { composePromptFromState, ModelType, parseJSONObjectFromText } from \"@elizaos/core\";\n\nexport const WHATSAPP_SEND_REACTION_ACTION = \"WHATSAPP_SEND_REACTION\";\n\nconst REACTION_TEMPLATE = `\nYou are extracting WhatsApp reaction parameters from a conversation.\n\nThe user wants to react to a WhatsApp message. Extract the following:\n1. messageId: The ID of the message to react to\n2. emoji: The emoji to use as a reaction\n\n{{recentMessages}}\n\nBased on the conversation, extract the reaction parameters.\n\nRespond with a JSON object:\n{\n \"messageId\": \"wamid.xxx\",\n \"emoji\": \"👍\"\n}\n`;\n\ninterface ReactionParams {\n messageId: string;\n emoji: string;\n}\n\nexport const sendReactionAction: Action = {\n name: WHATSAPP_SEND_REACTION_ACTION,\n similes: [\"WHATSAPP_REACT\", \"REACT_WHATSAPP\", \"WHATSAPP_EMOJI\"],\n description: \"Send a reaction emoji to a WhatsApp message\",\n descriptionCompressed: \"React to WhatsApp message with emoji.\",\n suppressPostActionContinuation: true,\n\n validate: async (\n _runtime: IAgentRuntime,\n message: Memory,\n _state?: State,\n _options?: HandlerOptions\n ): Promise<boolean> => {\n const text = message.content?.text?.toLowerCase() ?? \"\";\n const hasIntent =\n [\"whatsapp\", \"send\", \"reaction\"].some((keyword) => text.includes(keyword)) &&\n /\\b(?:whatsapp|send|reaction)\\b/i.test(text);\n return hasIntent && message.content?.source === \"whatsapp\";\n },\n\n handler: async (\n runtime: IAgentRuntime,\n message: Memory,\n state: State | undefined,\n _options?: HandlerOptions,\n callback?: HandlerCallback\n ): Promise<ActionResult> => {\n // Get WhatsApp settings\n const accessToken = runtime.getSetting(\"WHATSAPP_ACCESS_TOKEN\") as string;\n const phoneNumberId = runtime.getSetting(\"WHATSAPP_PHONE_NUMBER_ID\") as string;\n const apiVersion = (runtime.getSetting(\"WHATSAPP_API_VERSION\") as string) || \"v24.0\";\n\n if (!accessToken || !phoneNumberId) {\n if (callback) {\n await callback({\n text: \"WhatsApp is not configured. Missing access token or phone number ID.\",\n });\n }\n return { success: false, error: \"WhatsApp not configured\" };\n }\n\n const currentState = state ?? (await runtime.composeState(message));\n\n // Extract reaction parameters using LLM\n const prompt = composePromptFromState({\n state: currentState,\n template: REACTION_TEMPLATE,\n });\n\n let params: ReactionParams;\n try {\n const response = await runtime.useModel(ModelType.TEXT_SMALL, {\n prompt,\n });\n\n const parsed = parseJSONObjectFromText(response) as unknown as ReactionParams | null;\n if (!parsed?.messageId || !parsed.emoji) {\n // Try to use context from message\n const messageId = message.content?.messageId as string;\n if (!messageId) {\n if (callback) {\n await callback({\n text: \"Could not determine which message to react to\",\n });\n }\n return { success: false, error: \"Missing message ID\" };\n }\n params = { messageId, emoji: \"👍\" }; // Default to thumbs up\n } else {\n params = parsed;\n }\n } catch {\n if (callback) {\n await callback({\n text: \"Failed to parse reaction parameters\",\n });\n }\n return { success: false, error: \"Failed to parse reaction parameters\" };\n }\n\n // Get the recipient (sender of the original message)\n const to = message.content?.from as string;\n if (!to) {\n if (callback) {\n await callback({\n text: \"Could not determine the recipient for the reaction\",\n });\n }\n return { success: false, error: \"Missing recipient\" };\n }\n\n // Send the reaction via WhatsApp Cloud API\n try {\n const url = `https://graph.facebook.com/${apiVersion}/${phoneNumberId}/messages`;\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${accessToken}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n messaging_product: \"whatsapp\",\n recipient_type: \"individual\",\n to,\n type: \"reaction\",\n reaction: {\n message_id: params.messageId,\n emoji: params.emoji,\n },\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json();\n throw new Error(errorData.error?.message || `HTTP ${response.status}`);\n }\n\n return {\n success: true,\n data: {\n action: WHATSAPP_SEND_REACTION_ACTION,\n messageId: params.messageId,\n emoji: params.emoji,\n suppressVisibleCallback: true,\n suppressActionResultClipboard: true,\n },\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n if (callback) {\n await callback({\n text: `Failed to send reaction: ${errorMessage}`,\n });\n }\n return { success: false, error: errorMessage };\n }\n },\n\n examples: [\n [\n {\n name: \"{{name1}}\",\n content: {\n text: \"React with a thumbs up\",\n },\n },\n {\n name: \"{{agentName}}\",\n content: {\n text: \"I'll add that reaction.\",\n actions: [WHATSAPP_SEND_REACTION_ACTION],\n },\n },\n ],\n ] as ActionExample[][],\n};\n",
|
|
7
|
+
"import {\n ChannelType,\n type Content,\n createUniqueUuid,\n type IAgentRuntime,\n lifeOpsPassiveConnectorsEnabled,\n type Memory,\n Service,\n type UUID,\n} from \"@elizaos/core\";\nimport { checkWhatsAppUserAccess } from \"./accounts\";\nimport { WhatsAppClient } from \"./client\";\nimport { BaileysClient } from \"./clients/baileys-client\";\nimport {\n buildWhatsAppUserJid,\n chunkWhatsAppText,\n isWhatsAppGroupJid,\n isWhatsAppUserTarget,\n normalizeWhatsAppTarget,\n resolveWhatsAppSystemLocation,\n} from \"./normalize\";\nimport type {\n BaileysConfig,\n CloudAPIConfig,\n ConnectionStatus,\n NormalizedMessage,\n WhatsAppIncomingMessage,\n WhatsAppMessageResponse,\n WhatsAppWebhookEvent,\n} from \"./types\";\n\ntype RuntimeServiceConfig =\n | {\n transport: \"baileys\";\n authDir: string;\n dmPolicy?: \"open\" | \"allowlist\" | \"pairing\" | \"disabled\";\n groupPolicy?: \"open\" | \"allowlist\" | \"disabled\";\n allowFrom?: string[];\n groupAllowFrom?: string[];\n }\n | {\n transport: \"cloudapi\";\n accessToken: string;\n phoneNumberId: string;\n webhookVerifyToken?: string;\n apiVersion?: string;\n dmPolicy?: \"open\" | \"allowlist\" | \"pairing\" | \"disabled\";\n groupPolicy?: \"open\" | \"allowlist\" | \"disabled\";\n allowFrom?: string[];\n groupAllowFrom?: string[];\n };\n\nfunction readStringSetting(runtime: IAgentRuntime, key: string): string | undefined {\n const value = runtime.getSetting(key);\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value.trim();\n }\n\n const envValue = process.env[key];\n if (typeof envValue === \"string\" && envValue.trim().length > 0) {\n return envValue.trim();\n }\n\n return undefined;\n}\n\nfunction readCsvSetting(runtime: IAgentRuntime, key: string): string[] {\n const value = readStringSetting(runtime, key);\n if (!value) {\n return [];\n }\n\n return value\n .split(\",\")\n .map((entry) => entry.trim())\n .filter((entry) => entry.length > 0);\n}\n\nfunction resolveRuntimeConfig(runtime: IAgentRuntime): RuntimeServiceConfig | null {\n const dmPolicy = readStringSetting(runtime, \"WHATSAPP_DM_POLICY\") as\n | \"open\"\n | \"allowlist\"\n | \"pairing\"\n | \"disabled\"\n | undefined;\n const groupPolicy = readStringSetting(runtime, \"WHATSAPP_GROUP_POLICY\") as\n | \"open\"\n | \"allowlist\"\n | \"disabled\"\n | undefined;\n const allowFrom = readCsvSetting(runtime, \"WHATSAPP_ALLOW_FROM\");\n const groupAllowFrom = readCsvSetting(runtime, \"WHATSAPP_GROUP_ALLOW_FROM\");\n\n const authDir =\n readStringSetting(runtime, \"WHATSAPP_AUTH_DIR\") ??\n readStringSetting(runtime, \"WHATSAPP_SESSION_PATH\");\n if (authDir) {\n return {\n transport: \"baileys\",\n authDir,\n dmPolicy,\n groupPolicy,\n allowFrom,\n groupAllowFrom,\n };\n }\n\n const accessToken = readStringSetting(runtime, \"WHATSAPP_ACCESS_TOKEN\");\n const phoneNumberId = readStringSetting(runtime, \"WHATSAPP_PHONE_NUMBER_ID\");\n if (accessToken && phoneNumberId) {\n return {\n transport: \"cloudapi\",\n accessToken,\n phoneNumberId,\n webhookVerifyToken: readStringSetting(runtime, \"WHATSAPP_WEBHOOK_VERIFY_TOKEN\"),\n apiVersion: readStringSetting(runtime, \"WHATSAPP_API_VERSION\"),\n dmPolicy,\n groupPolicy,\n allowFrom,\n groupAllowFrom,\n };\n }\n\n return null;\n}\n\nfunction toTimestampMs(value: number | string | undefined): number {\n const parsed = Number(value);\n if (!Number.isFinite(parsed) || parsed <= 0) {\n return Date.now();\n }\n\n return parsed >= 1_000_000_000_000 ? parsed : parsed * 1000;\n}\n\nfunction toMemoryId(runtime: IAgentRuntime, chatId: string, messageId: string): UUID {\n return createUniqueUuid(runtime, `whatsapp:${chatId}:${messageId}`) as UUID;\n}\n\nfunction normalizeBaileysSendTarget(target: string): string {\n if (isWhatsAppGroupJid(target) || isWhatsAppUserTarget(target)) {\n return target;\n }\n const normalized = normalizeWhatsAppTarget(target);\n return normalized ? buildWhatsAppUserJid(normalized) : target;\n}\n\nfunction extractWebhookText(message: WhatsAppIncomingMessage): string {\n if (typeof message.text?.body === \"string\" && message.text.body.trim()) {\n return message.text.body.trim();\n }\n\n if (\n typeof message.interactive?.button_reply?.title === \"string\" &&\n message.interactive.button_reply.title.trim()\n ) {\n return message.interactive.button_reply.title.trim();\n }\n\n if (\n typeof message.interactive?.list_reply?.title === \"string\" &&\n message.interactive.list_reply.title.trim()\n ) {\n return message.interactive.list_reply.title.trim();\n }\n\n if (\n typeof message.interactive?.nfm_reply?.body === \"string\" &&\n message.interactive.nfm_reply.body.trim()\n ) {\n return message.interactive.nfm_reply.body.trim();\n }\n\n if (typeof message.image?.caption === \"string\" && message.image.caption.trim()) {\n return message.image.caption.trim();\n }\n\n if (typeof message.video?.caption === \"string\" && message.video.caption.trim()) {\n return message.video.caption.trim();\n }\n\n if (typeof message.document?.caption === \"string\" && message.document.caption.trim()) {\n return message.document.caption.trim();\n }\n\n if (message.reaction?.emoji) {\n return `Reaction: ${message.reaction.emoji}`;\n }\n\n if (message.location) {\n const { latitude, longitude } = message.location;\n return `Location: ${latitude}, ${longitude}`;\n }\n\n return \"\";\n}\n\nexport class WhatsAppConnectorService extends Service {\n static serviceType = \"whatsapp\";\n protected declare runtime: IAgentRuntime;\n\n capabilityDescription = \"The agent is able to send and receive messages on whatsapp\";\n\n public connected = false;\n public phoneNumber: string | null = null;\n\n private client: BaileysClient | WhatsAppClient | null = null;\n config: RuntimeServiceConfig | null = null;\n\n constructor(runtime?: IAgentRuntime) {\n super(runtime);\n if (runtime) {\n this.runtime = runtime;\n }\n }\n\n static async start(runtime: IAgentRuntime): Promise<WhatsAppConnectorService> {\n const service = new WhatsAppConnectorService(runtime);\n await service.initialize();\n return service;\n }\n\n async initialize(): Promise<void> {\n this.config = resolveRuntimeConfig(this.runtime);\n if (!this.config) {\n this.runtime.logger.warn(\n { src: \"plugin:whatsapp\", agentId: this.runtime.agentId },\n \"WhatsApp connector is not configured\"\n );\n return;\n }\n\n this.client =\n this.config.transport === \"baileys\"\n ? new BaileysClient({\n authMethod: \"baileys\",\n authDir: this.config.authDir,\n printQRInTerminal: false,\n } satisfies BaileysConfig)\n : new WhatsAppClient({\n accessToken: this.config.accessToken,\n phoneNumberId: this.config.phoneNumberId,\n webhookVerifyToken: this.config.webhookVerifyToken,\n apiVersion: this.config.apiVersion,\n } satisfies CloudAPIConfig);\n\n this.bindClientEvents(this.client);\n await this.client.start();\n\n if (this.config.transport === \"cloudapi\") {\n this.connected = true;\n }\n }\n\n async stop(): Promise<void> {\n if (this.client) {\n await this.client.stop();\n }\n this.connected = false;\n this.phoneNumber = null;\n }\n\n async handleWebhook(event: WhatsAppWebhookEvent): Promise<void> {\n for (const entry of event.entry ?? []) {\n for (const change of entry.changes ?? []) {\n const value = change.value;\n if (typeof value?.metadata?.display_phone_number === \"string\") {\n this.phoneNumber = value.metadata.display_phone_number;\n }\n\n for (const message of value?.messages ?? []) {\n await this.handleIncomingWebhookMessage(message);\n }\n }\n }\n }\n\n verifyWebhook(mode: string, token: string, challenge: string): string | null {\n const expectedToken =\n this.config?.transport === \"cloudapi\"\n ? this.config.webhookVerifyToken\n : readStringSetting(this.runtime, \"WHATSAPP_WEBHOOK_VERIFY_TOKEN\");\n\n if (mode === \"subscribe\" && expectedToken && token === expectedToken && challenge) {\n return challenge;\n }\n\n return null;\n }\n\n private bindClientEvents(client: BaileysClient | WhatsAppClient): void {\n client.on(\"connection\", (status: ConnectionStatus) => {\n this.connected = status === \"open\";\n if (status === \"open\" && client instanceof BaileysClient) {\n const nextPhone = client.getPhoneNumber();\n this.phoneNumber = (nextPhone && normalizeWhatsAppTarget(nextPhone)) ?? nextPhone;\n }\n if (status === \"close\") {\n this.phoneNumber = null;\n }\n });\n\n client.on(\"ready\", () => {\n this.connected = true;\n if (client instanceof BaileysClient) {\n const nextPhone = client.getPhoneNumber();\n this.phoneNumber = (nextPhone && normalizeWhatsAppTarget(nextPhone)) ?? nextPhone;\n }\n });\n\n client.on(\"message\", (message: NormalizedMessage) => {\n void this.handleNormalizedMessage(message).catch((error: unknown) => {\n this.runtime.logger.error(\n {\n src: \"plugin:whatsapp\",\n agentId: this.runtime.agentId,\n error: error instanceof Error ? error.message : String(error),\n },\n \"Failed to process inbound WhatsApp message\"\n );\n });\n });\n\n client.on(\"error\", (error: unknown) => {\n this.runtime.logger.error(\n {\n src: \"plugin:whatsapp\",\n agentId: this.runtime.agentId,\n error: error instanceof Error ? error.message : String(error),\n },\n \"WhatsApp client error\"\n );\n });\n }\n\n private async handleNormalizedMessage(message: NormalizedMessage): Promise<void> {\n const chatId = message.chatId ?? message.from;\n const senderId = message.senderId ?? message.from;\n const text = typeof message.content === \"string\" ? message.content.trim() : \"\";\n\n if (!chatId || !senderId || !text) {\n return;\n }\n\n await this.processIncomingMessage({\n chatId,\n senderId,\n text,\n externalMessageId: message.id,\n replyToExternalMessageId: message.replyToId,\n createdAt: toTimestampMs(message.timestamp),\n });\n }\n\n private async handleIncomingWebhookMessage(message: WhatsAppIncomingMessage): Promise<void> {\n const text = extractWebhookText(message);\n if (!text) {\n return;\n }\n\n const normalizedSender = normalizeWhatsAppTarget(message.from) ?? message.from;\n\n await this.processIncomingMessage({\n chatId: normalizedSender,\n senderId: normalizedSender,\n text,\n externalMessageId: message.id,\n replyToExternalMessageId: message.context?.id,\n createdAt: toTimestampMs(message.timestamp),\n });\n }\n\n private async processIncomingMessage(params: {\n chatId: string;\n senderId: string;\n text: string;\n externalMessageId: string;\n replyToExternalMessageId?: string;\n createdAt: number;\n }): Promise<void> {\n if (!this.runtime.messageService) {\n throw new Error(\"WhatsApp connector requires runtime.messageService\");\n }\n\n const isGroup = isWhatsAppGroupJid(params.chatId);\n const normalizedSender = normalizeWhatsAppTarget(params.senderId) ?? params.senderId;\n\n const accountConfig = {\n dmPolicy: this.config?.dmPolicy,\n groupPolicy: this.config?.groupPolicy,\n allowFrom: this.config?.allowFrom,\n groupAllowFrom: this.config?.groupAllowFrom,\n };\n\n const access = await checkWhatsAppUserAccess({\n runtime: this.runtime,\n identifier: normalizedSender,\n accountConfig,\n isGroup,\n ...(isGroup ? { groupId: params.chatId } : {}),\n metadata: { senderId: normalizedSender },\n });\n\n if (!access.allowed) {\n if (access.replyMessage) {\n await this.sendTextMessage(params.chatId, access.replyMessage);\n }\n return;\n }\n\n const channelType = isGroup ? ChannelType.GROUP : ChannelType.DM;\n const roomId = createUniqueUuid(this.runtime, `whatsapp-room:${params.chatId}`) as UUID;\n const worldId = createUniqueUuid(this.runtime, `whatsapp-world:${params.chatId}`) as UUID;\n const entityId = createUniqueUuid(this.runtime, `whatsapp-entity:${normalizedSender}`) as UUID;\n const inboundMemoryId = toMemoryId(this.runtime, params.chatId, params.externalMessageId);\n\n await this.runtime.ensureConnection({\n entityId,\n roomId,\n userId: normalizedSender as unknown as UUID,\n userName: normalizedSender,\n name: normalizedSender,\n source: \"whatsapp\",\n channelId: params.chatId,\n type: channelType,\n worldId,\n worldName: resolveWhatsAppSystemLocation({\n chatType: isGroup ? \"group\" : \"user\",\n chatId: params.chatId,\n }),\n });\n\n const inboundMemory: Memory = {\n id: inboundMemoryId,\n entityId,\n agentId: this.runtime.agentId,\n roomId,\n content: {\n text: params.text,\n source: \"whatsapp\",\n channelType,\n from: normalizedSender,\n messageId: params.externalMessageId,\n ...(params.replyToExternalMessageId\n ? {\n inReplyTo: toMemoryId(this.runtime, params.chatId, params.replyToExternalMessageId),\n }\n : {}),\n },\n metadata: {\n type: \"message\",\n source: \"whatsapp\",\n provider: \"whatsapp\",\n timestamp: params.createdAt,\n entityName: normalizedSender,\n entityUserName: normalizedSender,\n fromBot: false,\n fromId: normalizedSender,\n sourceId: entityId,\n chatType: channelType,\n messageIdFull: params.externalMessageId,\n sender: {\n id: normalizedSender,\n name: normalizedSender,\n username: normalizedSender,\n },\n whatsapp: {\n id: normalizedSender,\n userId: normalizedSender,\n username: normalizedSender,\n userName: normalizedSender,\n name: normalizedSender,\n chatId: params.chatId,\n messageId: params.externalMessageId,\n },\n rawChatId: params.chatId,\n rawSenderId: params.senderId,\n } as unknown as Memory[\"metadata\"],\n createdAt: params.createdAt,\n };\n\n const callback = async (content: Content): Promise<Memory[]> => {\n const text = typeof content.text === \"string\" ? content.text.trim() : \"\";\n if (!text) {\n return [];\n }\n\n const chunks = chunkWhatsAppText(text);\n const responseMemories: Memory[] = [];\n\n for (const [index, chunk] of chunks.entries()) {\n const response = await this.sendTextMessage(params.chatId, chunk, params.externalMessageId);\n const externalResponseId =\n response.messages?.[0]?.id ??\n `${params.externalMessageId}:response:${index}:${Date.now()}`;\n\n responseMemories.push({\n id: toMemoryId(this.runtime, params.chatId, externalResponseId),\n entityId: this.runtime.agentId,\n agentId: this.runtime.agentId,\n roomId,\n content: {\n ...content,\n text: chunk,\n source: \"whatsapp\",\n channelType,\n inReplyTo: inboundMemoryId,\n },\n metadata: {\n type: \"message\",\n source: \"whatsapp\",\n provider: \"whatsapp\",\n timestamp: Date.now(),\n fromBot: true,\n fromId: this.runtime.agentId,\n sourceId: this.runtime.agentId,\n chatType: channelType,\n messageIdFull: externalResponseId,\n whatsapp: {\n chatId: params.chatId,\n messageId: externalResponseId,\n },\n rawChatId: params.chatId,\n externalMessageId: externalResponseId,\n } as unknown as Memory[\"metadata\"],\n createdAt: Date.now(),\n });\n }\n\n return responseMemories;\n };\n\n // Inbound messages are always ingested into memory. The agent only\n // auto-generates a reply when WHATSAPP_AUTO_REPLY is explicitly enabled —\n // default-off prevents the runtime from speaking on the user's behalf to\n // real WhatsApp contacts.\n const autoReplyRaw = this.runtime.getSetting(\"WHATSAPP_AUTO_REPLY\");\n const autoReply =\n !lifeOpsPassiveConnectorsEnabled(this.runtime) &&\n (autoReplyRaw === true || autoReplyRaw === \"true\");\n\n if (!autoReply) {\n await this.runtime.createMemory(inboundMemory, \"messages\");\n return;\n }\n\n await this.runtime.messageService.handleMessage(this.runtime, inboundMemory, callback);\n }\n\n private async sendTextMessage(\n chatId: string,\n text: string,\n replyToMessageId?: string\n ): Promise<WhatsAppMessageResponse> {\n if (!this.client || !this.config) {\n throw new Error(\"WhatsApp client is not initialized\");\n }\n\n const response = await this.client.sendMessage({\n type: \"text\",\n to:\n this.config.transport === \"baileys\"\n ? normalizeBaileysSendTarget(chatId)\n : (normalizeWhatsAppTarget(chatId) ?? chatId),\n content: text,\n replyToMessageId,\n });\n\n return \"data\" in response\n ? (response.data as WhatsAppMessageResponse)\n : (response as WhatsAppMessageResponse);\n }\n\n async sendMessage(message: {\n type: \"text\";\n to: string;\n content: string;\n replyToMessageId?: string;\n }): Promise<WhatsAppMessageResponse> {\n return this.sendTextMessage(message.to, message.content, message.replyToMessageId);\n }\n}\n",
|
|
8
|
+
"import type { IAgentRuntime } from \"@elizaos/core\";\nimport { checkPairingAllowed, isInAllowlist, type PairingCheckResult } from \"@elizaos/core\";\n\n/**\n * Default account identifier used when no specific account is configured\n */\nexport const DEFAULT_ACCOUNT_ID = \"default\";\n\n/**\n * Token source indicator\n */\nexport type WhatsAppTokenSource = \"config\" | \"env\" | \"character\" | \"none\";\n\n/**\n * Group-specific runtime configuration (for account resolution)\n */\nexport interface WhatsAppGroupRuntimeConfig {\n /** If false, ignore messages from this group */\n enabled?: boolean;\n /** Allowlist for users in this group */\n allowFrom?: Array<string | number>;\n /** Require bot mention to respond */\n requireMention?: boolean;\n /** Custom system prompt for this group */\n systemPrompt?: string;\n /** Skills enabled for this group */\n skills?: string[];\n}\n\n/**\n * Configuration for a single WhatsApp account (runtime resolution)\n */\nexport interface WhatsAppAccountRuntimeConfig {\n /** Optional display name for this account */\n name?: string;\n /** If false, do not start this WhatsApp account */\n enabled?: boolean;\n /** WhatsApp Cloud API access token */\n accessToken?: string;\n /** Phone number ID from WhatsApp Business */\n phoneNumberId?: string;\n /** Business account ID */\n businessAccountId?: string;\n /** Webhook verification token */\n webhookVerifyToken?: string;\n /** API version to use */\n apiVersion?: string;\n /** Allowlist for DM senders */\n allowFrom?: Array<string | number>;\n /** Allowlist for groups */\n groupAllowFrom?: Array<string | number>;\n /** DM access policy */\n dmPolicy?: \"open\" | \"allowlist\" | \"pairing\" | \"disabled\";\n /** Group message access policy */\n groupPolicy?: \"open\" | \"allowlist\" | \"disabled\";\n /** Max media size in MB */\n mediaMaxMb?: number;\n /** Text chunk limit for messages */\n textChunkLimit?: number;\n /** Group-specific configurations */\n groups?: Record<string, WhatsAppGroupRuntimeConfig>;\n}\n\n/**\n * Multi-account WhatsApp configuration structure\n */\nexport interface WhatsAppMultiAccountConfig {\n /** Default/base configuration applied to all accounts */\n enabled?: boolean;\n accessToken?: string;\n phoneNumberId?: string;\n businessAccountId?: string;\n webhookVerifyToken?: string;\n apiVersion?: string;\n dmPolicy?: \"open\" | \"allowlist\" | \"pairing\" | \"disabled\";\n groupPolicy?: \"open\" | \"allowlist\" | \"disabled\";\n mediaMaxMb?: number;\n textChunkLimit?: number;\n /** Per-account configuration overrides */\n accounts?: Record<string, WhatsAppAccountRuntimeConfig>;\n /** Group configurations at base level */\n groups?: Record<string, WhatsAppGroupRuntimeConfig>;\n}\n\n/**\n * Token resolution result\n */\nexport interface WhatsAppTokenResolution {\n token: string;\n source: WhatsAppTokenSource;\n}\n\n/**\n * Resolved WhatsApp account with all configuration merged\n */\nexport interface ResolvedWhatsAppAccount {\n accountId: string;\n enabled: boolean;\n name?: string;\n accessToken: string;\n phoneNumberId: string;\n businessAccountId?: string;\n tokenSource: WhatsAppTokenSource;\n configured: boolean;\n config: WhatsAppAccountRuntimeConfig;\n}\n\n/**\n * Normalizes an account ID, returning the default if not provided\n */\nexport function normalizeAccountId(accountId?: string | null): string {\n if (!accountId || typeof accountId !== \"string\") {\n return DEFAULT_ACCOUNT_ID;\n }\n const trimmed = accountId.trim().toLowerCase();\n if (!trimmed || trimmed === \"default\") {\n return DEFAULT_ACCOUNT_ID;\n }\n return trimmed;\n}\n\n/**\n * Gets the multi-account configuration from runtime settings\n */\nexport function getMultiAccountConfig(runtime: IAgentRuntime): WhatsAppMultiAccountConfig {\n const characterWhatsApp = runtime.character?.settings?.whatsapp as\n | WhatsAppMultiAccountConfig\n | undefined;\n\n return {\n enabled: characterWhatsApp?.enabled,\n accessToken: characterWhatsApp?.accessToken,\n phoneNumberId: characterWhatsApp?.phoneNumberId,\n businessAccountId: characterWhatsApp?.businessAccountId,\n webhookVerifyToken: characterWhatsApp?.webhookVerifyToken,\n apiVersion: characterWhatsApp?.apiVersion,\n dmPolicy: characterWhatsApp?.dmPolicy,\n groupPolicy: characterWhatsApp?.groupPolicy,\n mediaMaxMb: characterWhatsApp?.mediaMaxMb,\n textChunkLimit: characterWhatsApp?.textChunkLimit,\n accounts: characterWhatsApp?.accounts,\n groups: characterWhatsApp?.groups,\n };\n}\n\n/**\n * Lists all configured account IDs\n */\nexport function listWhatsAppAccountIds(runtime: IAgentRuntime): string[] {\n const config = getMultiAccountConfig(runtime);\n const accounts = config.accounts;\n const ids = new Set<string>();\n\n // Check if default account is configured\n const envToken = runtime.getSetting(\"WHATSAPP_ACCESS_TOKEN\") as string | undefined;\n const envPhoneId = runtime.getSetting(\"WHATSAPP_PHONE_NUMBER_ID\") as string | undefined;\n\n const baseConfigured = Boolean(config.accessToken?.trim() && config.phoneNumberId?.trim());\n const envConfigured = Boolean(envToken?.trim() && envPhoneId?.trim());\n\n if (baseConfigured || envConfigured) {\n ids.add(DEFAULT_ACCOUNT_ID);\n }\n\n // Add named accounts\n if (accounts && typeof accounts === \"object\") {\n for (const id of Object.keys(accounts)) {\n if (id) {\n ids.add(normalizeAccountId(id));\n }\n }\n }\n\n const result = Array.from(ids);\n if (result.length === 0) {\n return [DEFAULT_ACCOUNT_ID];\n }\n\n return result.slice().sort((a, b) => a.localeCompare(b));\n}\n\n/**\n * Resolves the default account ID to use\n */\nexport function resolveDefaultWhatsAppAccountId(runtime: IAgentRuntime): string {\n const ids = listWhatsAppAccountIds(runtime);\n if (ids.includes(DEFAULT_ACCOUNT_ID)) {\n return DEFAULT_ACCOUNT_ID;\n }\n return ids[0] ?? DEFAULT_ACCOUNT_ID;\n}\n\n/**\n * Gets the account-specific configuration\n */\nfunction getAccountConfig(\n runtime: IAgentRuntime,\n accountId: string\n): WhatsAppAccountRuntimeConfig | undefined {\n const config = getMultiAccountConfig(runtime);\n const accounts = config.accounts;\n\n if (!accounts || typeof accounts !== \"object\") {\n return undefined;\n }\n\n // Try direct match first\n const direct = accounts[accountId];\n if (direct) {\n return direct;\n }\n\n // Try normalized match\n const normalized = normalizeAccountId(accountId);\n const matchKey = Object.keys(accounts).find((key) => normalizeAccountId(key) === normalized);\n return matchKey ? accounts[matchKey] : undefined;\n}\n\n/**\n * Resolves the access token for a WhatsApp account\n */\nexport function resolveWhatsAppToken(\n runtime: IAgentRuntime,\n accountId: string\n): WhatsAppTokenResolution {\n const multiConfig = getMultiAccountConfig(runtime);\n const accountConfig = getAccountConfig(runtime, accountId);\n\n // Check account-level config first\n if (accountConfig?.accessToken?.trim()) {\n return { token: accountConfig.accessToken.trim(), source: \"config\" };\n }\n\n // For default account, check base config\n if (accountId === DEFAULT_ACCOUNT_ID) {\n if (multiConfig.accessToken?.trim()) {\n return { token: multiConfig.accessToken.trim(), source: \"config\" };\n }\n\n // Check environment/runtime settings\n const envToken = runtime.getSetting(\"WHATSAPP_ACCESS_TOKEN\") as string | undefined;\n if (envToken?.trim()) {\n return { token: envToken.trim(), source: \"env\" };\n }\n }\n\n return { token: \"\", source: \"none\" };\n}\n\n/**\n * Merges base configuration with account-specific overrides\n */\n/**\n * Removes undefined values from an object to prevent them from overwriting during spread\n */\nfunction filterDefined<T extends object>(obj: T): Partial<T> {\n return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined)) as Partial<T>;\n}\n\nfunction mergeWhatsAppAccountConfig(\n runtime: IAgentRuntime,\n accountId: string\n): WhatsAppAccountRuntimeConfig {\n const multiConfig = getMultiAccountConfig(runtime);\n const { accounts: _ignored, ...baseConfig } = multiConfig;\n const accountConfig = getAccountConfig(runtime, accountId) ?? {};\n\n // Get environment/runtime settings for the base config\n const envToken = runtime.getSetting(\"WHATSAPP_ACCESS_TOKEN\") as string | undefined;\n const envPhoneId = runtime.getSetting(\"WHATSAPP_PHONE_NUMBER_ID\") as string | undefined;\n const envBusinessId = runtime.getSetting(\"WHATSAPP_BUSINESS_ACCOUNT_ID\") as string | undefined;\n const envWebhookToken = runtime.getSetting(\"WHATSAPP_WEBHOOK_VERIFY_TOKEN\") as string | undefined;\n const envDmPolicy = runtime.getSetting(\"WHATSAPP_DM_POLICY\") as string | undefined;\n const envGroupPolicy = runtime.getSetting(\"WHATSAPP_GROUP_POLICY\") as string | undefined;\n\n const envConfig: WhatsAppAccountRuntimeConfig = {\n accessToken: envToken || undefined,\n phoneNumberId: envPhoneId || undefined,\n businessAccountId: envBusinessId || undefined,\n webhookVerifyToken: envWebhookToken || undefined,\n dmPolicy: envDmPolicy as WhatsAppAccountRuntimeConfig[\"dmPolicy\"] | undefined,\n groupPolicy: envGroupPolicy as WhatsAppAccountRuntimeConfig[\"groupPolicy\"] | undefined,\n };\n\n // Merge order: env defaults < base config < account config\n // Filter undefined values to prevent them from overwriting defined values\n return {\n ...filterDefined(envConfig),\n ...filterDefined(baseConfig),\n ...filterDefined(accountConfig),\n };\n}\n\n/**\n * Resolves a complete WhatsApp account configuration\n */\nexport function resolveWhatsAppAccount(\n runtime: IAgentRuntime,\n accountId?: string | null\n): ResolvedWhatsAppAccount {\n const normalizedAccountId = normalizeAccountId(accountId);\n const multiConfig = getMultiAccountConfig(runtime);\n\n const baseEnabled = multiConfig.enabled !== false;\n const merged = mergeWhatsAppAccountConfig(runtime, normalizedAccountId);\n const accountEnabled = merged.enabled !== false;\n const enabled = baseEnabled && accountEnabled;\n\n const { token, source: tokenSource } = resolveWhatsAppToken(runtime, normalizedAccountId);\n const phoneNumberId = merged.phoneNumberId?.trim() || \"\";\n\n // Determine if this account is actually configured\n const configured = Boolean(token && phoneNumberId);\n\n return {\n accountId: normalizedAccountId,\n enabled,\n name: merged.name?.trim() || undefined,\n accessToken: token,\n phoneNumberId,\n businessAccountId: merged.businessAccountId?.trim() || undefined,\n tokenSource,\n configured,\n config: merged,\n };\n}\n\n/**\n * Lists all enabled WhatsApp accounts\n */\nexport function listEnabledWhatsAppAccounts(runtime: IAgentRuntime): ResolvedWhatsAppAccount[] {\n return listWhatsAppAccountIds(runtime)\n .map((accountId) => resolveWhatsAppAccount(runtime, accountId))\n .filter((account) => account.enabled && account.configured);\n}\n\n/**\n * Checks if multi-account mode is enabled\n */\nexport function isMultiAccountEnabled(runtime: IAgentRuntime): boolean {\n const accounts = listEnabledWhatsAppAccounts(runtime);\n return accounts.length > 1;\n}\n\n/**\n * Resolves group configuration for a specific group\n */\nexport function resolveWhatsAppGroupConfig(\n runtime: IAgentRuntime,\n accountId: string,\n groupId: string\n): WhatsAppGroupRuntimeConfig | undefined {\n const multiConfig = getMultiAccountConfig(runtime);\n const accountConfig = getAccountConfig(runtime, accountId);\n\n // Check account-level groups first\n const accountGroup = accountConfig?.groups?.[groupId];\n if (accountGroup) {\n return accountGroup;\n }\n\n // Fall back to base-level groups\n return multiConfig.groups?.[groupId];\n}\n\n/**\n * Checks if a user is allowed based on policy and allowlist\n */\nexport function isWhatsAppUserAllowed(params: {\n identifier: string;\n accountConfig: WhatsAppAccountRuntimeConfig;\n isGroup: boolean;\n groupId?: string;\n groupConfig?: WhatsAppGroupRuntimeConfig;\n}): boolean {\n const { identifier, accountConfig, isGroup, groupConfig } = params;\n\n if (isGroup) {\n const policy = accountConfig.groupPolicy ?? \"allowlist\";\n if (policy === \"disabled\") {\n return false;\n }\n\n if (policy === \"open\") {\n return true;\n }\n\n // Check group-specific allowlist first\n if (groupConfig?.allowFrom?.length) {\n return groupConfig.allowFrom.some((allowed) => String(allowed) === identifier);\n }\n\n // Check account-level group allowlist\n if (accountConfig.groupAllowFrom?.length) {\n return accountConfig.groupAllowFrom.some((allowed) => String(allowed) === identifier);\n }\n\n return policy !== \"allowlist\";\n }\n\n // DM handling\n const policy = accountConfig.dmPolicy ?? \"pairing\";\n if (policy === \"disabled\") {\n return false;\n }\n\n if (policy === \"open\") {\n return true;\n }\n\n if (policy === \"pairing\") {\n return true;\n }\n\n // Allowlist policy\n if (accountConfig.allowFrom?.length) {\n return accountConfig.allowFrom.some((allowed) => String(allowed) === identifier);\n }\n\n return false;\n}\n\n/**\n * Checks if mention is required in a group\n */\nexport function isWhatsAppMentionRequired(params: {\n accountConfig: WhatsAppAccountRuntimeConfig;\n groupConfig?: WhatsAppGroupRuntimeConfig;\n}): boolean {\n const { groupConfig } = params;\n return groupConfig?.requireMention ?? false;\n}\n\n/**\n * Result of an async WhatsApp access check\n */\nexport interface WhatsAppAccessCheckResult {\n /** Whether the sender is allowed to proceed */\n allowed: boolean;\n /** If not allowed (pairing policy), the pairing code */\n pairingCode?: string;\n /** Whether a new pairing request was created */\n newPairingRequest?: boolean;\n /** Human-readable message to send to the user when blocked */\n replyMessage?: string;\n}\n\n/**\n * Checks if a user is allowed based on policy and allowlist, with async pairing support.\n *\n * For non-pairing policies, this behaves identically to `isWhatsAppUserAllowed`.\n * For the \"pairing\" policy, this actually checks the PairingService allowlist\n * and creates pairing requests when needed.\n *\n * @example\n * ```typescript\n * const result = await checkWhatsAppUserAccess({\n * runtime,\n * identifier: message.from,\n * accountConfig,\n * isGroup: false,\n * metadata: { name: contact.name },\n * });\n *\n * if (!result.allowed) {\n * if (result.replyMessage) {\n * await sendMessage(result.replyMessage);\n * }\n * return; // Block message processing\n * }\n * ```\n */\nexport async function checkWhatsAppUserAccess(params: {\n runtime: IAgentRuntime;\n identifier: string;\n accountConfig: WhatsAppAccountRuntimeConfig;\n isGroup: boolean;\n groupId?: string;\n groupConfig?: WhatsAppGroupRuntimeConfig;\n metadata?: Record<string, string>;\n}): Promise<WhatsAppAccessCheckResult> {\n const { runtime, identifier, accountConfig, isGroup, groupConfig, metadata } = params;\n\n if (isGroup) {\n // Group access - same logic as synchronous version\n const policy = accountConfig.groupPolicy ?? \"allowlist\";\n if (policy === \"disabled\") {\n return { allowed: false };\n }\n\n if (policy === \"open\") {\n return { allowed: true };\n }\n\n // Check group-specific allowlist first\n if (groupConfig?.allowFrom?.length) {\n const allowed = groupConfig.allowFrom.some((a) => String(a) === identifier);\n return { allowed };\n }\n\n // Check account-level group allowlist\n if (accountConfig.groupAllowFrom?.length) {\n const allowed = accountConfig.groupAllowFrom.some((a) => String(a) === identifier);\n return { allowed };\n }\n\n return { allowed: policy !== \"allowlist\" };\n }\n\n // DM handling\n const policy = accountConfig.dmPolicy ?? \"pairing\";\n if (policy === \"disabled\") {\n return { allowed: false };\n }\n\n if (policy === \"open\") {\n return { allowed: true };\n }\n\n if (policy === \"pairing\") {\n // Use the PairingService for actual pairing workflow\n const result: PairingCheckResult = await checkPairingAllowed(runtime, {\n channel: \"whatsapp\",\n senderId: identifier,\n metadata,\n });\n\n return {\n allowed: result.allowed,\n pairingCode: result.pairingCode,\n newPairingRequest: result.newRequest,\n replyMessage: result.replyMessage,\n };\n }\n\n // Allowlist policy - check static allowlist first\n if (accountConfig.allowFrom?.length) {\n const allowed = accountConfig.allowFrom.some((a) => String(a) === identifier);\n if (allowed) {\n return { allowed: true };\n }\n }\n\n // Also check the dynamic pairing allowlist for the allowlist policy\n const inDynamicAllowlist = await isInAllowlist(runtime, \"whatsapp\", identifier);\n return { allowed: inDynamicAllowlist };\n}\n",
|
|
9
|
+
"import { EventEmitter } from \"node:events\";\nimport axios, { type AxiosInstance, type AxiosResponse } from \"axios\";\nimport type { IWhatsAppClient } from \"./clients/interface\";\nimport type {\n CloudAPIConfig,\n ConnectionStatus,\n SendReactionParams,\n SendReactionResult,\n WhatsAppInteractiveMessage,\n WhatsAppLocationMessage,\n WhatsAppMediaMessage,\n WhatsAppMessage,\n WhatsAppMessageResponse,\n WhatsAppReactionMessage,\n} from \"./types\";\n\nconst DEFAULT_API_VERSION = \"v24.0\";\n\nexport class WhatsAppClient extends EventEmitter implements IWhatsAppClient {\n private client: AxiosInstance;\n private config: CloudAPIConfig;\n private connectionStatus: ConnectionStatus = \"close\";\n\n constructor(config: CloudAPIConfig) {\n super();\n this.config = config;\n const apiVersion = config.apiVersion || DEFAULT_API_VERSION;\n\n this.client = axios.create({\n baseURL: `https://graph.facebook.com/${apiVersion}`,\n headers: {\n Authorization: `Bearer ${config.accessToken}`,\n \"Content-Type\": \"application/json\",\n },\n });\n }\n\n async start(): Promise<void> {\n this.connectionStatus = \"open\";\n this.emit(\"connection\", \"open\");\n this.emit(\"ready\");\n }\n\n async stop(): Promise<void> {\n this.connectionStatus = \"close\";\n this.emit(\"connection\", \"close\");\n }\n\n getConnectionStatus(): ConnectionStatus {\n return this.connectionStatus;\n }\n\n /**\n * Get the configured phone number ID.\n */\n getPhoneNumberId(): string {\n return this.config.phoneNumberId;\n }\n\n /**\n * Send a message of any supported type.\n */\n async sendMessage(message: WhatsAppMessage): Promise<AxiosResponse<WhatsAppMessageResponse>> {\n const endpoint = `/${this.config.phoneNumberId}/messages`;\n const payload = this.buildMessagePayload(message);\n return this.client.post(endpoint, payload);\n }\n\n /**\n * Send a text message.\n */\n async sendTextMessage(\n to: string,\n text: string,\n _previewUrl = false\n ): Promise<AxiosResponse<WhatsAppMessageResponse>> {\n return this.sendMessage({\n type: \"text\",\n to,\n content: text,\n });\n }\n\n /**\n * Send a reaction to a message.\n */\n async sendReaction(params: SendReactionParams): Promise<SendReactionResult> {\n const endpoint = `/${this.config.phoneNumberId}/messages`;\n\n const payload = {\n messaging_product: \"whatsapp\",\n recipient_type: \"individual\",\n to: params.to,\n type: \"reaction\",\n reaction: {\n message_id: params.messageId,\n emoji: params.emoji,\n },\n };\n\n try {\n const response = await this.client.post<WhatsAppMessageResponse>(endpoint, payload);\n return {\n success: true,\n messageId: response.data.messages?.[0]?.id,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return {\n success: false,\n error: errorMessage,\n };\n }\n }\n\n /**\n * Remove a reaction from a message (send empty emoji).\n */\n async removeReaction(to: string, messageId: string): Promise<SendReactionResult> {\n return this.sendReaction({\n to,\n messageId,\n emoji: \"\",\n });\n }\n\n /**\n * Send an image message.\n */\n async sendImage(\n to: string,\n imageUrl: string,\n caption?: string\n ): Promise<AxiosResponse<WhatsAppMessageResponse>> {\n return this.sendMessage({\n type: \"image\",\n to,\n content: {\n link: imageUrl,\n caption,\n } as WhatsAppMediaMessage,\n });\n }\n\n /**\n * Send a video message.\n */\n async sendVideo(\n to: string,\n videoUrl: string,\n caption?: string\n ): Promise<AxiosResponse<WhatsAppMessageResponse>> {\n return this.sendMessage({\n type: \"video\",\n to,\n content: {\n link: videoUrl,\n caption,\n } as WhatsAppMediaMessage,\n });\n }\n\n /**\n * Send an audio message.\n */\n async sendAudio(to: string, audioUrl: string): Promise<AxiosResponse<WhatsAppMessageResponse>> {\n return this.sendMessage({\n type: \"audio\",\n to,\n content: {\n link: audioUrl,\n } as WhatsAppMediaMessage,\n });\n }\n\n /**\n * Send a document message.\n */\n async sendDocument(\n to: string,\n documentUrl: string,\n filename?: string,\n caption?: string\n ): Promise<AxiosResponse<WhatsAppMessageResponse>> {\n return this.sendMessage({\n type: \"document\",\n to,\n content: {\n link: documentUrl,\n filename,\n caption,\n } as WhatsAppMediaMessage,\n });\n }\n\n /**\n * Send a location message.\n */\n async sendLocation(\n to: string,\n latitude: number,\n longitude: number,\n name?: string,\n address?: string\n ): Promise<AxiosResponse<WhatsAppMessageResponse>> {\n return this.sendMessage({\n type: \"location\",\n to,\n content: {\n latitude,\n longitude,\n name,\n address,\n } as WhatsAppLocationMessage,\n });\n }\n\n /**\n * Send an interactive button message.\n */\n async sendButtonMessage(\n to: string,\n bodyText: string,\n buttons: Array<{ id: string; title: string }>,\n headerText?: string,\n footerText?: string\n ): Promise<AxiosResponse<WhatsAppMessageResponse>> {\n const interactive: WhatsAppInteractiveMessage = {\n type: \"button\",\n body: { text: bodyText },\n action: {\n buttons: buttons.map((btn) => ({\n type: \"reply\" as const,\n reply: { id: btn.id, title: btn.title },\n })),\n },\n };\n\n if (headerText) {\n interactive.header = { type: \"text\", text: headerText };\n }\n if (footerText) {\n interactive.footer = { text: footerText };\n }\n\n return this.sendMessage({\n type: \"interactive\",\n to,\n content: interactive,\n });\n }\n\n /**\n * Send an interactive list message.\n */\n async sendListMessage(\n to: string,\n bodyText: string,\n buttonText: string,\n sections: Array<{\n title?: string;\n rows: Array<{ id: string; title: string; description?: string }>;\n }>,\n headerText?: string,\n footerText?: string\n ): Promise<AxiosResponse<WhatsAppMessageResponse>> {\n const interactive: WhatsAppInteractiveMessage = {\n type: \"list\",\n body: { text: bodyText },\n action: {\n button: buttonText,\n sections,\n },\n };\n\n if (headerText) {\n interactive.header = { type: \"text\", text: headerText };\n }\n if (footerText) {\n interactive.footer = { text: footerText };\n }\n\n return this.sendMessage({\n type: \"interactive\",\n to,\n content: interactive,\n });\n }\n\n /**\n * Mark a message as read.\n */\n async markMessageAsRead(messageId: string): Promise<boolean> {\n const endpoint = `/${this.config.phoneNumberId}/messages`;\n\n const payload = {\n messaging_product: \"whatsapp\",\n status: \"read\",\n message_id: messageId,\n };\n\n try {\n await this.client.post(endpoint, payload);\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Download media by ID.\n */\n async getMediaUrl(mediaId: string): Promise<string | null> {\n try {\n const response = await this.client.get(`/${mediaId}`);\n return response.data.url || null;\n } catch {\n return null;\n }\n }\n\n /**\n * Verify webhook token.\n */\n async verifyWebhook(token: string): Promise<boolean> {\n return token === this.config.webhookVerifyToken;\n }\n\n /**\n * Build the message payload based on message type.\n */\n private buildMessagePayload(message: WhatsAppMessage): Record<string, unknown> {\n const basePayload = {\n messaging_product: \"whatsapp\",\n recipient_type: \"individual\",\n to: message.to,\n type: message.type,\n };\n\n // Add context for replies\n const contextPayload = message.replyToMessageId\n ? { context: { message_id: message.replyToMessageId } }\n : {};\n\n switch (message.type) {\n case \"text\":\n return {\n ...basePayload,\n ...contextPayload,\n text: {\n body: message.content as string,\n },\n };\n\n case \"template\":\n return {\n ...basePayload,\n ...contextPayload,\n template: message.content,\n };\n\n case \"image\": {\n const imageContent = message.content as WhatsAppMediaMessage;\n return {\n ...basePayload,\n ...contextPayload,\n image: {\n link: imageContent.link,\n caption: imageContent.caption,\n },\n };\n }\n\n case \"video\": {\n const videoContent = message.content as WhatsAppMediaMessage;\n return {\n ...basePayload,\n ...contextPayload,\n video: {\n link: videoContent.link,\n caption: videoContent.caption,\n },\n };\n }\n\n case \"audio\": {\n const audioContent = message.content as WhatsAppMediaMessage;\n return {\n ...basePayload,\n ...contextPayload,\n audio: {\n link: audioContent.link,\n },\n };\n }\n\n case \"document\": {\n const docContent = message.content as WhatsAppMediaMessage;\n return {\n ...basePayload,\n ...contextPayload,\n document: {\n link: docContent.link,\n filename: docContent.filename,\n caption: docContent.caption,\n },\n };\n }\n\n case \"location\": {\n const locContent = message.content as WhatsAppLocationMessage;\n return {\n ...basePayload,\n ...contextPayload,\n location: {\n latitude: locContent.latitude,\n longitude: locContent.longitude,\n name: locContent.name,\n address: locContent.address,\n },\n };\n }\n\n case \"reaction\": {\n const reactionContent = message.content as WhatsAppReactionMessage;\n return {\n ...basePayload,\n reaction: {\n message_id: reactionContent.messageId,\n emoji: reactionContent.emoji,\n },\n };\n }\n\n case \"interactive\": {\n const interactiveContent = message.content as WhatsAppInteractiveMessage;\n return {\n ...basePayload,\n ...contextPayload,\n interactive: interactiveContent,\n };\n }\n\n default:\n return basePayload;\n }\n }\n}\n",
|
|
10
|
+
"import { EventEmitter } from \"node:events\";\nimport { BaileysAuthManager } from \"../baileys/auth\";\nimport { BaileysConnection } from \"../baileys/connection\";\nimport { MessageAdapter } from \"../baileys/message-adapter\";\nimport { QRCodeGenerator } from \"../baileys/qr-code\";\nimport type {\n BaileysConfig,\n ConnectionStatus,\n WhatsAppMessage,\n WhatsAppMessageResponse,\n} from \"../types\";\nimport type { IWhatsAppClient } from \"./interface\";\n\nexport class BaileysClient extends EventEmitter implements IWhatsAppClient {\n private readonly config: BaileysConfig;\n private readonly authManager: BaileysAuthManager;\n private readonly connection: BaileysConnection;\n private readonly qrGenerator: QRCodeGenerator;\n private readonly adapter: MessageAdapter;\n\n constructor(config: BaileysConfig) {\n super();\n this.config = config;\n this.authManager = new BaileysAuthManager(config.authDir);\n this.connection = new BaileysConnection(this.authManager);\n this.qrGenerator = new QRCodeGenerator();\n this.adapter = new MessageAdapter();\n this.setupEventForwarding();\n }\n\n private setupEventForwarding(): void {\n this.connection.on(\"qr\", async (qr: string) => {\n try {\n const qrData = await this.qrGenerator.generate(qr);\n if (this.config.printQRInTerminal !== false) {\n console.log(\"\\n=== Scan QR Code ===\\n\");\n console.log(qrData.terminal);\n }\n this.emit(\"qr\", qrData);\n } catch (error) {\n this.emit(\"error\", error);\n }\n });\n\n this.connection.on(\"connection\", (status: ConnectionStatus) => {\n this.emit(\"connection\", status);\n if (status === \"open\") {\n this.emit(\"ready\");\n }\n });\n\n this.connection.on(\"messages\", (messages: unknown[]) => {\n for (const message of messages) {\n const maybe = message as {\n key?: { fromMe?: boolean };\n message?: unknown;\n };\n if (!maybe.key?.fromMe && maybe.message) {\n this.emit(\n \"message\",\n this.adapter.toNormalized(message as Parameters<MessageAdapter[\"toNormalized\"]>[0])\n );\n }\n }\n });\n\n this.connection.on(\"error\", (error: unknown) => {\n this.emit(\"error\", error);\n });\n }\n\n async start(): Promise<void> {\n await this.connection.connect();\n }\n\n async stop(): Promise<void> {\n await this.connection.disconnect();\n }\n\n async sendMessage(message: WhatsAppMessage): Promise<WhatsAppMessageResponse> {\n const socket = this.connection.getSocket();\n if (!socket) {\n throw new Error(\"Not connected to WhatsApp via Baileys\");\n }\n\n const payload = this.adapter.toBaileys(message);\n const result = await socket.sendMessage(\n message.to,\n payload as Parameters<typeof socket.sendMessage>[1]\n );\n const id = result?.key?.id ?? \"\";\n\n return {\n messaging_product: \"whatsapp\",\n contacts: [{ input: message.to, wa_id: message.to }],\n messages: [{ id }],\n };\n }\n\n getConnectionStatus(): ConnectionStatus {\n return this.connection.getStatus();\n }\n\n getPhoneNumber(): string | null {\n return this.connection.getSocket()?.user?.id?.split(\":\")[0] ?? null;\n }\n}\n",
|
|
11
|
+
"import type { AuthenticationState } from \"@whiskeysockets/baileys\";\nimport { useMultiFileAuthState } from \"@whiskeysockets/baileys\";\n\nexport class BaileysAuthManager {\n private readonly authDir: string;\n private state?: AuthenticationState;\n private saveCreds?: () => Promise<void>;\n\n constructor(authDir: string) {\n this.authDir = authDir;\n }\n\n async initialize(): Promise<AuthenticationState> {\n const result = await useMultiFileAuthState(this.authDir);\n this.state = result.state;\n this.saveCreds = result.saveCreds;\n return this.state;\n }\n\n async save(): Promise<void> {\n if (this.saveCreds) {\n await this.saveCreds();\n }\n }\n}\n",
|
|
12
|
+
"import { EventEmitter } from \"node:events\";\nimport type { Boom } from \"@hapi/boom\";\nimport makeWASocket, { DisconnectReason, type WASocket } from \"@whiskeysockets/baileys\";\nimport pino from \"pino\";\nimport type { ConnectionStatus } from \"../types\";\nimport type { BaileysAuthManager } from \"./auth\";\n\nexport class BaileysConnection extends EventEmitter {\n private socket?: WASocket;\n private readonly authManager: BaileysAuthManager;\n private connectionStatus: ConnectionStatus = \"close\";\n private reconnecting = false;\n private reconnectAttempts = 0;\n private readonly maxReconnectAttempts = 10;\n\n constructor(authManager: BaileysAuthManager) {\n super();\n this.authManager = authManager;\n }\n\n async connect(): Promise<WASocket> {\n this.connectionStatus = \"connecting\";\n this.emit(\"connection\", \"connecting\");\n\n const state = await this.authManager.initialize();\n this.socket = makeWASocket({\n auth: state,\n printQRInTerminal: false,\n logger: pino({ level: \"silent\" }),\n browser: [\"Chrome (Linux)\", \"\", \"\"],\n });\n\n this.setupEventHandlers();\n return this.socket;\n }\n\n private setupEventHandlers(): void {\n if (!this.socket) {\n return;\n }\n\n this.socket.ev.on(\"connection.update\", async (update) => {\n const { connection, qr, lastDisconnect } = update;\n\n if (qr) {\n this.emit(\"qr\", qr);\n }\n\n if (connection) {\n this.connectionStatus = connection;\n this.emit(\"connection\", connection);\n }\n\n if (connection === \"open\") {\n this.reconnectAttempts = 0;\n return;\n }\n\n if (connection !== \"close\") {\n return;\n }\n\n const statusCode = (lastDisconnect?.error as Boom | undefined)?.output?.statusCode;\n const isQRTimeout = statusCode === 515;\n const shouldReconnect = statusCode !== DisconnectReason.loggedOut && statusCode !== 405;\n\n if (lastDisconnect?.error && !isQRTimeout) {\n this.emit(\"error\", lastDisconnect.error);\n }\n\n if (!shouldReconnect) {\n return;\n }\n\n if (this.reconnecting) {\n return;\n }\n\n if (this.reconnectAttempts >= this.maxReconnectAttempts) {\n this.emit(\"error\", new Error(\"Max reconnection attempts reached\"));\n return;\n }\n\n this.reconnecting = true;\n try {\n this.reconnectAttempts += 1;\n const baseDelayMs = isQRTimeout ? 1000 : 3000;\n const backoffMs = Math.min(baseDelayMs * 2 ** (this.reconnectAttempts - 1), 30000);\n await new Promise((resolve) => setTimeout(resolve, backoffMs));\n await this.connect();\n } catch (error) {\n this.emit(\"error\", error);\n } finally {\n this.reconnecting = false;\n }\n });\n\n this.socket.ev.on(\"creds.update\", async () => {\n await this.authManager.save();\n });\n\n this.socket.ev.on(\"messages.upsert\", ({ messages }) => {\n this.emit(\"messages\", messages);\n });\n }\n\n getSocket(): WASocket | undefined {\n return this.socket;\n }\n\n getStatus(): ConnectionStatus {\n return this.connectionStatus;\n }\n\n async disconnect(): Promise<void> {\n if (!this.socket) {\n return;\n }\n\n (\n this.socket.ev as unknown as {\n removeAllListeners: (...args: unknown[]) => void;\n }\n ).removeAllListeners();\n (this.socket as unknown as { ws?: { close?: () => void } }).ws?.close?.();\n this.socket = undefined;\n this.connectionStatus = \"close\";\n this.emit(\"connection\", \"close\");\n }\n}\n",
|
|
13
|
+
"import type { proto } from \"@whiskeysockets/baileys\";\nimport type {\n NormalizedMessage,\n WhatsAppMediaMessage,\n WhatsAppMessage,\n WhatsAppTemplate,\n} from \"../types\";\n\nexport class MessageAdapter {\n toNormalized(msg: proto.IWebMessageInfo): NormalizedMessage {\n const chatId = msg.key?.remoteJid ?? \"\";\n const senderId = msg.key?.participant ?? chatId;\n\n return {\n id: msg.key?.id ?? \"\",\n from: chatId,\n timestamp: Number(msg.messageTimestamp ?? 0),\n type: this.detectType(msg),\n content: this.extractContent(msg),\n chatId,\n senderId,\n replyToId: this.extractReplyToId(msg),\n };\n }\n\n toBaileys(msg: WhatsAppMessage): Record<string, unknown> {\n switch (msg.type) {\n case \"text\":\n return { text: msg.content as string };\n case \"image\":\n return this.mediaWithCaption(\"image\", msg.content as WhatsAppMediaMessage);\n case \"video\":\n return this.mediaWithCaption(\"video\", msg.content as WhatsAppMediaMessage);\n case \"audio\":\n return this.mediaNoCaption(\"audio\", msg.content as WhatsAppMediaMessage);\n case \"document\":\n return this.mediaWithFilename(msg.content as WhatsAppMediaMessage);\n case \"template\":\n return { text: this.renderTemplate(msg.content as WhatsAppTemplate) };\n default:\n throw new Error(`Message type ${msg.type} is not yet supported for Baileys`);\n }\n }\n\n private mediaWithCaption(\n key: \"image\" | \"video\",\n media: WhatsAppMediaMessage\n ): Record<string, unknown> {\n if (!media?.link) {\n throw new Error(`${key} message requires a media link`);\n }\n return {\n [key]: { url: media.link },\n ...(media.caption ? { caption: media.caption } : {}),\n };\n }\n\n private mediaNoCaption(key: \"audio\", media: WhatsAppMediaMessage): Record<string, unknown> {\n if (!media?.link) {\n throw new Error(`${key} message requires a media link`);\n }\n return { [key]: { url: media.link } };\n }\n\n private mediaWithFilename(media: WhatsAppMediaMessage): Record<string, unknown> {\n if (!media?.link) {\n throw new Error(\"document message requires a media link\");\n }\n return {\n document: { url: media.link },\n ...(media.filename ? { fileName: media.filename } : {}),\n ...(media.caption ? { caption: media.caption } : {}),\n };\n }\n\n private detectType(\n msg: proto.IWebMessageInfo\n ): \"text\" | \"image\" | \"audio\" | \"video\" | \"document\" {\n if (msg.message?.conversation || msg.message?.extendedTextMessage) {\n return \"text\";\n }\n if (msg.message?.imageMessage) {\n return \"image\";\n }\n if (msg.message?.audioMessage) {\n return \"audio\";\n }\n if (msg.message?.videoMessage) {\n return \"video\";\n }\n if (msg.message?.documentMessage) {\n return \"document\";\n }\n return \"text\";\n }\n\n private extractContent(msg: proto.IWebMessageInfo): string {\n return (\n msg.message?.conversation ??\n msg.message?.extendedTextMessage?.text ??\n msg.message?.imageMessage?.caption ??\n msg.message?.videoMessage?.caption ??\n msg.message?.documentMessage?.caption ??\n \"\"\n );\n }\n\n private extractReplyToId(msg: proto.IWebMessageInfo): string | undefined {\n const contextInfo =\n msg.message?.extendedTextMessage?.contextInfo ??\n msg.message?.imageMessage?.contextInfo ??\n msg.message?.videoMessage?.contextInfo ??\n msg.message?.documentMessage?.contextInfo;\n\n return typeof contextInfo?.stanzaId === \"string\" ? contextInfo.stanzaId : undefined;\n }\n\n private renderTemplate(template: WhatsAppTemplate): string {\n const params = template.components?.flatMap((component) =>\n component.parameters.map((parameter) => parameter.text).filter(Boolean)\n );\n return params && params.length > 0 ? `${template.name}: ${params.join(\", \")}` : template.name;\n }\n}\n",
|
|
14
|
+
"import QRCode from \"qrcode\";\nimport QRCodeTerminal from \"qrcode-terminal\";\nimport type { QRCodeData } from \"../types\";\n\nexport class QRCodeGenerator {\n async generate(qrString: string): Promise<QRCodeData> {\n return {\n terminal: await this.generateTerminal(qrString),\n dataURL: await QRCode.toDataURL(qrString),\n raw: qrString,\n };\n }\n\n private async generateTerminal(qr: string): Promise<string> {\n return new Promise((resolve) => {\n QRCodeTerminal.generate(qr, { small: true }, (output: string) => {\n resolve(output);\n });\n });\n }\n}\n",
|
|
15
|
+
"/**\n * WhatsApp text chunk limit\n */\nexport const WHATSAPP_TEXT_CHUNK_LIMIT = 4096;\n\n/**\n * Regex for WhatsApp user JID (e.g., \"41796666864:0@s.whatsapp.net\")\n */\nconst WHATSAPP_USER_JID_RE = /^(\\d+)(?::\\d+)?@s\\.whatsapp\\.net$/i;\n\n/**\n * Regex for WhatsApp LID (e.g., \"123@lid\")\n */\nconst WHATSAPP_LID_RE = /^(\\d+)@lid$/i;\n\n/**\n * Strips WhatsApp target prefixes from a value\n */\nfunction stripWhatsAppTargetPrefixes(value: string): string {\n let candidate = value.trim();\n for (;;) {\n const before = candidate;\n candidate = candidate.replace(/^whatsapp:/i, \"\").trim();\n if (candidate === before) {\n return candidate;\n }\n }\n}\n\n/**\n * Normalizes a phone number to E.164 format\n */\nexport function normalizeE164(input: string): string {\n const stripped = input.replace(/[\\s\\-().]+/g, \"\");\n const digitsOnly = stripped.replace(/[^\\d+]/g, \"\");\n\n if (!digitsOnly) {\n return \"\";\n }\n\n // If it starts with +, keep as-is (already E.164)\n if (digitsOnly.startsWith(\"+\")) {\n return digitsOnly;\n }\n\n // If it starts with 00, replace with +\n if (digitsOnly.startsWith(\"00\")) {\n return `+${digitsOnly.slice(2)}`;\n }\n\n // Assume it's a full number without the +\n if (digitsOnly.length >= 10) {\n return `+${digitsOnly}`;\n }\n\n // Return as-is if too short\n return digitsOnly;\n}\n\n/**\n * Checks if a value is a WhatsApp group JID (e.g., \"123456789-987654321@g.us\")\n */\nexport function isWhatsAppGroupJid(value: string): boolean {\n const candidate = stripWhatsAppTargetPrefixes(value);\n const lower = candidate.toLowerCase();\n if (!lower.endsWith(\"@g.us\")) {\n return false;\n }\n const localPart = candidate.slice(0, candidate.length - \"@g.us\".length);\n if (!localPart || localPart.includes(\"@\")) {\n return false;\n }\n return /^[0-9]+(-[0-9]+)*$/.test(localPart);\n}\n\n/**\n * Checks if a value looks like a WhatsApp user target\n * (e.g., \"41796666864:0@s.whatsapp.net\" or \"123@lid\")\n */\nexport function isWhatsAppUserTarget(value: string): boolean {\n const candidate = stripWhatsAppTargetPrefixes(value);\n return WHATSAPP_USER_JID_RE.test(candidate) || WHATSAPP_LID_RE.test(candidate);\n}\n\n/**\n * Extracts the phone number from a WhatsApp user JID\n * \"41796666864:0@s.whatsapp.net\" -> \"41796666864\"\n * \"123456@lid\" -> \"123456\"\n */\nfunction extractUserJidPhone(jid: string): string | null {\n const userMatch = jid.match(WHATSAPP_USER_JID_RE);\n if (userMatch) {\n return userMatch[1];\n }\n const lidMatch = jid.match(WHATSAPP_LID_RE);\n if (lidMatch) {\n return lidMatch[1];\n }\n return null;\n}\n\n/**\n * Normalizes a WhatsApp target (phone number, user JID, or group JID)\n * Returns null if the target is invalid\n */\nexport function normalizeWhatsAppTarget(value: string): string | null {\n const candidate = stripWhatsAppTargetPrefixes(value);\n if (!candidate) {\n return null;\n }\n\n // Handle group JIDs\n if (isWhatsAppGroupJid(candidate)) {\n const localPart = candidate.slice(0, candidate.length - \"@g.us\".length);\n return `${localPart}@g.us`;\n }\n\n // Handle user JIDs (e.g., \"41796666864:0@s.whatsapp.net\")\n if (isWhatsAppUserTarget(candidate)) {\n const phone = extractUserJidPhone(candidate);\n if (!phone) {\n return null;\n }\n const normalized = normalizeE164(phone);\n return normalized.length > 1 ? normalized : null;\n }\n\n // If the caller passed a JID-ish string that we don't understand, fail fast.\n // Otherwise normalizeE164 would happily treat \"group:120@g.us\" as a phone number.\n if (candidate.includes(\"@\")) {\n return null;\n }\n\n // Treat as a phone number\n const normalized = normalizeE164(candidate);\n return normalized.length > 1 ? normalized : null;\n}\n\n/**\n * Formats a WhatsApp ID for display\n */\nexport function formatWhatsAppId(id: string): string {\n if (isWhatsAppGroupJid(id)) {\n return `group:${id}`;\n }\n const normalized = normalizeWhatsAppTarget(id);\n return normalized || id;\n}\n\n/**\n * Checks if a WhatsApp ID is a group\n */\nexport function isWhatsAppGroup(id: string): boolean {\n return isWhatsAppGroupJid(id);\n}\n\n/**\n * Gets the chat type from a WhatsApp ID\n */\nexport function getWhatsAppChatType(id: string): \"group\" | \"user\" {\n return isWhatsAppGroupJid(id) ? \"group\" : \"user\";\n}\n\n/**\n * Builds a WhatsApp JID from a phone number\n */\nexport function buildWhatsAppUserJid(phoneNumber: string): string {\n const normalized = normalizeE164(phoneNumber);\n const digits = normalized.replace(/^\\+/, \"\");\n return `${digits}@s.whatsapp.net`;\n}\n\n/**\n * Options for text chunking\n */\nexport interface ChunkWhatsAppTextOpts {\n limit?: number;\n}\n\n/**\n * Splits text at the last safe break point within the limit\n */\nfunction splitAtBreakPoint(text: string, limit: number): { chunk: string; remainder: string } {\n if (text.length <= limit) {\n return { chunk: text, remainder: \"\" };\n }\n\n const searchArea = text.slice(0, limit);\n\n // Prefer double newlines (paragraph breaks)\n const doubleNewline = searchArea.lastIndexOf(\"\\n\\n\");\n if (doubleNewline > limit * 0.5) {\n return {\n chunk: text.slice(0, doubleNewline).trimEnd(),\n remainder: text.slice(doubleNewline + 2).trimStart(),\n };\n }\n\n // Try single newlines\n const singleNewline = searchArea.lastIndexOf(\"\\n\");\n if (singleNewline > limit * 0.5) {\n return {\n chunk: text.slice(0, singleNewline).trimEnd(),\n remainder: text.slice(singleNewline + 1).trimStart(),\n };\n }\n\n // Try sentence boundaries\n const sentenceEnd = Math.max(\n searchArea.lastIndexOf(\". \"),\n searchArea.lastIndexOf(\"! \"),\n searchArea.lastIndexOf(\"? \")\n );\n if (sentenceEnd > limit * 0.5) {\n return {\n chunk: text.slice(0, sentenceEnd + 1).trimEnd(),\n remainder: text.slice(sentenceEnd + 2).trimStart(),\n };\n }\n\n // Try word boundaries\n const space = searchArea.lastIndexOf(\" \");\n if (space > limit * 0.5) {\n return {\n chunk: text.slice(0, space).trimEnd(),\n remainder: text.slice(space + 1).trimStart(),\n };\n }\n\n // Hard break at limit\n return {\n chunk: text.slice(0, limit),\n remainder: text.slice(limit),\n };\n}\n\n/**\n * Chunks text for WhatsApp messages\n */\nexport function chunkWhatsAppText(text: string, opts: ChunkWhatsAppTextOpts = {}): string[] {\n const limit = opts.limit ?? WHATSAPP_TEXT_CHUNK_LIMIT;\n\n if (!text?.trim()) {\n return [];\n }\n\n const normalizedText = text.trim();\n if (normalizedText.length <= limit) {\n return [normalizedText];\n }\n\n const chunks: string[] = [];\n let remaining = normalizedText;\n\n while (remaining.length > 0) {\n const { chunk, remainder } = splitAtBreakPoint(remaining, limit);\n if (chunk) {\n chunks.push(chunk);\n }\n remaining = remainder;\n }\n\n return chunks.filter((c) => c.length > 0);\n}\n\n/**\n * Truncates text to a maximum length with ellipsis\n */\nexport function truncateText(text: string, maxLength: number): string {\n if (text.length <= maxLength) {\n return text;\n }\n if (maxLength <= 3) {\n return \"...\".slice(0, maxLength);\n }\n return `${text.slice(0, maxLength - 3)}...`;\n}\n\n/**\n * Resolves the system location string for logging\n */\nexport function resolveWhatsAppSystemLocation(params: {\n chatType: \"group\" | \"user\";\n chatId: string;\n chatName?: string;\n}): string {\n const { chatType, chatId, chatName } = params;\n const name = chatName || chatId.slice(0, 8);\n return `WhatsApp ${chatType}:${name}`;\n}\n\n/**\n * Validates a WhatsApp phone number\n */\nexport function isValidWhatsAppNumber(value: string): boolean {\n const normalized = normalizeWhatsAppTarget(value);\n if (!normalized) {\n return false;\n }\n // Must be E.164 format with at least 10 digits\n if (!normalized.startsWith(\"+\")) {\n return false;\n }\n const digits = normalized.replace(/^\\+/, \"\");\n return /^\\d{10,15}$/.test(digits);\n}\n\n/**\n * Formats a phone number for WhatsApp display\n */\nexport function formatWhatsAppPhoneNumber(phoneNumber: string): string {\n const normalized = normalizeE164(phoneNumber);\n if (!normalized) {\n return phoneNumber;\n }\n // Format as +XX XXX XXX XXXX for display\n const digits = normalized.replace(/^\\+/, \"\");\n if (digits.length <= 10) {\n return normalized;\n }\n // Simple formatting: country code + rest\n const countryCode = digits.slice(0, digits.length - 10);\n const rest = digits.slice(-10);\n return `+${countryCode} ${rest.slice(0, 3)} ${rest.slice(3, 6)} ${rest.slice(6)}`;\n}\n",
|
|
16
|
+
"/**\n * WhatsApp setup HTTP routes.\n *\n * Provides QR-code pairing, status, disconnect, and webhook endpoints:\n *\n * GET /api/whatsapp/webhook Meta webhook verification\n * POST /api/whatsapp/webhook Meta webhook event delivery\n * POST /api/whatsapp/pair Start QR pairing session\n * GET /api/whatsapp/status Check connection / pairing status\n * POST /api/whatsapp/pair/stop Stop active pairing session\n * POST /api/whatsapp/disconnect Logout + remove auth state\n *\n * These routes are registered with `rawPath: true` so they mount at their\n * legacy paths without the plugin-name prefix.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { IAgentRuntime, Route, RouteRequest, RouteResponse } from \"@elizaos/core\";\nimport type { WhatsAppPairingEvent } from \"./pairing-service.js\";\nimport {\n sanitizeAccountId,\n WhatsAppPairingSession,\n whatsappAuthExists,\n whatsappLogout,\n} from \"./pairing-service.js\";\n\n// ── Module-level state ─────────────────────────────────────────────────\n// Replaces WhatsAppRouteState.whatsappPairingSessions — shared across\n// all route handler invocations within this plugin.\n\ninterface PairingSessionLike {\n start(): Promise<void>;\n stop(): void;\n getStatus(): string;\n}\n\nconst whatsappPairingSessions: Map<string, PairingSessionLike> = new Map();\n\nconst MAX_PAIRING_SESSIONS = 10;\n\n/**\n * Minimal interface for the connector-setup service exposed by the agent.\n * Plugins access it via `runtime.getService(\"connector-setup\")`.\n */\ninterface ConnectorSetupService {\n getConfig(): Record<string, unknown>;\n persistConfig(config: Record<string, unknown>): void;\n updateConfig(updater: (config: Record<string, unknown>) => void): void;\n registerEscalationChannel(channelName: string): boolean;\n setOwnerContact(update: {\n source: string;\n channelId?: string;\n entityId?: string;\n roomId?: string;\n }): boolean;\n getWorkspaceDir(): string;\n broadcastWs(data: object): void;\n}\n\nfunction isConnectorSetupService(service: unknown): service is ConnectorSetupService {\n return (\n typeof service === \"object\" &&\n service !== null &&\n typeof (service as ConnectorSetupService).getConfig === \"function\" &&\n typeof (service as ConnectorSetupService).persistConfig === \"function\" &&\n typeof (service as ConnectorSetupService).updateConfig === \"function\" &&\n typeof (service as ConnectorSetupService).registerEscalationChannel === \"function\" &&\n typeof (service as ConnectorSetupService).setOwnerContact === \"function\" &&\n typeof (service as ConnectorSetupService).getWorkspaceDir === \"function\" &&\n typeof (service as ConnectorSetupService).broadcastWs === \"function\"\n );\n}\n\nfunction getSetupService(runtime: IAgentRuntime): ConnectorSetupService | null {\n const service = runtime.getService(\"connector-setup\");\n return isConnectorSetupService(service) ? service : null;\n}\n\n/** Clean up disconnected / timed-out / errored sessions. */\nfunction cleanupStaleSessions(): void {\n for (const [id, session] of whatsappPairingSessions) {\n const status = session.getStatus();\n if (status === \"disconnected\" || status === \"timeout\" || status === \"error\") {\n session.stop();\n whatsappPairingSessions.delete(id);\n }\n }\n}\n\n// ── GET /api/whatsapp/webhook ──────────────────────────────────────────\nasync function handleWebhookVerify(\n req: RouteRequest,\n res: RouteResponse,\n runtime: IAgentRuntime\n): Promise<void> {\n const url = new URL(\n (req as unknown as { url?: string }).url ?? \"/\",\n `http://${(req as unknown as { headers?: Record<string, string> }).headers?.host ?? \"localhost\"}`\n );\n const mode = url.searchParams.get(\"hub.mode\") ?? \"\";\n const token = url.searchParams.get(\"hub.verify_token\") ?? \"\";\n const challenge = url.searchParams.get(\"hub.challenge\") ?? \"\";\n\n const service = runtime.getService(\"whatsapp\") as\n | {\n verifyWebhook?: (mode: string, token: string, challenge: string) => string | null;\n }\n | null\n | undefined;\n\n if (!service || typeof service.verifyWebhook !== \"function\") {\n res.status(503).json({ error: \"WhatsApp service unavailable\" });\n return;\n }\n\n const verifiedChallenge = service.verifyWebhook(mode, token, challenge);\n if (!verifiedChallenge) {\n res.status(403).json({ error: \"Webhook verification failed\" });\n return;\n }\n\n // Webhook verification must return the challenge as plain text\n res.status(200).json(verifiedChallenge);\n}\n\n// ── POST /api/whatsapp/webhook ─────────────────────────────────────────\nasync function handleWebhookEvent(\n req: RouteRequest,\n res: RouteResponse,\n runtime: IAgentRuntime\n): Promise<void> {\n const service = runtime.getService(\"whatsapp\") as\n | {\n handleWebhook?: (event: Record<string, unknown>) => Promise<void>;\n }\n | null\n | undefined;\n\n if (!service || typeof service.handleWebhook !== \"function\") {\n res.status(503).json({ error: \"WhatsApp service unavailable\" });\n return;\n }\n\n const body = req.body as Record<string, unknown> | null;\n if (!body) {\n res.status(400).json({ error: \"Missing request body\" });\n return;\n }\n\n await service.handleWebhook(body);\n\n // Meta expects a 200 with \"EVENT_RECEIVED\" text\n res.status(200).json(\"EVENT_RECEIVED\");\n}\n\n// ── POST /api/whatsapp/pair ────────────────────────────────────────────\nasync function handlePair(\n req: RouteRequest,\n res: RouteResponse,\n runtime: IAgentRuntime\n): Promise<void> {\n cleanupStaleSessions();\n\n const setupService = getSetupService(runtime);\n const body = req.body as { accountId?: string } | null;\n\n let accountId: string;\n try {\n accountId = sanitizeAccountId(\n body && typeof body.accountId === \"string\" && body.accountId.trim()\n ? body.accountId.trim()\n : \"default\"\n );\n } catch (err) {\n res.status(400).json({ error: (err as Error).message });\n return;\n }\n\n const isReplacing = whatsappPairingSessions.has(accountId);\n if (!isReplacing && whatsappPairingSessions.size >= MAX_PAIRING_SESSIONS) {\n res.status(429).json({\n error: `Too many concurrent pairing sessions (max ${MAX_PAIRING_SESSIONS})`,\n });\n return;\n }\n\n const workspaceDir = setupService?.getWorkspaceDir() ?? \".\";\n const authDir = path.join(workspaceDir, \"whatsapp-auth\", accountId);\n whatsappPairingSessions.get(accountId)?.stop();\n\n const session = new WhatsAppPairingSession({\n authDir,\n accountId,\n onEvent: (event: WhatsAppPairingEvent) => {\n setupService?.broadcastWs(event);\n\n if (event.status === \"connected\") {\n if (setupService) {\n setupService.updateConfig((config) => {\n if (!config.connectors) config.connectors = {};\n const connectors = config.connectors as Record<string, Record<string, unknown>>;\n connectors.whatsapp = {\n ...(connectors.whatsapp ?? {}),\n authDir,\n enabled: true,\n };\n });\n\n // Auto-populate owner contact so LifeOps can deliver reminders\n const phoneNumber = (event as unknown as Record<string, unknown>).phoneNumber as\n | string\n | undefined;\n setupService.setOwnerContact({\n source: \"whatsapp\",\n channelId: phoneNumber ?? undefined,\n });\n }\n }\n },\n });\n\n whatsappPairingSessions.set(accountId, session);\n\n try {\n await session.start();\n res.status(200).json({ ok: true, accountId, status: session.getStatus() });\n } catch (err) {\n res.status(500).json({ ok: false, error: String(err) });\n }\n}\n\n// ── GET /api/whatsapp/status ───────────────────────────────────────────\nasync function handleStatus(\n req: RouteRequest,\n res: RouteResponse,\n runtime: IAgentRuntime\n): Promise<void> {\n cleanupStaleSessions();\n\n const setupService = getSetupService(runtime);\n const url = new URL(\n (req as unknown as { url?: string }).url ?? \"/\",\n `http://${(req as unknown as { headers?: Record<string, string> }).headers?.host ?? \"localhost\"}`\n );\n\n let accountId: string;\n try {\n accountId = sanitizeAccountId(url.searchParams.get(\"accountId\") || \"default\");\n } catch (err) {\n res.status(400).json({ error: (err as Error).message });\n return;\n }\n\n const session = whatsappPairingSessions.get(accountId);\n const workspaceDir = setupService?.getWorkspaceDir() ?? \".\";\n\n let serviceConnected = false;\n let servicePhone: string | null = null;\n try {\n const waService = runtime.getService(\"whatsapp\");\n if (waService && typeof waService === \"object\") {\n const waState = waService as unknown as Record<string, unknown>;\n serviceConnected = Boolean(waState.connected);\n servicePhone = typeof waState.phoneNumber === \"string\" ? waState.phoneNumber : null;\n }\n } catch {\n /* service not yet registered */\n }\n\n res.status(200).json({\n accountId,\n status: session?.getStatus() ?? \"idle\",\n authExists: whatsappAuthExists(workspaceDir, accountId),\n serviceConnected,\n servicePhone,\n });\n}\n\n// ── POST /api/whatsapp/pair/stop ───────────────────────────────────────\nasync function handlePairStop(\n req: RouteRequest,\n res: RouteResponse,\n _runtime: IAgentRuntime\n): Promise<void> {\n const body = req.body as { accountId?: string } | null;\n\n let accountId: string;\n try {\n accountId = sanitizeAccountId(\n body && typeof body.accountId === \"string\" && body.accountId.trim()\n ? body.accountId.trim()\n : \"default\"\n );\n } catch (err) {\n res.status(400).json({ error: (err as Error).message });\n return;\n }\n\n const session = whatsappPairingSessions.get(accountId);\n if (session) {\n session.stop();\n whatsappPairingSessions.delete(accountId);\n }\n\n res.status(200).json({ ok: true, accountId, status: \"idle\" });\n}\n\n// ── POST /api/whatsapp/disconnect ──────────────────────────────────────\nasync function handleDisconnect(\n req: RouteRequest,\n res: RouteResponse,\n runtime: IAgentRuntime\n): Promise<void> {\n const setupService = getSetupService(runtime);\n const body = req.body as { accountId?: string } | null;\n\n let accountId: string;\n try {\n accountId = sanitizeAccountId(\n body && typeof body.accountId === \"string\" && body.accountId.trim()\n ? body.accountId.trim()\n : \"default\"\n );\n } catch (err) {\n res.status(400).json({ error: (err as Error).message });\n return;\n }\n\n const session = whatsappPairingSessions.get(accountId);\n if (session) {\n session.stop();\n whatsappPairingSessions.delete(accountId);\n }\n\n const workspaceDir = setupService?.getWorkspaceDir() ?? \".\";\n\n try {\n await whatsappLogout(workspaceDir, accountId);\n } catch (logoutErr) {\n console.warn(\n `[whatsapp] Logout failed for ${accountId}, deleting auth files directly:`,\n String(logoutErr)\n );\n const authDir = path.join(workspaceDir, \"whatsapp-auth\", accountId);\n try {\n fs.rmSync(authDir, { recursive: true, force: true });\n } catch {\n /* may not exist */\n }\n }\n\n if (setupService) {\n setupService.updateConfig((config) => {\n const connectors = config.connectors as Record<string, unknown> | undefined;\n if (connectors) {\n delete connectors.whatsapp;\n }\n });\n }\n\n res.status(200).json({ ok: true, accountId });\n}\n\n/**\n * Plugin routes for WhatsApp setup and webhooks.\n * Registered with `rawPath: true` to preserve legacy `/api/whatsapp/*` paths.\n */\nexport const whatsappSetupRoutes: Route[] = [\n {\n name: \"whatsapp-webhook-verify\",\n type: \"GET\",\n path: \"/api/whatsapp/webhook\",\n handler: handleWebhookVerify,\n rawPath: true,\n public: true, // Meta webhook verification must bypass auth\n },\n {\n name: \"whatsapp-webhook-event\",\n type: \"POST\",\n path: \"/api/whatsapp/webhook\",\n handler: handleWebhookEvent,\n rawPath: true,\n public: true, // Meta webhook delivery must bypass auth\n },\n {\n type: \"POST\",\n path: \"/api/whatsapp/pair\",\n handler: handlePair,\n rawPath: true,\n },\n {\n type: \"GET\",\n path: \"/api/whatsapp/status\",\n handler: handleStatus,\n rawPath: true,\n },\n {\n type: \"POST\",\n path: \"/api/whatsapp/pair/stop\",\n handler: handlePairStop,\n rawPath: true,\n },\n {\n type: \"POST\",\n path: \"/api/whatsapp/disconnect\",\n handler: handleDisconnect,\n rawPath: true,\n },\n];\n\n/**\n * Stop all active pairing sessions. Called during shutdown cleanup.\n */\nexport function stopAllPairingSessions(): void {\n for (const session of whatsappPairingSessions.values()) {\n try {\n session.stop();\n } catch {\n /* non-fatal */\n }\n }\n whatsappPairingSessions.clear();\n}\n",
|
|
17
|
+
"/**\n * WhatsApp pairing service — manages Baileys sessions for QR code authentication.\n *\n * This service is separate from the main WhatsApp plugin because the plugin\n * initializes during runtime startup (too late for interactive QR flow).\n * Once pairing succeeds, the auth state is persisted to disk so the plugin\n * can reconnect automatically on subsequent startups.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nconst LOG_PREFIX = \"[whatsapp-pairing]\";\n\n/** Validate accountId to prevent path traversal. Only allows alphanumeric, dash, underscore. */\nexport function sanitizeAccountId(raw: string): string {\n const cleaned = raw.replace(/[^a-zA-Z0-9_-]/g, \"\");\n if (!cleaned || cleaned !== raw) {\n throw new Error(\n `Invalid accountId: must only contain alphanumeric characters, dashes, and underscores`\n );\n }\n return cleaned;\n}\n\nexport type WhatsAppPairingStatus =\n | \"idle\"\n | \"initializing\"\n | \"waiting_for_qr\"\n | \"connected\"\n | \"disconnected\"\n | \"timeout\"\n | \"error\";\n\nexport interface WhatsAppPairingEvent {\n type: \"whatsapp-qr\" | \"whatsapp-status\";\n accountId: string;\n qrDataUrl?: string;\n expiresInMs?: number;\n status?: WhatsAppPairingStatus;\n phoneNumber?: string;\n error?: string;\n}\n\nexport interface WhatsAppPairingOptions {\n authDir: string;\n accountId: string;\n onEvent: (event: WhatsAppPairingEvent) => void;\n}\n\nexport class WhatsAppPairingSession {\n private socket: ReturnType<typeof import(\"@whiskeysockets/baileys\").default> | null = null;\n private status: WhatsAppPairingStatus = \"idle\";\n private options: WhatsAppPairingOptions;\n private qrAttempts = 0;\n private readonly MAX_QR_ATTEMPTS = 5;\n private restartTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(options: WhatsAppPairingOptions) {\n this.options = options;\n }\n\n async start(): Promise<void> {\n this.setStatus(\"initializing\");\n\n const baileys = await import(\"@whiskeysockets/baileys\");\n const makeWASocket = baileys.default;\n const { useMultiFileAuthState, fetchLatestBaileysVersion, DisconnectReason } = baileys;\n const QRCode = (await import(\"qrcode\")).default;\n const { Boom } = await import(\"@hapi/boom\");\n\n fs.mkdirSync(this.options.authDir, { recursive: true });\n\n const { state, saveCreds } = await useMultiFileAuthState(this.options.authDir);\n const { version } = await fetchLatestBaileysVersion();\n\n const pino = (await import(\"pino\")).default;\n const baileysLogger = pino({ level: \"silent\" });\n\n this.socket = makeWASocket({\n version,\n auth: state,\n logger: baileysLogger,\n printQRInTerminal: false,\n browser: [\"Eliza AI\", \"Desktop\", \"1.0.0\"],\n });\n\n this.socket.ev.on(\"creds.update\", saveCreds);\n\n this.socket.ev.on(\"connection.update\", async (update) => {\n const { connection, lastDisconnect, qr } = update;\n\n if (qr) {\n this.qrAttempts++;\n console.info(\n `${LOG_PREFIX} QR code received (attempt ${this.qrAttempts}/${this.MAX_QR_ATTEMPTS})`\n );\n if (this.qrAttempts > this.MAX_QR_ATTEMPTS) {\n this.setStatus(\"timeout\");\n this.stop();\n return;\n }\n\n try {\n const qrDataUrl = await QRCode.toDataURL(qr, {\n width: 256,\n margin: 2,\n color: { dark: \"#000000\", light: \"#ffffff\" },\n });\n\n this.setStatus(\"waiting_for_qr\");\n this.options.onEvent({\n type: \"whatsapp-qr\",\n accountId: this.options.accountId,\n qrDataUrl,\n expiresInMs: 20_000,\n });\n } catch {\n // QR generation failure — non-fatal, next QR attempt will retry.\n }\n }\n\n if (connection === \"close\") {\n const statusCode = (lastDisconnect?.error as InstanceType<typeof Boom>)?.output?.statusCode;\n console.info(\n `${LOG_PREFIX} Connection closed, statusCode=${statusCode}, status=${this.status}`\n );\n if (statusCode === DisconnectReason.loggedOut) {\n this.setStatus(\"disconnected\");\n } else if (\n statusCode === DisconnectReason.restartRequired ||\n statusCode === DisconnectReason.timedOut ||\n statusCode === DisconnectReason.connectionClosed ||\n statusCode === DisconnectReason.connectionReplaced\n ) {\n console.info(`${LOG_PREFIX} Restarting pairing after transient close...`);\n this.socket = null;\n this.qrAttempts = 0;\n this.restartTimer = setTimeout(() => {\n this.restartTimer = null;\n this.start().catch((err) => {\n console.error(`${LOG_PREFIX} Restart failed:`, err);\n this.setStatus(\"error\");\n this.options.onEvent({\n type: \"whatsapp-status\",\n accountId: this.options.accountId,\n status: \"error\",\n error: String(err),\n });\n });\n }, 3000);\n }\n } else if (connection === \"open\") {\n const phoneNumber = this.socket?.user?.id?.split(\":\")[0] ?? \"\";\n this.setStatus(\"connected\");\n this.options.onEvent({\n type: \"whatsapp-status\",\n accountId: this.options.accountId,\n status: \"connected\",\n phoneNumber,\n });\n }\n });\n }\n\n stop(): void {\n if (this.restartTimer) {\n clearTimeout(this.restartTimer);\n this.restartTimer = null;\n }\n try {\n this.socket?.end(undefined);\n } catch {\n // Ignore cleanup errors.\n }\n this.socket = null;\n }\n\n getStatus(): WhatsAppPairingStatus {\n return this.status;\n }\n\n private setStatus(status: WhatsAppPairingStatus): void {\n this.status = status;\n this.options.onEvent({\n type: \"whatsapp-status\",\n accountId: this.options.accountId,\n status,\n });\n }\n}\n\nexport function whatsappAuthExists(workspaceDir: string, accountId = \"default\"): boolean {\n const credsPath = path.join(workspaceDir, \"whatsapp-auth\", accountId, \"creds.json\");\n return fs.existsSync(credsPath);\n}\n\nexport async function whatsappLogout(workspaceDir: string, accountId = \"default\"): Promise<void> {\n const authDir = path.join(workspaceDir, \"whatsapp-auth\", accountId);\n const credsPath = path.join(authDir, \"creds.json\");\n\n if (fs.existsSync(credsPath)) {\n try {\n const baileys = await import(\"@whiskeysockets/baileys\");\n const makeWASocket = baileys.default;\n const { useMultiFileAuthState, fetchLatestBaileysVersion } = baileys;\n const pino = (await import(\"pino\")).default;\n const logger = pino({ level: \"silent\" });\n\n const { state } = await useMultiFileAuthState(authDir);\n const { version } = await fetchLatestBaileysVersion();\n\n const sock = makeWASocket({\n version,\n auth: state,\n logger,\n printQRInTerminal: false,\n });\n\n await new Promise<void>((resolve) => {\n let settled = false;\n const finish = () => {\n if (settled) return;\n settled = true;\n clearTimeout(timeout);\n try {\n sock.ev.removeAllListeners(\"connection.update\");\n } catch {\n /* */\n }\n try {\n sock.end(undefined);\n } catch {\n /* */\n }\n resolve();\n };\n\n const timeout = setTimeout(finish, 10_000);\n\n sock.ev.on(\"connection.update\", async (update) => {\n if (update.connection === \"open\") {\n try {\n await sock.logout();\n } catch {\n // May fail if already logged out remotely.\n }\n finish();\n } else if (update.connection === \"close\") {\n finish();\n }\n });\n });\n } catch {\n // If Baileys can't connect, just delete files anyway.\n }\n }\n\n fs.rmSync(authDir, { recursive: true, force: true });\n}\n",
|
|
18
|
+
"import type { WhatsAppConfig } from \"../types\";\n\nexport function detectAuthMethod(\n config: WhatsAppConfig | Record<string, unknown>\n): \"baileys\" | \"cloudapi\" {\n const explicitMethod = (config as { authMethod?: unknown }).authMethod;\n if (explicitMethod !== undefined) {\n if (explicitMethod === \"baileys\" || explicitMethod === \"cloudapi\") {\n return explicitMethod;\n }\n throw new Error(\n `Invalid authMethod: \"${String(explicitMethod)}\". Must be either \"baileys\" or \"cloudapi\".`\n );\n }\n\n if (\"authDir\" in config && config.authDir) {\n return \"baileys\";\n }\n\n if (\"accessToken\" in config && \"phoneNumberId\" in config) {\n return \"cloudapi\";\n }\n\n throw new Error(\n \"Cannot detect auth method. Provide either authDir (Baileys) or accessToken + phoneNumberId (Cloud API).\"\n );\n}\n",
|
|
19
|
+
"import { WhatsAppClient } from \"../client\";\nimport type { BaileysConfig, CloudAPIConfig, WhatsAppConfig } from \"../types\";\nimport { detectAuthMethod } from \"../utils/config-detector\";\nimport { BaileysClient } from \"./baileys-client\";\nimport type { IWhatsAppClient } from \"./interface\";\n\nexport const ClientFactory = {\n create(config: WhatsAppConfig): IWhatsAppClient {\n const authMethod = detectAuthMethod(config);\n if (authMethod === \"baileys\") {\n return new BaileysClient(config as BaileysConfig);\n }\n return new WhatsAppClient(config as CloudAPIConfig);\n },\n};\n",
|
|
20
|
+
"export type WhatsAppConfig = CloudAPIConfig | BaileysConfig;\n\nexport interface CloudAPIConfig {\n authMethod?: \"cloudapi\";\n accessToken: string;\n phoneNumberId: string;\n webhookVerifyToken?: string;\n businessAccountId?: string;\n apiVersion?: string;\n}\n\nexport interface BaileysConfig {\n authMethod?: \"baileys\";\n authDir: string;\n printQRInTerminal?: boolean;\n sessionPath?: string;\n}\n\n/**\n * Message types supported by WhatsApp Cloud API.\n */\nexport type WhatsAppMessageType =\n | \"text\"\n | \"template\"\n | \"image\"\n | \"audio\"\n | \"video\"\n | \"document\"\n | \"sticker\"\n | \"location\"\n | \"contacts\"\n | \"interactive\"\n | \"reaction\";\n\nexport interface WhatsAppMessage {\n type: WhatsAppMessageType;\n to: string;\n content:\n | string\n | WhatsAppTemplate\n | WhatsAppMediaMessage\n | WhatsAppInteractiveMessage\n | WhatsAppReactionMessage\n | WhatsAppLocationMessage;\n replyToMessageId?: string;\n}\n\nexport interface WhatsAppTemplate {\n name: string;\n language: {\n code: string;\n };\n components?: Array<{\n type: string;\n parameters: Array<{\n type: string;\n text?: string;\n image?: { link: string };\n document?: { link: string; filename?: string };\n video?: { link: string };\n }>;\n }>;\n}\n\n/**\n * Media message content.\n */\nexport interface WhatsAppMediaMessage {\n link?: string;\n id?: string;\n caption?: string;\n filename?: string;\n mimeType?: string;\n}\n\n/**\n * Reaction message content.\n */\nexport interface WhatsAppReactionMessage {\n messageId: string;\n emoji: string;\n}\n\n/**\n * Location message content.\n */\nexport interface WhatsAppLocationMessage {\n latitude: number;\n longitude: number;\n name?: string;\n address?: string;\n}\n\n/**\n * Interactive message types.\n */\nexport type InteractiveMessageType = \"button\" | \"list\" | \"product\" | \"product_list\" | \"flow\";\n\n/**\n * Interactive message content.\n */\nexport interface WhatsAppInteractiveMessage {\n type: InteractiveMessageType;\n header?: {\n type: \"text\" | \"image\" | \"video\" | \"document\";\n text?: string;\n image?: { link: string };\n video?: { link: string };\n document?: { link: string; filename?: string };\n };\n body: {\n text: string;\n };\n footer?: {\n text: string;\n };\n action: WhatsAppInteractiveAction;\n}\n\n/**\n * Interactive action based on message type.\n */\nexport type WhatsAppInteractiveAction =\n | WhatsAppButtonAction\n | WhatsAppListAction\n | WhatsAppFlowAction;\n\n/**\n * Button action for interactive messages.\n */\nexport interface WhatsAppButtonAction {\n buttons: Array<{\n type: \"reply\";\n reply: {\n id: string;\n title: string;\n };\n }>;\n}\n\n/**\n * List action for interactive messages.\n */\nexport interface WhatsAppListAction {\n button: string;\n sections: Array<{\n title?: string;\n rows: Array<{\n id: string;\n title: string;\n description?: string;\n }>;\n }>;\n}\n\n/**\n * Flow action for interactive messages.\n */\nexport interface WhatsAppFlowAction {\n name: \"flow\";\n parameters: {\n flow_message_version: string;\n flow_token: string;\n flow_id: string;\n flow_cta: string;\n flow_action: \"navigate\" | \"data_exchange\";\n flow_action_payload?: {\n screen: string;\n data?: Record<string, unknown>;\n };\n };\n}\n\nexport interface WhatsAppIncomingMessage {\n from: string;\n id: string;\n timestamp: string;\n text?: {\n body: string;\n };\n image?: {\n caption?: string;\n mime_type: string;\n sha256: string;\n id: string;\n };\n video?: {\n caption?: string;\n mime_type: string;\n sha256: string;\n id: string;\n };\n audio?: {\n mime_type: string;\n sha256: string;\n id: string;\n voice?: boolean;\n };\n document?: {\n caption?: string;\n filename: string;\n mime_type: string;\n sha256: string;\n id: string;\n };\n sticker?: {\n mime_type: string;\n sha256: string;\n id: string;\n animated?: boolean;\n };\n location?: {\n latitude: number;\n longitude: number;\n name?: string;\n address?: string;\n };\n contacts?: Array<{\n name: {\n formatted_name: string;\n first_name?: string;\n last_name?: string;\n };\n phones?: Array<{\n phone: string;\n type: string;\n }>;\n }>;\n interactive?: {\n type: \"button_reply\" | \"list_reply\" | \"nfm_reply\";\n button_reply?: {\n id: string;\n title: string;\n };\n list_reply?: {\n id: string;\n title: string;\n description?: string;\n };\n nfm_reply?: {\n response_json: string;\n body: string;\n name: string;\n };\n };\n reaction?: {\n message_id: string;\n emoji: string;\n };\n context?: {\n from: string;\n id: string;\n referred_product?: {\n catalog_id: string;\n product_retailer_id: string;\n };\n };\n type: string;\n}\n\nexport interface WhatsAppStatusUpdate {\n id: string;\n status: \"sent\" | \"delivered\" | \"read\" | \"failed\";\n timestamp: string;\n recipient_id: string;\n conversation?: {\n id: string;\n origin?: {\n type: string;\n };\n expiration_timestamp?: string;\n };\n pricing?: {\n billable: boolean;\n pricing_model: string;\n category: string;\n };\n errors?: Array<{\n code: number;\n title: string;\n message?: string;\n error_data?: {\n details: string;\n };\n }>;\n}\n\nexport interface WhatsAppWebhookEvent {\n object: string;\n entry: Array<{\n id: string;\n changes: Array<{\n value: {\n messaging_product: string;\n metadata: {\n display_phone_number: string;\n phone_number_id: string;\n };\n statuses?: WhatsAppStatusUpdate[];\n messages?: WhatsAppIncomingMessage[];\n contacts?: Array<{\n profile: {\n name: string;\n };\n wa_id: string;\n }>;\n errors?: Array<{\n code: number;\n title: string;\n message?: string;\n error_data?: {\n details: string;\n };\n }>;\n };\n field: string;\n }>;\n }>;\n}\n\nexport interface WhatsAppMessageResponse {\n messaging_product: string;\n contacts: Array<{\n input: string;\n wa_id: string;\n }>;\n messages: Array<{\n id: string;\n message_status?: string;\n }>;\n}\n\nexport interface QRCodeData {\n terminal: string;\n dataURL: string;\n raw: string;\n}\n\nexport type ConnectionStatus = \"connecting\" | \"open\" | \"close\";\n\nexport interface NormalizedMessage {\n id: string;\n from: string;\n timestamp: number;\n type: \"text\" | \"image\" | \"audio\" | \"video\" | \"document\";\n content: string;\n chatId?: string;\n senderId?: string;\n replyToId?: string;\n}\n\n/**\n * Send reaction parameters.\n */\nexport interface SendReactionParams {\n to: string;\n messageId: string;\n emoji: string;\n}\n\n/**\n * Send reaction result.\n */\nexport interface SendReactionResult {\n success: boolean;\n messageId?: string;\n error?: string;\n}\n\n/**\n * WhatsApp event types.\n */\nexport enum WhatsAppEventType {\n MESSAGE_RECEIVED = \"WHATSAPP_MESSAGE_RECEIVED\",\n MESSAGE_SENT = \"WHATSAPP_MESSAGE_SENT\",\n MESSAGE_DELIVERED = \"WHATSAPP_MESSAGE_DELIVERED\",\n MESSAGE_READ = \"WHATSAPP_MESSAGE_READ\",\n MESSAGE_FAILED = \"WHATSAPP_MESSAGE_FAILED\",\n REACTION_RECEIVED = \"WHATSAPP_REACTION_RECEIVED\",\n REACTION_SENT = \"WHATSAPP_REACTION_SENT\",\n INTERACTIVE_REPLY = \"WHATSAPP_INTERACTIVE_REPLY\",\n WEBHOOK_VERIFIED = \"WHATSAPP_WEBHOOK_VERIFIED\",\n}\n\n/**\n * Common WhatsApp reaction emojis.\n */\nexport const WHATSAPP_REACTIONS = {\n THUMBS_UP: \"👍\",\n THUMBS_DOWN: \"👎\",\n HEART: \"❤️\",\n LAUGHING: \"😂\",\n SURPRISED: \"😮\",\n SAD: \"😢\",\n PRAYING: \"🙏\",\n CLAPPING: \"👏\",\n FIRE: \"🔥\",\n CELEBRATION: \"🎉\",\n} as const;\n\nexport type WhatsAppReactionEmoji = (typeof WHATSAPP_REACTIONS)[keyof typeof WHATSAPP_REACTIONS];\n",
|
|
21
|
+
"import type { Plugin } from \"@elizaos/core\";\nimport { sendMessageAction, sendReactionAction } from \"./actions\";\nimport { WhatsAppConnectorService } from \"./runtime-service\";\nimport { whatsappSetupRoutes } from \"./setup-routes\";\n\nconst whatsappPlugin: Plugin = {\n name: \"whatsapp\",\n description: \"WhatsApp integration for ElizaOS (Cloud API + Baileys)\",\n actions: [sendMessageAction, sendReactionAction],\n services: [WhatsAppConnectorService],\n routes: whatsappSetupRoutes,\n};\n\nexport default whatsappPlugin;\n\n// Account management exports\nexport {\n checkWhatsAppUserAccess,\n DEFAULT_ACCOUNT_ID,\n isMultiAccountEnabled,\n isWhatsAppMentionRequired,\n isWhatsAppUserAllowed,\n listEnabledWhatsAppAccounts,\n listWhatsAppAccountIds,\n normalizeAccountId,\n type ResolvedWhatsAppAccount,\n resolveDefaultWhatsAppAccountId,\n resolveWhatsAppAccount,\n resolveWhatsAppGroupConfig,\n resolveWhatsAppToken,\n type WhatsAppAccessCheckResult,\n type WhatsAppAccountRuntimeConfig,\n type WhatsAppGroupRuntimeConfig,\n type WhatsAppMultiAccountConfig,\n type WhatsAppTokenResolution,\n type WhatsAppTokenSource,\n} from \"./accounts\";\nexport { ClientFactory } from \"./clients/factory\";\n// Channel configuration types\nexport type {\n WhatsAppAccountConfig,\n WhatsAppAckReactionConfig,\n WhatsAppActionConfig,\n WhatsAppChannelConfig,\n WhatsAppGroupConfig,\n} from \"./config\";\n// Normalization and utility exports\nexport {\n buildWhatsAppUserJid,\n type ChunkWhatsAppTextOpts,\n chunkWhatsAppText,\n formatWhatsAppId,\n formatWhatsAppPhoneNumber,\n getWhatsAppChatType,\n isValidWhatsAppNumber,\n isWhatsAppGroup,\n isWhatsAppGroupJid,\n isWhatsAppUserTarget,\n normalizeE164,\n normalizeWhatsAppTarget,\n resolveWhatsAppSystemLocation,\n truncateText,\n WHATSAPP_TEXT_CHUNK_LIMIT,\n} from \"./normalize\";\nexport {\n sanitizeAccountId as sanitizeWhatsAppAccountId,\n type WhatsAppPairingEvent,\n type WhatsAppPairingOptions,\n WhatsAppPairingSession,\n type WhatsAppPairingStatus,\n whatsappAuthExists,\n whatsappLogout,\n} from \"./pairing-service\";\nexport { WhatsAppConnectorService } from \"./runtime-service\";\nexport { stopAllPairingSessions, whatsappSetupRoutes } from \"./setup-routes\";\nexport * from \"./types\";\n"
|
|
22
|
+
],
|
|
23
|
+
"mappings": "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",
|
|
24
|
+
"debugId": "60D99E2A9F2E72FB64756E2164756E21",
|
|
25
|
+
"names": []
|
|
26
|
+
}
|