@elizaos/plugin-twilio 2.0.0-alpha.1
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/LICENSE +21 -0
- package/README.md +343 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +1650 -0
- package/dist/index.js.map +1 -0
- package/package.json +103 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/actions/sendSms.ts","../src/constants.ts","../src/utils.ts","../src/actions/makeCall.ts","../src/actions/sendMms.ts","../src/providers/conversationHistory.ts","../src/providers/callState.ts","../src/service.ts","../src/types.ts","../src/tests.ts"],"sourcesContent":["import { type IAgentRuntime, type Plugin, logger } from \"@elizaos/core\";\nimport sendSmsAction from \"./actions/sendSms\";\nimport makeCallAction from \"./actions/makeCall\";\nimport sendMmsAction from \"./actions/sendMms\";\nimport conversationHistoryProvider from \"./providers/conversationHistory\";\nimport callStateProvider from \"./providers/callState\";\nimport { TwilioService } from \"./service\";\nimport { TwilioTestSuite } from \"./tests\";\n\nconst twilioPlugin: Plugin = {\n name: \"twilio\",\n description:\n \"Twilio plugin for bidirectional voice and text messaging integration\",\n services: [TwilioService],\n actions: [sendSmsAction, makeCallAction, sendMmsAction],\n providers: [conversationHistoryProvider, callStateProvider],\n tests: [new TwilioTestSuite()],\n init: async (config: Record<string, string>, runtime: IAgentRuntime) => {\n const accountSid = runtime.getSetting(\"TWILIO_ACCOUNT_SID\") as string;\n const authToken = runtime.getSetting(\"TWILIO_AUTH_TOKEN\") as string;\n const phoneNumber = runtime.getSetting(\"TWILIO_PHONE_NUMBER\") as string;\n const webhookUrl = runtime.getSetting(\"TWILIO_WEBHOOK_URL\") as string;\n\n if (!accountSid || accountSid.trim() === \"\") {\n logger.warn(\n \"Twilio Account SID not provided - Twilio plugin is loaded but will not be functional\",\n );\n logger.warn(\n \"To enable Twilio functionality, please provide TWILIO_ACCOUNT_SID in your .env file\",\n );\n return;\n }\n\n if (!authToken || authToken.trim() === \"\") {\n logger.warn(\n \"Twilio Auth Token not provided - Twilio plugin is loaded but will not be functional\",\n );\n logger.warn(\n \"To enable Twilio functionality, please provide TWILIO_AUTH_TOKEN in your .env file\",\n );\n return;\n }\n\n if (!phoneNumber || phoneNumber.trim() === \"\") {\n logger.warn(\n \"Twilio Phone Number not provided - Twilio plugin is loaded but will not be functional\",\n );\n logger.warn(\n \"To enable Twilio functionality, please provide TWILIO_PHONE_NUMBER in your .env file\",\n );\n return;\n }\n\n if (!webhookUrl || webhookUrl.trim() === \"\") {\n logger.warn(\n \"Twilio Webhook URL not provided - Twilio will not be able to receive incoming messages or calls\",\n );\n logger.warn(\n \"To enable incoming communication, please provide TWILIO_WEBHOOK_URL in your .env file\",\n );\n }\n\n logger.info(\"Twilio plugin initialized successfully\");\n },\n};\n\nexport default twilioPlugin;\n","import {\n Action,\n type IAgentRuntime,\n type Memory,\n type State,\n type HandlerCallback,\n logger,\n} from \"@elizaos/core\";\nimport { SendSmsSchema } from \"../types\";\nimport { TwilioService } from \"../service\";\nimport { TWILIO_SERVICE_NAME } from \"../constants\";\nimport {\n validateMessagingAddress,\n chunkTextForSms,\n extractPhoneNumber,\n} from \"../utils\";\n\nconst sendSmsAction: Action = {\n name: \"SEND_SMS\",\n description: \"Send an SMS message to a phone number via Twilio\",\n validate: async (runtime: IAgentRuntime, message: Memory, state?: State) => {\n // Check if Twilio service is available\n const twilioService = runtime.getService(TWILIO_SERVICE_NAME);\n if (!twilioService) {\n logger.error(\"Twilio service not found\");\n return false;\n }\n\n // Check if message contains phone number and SMS intent\n const text = message.content.text || \"\";\n const phoneNumber = extractPhoneNumber(text);\n const hasSmsIntent =\n text.toLowerCase().includes(\"sms\") ||\n text.toLowerCase().includes(\"text\") ||\n text.toLowerCase().includes(\"message\");\n\n return !!phoneNumber && hasSmsIntent;\n },\n handler: async (\n runtime: IAgentRuntime,\n message: Memory,\n state?: State,\n options?: any,\n callback?: HandlerCallback,\n ) => {\n try {\n const twilioService = runtime.getService(\n TWILIO_SERVICE_NAME,\n ) as unknown as TwilioService;\n if (!twilioService) {\n throw new Error(\"Twilio service not available\");\n }\n\n const text = message.content.text || \"\";\n\n // Extract phone number from the message\n const phoneNumber = extractPhoneNumber(text);\n if (!phoneNumber) {\n throw new Error(\"No phone number found in message\");\n }\n\n // Extract the message content\n // Remove the phone number and command keywords from the text\n let messageContent = text\n .replace(phoneNumber, \"\")\n .replace(\n /^(send\\s*(an?\\s*)?(sms|text|message)\\s*(to\\s*)?|text\\s+)/gi,\n \"\",\n )\n .replace(/\\b(saying|with\\s*(the\\s*)?(message|text))\\b/gi, \"\")\n .trim();\n\n // Remove quotes if present\n messageContent = messageContent.replace(/^[\"']|[\"']$/g, \"\").trim();\n\n // If no message content extracted, use a default\n if (!messageContent) {\n messageContent = \"Hello from your AI assistant!\";\n }\n\n // Validate phone number\n if (!validateMessagingAddress(phoneNumber)) {\n throw new Error(\"Invalid phone number format\");\n }\n\n // Handle long messages by chunking\n const messageChunks = chunkTextForSms(messageContent);\n\n // Send each chunk\n for (const chunk of messageChunks) {\n await twilioService.sendSms(phoneNumber, chunk);\n logger.info(`SMS sent to ${phoneNumber}: ${chunk.substring(0, 50)}...`);\n }\n\n if (callback) {\n callback({\n text: `SMS message sent successfully to ${phoneNumber}`,\n success: true,\n });\n }\n } catch (error) {\n logger.error({ error: String(error) }, \"Error sending SMS\");\n if (callback) {\n callback({\n text: `Failed to send SMS: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n success: false,\n });\n }\n }\n },\n examples: [\n [\n {\n name: \"user\",\n content: {\n text: \"Send an SMS to +18885551234 saying 'Hello from AI assistant!'\",\n },\n },\n {\n name: \"assistant\",\n content: {\n text: \"I'll send that SMS message for you.\",\n action: \"SEND_SMS\",\n },\n },\n ],\n [\n {\n name: \"user\",\n content: {\n text: \"Text +15555551234 with the message 'Meeting confirmed for 3pm tomorrow'\",\n },\n },\n {\n name: \"assistant\",\n content: {\n text: \"Sending the meeting confirmation SMS now.\",\n action: \"SEND_SMS\",\n },\n },\n ],\n ],\n similes: [\n \"send sms\",\n \"send text\",\n \"text message\",\n \"sms to\",\n \"text to\",\n \"message phone\",\n ],\n};\n\nexport default sendSmsAction;\n","export const MESSAGE_CONSTANTS = {\n MAX_MESSAGES: 10,\n RECENT_MESSAGE_COUNT: 3,\n CHAT_HISTORY_COUNT: 5,\n INTEREST_DECAY_TIME: 5 * 60 * 1000, // 5 minutes\n PARTIAL_INTEREST_DECAY: 3 * 60 * 1000, // 3 minutes\n DEFAULT_SIMILARITY_THRESHOLD: 0.3,\n DEFAULT_SIMILARITY_THRESHOLD_FOLLOW_UPS: 0.2,\n} as const;\n\nexport const MESSAGE_LENGTH_THRESHOLDS = {\n LOSE_INTEREST: 100,\n SHORT_MESSAGE: 10,\n VERY_SHORT_MESSAGE: 2,\n IGNORE_RESPONSE: 4,\n} as const;\n\n/**\n * An array of words or phrases that indicate losing interest or annoyance.\n * @type {readonly [\"shut up\", \"stop\", \"please shut up\", \"shut up please\", \"dont talk\", \"silence\", \"stop talking\", \"be quiet\", \"hush\", \"wtf\", \"chill\", \"stfu\", \"stupid bot\", \"dumb bot\", \"stop responding\", \"god damn it\", \"god damn\", \"goddamnit\", \"can you not\", \"can you stop\", \"be quiet\", \"hate you\", \"hate this\", \"fuck up\"]}\n */\nexport const LOSE_INTEREST_WORDS = [\n \"shut up\",\n \"stop\",\n \"please shut up\",\n \"shut up please\",\n \"dont talk\",\n \"silence\",\n \"stop talking\",\n \"be quiet\",\n \"hush\",\n \"wtf\",\n \"chill\",\n \"stfu\",\n \"stupid bot\",\n \"dumb bot\",\n \"stop responding\",\n \"god damn it\",\n \"god damn\",\n \"goddamnit\",\n \"can you not\",\n \"can you stop\",\n \"be quiet\",\n \"hate you\",\n \"hate this\",\n \"fuck up\",\n] as const;\n\nexport const IGNORE_RESPONSE_WORDS = [\n \"lol\",\n \"nm\",\n \"uh\",\n \"wtf\",\n \"stfu\",\n \"dumb\",\n \"jfc\",\n \"omg\",\n] as const;\n\nexport const TWILIO_SERVICE_NAME = \"twilio\";\n\n// Twilio constants\nexport const TWILIO_CONSTANTS = {\n // Message limits\n SMS_MAX_LENGTH: 1600,\n MMS_MAX_MEDIA_SIZE: 5242880, // 5MB\n MMS_MAX_MEDIA_COUNT: 10,\n\n // Voice constants\n DEFAULT_VOICE: \"alice\",\n DEFAULT_LANGUAGE: \"en-US\",\n VOICE_STREAM_TIMEOUT: 300000, // 5 minutes\n\n // API endpoints\n API_BASE_URL: \"https://api.twilio.com\",\n\n // Webhook paths\n WEBHOOK_PATHS: {\n SMS: \"/webhooks/twilio/sms\",\n VOICE: \"/webhooks/twilio/voice\",\n STATUS: \"/webhooks/twilio/status\",\n VOICE_STREAM: \"/webhooks/twilio/voice-stream\",\n },\n\n // TwiML templates\n TWIML: {\n DEFAULT_VOICE_RESPONSE: `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Response>\n <Say voice=\"alice\">Hello from Eliza AI assistant. How can I help you today?</Say>\n <Pause length=\"1\"/>\n</Response>`,\n\n STREAM_RESPONSE: (\n streamUrl: string,\n ) => `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Response>\n <Start>\n <Stream url=\"${streamUrl}\" />\n </Start>\n <Say>Please wait while I connect you to the AI assistant.</Say>\n <Pause length=\"60\"/>\n</Response>`,\n },\n\n // Rate limits\n RATE_LIMITS: {\n SMS_PER_SECOND: 1,\n CALLS_PER_SECOND: 1,\n WEBHOOK_TIMEOUT: 15000, // 15 seconds\n },\n\n // Cache TTL\n CACHE_TTL: {\n CONVERSATION: 3600, // 1 hour\n MEDIA: 86400, // 24 hours\n CALL_STATE: 1800, // 30 minutes\n },\n} as const;\n\n// Audio formats for voice\nexport const AUDIO_FORMATS = {\n INPUT: \"audio/x-mulaw\",\n OUTPUT: \"audio/x-mulaw\",\n SAMPLE_RATE: 8000,\n CHANNELS: 1,\n} as const;\n\n// Supported media types\nexport const SUPPORTED_MEDIA_TYPES = [\n \"image/jpeg\",\n \"image/png\",\n \"image/gif\",\n \"audio/mpeg\",\n \"audio/ogg\",\n \"audio/wav\",\n \"video/mp4\",\n] as const;\n\n// Error messages\nexport const ERROR_MESSAGES = {\n INVALID_PHONE_NUMBER:\n \"Invalid phone number format. Please use E.164 format (e.g., +18885551212)\",\n MISSING_CREDENTIALS: \"Twilio credentials not configured\",\n WEBHOOK_VALIDATION_FAILED: \"Failed to validate Twilio webhook signature\",\n RATE_LIMIT_EXCEEDED: \"Rate limit exceeded. Please try again later.\",\n MEDIA_TOO_LARGE: \"Media file too large. Maximum size is 5MB\",\n UNSUPPORTED_MEDIA_TYPE: \"Unsupported media type\",\n} as const;\n","import { logger } from \"@elizaos/core\";\nimport { TWILIO_CONSTANTS } from \"./constants\";\n\n/**\n * Validates a phone number in E.164 format\n * @param phoneNumber The phone number to validate\n * @returns true if valid, false otherwise\n */\nexport function validatePhoneNumber(phoneNumber: string): boolean {\n // E.164 format: +[country code][area code][phone number]\n // Example: +18885551212\n const e164Regex = /^\\+[1-9]\\d{1,14}$/;\n return e164Regex.test(phoneNumber);\n}\n\n/**\n * Validates a messaging address for SMS/WhatsApp.\n * Accepts E.164 or WhatsApp-prefixed addresses.\n * @param address The address to validate\n * @returns true if valid, false otherwise\n */\nexport function validateMessagingAddress(address: string): boolean {\n const messagingRegex = /^(whatsapp:)?\\+[1-9]\\d{1,14}$/;\n return messagingRegex.test(address);\n}\n\n/**\n * Determine if an address is a WhatsApp address.\n */\nexport function isWhatsAppAddress(address: string): boolean {\n return address.startsWith(\"whatsapp:\");\n}\n\n/**\n * Remove WhatsApp prefix if present.\n */\nexport function stripWhatsAppPrefix(address: string): string {\n return isWhatsAppAddress(address)\n ? address.slice(\"whatsapp:\".length)\n : address;\n}\n\n/**\n * Format a messaging address, preserving WhatsApp prefix if provided.\n */\nexport function formatMessagingAddress(\n address: string,\n defaultCountryCode: string = \"+1\",\n): string | null {\n const hasPrefix = isWhatsAppAddress(address);\n const formatted = formatPhoneNumber(\n stripWhatsAppPrefix(address),\n defaultCountryCode,\n );\n if (!formatted) {\n return null;\n }\n return hasPrefix ? `whatsapp:${formatted}` : formatted;\n}\n\n/**\n * Formats a phone number to E.164 format if possible\n * @param phoneNumber The phone number to format\n * @param defaultCountryCode The default country code to use if not provided\n * @returns The formatted phone number or null if invalid\n */\nexport function formatPhoneNumber(\n phoneNumber: string,\n defaultCountryCode: string = \"+1\",\n): string | null {\n // Remove all non-numeric characters except +\n let cleaned = phoneNumber.replace(/[^\\d+]/g, \"\");\n\n // If it doesn't start with +, add the default country code\n if (!cleaned.startsWith(\"+\")) {\n // If it starts with the country code without +, add the +\n if (cleaned.startsWith(\"1\") && cleaned.length === 11) {\n cleaned = \"+\" + cleaned;\n } else if (cleaned.length === 10) {\n // Assume it's a US number without country code\n cleaned = defaultCountryCode + cleaned;\n } else {\n return null;\n }\n }\n\n // Validate the formatted number\n if (validatePhoneNumber(cleaned)) {\n return cleaned;\n }\n\n return null;\n}\n\n/**\n * Generates TwiML for various scenarios\n */\nexport const generateTwiML = {\n /**\n * Generates TwiML for a simple voice response\n * @param message The message to say\n * @param voice The voice to use (default: alice)\n * @returns TwiML string\n */\n say: (message: string, voice: string = \"alice\"): string => {\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Response>\n <Say voice=\"${voice}\">${escapeXml(message)}</Say>\n</Response>`;\n },\n\n /**\n * Generates TwiML for gathering input\n * @param prompt The prompt message\n * @param options Gather options\n * @returns TwiML string\n */\n gather: (\n prompt: string,\n options: {\n numDigits?: number;\n timeout?: number;\n action?: string;\n method?: string;\n } = {},\n ): string => {\n const {\n numDigits = 1,\n timeout = 5,\n action = \"\",\n method = \"POST\",\n } = options;\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Response>\n <Gather numDigits=\"${numDigits}\" timeout=\"${timeout}\" action=\"${action}\" method=\"${method}\">\n <Say>${escapeXml(prompt)}</Say>\n </Gather>\n</Response>`;\n },\n\n /**\n * Generates TwiML for starting a media stream\n * @param streamUrl The WebSocket URL for streaming\n * @param customParameters Optional custom parameters\n * @returns TwiML string\n */\n stream: (\n streamUrl: string,\n customParameters?: Record<string, string>,\n ): string => {\n let params = \"\";\n if (customParameters) {\n params = Object.entries(customParameters)\n .map(\n ([key, value]) =>\n `<Parameter name=\"${key}\" value=\"${escapeXml(value)}\" />`,\n )\n .join(\"\\n \");\n }\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Response>\n <Start>\n <Stream url=\"${streamUrl}\">\n ${params}\n </Stream>\n </Start>\n <Say>Please wait while I connect you to the AI assistant.</Say>\n <Pause length=\"60\"/>\n</Response>`;\n },\n\n /**\n * Generates TwiML for recording a call\n * @param options Recording options\n * @returns TwiML string\n */\n record: (\n options: {\n maxLength?: number;\n timeout?: number;\n transcribe?: boolean;\n action?: string;\n } = {},\n ): string => {\n const {\n maxLength = 3600,\n timeout = 5,\n transcribe = false,\n action = \"\",\n } = options;\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Response>\n <Record maxLength=\"${maxLength}\" timeout=\"${timeout}\" transcribe=\"${transcribe}\" action=\"${action}\" />\n</Response>`;\n },\n\n /**\n * Generates TwiML to hang up\n * @returns TwiML string\n */\n hangup: (): string => {\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Response>\n <Hangup />\n</Response>`;\n },\n};\n\n/**\n * Escapes XML special characters\n * @param str The string to escape\n * @returns The escaped string\n */\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\n/**\n * Parses media URLs from webhook data\n * @param webhookData The webhook data object\n * @param numMedia The number of media items\n * @returns Array of media objects\n */\nexport function parseMediaFromWebhook(\n webhookData: any,\n numMedia: number,\n): Array<{\n url: string;\n contentType: string;\n sid: string;\n}> {\n const media: Array<{\n url: string;\n contentType: string;\n sid: string;\n }> = [];\n\n for (let i = 0; i < numMedia; i++) {\n const url = webhookData[`MediaUrl${i}`];\n const contentType = webhookData[`MediaContentType${i}`];\n\n if (url) {\n media.push({\n url,\n contentType: contentType || \"unknown\",\n sid: `media_${i}`,\n });\n }\n }\n\n return media;\n}\n\n/**\n * Extracts phone number from various formats\n * @param input The input string that may contain a phone number\n * @returns The extracted phone number or null\n */\nexport function extractPhoneNumber(input: string): string | null {\n const wantsWhatsApp = input.toLowerCase().includes(\"whatsapp:\");\n\n // Try to find a phone number pattern\n const patterns = [\n /\\+\\d{1,15}/, // E.164 format\n /\\(\\d{3}\\)\\s*\\d{3}-\\d{4}/, // (555) 555-5555\n /\\d{3}-\\d{3}-\\d{4}/, // 555-555-5555\n /\\d{10,15}/, // Just digits\n ];\n\n for (const pattern of patterns) {\n const match = input.match(pattern);\n if (match) {\n const formatted = formatPhoneNumber(match[0]);\n if (formatted) {\n return wantsWhatsApp ? `whatsapp:${formatted}` : formatted;\n }\n }\n }\n\n return null;\n}\n\n/**\n * Validates webhook signature from Twilio\n * @param authToken The auth token\n * @param signature The X-Twilio-Signature header\n * @param url The full URL of the webhook\n * @param params The request parameters\n * @returns true if valid, false otherwise\n */\nexport function validateWebhookSignature(\n authToken: string,\n signature: string,\n url: string,\n params: Record<string, string>,\n): boolean {\n try {\n // Note: In production, you should use the twilio.validateRequest method\n // This is a simplified version for demonstration\n logger.warn(\"Webhook signature validation not fully implemented\");\n return true; // TODO: Implement proper validation\n } catch (error) {\n logger.error(\n { error: String(error) },\n \"Error validating webhook signature\",\n );\n return false;\n }\n}\n\n/**\n * Chunks text for SMS messages (respecting 160 character limit)\n * @param text The text to chunk\n * @param maxLength Maximum length per chunk (default: 160)\n * @returns Array of text chunks\n */\nexport function chunkTextForSms(\n text: string,\n maxLength: number = 160,\n): string[] {\n if (text.length <= maxLength) {\n return [text];\n }\n\n const chunks: string[] = [];\n const words = text.split(\" \");\n let currentChunk = \"\";\n\n for (const word of words) {\n if ((currentChunk + \" \" + word).trim().length <= maxLength) {\n currentChunk = (currentChunk + \" \" + word).trim();\n } else {\n if (currentChunk) {\n chunks.push(currentChunk);\n }\n currentChunk = word;\n }\n }\n\n if (currentChunk) {\n chunks.push(currentChunk);\n }\n\n return chunks;\n}\n\n/**\n * Converts audio buffer between formats\n * @param audioBuffer The audio buffer to convert\n * @param fromFormat The source format\n * @param toFormat The target format\n * @returns The converted audio buffer\n */\nexport async function convertAudioFormat(\n audioBuffer: Buffer,\n fromFormat: string,\n toFormat: string,\n): Promise<Buffer> {\n // TODO: Implement audio conversion using fluent-ffmpeg\n logger.warn(\"Audio conversion not implemented yet\");\n return audioBuffer;\n}\n\n/**\n * Generates a webhook URL for a specific path\n * @param baseUrl The base webhook URL\n * @param path The path to append\n * @returns The full webhook URL\n */\nexport function getWebhookUrl(baseUrl: string, path: string): string {\n // Ensure base URL doesn't end with / and path starts with /\n const cleanBase = baseUrl.replace(/\\/$/, \"\");\n const cleanPath = path.startsWith(\"/\") ? path : \"/\" + path;\n return cleanBase + cleanPath;\n}\n","import {\n Action,\n type IAgentRuntime,\n type Memory,\n type State,\n type HandlerCallback,\n logger,\n} from \"@elizaos/core\";\nimport { MakeCallSchema } from \"../types\";\nimport { TwilioService } from \"../service\";\nimport { TWILIO_SERVICE_NAME } from \"../constants\";\nimport {\n validatePhoneNumber,\n generateTwiML,\n extractPhoneNumber,\n} from \"../utils\";\n\nconst makeCallAction: Action = {\n name: \"MAKE_CALL\",\n description: \"Make a phone call via Twilio with a message or custom TwiML\",\n validate: async (runtime: IAgentRuntime, message: Memory, state?: State) => {\n // Check if Twilio service is available\n const twilioService = runtime.getService(TWILIO_SERVICE_NAME);\n if (!twilioService) {\n logger.error(\"Twilio service not found\");\n return false;\n }\n\n // Check if message contains phone number and call intent\n const text = message.content.text || \"\";\n const phoneNumber = extractPhoneNumber(text);\n const callIntent =\n text.toLowerCase().includes(\"call\") ||\n text.toLowerCase().includes(\"phone\") ||\n text.toLowerCase().includes(\"dial\");\n\n return !!phoneNumber && callIntent;\n },\n handler: async (\n runtime: IAgentRuntime,\n message: Memory,\n state?: State,\n options?: any,\n callback?: HandlerCallback,\n ) => {\n try {\n const twilioService = runtime.getService(\n TWILIO_SERVICE_NAME,\n ) as unknown as TwilioService;\n if (!twilioService) {\n throw new Error(\"Twilio service not available\");\n }\n\n const text = message.content.text || \"\";\n\n // Extract phone number from the message\n const phoneNumber = extractPhoneNumber(text);\n if (!phoneNumber) {\n throw new Error(\"No phone number found in message\");\n }\n\n // Extract the call message content\n // Remove the phone number and command keywords from the text\n let callMessage = text\n .replace(phoneNumber, \"\")\n .replace(/call|phone|dial/gi, \"\")\n .replace(/and\\s*say/gi, \"\")\n .replace(/with\\s*(the\\s*)?(message|saying)/gi, \"\")\n .trim();\n\n // Remove quotes if present\n callMessage = callMessage.replace(/^[\"']|[\"']$/g, \"\").trim();\n\n // If no message content extracted, use a default\n if (!callMessage) {\n callMessage =\n \"Hello, this is an automated call from your AI assistant.\";\n }\n\n // Validate phone number\n if (!validatePhoneNumber(phoneNumber)) {\n throw new Error(\"Invalid phone number format\");\n }\n\n // Generate TwiML for the call\n const twiml = generateTwiML.say(callMessage);\n\n // Make the call\n const call = await twilioService.makeCall(phoneNumber, twiml);\n logger.info(`Call initiated to ${phoneNumber}, Call SID: ${call.sid}`);\n\n if (callback) {\n callback({\n text: `Call initiated successfully to ${phoneNumber}. Call ID: ${call.sid}`,\n success: true,\n });\n }\n } catch (error) {\n logger.error({ error: String(error) }, \"Error making call\");\n if (callback) {\n callback({\n text: `Failed to make call: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n success: false,\n });\n }\n }\n },\n examples: [\n [\n {\n name: \"user\",\n content: {\n text: \"Call +18885551234 and say 'This is an important reminder about your appointment tomorrow at 3pm'\",\n },\n },\n {\n name: \"assistant\",\n content: {\n text: \"I'll place that call with your reminder message.\",\n action: \"MAKE_CALL\",\n },\n },\n ],\n [\n {\n name: \"user\",\n content: {\n text: \"Phone +15555551234 with an automated message about the meeting cancellation\",\n },\n },\n {\n name: \"assistant\",\n content: {\n text: \"Initiating the call with the cancellation message.\",\n action: \"MAKE_CALL\",\n },\n },\n ],\n ],\n similes: [\n \"make call\",\n \"phone call\",\n \"call phone\",\n \"dial number\",\n \"voice call\",\n \"ring phone\",\n ],\n};\n\nexport default makeCallAction;\n","import {\n Action,\n type IAgentRuntime,\n type Memory,\n type State,\n type HandlerCallback,\n logger,\n} from \"@elizaos/core\";\nimport { SendMmsSchema } from \"../types\";\nimport { TwilioService } from \"../service\";\nimport { TWILIO_SERVICE_NAME, SUPPORTED_MEDIA_TYPES } from \"../constants\";\nimport { validateMessagingAddress, extractPhoneNumber } from \"../utils\";\n\nconst sendMmsAction: Action = {\n name: \"SEND_MMS\",\n description:\n \"Send an MMS (multimedia message) with images, audio, or video via Twilio\",\n validate: async (runtime: IAgentRuntime, message: Memory, state?: State) => {\n // Check if Twilio service is available\n const twilioService = runtime.getService(TWILIO_SERVICE_NAME);\n if (!twilioService) {\n logger.error(\"Twilio service not found\");\n return false;\n }\n\n // Check if message contains phone number and media intent\n const text = message.content.text || \"\";\n const phoneNumber = extractPhoneNumber(text);\n const mediaIntent =\n text.toLowerCase().includes(\"image\") ||\n text.toLowerCase().includes(\"photo\") ||\n text.toLowerCase().includes(\"picture\") ||\n text.toLowerCase().includes(\"video\") ||\n text.toLowerCase().includes(\"media\") ||\n text.toLowerCase().includes(\"mms\");\n\n // Also check for URLs that might be media\n const urlPattern = /https?:\\/\\/[^\\s]+/g;\n const hasUrls = urlPattern.test(text);\n\n return !!phoneNumber && (mediaIntent || hasUrls);\n },\n handler: async (\n runtime: IAgentRuntime,\n message: Memory,\n state?: State,\n options?: any,\n callback?: HandlerCallback,\n ) => {\n try {\n const twilioService = runtime.getService(\n TWILIO_SERVICE_NAME,\n ) as unknown as TwilioService;\n if (!twilioService) {\n throw new Error(\"Twilio service not available\");\n }\n\n const text = message.content.text || \"\";\n\n // Extract phone number from the message\n const phoneNumber = extractPhoneNumber(text);\n if (!phoneNumber) {\n throw new Error(\"No phone number found in message\");\n }\n\n // Extract URLs from the message\n const urlPattern = /https?:\\/\\/[^\\s]+/g;\n const mediaUrls: string[] = text.match(urlPattern) || [];\n\n if (mediaUrls.length === 0) {\n // If no URLs found but MMS was requested, use a default demo image\n mediaUrls.push(\"https://demo.twilio.com/owl.png\");\n }\n\n // Extract the message content\n let messageContent = text\n .replace(phoneNumber, \"\")\n .replace(\n /send\\s*(an?\\s*)?(mms|picture|photo|image|video|media)\\s*(to\\s*)?/gi,\n \"\",\n )\n .replace(/with\\s*(the\\s*)?(image|photo|picture|video|media|mms)/gi, \"\")\n .replace(/at|from/gi, \"\")\n .replace(urlPattern, \"\") // Remove URLs from message\n .replace(/saying|with\\s*(the\\s*)?(message|text)/gi, \"\")\n .trim();\n\n // Remove quotes if present\n messageContent = messageContent.replace(/^[\"']|[\"']$/g, \"\").trim();\n\n // If no message content extracted, use a default\n if (!messageContent) {\n messageContent = \"Here's the media you requested\";\n }\n\n // Validate phone number\n if (!validateMessagingAddress(phoneNumber)) {\n throw new Error(\"Invalid phone number format\");\n }\n\n // Send the MMS\n const sentMessage = await twilioService.sendSms(\n phoneNumber,\n messageContent,\n mediaUrls,\n );\n logger.info(\n `MMS sent to ${phoneNumber} with ${mediaUrls.length} media attachment(s)`,\n );\n\n if (callback) {\n callback({\n text: `MMS sent successfully to ${phoneNumber} with ${mediaUrls.length} media attachment(s)`,\n success: true,\n });\n }\n } catch (error) {\n logger.error({ error: String(error) }, \"Error sending MMS\");\n if (callback) {\n callback({\n text: `Failed to send MMS: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n success: false,\n });\n }\n }\n },\n examples: [\n [\n {\n name: \"user\",\n content: {\n text: \"Send a picture to +18885551234 with the image from https://example.com/photo.jpg saying 'Check out this photo!'\",\n },\n },\n {\n name: \"assistant\",\n content: {\n text: \"I'll send that photo with your message.\",\n action: \"SEND_MMS\",\n },\n },\n ],\n [\n {\n name: \"user\",\n content: {\n text: \"Send an MMS to +15555551234 with the video at https://example.com/video.mp4\",\n },\n },\n {\n name: \"assistant\",\n content: {\n text: \"Sending the video message now.\",\n action: \"SEND_MMS\",\n },\n },\n ],\n ],\n similes: [\n \"send mms\",\n \"send picture\",\n \"send photo\",\n \"send image\",\n \"send video\",\n \"send media\",\n \"picture message\",\n \"photo message\",\n ],\n};\n\nexport default sendMmsAction;\n","import type { IAgentRuntime, Memory, Provider, State } from \"@elizaos/core\";\nimport { TWILIO_SERVICE_NAME } from \"../constants\";\nimport { TwilioService } from \"../service\";\n\nconst conversationHistoryProvider: Provider = {\n name: \"twilioConversationHistory\",\n description:\n \"Provides recent SMS/MMS conversation history with a phone number\",\n get: async (runtime: IAgentRuntime, message: Memory, state?: State) => {\n try {\n const twilioService = runtime.getService(\n TWILIO_SERVICE_NAME,\n ) as unknown as TwilioService;\n if (!twilioService) {\n return {\n text: \"No Twilio conversation history available - service not initialized\",\n };\n }\n\n // Extract phone number from the current context\n if (typeof message.content === \"string\") {\n return {\n text: \"No phone number found in context\",\n };\n }\n\n const phoneNumber =\n message.content.phoneNumber ||\n message.content.text?.match(/\\+?\\d{10,15}/)?.[0];\n\n if (!phoneNumber || typeof phoneNumber !== \"string\") {\n return {\n text: \"No phone number found in context\",\n };\n }\n\n // Get conversation history using the public method\n const conversationHistory = twilioService.getConversationHistory(\n phoneNumber,\n 10,\n );\n\n if (!conversationHistory || conversationHistory.length === 0) {\n return {\n text: `No recent conversation history with ${phoneNumber}`,\n };\n }\n\n // Format conversation history\n const history = conversationHistory\n .map((msg: any) => {\n const direction = msg.direction === \"inbound\" ? \"From\" : \"To\";\n const time = new Date(msg.dateCreated).toLocaleString();\n return `[${time}] ${direction} ${phoneNumber}: ${msg.body}`;\n })\n .join(\"\\n\");\n\n return {\n text: `Recent SMS conversation with ${phoneNumber}:\\n${history}`,\n data: {\n phoneNumber,\n messageCount: conversationHistory.length,\n lastMessage: conversationHistory[conversationHistory.length - 1],\n },\n };\n } catch (error) {\n console.error(\"Error in conversationHistoryProvider:\", error);\n return {\n text: \"Error retrieving conversation history\",\n };\n }\n },\n};\n\nexport default conversationHistoryProvider;\n","import type { IAgentRuntime, Memory, Provider, State } from \"@elizaos/core\";\nimport { TWILIO_SERVICE_NAME } from \"../constants\";\nimport { TwilioService } from \"../service\";\n\nconst callStateProvider: Provider = {\n name: \"twilioCallState\",\n description: \"Provides information about active voice calls and streams\",\n get: async (runtime: IAgentRuntime, message: Memory, state?: State) => {\n try {\n const twilioService = runtime.getService(\n TWILIO_SERVICE_NAME,\n ) as unknown as TwilioService;\n if (!twilioService) {\n return {\n text: \"No Twilio call state available - service not initialized\",\n };\n }\n\n // Get active voice streams\n // @ts-ignore - accessing private property for provider\n const activeStreams = twilioService.voiceStreams;\n\n if (!activeStreams || activeStreams.size === 0) {\n return {\n text: \"No active voice calls\",\n data: {\n activeCallCount: 0,\n },\n };\n }\n\n // Format active call information\n const callInfo: string[] = [];\n const callData: any[] = [];\n\n activeStreams.forEach((stream, callSid) => {\n callInfo.push(`Call ${callSid}: ${stream.from} → ${stream.to}`);\n callData.push({\n callSid,\n streamSid: stream.streamSid,\n from: stream.from,\n to: stream.to,\n });\n });\n\n return {\n text: `Active voice calls (${activeStreams.size}):\\n${callInfo.join(\"\\n\")}`,\n data: {\n activeCallCount: activeStreams.size,\n calls: callData,\n },\n };\n } catch (error) {\n console.error(\"Error in callStateProvider:\", error);\n return {\n text: \"Error retrieving call state\",\n };\n }\n },\n};\n\nexport default callStateProvider;\n","import {\n ChannelType,\n ContentType,\n EventType,\n Service,\n createMessageMemory,\n createUniqueUuid,\n logger,\n stringToUuid,\n type HandlerCallback,\n type IAgentRuntime,\n type Media,\n type Memory,\n type UUID,\n} from \"@elizaos/core\";\n// @ts-ignore - Twilio types not available in workspace\nimport bodyParser from \"body-parser\";\nimport express, { Express } from \"express\";\nimport NodeCache from \"node-cache\";\nimport twilio from \"twilio\";\nimport { WebSocketServer } from \"ws\";\nimport {\n ERROR_MESSAGES,\n TWILIO_CONSTANTS,\n TWILIO_SERVICE_NAME,\n} from \"./constants\";\nimport {\n CACHE_KEYS,\n TwilioCall,\n TwilioConfig,\n TwilioError,\n TwilioEventType,\n TwilioMessage,\n TwilioMedia,\n TwilioServiceInterface,\n TwilioSmsWebhook,\n TwilioStatusWebhook,\n TwilioVoiceStream,\n TwilioVoiceWebhook,\n} from \"./types\";\nimport {\n formatMessagingAddress,\n isWhatsAppAddress,\n stripWhatsAppPrefix,\n validateMessagingAddress,\n validatePhoneNumber,\n} from \"./utils\";\n\ntype MessageService = {\n handleMessage: (\n runtime: IAgentRuntime,\n message: Memory,\n callback?: HandlerCallback,\n ) => Promise<void>;\n};\n\nconst getMessageService = (runtime: IAgentRuntime): MessageService | null => {\n if (\"messageService\" in runtime) {\n const withMessageService = runtime as IAgentRuntime & {\n messageService?: MessageService | null;\n };\n return withMessageService.messageService ?? null;\n }\n return null;\n};\n\nexport class TwilioService extends Service implements TwilioServiceInterface {\n static serviceType: string = TWILIO_SERVICE_NAME;\n\n // Required static methods for Service type\n static async start(runtime: IAgentRuntime): Promise<TwilioService> {\n const service = new TwilioService();\n await service.initialize(runtime);\n return service;\n }\n\n static async stop(_runtime: IAgentRuntime): Promise<void> {\n // Stop method is handled by instance cleanup\n return;\n }\n\n private twilioConfig!: TwilioConfig;\n private client!: any; // Twilio client\n private app!: Express;\n private server: any;\n private wss!: WebSocketServer;\n private cache: NodeCache;\n private voiceStreams: Map<string, TwilioVoiceStream>;\n private isInitialized: boolean = false;\n\n constructor() {\n super();\n this.voiceStreams = new Map();\n this.cache = new NodeCache({ stdTTL: 600 }); // 10 minute default TTL\n }\n\n async initialize(runtime: IAgentRuntime): Promise<void> {\n if (this.isInitialized) {\n logger.warn(\"TwilioService already initialized\");\n return;\n }\n\n this.runtime = runtime;\n\n // Get configuration from runtime\n const configuredPhoneNumber = runtime.getSetting(\n \"TWILIO_PHONE_NUMBER\",\n ) as string;\n const normalizedPhoneNumber = stripWhatsAppPrefix(\n configuredPhoneNumber || \"\",\n );\n\n this.twilioConfig = {\n accountSid: runtime.getSetting(\"TWILIO_ACCOUNT_SID\") as string,\n authToken: runtime.getSetting(\"TWILIO_AUTH_TOKEN\") as string,\n phoneNumber: normalizedPhoneNumber,\n webhookUrl: runtime.getSetting(\"TWILIO_WEBHOOK_URL\") as string,\n webhookPort: parseInt(\n runtime.getSetting(\"TWILIO_WEBHOOK_PORT\") || \"3000\",\n ),\n };\n\n // Validate configuration\n if (\n !this.twilioConfig.accountSid ||\n !this.twilioConfig.authToken ||\n !this.twilioConfig.phoneNumber\n ) {\n throw new TwilioError(ERROR_MESSAGES.MISSING_CREDENTIALS);\n }\n\n // Initialize Twilio client\n this.client = twilio(\n this.twilioConfig.accountSid,\n this.twilioConfig.authToken,\n );\n\n // Set up webhook server\n await this.setupWebhookServer();\n\n // Update phone number webhook URLs\n await this.updatePhoneNumberWebhooks();\n\n this.isInitialized = true;\n logger.info(\"TwilioService initialized successfully\");\n }\n\n // Implement stop method required by Service interface\n async stop(): Promise<void> {\n await this.cleanup();\n }\n\n // Add capability description getter\n get capabilityDescription(): string {\n return \"Twilio voice and SMS integration service for bidirectional communication\";\n }\n\n private async setupWebhookServer(): Promise<void> {\n this.app = express();\n\n // Middleware\n this.app.use(bodyParser.urlencoded({ extended: false }));\n this.app.use(bodyParser.json());\n\n // SMS webhook\n this.app.post(TWILIO_CONSTANTS.WEBHOOK_PATHS.SMS, async (req, res) => {\n try {\n const webhook = req.body as TwilioSmsWebhook;\n await this.handleIncomingSms(webhook);\n res.type(\"text/xml\").send(\"<Response></Response>\");\n } catch (error) {\n logger.error({ error: String(error) }, \"Error handling SMS webhook\");\n res.status(500).send(\"<Response></Response>\");\n }\n });\n\n // Voice webhook\n this.app.post(TWILIO_CONSTANTS.WEBHOOK_PATHS.VOICE, async (req, res) => {\n try {\n const webhook = req.body as TwilioVoiceWebhook;\n const twiml = await this.handleIncomingCall(webhook);\n res.type(\"text/xml\").send(twiml);\n } catch (error) {\n logger.error({ error: String(error) }, \"Error handling voice webhook\");\n res\n .type(\"text/xml\")\n .send(TWILIO_CONSTANTS.TWIML.DEFAULT_VOICE_RESPONSE);\n }\n });\n\n // Status callback webhook\n this.app.post(TWILIO_CONSTANTS.WEBHOOK_PATHS.STATUS, (req, res) => {\n const webhook = req.body as TwilioStatusWebhook;\n const {\n MessageSid,\n MessageStatus,\n SmsStatus,\n CallSid,\n CallStatus,\n ErrorCode,\n ErrorMessage,\n To,\n From,\n MessagingServiceSid,\n AccountSid,\n ApiVersion,\n } = webhook;\n logger.info(\n {\n MessageSid,\n MessageStatus,\n SmsStatus,\n CallSid,\n CallStatus,\n ErrorCode,\n ErrorMessage,\n To,\n From,\n MessagingServiceSid,\n AccountSid,\n ApiVersion,\n },\n \"Status callback received\",\n );\n res.sendStatus(200);\n });\n\n // Start HTTP server\n this.server = this.app.listen(this.twilioConfig.webhookPort, () => {\n logger.info(\n `Twilio webhook server listening on port ${this.twilioConfig.webhookPort}`,\n );\n });\n\n // Set up WebSocket server for voice streaming\n this.wss = new WebSocketServer({ server: this.server });\n this.setupVoiceStreamingWebSocket();\n }\n\n private setupVoiceStreamingWebSocket(): void {\n this.wss.on(\"connection\", (ws, req) => {\n const url = new URL(req.url!, `http://${req.headers.host}`);\n const callSid = url.searchParams.get(\"callSid\");\n\n if (!callSid) {\n logger.error(\"No callSid provided for voice stream\");\n ws.close();\n return;\n }\n\n logger.info(`Voice stream connected for call ${callSid}`);\n\n ws.on(\"message\", async (data) => {\n try {\n const message = JSON.parse(data.toString());\n\n switch (message.event) {\n case \"start\":\n this.handleStreamStart(callSid, message, ws);\n break;\n case \"media\":\n this.handleStreamMedia(callSid, message);\n break;\n case \"stop\":\n this.handleStreamStop(callSid);\n break;\n }\n } catch (error) {\n logger.error(\n { error: String(error) },\n \"Error processing voice stream message\",\n );\n }\n });\n\n ws.on(\"close\", () => {\n logger.info(`Voice stream closed for call ${callSid}`);\n this.voiceStreams.delete(callSid);\n // Emit event through runtime if available\n if (this.runtime) {\n this.runtime.emitEvent(TwilioEventType.VOICE_STREAM_ENDED, {\n callSid,\n });\n }\n });\n });\n }\n\n private handleStreamStart(callSid: string, message: any, ws: any): void {\n const stream: TwilioVoiceStream = {\n streamSid: message.streamSid,\n callSid,\n from: message.start.customParameters.from,\n to: message.start.customParameters.to,\n socket: ws,\n };\n\n this.voiceStreams.set(callSid, stream);\n if (this.runtime) {\n this.runtime.emitEvent(TwilioEventType.VOICE_STREAM_STARTED, { stream });\n }\n }\n\n private handleStreamMedia(callSid: string, message: any): void {\n const stream = this.voiceStreams.get(callSid);\n if (!stream) return;\n\n // Process audio data\n const audioBuffer = Buffer.from(message.media.payload, \"base64\");\n\n // Emit audio data for processing by other services\n if (this.runtime) {\n this.runtime.emitEvent(\"audio:received\", {\n callSid,\n audio: audioBuffer,\n timestamp: message.media.timestamp,\n });\n }\n }\n\n private handleStreamStop(callSid: string): void {\n this.voiceStreams.delete(callSid);\n if (this.runtime) {\n this.runtime.emitEvent(TwilioEventType.VOICE_STREAM_ENDED, { callSid });\n }\n }\n\n private async updatePhoneNumberWebhooks(): Promise<void> {\n try {\n const phoneNumbers = await this.client.incomingPhoneNumbers.list({\n phoneNumber: this.twilioConfig.phoneNumber,\n });\n\n if (phoneNumbers.length === 0) {\n throw new TwilioError(\n `Phone number ${this.twilioConfig.phoneNumber} not found`,\n );\n }\n\n const phoneNumber = phoneNumbers[0];\n\n await this.client.incomingPhoneNumbers(phoneNumber.sid).update({\n smsUrl: `${this.twilioConfig.webhookUrl}${TWILIO_CONSTANTS.WEBHOOK_PATHS.SMS}`,\n smsMethod: \"POST\",\n voiceUrl: `${this.twilioConfig.webhookUrl}${TWILIO_CONSTANTS.WEBHOOK_PATHS.VOICE}`,\n voiceMethod: \"POST\",\n statusCallback: `${this.twilioConfig.webhookUrl}${TWILIO_CONSTANTS.WEBHOOK_PATHS.STATUS}`,\n statusCallbackMethod: \"POST\",\n });\n\n logger.info(\n `Updated webhooks for phone number ${this.twilioConfig.phoneNumber}`,\n );\n } catch (error) {\n logger.error(\n { error: String(error) },\n \"Error updating phone number webhooks\",\n );\n throw error;\n }\n }\n\n async sendSms(\n to: string,\n body: string,\n mediaUrl?: string[],\n fromOverride?: string,\n ): Promise<TwilioMessage> {\n const normalizedTo = formatMessagingAddress(to);\n if (!normalizedTo || !validateMessagingAddress(normalizedTo)) {\n throw new TwilioError(ERROR_MESSAGES.INVALID_PHONE_NUMBER);\n }\n\n const normalizedFrom = formatMessagingAddress(\n fromOverride || this.twilioConfig.phoneNumber,\n );\n if (!normalizedFrom) {\n throw new TwilioError(ERROR_MESSAGES.INVALID_PHONE_NUMBER);\n }\n\n const fromNumber = isWhatsAppAddress(normalizedTo)\n ? `whatsapp:${stripWhatsAppPrefix(normalizedFrom)}`\n : stripWhatsAppPrefix(normalizedFrom);\n\n try {\n const message = await this.client.messages.create({\n from: fromNumber,\n to: normalizedTo,\n body,\n mediaUrl,\n statusCallback: `${this.twilioConfig.webhookUrl}${TWILIO_CONSTANTS.WEBHOOK_PATHS.STATUS}`,\n });\n\n const twilioMessage: TwilioMessage = {\n sid: message.sid,\n from: message.from,\n to: message.to,\n body: message.body,\n direction: \"outbound\",\n status: message.status,\n dateCreated: message.dateCreated,\n dateSent: message.dateSent || undefined,\n };\n\n // Cache the message\n const conversationKey = CACHE_KEYS.CONVERSATION(normalizedTo);\n let conversationHistory =\n (this.cache.get(conversationKey) as TwilioMessage[]) || [];\n conversationHistory.push(twilioMessage);\n // Keep only last 50 messages\n if (conversationHistory.length > 50) {\n conversationHistory = conversationHistory.slice(-50);\n }\n this.cache.set(\n conversationKey,\n conversationHistory,\n TWILIO_CONSTANTS.CACHE_TTL.CONVERSATION,\n );\n\n if (this.runtime) {\n this.runtime.emitEvent(TwilioEventType.SMS_SENT, twilioMessage);\n }\n return twilioMessage;\n } catch (error: any) {\n throw new TwilioError(\n `Failed to send SMS: ${error.message}`,\n error.code,\n error.moreInfo,\n );\n }\n }\n\n async makeCall(\n to: string,\n twiml?: string,\n url?: string,\n ): Promise<TwilioCall> {\n if (!validatePhoneNumber(to)) {\n throw new TwilioError(ERROR_MESSAGES.INVALID_PHONE_NUMBER);\n }\n\n try {\n const callParams: any = {\n from: this.twilioConfig.phoneNumber,\n to,\n statusCallback: `${this.twilioConfig.webhookUrl}${TWILIO_CONSTANTS.WEBHOOK_PATHS.STATUS}`,\n statusCallbackEvent: [\"initiated\", \"ringing\", \"answered\", \"completed\"],\n };\n\n if (twiml) {\n callParams.twiml = twiml;\n } else if (url) {\n callParams.url = url;\n } else {\n callParams.twiml = TWILIO_CONSTANTS.TWIML.DEFAULT_VOICE_RESPONSE;\n }\n\n const call = await this.client.calls.create(callParams);\n\n const twilioCall: TwilioCall = {\n sid: call.sid,\n from: call.from,\n to: call.to,\n status: call.status,\n direction: \"outbound\",\n dateCreated: call.dateCreated,\n };\n\n // Cache call state\n this.cache.set(\n CACHE_KEYS.CALL_STATE(call.sid),\n twilioCall,\n TWILIO_CONSTANTS.CACHE_TTL.CALL_STATE,\n );\n\n return twilioCall;\n } catch (error: any) {\n throw new TwilioError(\n `Failed to make call: ${error.message}`,\n error.code,\n error.moreInfo,\n );\n }\n }\n\n async handleIncomingSms(webhook: TwilioSmsWebhook): Promise<void> {\n const message: TwilioMessage = {\n sid: webhook.MessageSid,\n from: webhook.From,\n to: webhook.To,\n body: webhook.Body,\n direction: \"inbound\",\n status: \"received\",\n dateCreated: new Date(),\n };\n\n // Handle media if present\n if (webhook.NumMedia && parseInt(webhook.NumMedia) > 0) {\n message.media = [];\n // Twilio sends media as MediaUrl0, MediaUrl1, etc.\n for (let i = 0; i < parseInt(webhook.NumMedia); i++) {\n const mediaUrl = (webhook as any)[`MediaUrl${i}`];\n const contentType = (webhook as any)[`MediaContentType${i}`];\n if (mediaUrl) {\n message.media.push({\n url: mediaUrl,\n contentType: contentType || \"unknown\",\n sid: `media_${i}`,\n });\n }\n }\n }\n\n // Store in cache for conversation context\n const conversationKey = CACHE_KEYS.CONVERSATION(webhook.From);\n let conversationHistory =\n (this.cache.get(conversationKey) as TwilioMessage[]) || [];\n conversationHistory.push(message);\n // Keep only last 50 messages\n if (conversationHistory.length > 50) {\n conversationHistory = conversationHistory.slice(-50);\n }\n this.cache.set(\n conversationKey,\n conversationHistory,\n TWILIO_CONSTANTS.CACHE_TTL.CONVERSATION,\n );\n\n if (this.runtime) {\n this.runtime.emitEvent(TwilioEventType.SMS_RECEIVED, message);\n }\n\n // Process message with agent runtime\n await this.processIncomingMessage(message);\n }\n\n async handleIncomingCall(webhook: TwilioVoiceWebhook): Promise<string> {\n const call: TwilioCall = {\n sid: webhook.CallSid,\n from: webhook.From,\n to: webhook.To,\n status: webhook.CallStatus,\n direction: \"inbound\",\n dateCreated: new Date(),\n };\n\n // Cache call state\n this.cache.set(\n CACHE_KEYS.CALL_STATE(webhook.CallSid),\n call,\n TWILIO_CONSTANTS.CACHE_TTL.CALL_STATE,\n );\n\n if (this.runtime) {\n this.runtime.emitEvent(TwilioEventType.CALL_RECEIVED, call);\n }\n\n // Generate TwiML response for voice streaming\n const streamUrl = `wss://${new URL(this.twilioConfig.webhookUrl).host}${TWILIO_CONSTANTS.WEBHOOK_PATHS.VOICE_STREAM}?callSid=${webhook.CallSid}`;\n return TWILIO_CONSTANTS.TWIML.STREAM_RESPONSE(streamUrl);\n }\n\n async startVoiceStream(callSid: string): Promise<void> {\n const stream = this.voiceStreams.get(callSid);\n if (!stream) {\n throw new TwilioError(`No voice stream found for call ${callSid}`);\n }\n\n // Start streaming audio processing\n logger.info(`Starting voice stream processing for call ${callSid}`);\n }\n\n async endVoiceStream(callSid: string): Promise<void> {\n const stream = this.voiceStreams.get(callSid);\n if (stream && stream.socket) {\n stream.socket.close();\n }\n this.voiceStreams.delete(callSid);\n }\n\n private async processIncomingMessage(message: TwilioMessage): Promise<void> {\n try {\n const text = message.body?.trim();\n if (!text) {\n return;\n }\n\n const source = isWhatsAppAddress(message.from) ? \"whatsapp\" : \"twilio\";\n const entityId = createUniqueUuid(this.runtime, message.from);\n const roomId = createUniqueUuid(this.runtime, `twilio:${message.from}`);\n const worldId = createUniqueUuid(this.runtime, `twilio:${message.to}`);\n await this.runtime.ensureConnection({\n entityId,\n roomId,\n worldId,\n userName: message.from,\n source,\n channelId: message.from,\n type: ChannelType.DM,\n });\n\n const attachments = this.buildMediaAttachments(message.media);\n const memory = createMessageMemory({\n id: stringToUuid(message.sid),\n entityId,\n roomId,\n content: {\n text,\n source,\n channelType: ChannelType.DM,\n phoneNumber: message.from,\n attachments: attachments.length > 0 ? attachments : undefined,\n },\n });\n\n const callback: HandlerCallback = async (content) => {\n const responseText =\n typeof content.text === \"string\" ? content.text.trim() : \"\";\n if (!responseText) {\n return [];\n }\n\n await this.sendSms(message.from, responseText, undefined, message.to);\n return [];\n };\n\n const messageService = getMessageService(this.runtime);\n if (messageService) {\n await messageService.handleMessage(this.runtime, memory, callback);\n } else {\n logger.warn(\"messageService unavailable; falling back to event emit\");\n await this.runtime.emitEvent(EventType.MESSAGE_RECEIVED, {\n message: memory,\n callback,\n source,\n });\n }\n } catch (error) {\n logger.error(\n { error: String(error) },\n \"Error processing incoming message\",\n );\n }\n }\n\n private buildMediaAttachments(media?: TwilioMedia[]): Media[] {\n if (!media || media.length === 0) {\n return [];\n }\n\n return media.map((item) => ({\n id: item.sid,\n url: item.url,\n contentType: this.resolveContentType(item.contentType),\n }));\n }\n\n private resolveContentType(contentType: string): ContentType | undefined {\n if (contentType.startsWith(\"image/\")) {\n return ContentType.IMAGE;\n }\n if (contentType.startsWith(\"video/\")) {\n return ContentType.VIDEO;\n }\n if (contentType.startsWith(\"audio/\")) {\n return ContentType.AUDIO;\n }\n return ContentType.DOCUMENT;\n }\n\n sendStreamAudio(callSid: string, audio: Buffer): void {\n const stream = this.voiceStreams.get(callSid);\n if (!stream || !stream.socket) return;\n\n // Convert audio to base64 and send via WebSocket\n const payload = {\n event: \"media\",\n streamSid: stream.streamSid,\n media: {\n payload: audio.toString(\"base64\"),\n },\n };\n\n stream.socket.send(JSON.stringify(payload));\n }\n\n async cleanup(): Promise<void> {\n // Close all voice streams\n for (const [callSid, stream] of this.voiceStreams) {\n if (stream.socket) {\n stream.socket.close();\n }\n }\n this.voiceStreams.clear();\n\n // Close WebSocket server\n if (this.wss) {\n this.wss.close();\n }\n\n // Close HTTP server\n if (this.server) {\n this.server.close();\n }\n\n // Clear cache\n this.cache.flushAll();\n\n this.isInitialized = false;\n logger.info(\"TwilioService cleaned up\");\n }\n\n // Getters for service information\n get serviceType(): string {\n return TWILIO_SERVICE_NAME;\n }\n\n get serviceName(): string {\n return \"twilio\";\n }\n\n get phoneNumber(): string {\n return this.twilioConfig.phoneNumber;\n }\n\n get isConnected(): boolean {\n return this.isInitialized;\n }\n\n // Add public method to get conversation history\n getConversationHistory(\n phoneNumber: string,\n limit: number = 10,\n ): TwilioMessage[] {\n const cacheKey = CACHE_KEYS.CONVERSATION(phoneNumber);\n const messages = this.cache.get(cacheKey) as TwilioMessage[];\n\n if (!messages || !Array.isArray(messages)) {\n return [];\n }\n\n return messages.slice(-limit);\n }\n\n // Add method to get call state\n getCallState(callSid: string): TwilioCall | undefined {\n const cacheKey = CACHE_KEYS.CALL_STATE(callSid);\n return this.cache.get(cacheKey) as TwilioCall | undefined;\n }\n}\n","import { z } from \"zod\";\n\n// Twilio message types\nexport interface TwilioMessage {\n sid: string;\n from: string;\n to: string;\n body: string;\n media?: TwilioMedia[];\n direction: \"inbound\" | \"outbound\";\n status: string;\n dateCreated: Date;\n dateSent?: Date;\n}\n\nexport interface TwilioMedia {\n contentType: string;\n url: string;\n sid: string;\n}\n\n// Voice call types\nexport interface TwilioCall {\n sid: string;\n from: string;\n to: string;\n status: string;\n direction: \"inbound\" | \"outbound\";\n duration?: number;\n dateCreated: Date;\n dateEnded?: Date;\n}\n\n// WebSocket connection for voice streaming\nexport interface TwilioVoiceStream {\n streamSid: string;\n callSid: string;\n from: string;\n to: string;\n socket: any; // WebSocket instance\n}\n\n// Webhook request types\nexport interface TwilioSmsWebhook {\n MessageSid: string;\n From: string;\n To: string;\n Body: string;\n NumMedia?: string;\n MediaUrl0?: string;\n MediaContentType0?: string;\n}\n\nexport interface TwilioVoiceWebhook {\n CallSid: string;\n From: string;\n To: string;\n CallStatus: string;\n Direction: string;\n}\n\nexport interface TwilioStatusWebhook {\n MessageSid?: string;\n MessageStatus?: string;\n SmsStatus?: string;\n CallSid?: string;\n CallStatus?: string;\n ErrorCode?: string;\n ErrorMessage?: string;\n To?: string;\n From?: string;\n MessagingServiceSid?: string;\n AccountSid?: string;\n ApiVersion?: string;\n}\n\n// Configuration\nexport interface TwilioConfig {\n accountSid: string;\n authToken: string;\n phoneNumber: string;\n webhookUrl: string;\n webhookPort?: number;\n}\n\nconst E164_REGEX = /^\\+\\d{1,15}$/;\nconst MESSAGING_REGEX = /^(whatsapp:)?\\+\\d{1,15}$/;\n\n// Zod schemas for validation\nexport const TwilioMessageSchema = z.object({\n to: z.string().regex(MESSAGING_REGEX),\n body: z.string().min(1).max(1600),\n mediaUrl: z.array(z.string().url()).optional(),\n});\n\nexport const TwilioCallSchema = z.object({\n to: z.string().regex(E164_REGEX),\n twiml: z.string().optional(),\n url: z.string().url().optional(),\n});\n\n// Action parameters\nexport const SendSmsSchema = z.object({\n to: z.string().regex(MESSAGING_REGEX),\n message: z.string().min(1).max(1600),\n mediaUrl: z.array(z.string().url()).optional(),\n});\n\nexport const MakeCallSchema = z.object({\n to: z.string().regex(E164_REGEX),\n message: z.string().optional(),\n url: z.string().url().optional(),\n});\n\nexport const SendMmsSchema = z.object({\n to: z.string().regex(MESSAGING_REGEX),\n message: z.string().min(1).max(1600),\n mediaUrl: z.array(z.string().url()).min(1),\n});\n\n// Cache keys\nexport const CACHE_KEYS = {\n CONVERSATION: (phoneNumber: string) => `twilio:conversation:${phoneNumber}`,\n CALL_STATE: (callSid: string) => `twilio:call:${callSid}`,\n MEDIA: (mediaSid: string) => `twilio:media:${mediaSid}`,\n} as const;\n\n// Event types\nexport enum TwilioEventType {\n SMS_RECEIVED = \"sms:received\",\n SMS_SENT = \"sms:sent\",\n CALL_RECEIVED = \"call:received\",\n CALL_ENDED = \"call:ended\",\n VOICE_STREAM_STARTED = \"voice:stream:started\",\n VOICE_STREAM_ENDED = \"voice:stream:ended\",\n}\n\n// Error types\nexport class TwilioError extends Error {\n constructor(\n message: string,\n public code?: number,\n public twilioCode?: string,\n ) {\n super(message);\n this.name = \"TwilioError\";\n }\n}\n\nexport interface TwilioServiceInterface {\n sendSms(\n to: string,\n body: string,\n mediaUrl?: string[],\n from?: string,\n ): Promise<TwilioMessage>;\n makeCall(to: string, twiml?: string, url?: string): Promise<TwilioCall>;\n handleIncomingSms(webhook: TwilioSmsWebhook): Promise<void>;\n handleIncomingCall(webhook: TwilioVoiceWebhook): Promise<string>; // Returns TwiML\n startVoiceStream(callSid: string): Promise<void>;\n endVoiceStream(callSid: string): Promise<void>;\n}\n","import {\n type IAgentRuntime,\n type TestSuite,\n type TestCase,\n logger,\n} from \"@elizaos/core\";\nimport { TwilioService } from \"./service\";\nimport { TWILIO_SERVICE_NAME } from \"./constants\";\nimport * as readline from \"readline\";\nimport axios from \"axios\";\n\nexport class TwilioTestSuite implements TestSuite {\n name = \"Twilio Plugin Test Suite\";\n description = \"Tests for Twilio voice and SMS functionality\";\n\n tests: TestCase[] = [\n {\n name: \"Service Initialization Test\",\n fn: async (runtime: IAgentRuntime) => {\n const twilioService = runtime.getService(\n TWILIO_SERVICE_NAME,\n ) as unknown as TwilioService;\n if (!twilioService) {\n throw new Error(\"Twilio service not initialized\");\n }\n\n // Check service properties\n if (!twilioService.isConnected) {\n throw new Error(\"Twilio service is not connected\");\n }\n\n if (!twilioService.phoneNumber) {\n throw new Error(\"Twilio phone number not configured\");\n }\n\n logger.info(\n `✅ Service initialized with phone number: ${twilioService.phoneNumber}`,\n );\n },\n },\n {\n name: \"Send SMS Test\",\n fn: async (runtime: IAgentRuntime) => {\n const twilioService = runtime.getService(\n TWILIO_SERVICE_NAME,\n ) as unknown as TwilioService;\n if (!twilioService) {\n throw new Error(\"Twilio service not initialized\");\n }\n\n const testNumber = runtime.getSetting(\"TWILIO_TEST_PHONE_NUMBER\");\n if (!testNumber) {\n logger.warn(\"TWILIO_TEST_PHONE_NUMBER not set, skipping SMS test\");\n return;\n }\n\n const result = await twilioService.sendSms(\n testNumber,\n \"Test SMS from Eliza Twilio plugin\",\n );\n\n logger.info(`✅ SMS test successful. Message SID: ${result.sid}`);\n },\n },\n {\n name: \"Send MMS Test\",\n fn: async (runtime: IAgentRuntime) => {\n const twilioService = runtime.getService(\n TWILIO_SERVICE_NAME,\n ) as unknown as TwilioService;\n if (!twilioService) {\n throw new Error(\"Twilio service not initialized\");\n }\n\n const testNumber = runtime.getSetting(\"TWILIO_TEST_PHONE_NUMBER\");\n if (!testNumber) {\n logger.warn(\"TWILIO_TEST_PHONE_NUMBER not set, skipping MMS test\");\n return;\n }\n\n const result = await twilioService.sendSms(\n testNumber,\n \"Test MMS from Eliza Twilio plugin\",\n [\"https://demo.twilio.com/owl.png\"], // Twilio's demo image\n );\n\n logger.info(`✅ MMS test successful. Message SID: ${result.sid}`);\n },\n },\n {\n name: \"Make Call Test\",\n fn: async (runtime: IAgentRuntime) => {\n const twilioService = runtime.getService(\n TWILIO_SERVICE_NAME,\n ) as unknown as TwilioService;\n if (!twilioService) {\n throw new Error(\"Twilio service not initialized\");\n }\n\n const testNumber = runtime.getSetting(\"TWILIO_TEST_PHONE_NUMBER\");\n if (!testNumber) {\n logger.warn(\"TWILIO_TEST_PHONE_NUMBER not set, skipping call test\");\n return;\n }\n\n const twiml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Response>\n <Say voice=\"alice\">This is a test call from Eliza Twilio plugin. Goodbye!</Say>\n <Hangup/>\n</Response>`;\n\n const result = await twilioService.makeCall(testNumber, twiml);\n\n logger.info(`✅ Call test successful. Call SID: ${result.sid}`);\n },\n },\n {\n name: \"Webhook Server Test\",\n fn: async (runtime: IAgentRuntime) => {\n const twilioService = runtime.getService(\n TWILIO_SERVICE_NAME,\n ) as unknown as TwilioService;\n if (!twilioService) {\n throw new Error(\"Twilio service not initialized\");\n }\n\n // Check if service is connected (webhook server running)\n if (!twilioService.isConnected) {\n throw new Error(\"Webhook server is not running\");\n }\n\n const webhookPort = runtime.getSetting(\"TWILIO_WEBHOOK_PORT\") || \"3000\";\n logger.info(`✅ Webhook server is running on port ${webhookPort}`);\n\n // Test webhook endpoints\n const webhookUrl = runtime.getSetting(\"TWILIO_WEBHOOK_URL\");\n if (webhookUrl && webhookUrl.includes(\"localhost\")) {\n try {\n // Test SMS webhook endpoint\n const smsResponse = await axios.post(\n `http://localhost:${webhookPort}/webhooks/twilio/sms`,\n {\n MessageSid: \"TEST123\",\n From: \"+18885551234\",\n To: twilioService.phoneNumber,\n Body: \"Test webhook message\",\n },\n {\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n },\n );\n\n if (smsResponse.status === 200) {\n logger.info(\"✅ SMS webhook endpoint is responding\");\n }\n\n // Test voice webhook endpoint\n const voiceResponse = await axios.post(\n `http://localhost:${webhookPort}/webhooks/twilio/voice`,\n {\n CallSid: \"CATEST123\",\n From: \"+18885551234\",\n To: twilioService.phoneNumber,\n CallStatus: \"ringing\",\n },\n {\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n },\n );\n\n if (voiceResponse.status === 200) {\n logger.info(\"✅ Voice webhook endpoint is responding\");\n }\n } catch (error) {\n logger.warn(\n { error: String(error) },\n \"Could not test webhook endpoints locally\",\n );\n }\n }\n },\n },\n {\n name: \"Conversation History Test\",\n fn: async (runtime: IAgentRuntime) => {\n const twilioService = runtime.getService(\n TWILIO_SERVICE_NAME,\n ) as unknown as TwilioService;\n if (!twilioService) {\n throw new Error(\"Twilio service not initialized\");\n }\n\n const testNumber = runtime.getSetting(\"TWILIO_TEST_PHONE_NUMBER\");\n if (!testNumber) {\n logger.warn(\n \"TWILIO_TEST_PHONE_NUMBER not set, skipping conversation history test\",\n );\n return;\n }\n\n // Send a test message first\n await twilioService.sendSms(testNumber, \"History test message\");\n\n // Get conversation history\n const history = twilioService.getConversationHistory(testNumber, 5);\n\n if (history.length > 0) {\n logger.info(\n `✅ Conversation history retrieved: ${history.length} messages`,\n );\n logger.info(` Latest message: ${history[history.length - 1].body}`);\n } else {\n logger.info(\n \"✅ Conversation history is empty (expected for new number)\",\n );\n }\n },\n },\n {\n name: \"Error Handling Test\",\n fn: async (runtime: IAgentRuntime) => {\n const twilioService = runtime.getService(\n TWILIO_SERVICE_NAME,\n ) as unknown as TwilioService;\n if (!twilioService) {\n throw new Error(\"Twilio service not initialized\");\n }\n\n // Test invalid phone number\n try {\n await twilioService.sendSms(\"invalid-number\", \"Test\");\n throw new Error(\"Expected error for invalid phone number\");\n } catch (error: any) {\n if (error.message.includes(\"Invalid phone number\")) {\n logger.info(\"✅ Invalid phone number error handled correctly\");\n } else {\n throw error;\n }\n }\n\n // Test empty message\n try {\n await twilioService.sendSms(\"+18885551234\", \"\");\n // This might not throw an error, but Twilio will reject it\n logger.info(\"✅ Empty message handled\");\n } catch (error) {\n logger.info(\"✅ Empty message error handled correctly\");\n }\n },\n },\n {\n name: \"Interactive Test Mode\",\n fn: async (runtime: IAgentRuntime) => {\n const twilioService = runtime.getService(\n TWILIO_SERVICE_NAME,\n ) as unknown as TwilioService;\n if (!twilioService) {\n throw new Error(\"Twilio service not initialized\");\n }\n\n const phoneNumber = runtime.getSetting(\"TWILIO_PHONE_NUMBER\");\n const testNumber = runtime.getSetting(\"TWILIO_TEST_PHONE_NUMBER\");\n\n if (!phoneNumber || !testNumber) {\n throw new Error(\n \"TWILIO_PHONE_NUMBER and TWILIO_TEST_PHONE_NUMBER must be set for interactive testing\",\n );\n }\n\n logger.info(\"\\n🎮 INTERACTIVE TWILIO TEST MODE\");\n logger.info(\"================================\");\n logger.info(`📱 Your Twilio Number: ${phoneNumber}`);\n logger.info(`📱 Test Target Number: ${testNumber}`);\n logger.info(\"\\n📋 Instructions:\");\n logger.info(\n \"1. The webhook server is running and listening for incoming messages\",\n );\n logger.info(\n \"2. Text or call your Twilio number to test incoming messages\",\n );\n logger.info(\"3. The test will send a test SMS and make a test call\");\n logger.info(\"4. Watch the console for incoming message logs\");\n logger.info(\"\\nPress Enter to start the interactive test...\");\n\n // Wait for user to press enter\n await new Promise<void>((resolve) => {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n rl.question(\"\", () => {\n rl.close();\n resolve();\n });\n });\n\n // Test 1: Send SMS\n logger.info(\"\\n📤 Test 1: Sending SMS...\");\n try {\n const smsResult = await twilioService.sendSms(\n testNumber,\n \"🎉 Interactive test SMS from ElizaOS! Reply to test two-way messaging.\",\n );\n logger.info(`✅ SMS sent! SID: ${smsResult.sid}`);\n logger.info(` Status: ${smsResult.status}`);\n } catch (error) {\n logger.error(`❌ SMS failed: ${error}`);\n }\n\n await new Promise((resolve) => setTimeout(resolve, 2000));\n\n // Test 2: Make Call\n logger.info(\"\\n📤 Test 2: Making call...\");\n try {\n const twiml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Response>\n <Say voice=\"alice\">Hello from ElizaOS interactive test! This call confirms your Twilio integration is working.</Say>\n <Play>https://api.twilio.com/cowbell.mp3</Play>\n <Say voice=\"alice\">Thank you for testing. Goodbye!</Say>\n</Response>`;\n\n const callResult = await twilioService.makeCall(testNumber, twiml);\n logger.info(`✅ Call initiated! SID: ${callResult.sid}`);\n logger.info(` Status: ${callResult.status}`);\n } catch (error) {\n logger.error(`❌ Call failed: ${error}`);\n }\n\n logger.info(\"\\n📥 Test 3: Waiting for incoming messages...\");\n logger.info(\" Text your Twilio number now!\");\n logger.info(\" The server will log any incoming SMS\");\n logger.info(\"\\n⏱️ Test will continue for 30 seconds...\");\n\n // Keep test running for 30 seconds to receive messages\n await new Promise((resolve) => setTimeout(resolve, 30000));\n\n logger.info(\"\\n✨ Interactive test complete!\");\n logger.info(\"Check logs for detailed results.\");\n },\n },\n ];\n}\n"],"mappings":"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","names":["logger","logger","logger","logger","logger","logger","logger","logger","logger","logger","logger","logger"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@elizaos/plugin-twilio",
|
|
3
|
+
"version": "2.0.0-alpha.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/elizaos-plugins/plugin-twilio.git"
|
|
11
|
+
},
|
|
12
|
+
"exports": {
|
|
13
|
+
"./package.json": "./package.json",
|
|
14
|
+
".": {
|
|
15
|
+
"import": {
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"default": "./dist/index.js"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist"
|
|
23
|
+
],
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@elizaos/core": "2.0.0-alpha.1",
|
|
26
|
+
"axios": "^1.6.5",
|
|
27
|
+
"body-parser": "^1.20.2",
|
|
28
|
+
"express": "^4.18.2",
|
|
29
|
+
"fluent-ffmpeg": "^2.1.3",
|
|
30
|
+
"multer": "^1.4.5-lts.1",
|
|
31
|
+
"node-cache": "^5.1.2",
|
|
32
|
+
"twilio": "^5.4.0",
|
|
33
|
+
"ws": "^8.16.0",
|
|
34
|
+
"zod": "3.24.2"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/express": "^4.17.21",
|
|
38
|
+
"@types/fluent-ffmpeg": "^2.1.24",
|
|
39
|
+
"@types/multer": "^1.4.11",
|
|
40
|
+
"@types/ws": "^8.5.10",
|
|
41
|
+
"prettier": "3.5.3",
|
|
42
|
+
"tsup": "8.4.0",
|
|
43
|
+
"vitest": "1.6.1"
|
|
44
|
+
},
|
|
45
|
+
"scripts": {
|
|
46
|
+
"build": "tsup",
|
|
47
|
+
"dev": "tsup --watch",
|
|
48
|
+
"test": "elizaos test",
|
|
49
|
+
"test:unit": "vitest",
|
|
50
|
+
"lint": "prettier --write ./src",
|
|
51
|
+
"clean": "rm -rf dist .turbo node_modules .turbo-tsconfig.json tsconfig.tsbuildinfo",
|
|
52
|
+
"format": "prettier --write ./src",
|
|
53
|
+
"format:check": "prettier --check ./src"
|
|
54
|
+
},
|
|
55
|
+
"peerDependencies": {
|
|
56
|
+
"whatwg-url": "7.1.0"
|
|
57
|
+
},
|
|
58
|
+
"publishConfig": {
|
|
59
|
+
"access": "public"
|
|
60
|
+
},
|
|
61
|
+
"gitHead": "05d4ca11d769db8c7f54a722ee24b2ce2b951543",
|
|
62
|
+
"agentConfig": {
|
|
63
|
+
"pluginType": "elizaos:plugin:1.0.0",
|
|
64
|
+
"pluginParameters": {
|
|
65
|
+
"TWILIO_ACCOUNT_SID": {
|
|
66
|
+
"type": "string",
|
|
67
|
+
"description": "Twilio Account SID used to authenticate with Twilio API",
|
|
68
|
+
"required": true,
|
|
69
|
+
"sensitive": true
|
|
70
|
+
},
|
|
71
|
+
"TWILIO_AUTH_TOKEN": {
|
|
72
|
+
"type": "string",
|
|
73
|
+
"description": "Twilio Auth Token used to authenticate with Twilio API",
|
|
74
|
+
"required": true,
|
|
75
|
+
"sensitive": true
|
|
76
|
+
},
|
|
77
|
+
"TWILIO_PHONE_NUMBER": {
|
|
78
|
+
"type": "string",
|
|
79
|
+
"description": "Twilio phone number to send messages from (E.164 format, e.g., +18885551212)",
|
|
80
|
+
"required": true,
|
|
81
|
+
"sensitive": false
|
|
82
|
+
},
|
|
83
|
+
"TWILIO_WEBHOOK_URL": {
|
|
84
|
+
"type": "string",
|
|
85
|
+
"description": "Public URL for receiving Twilio webhooks (e.g., https://your-domain.com/webhooks/twilio)",
|
|
86
|
+
"required": true,
|
|
87
|
+
"sensitive": false
|
|
88
|
+
},
|
|
89
|
+
"TWILIO_WEBHOOK_PORT": {
|
|
90
|
+
"type": "string",
|
|
91
|
+
"description": "Port to run the webhook server on (default: 3000)",
|
|
92
|
+
"required": false,
|
|
93
|
+
"sensitive": false
|
|
94
|
+
},
|
|
95
|
+
"TWILIO_TEST_PHONE_NUMBER": {
|
|
96
|
+
"type": "string",
|
|
97
|
+
"description": "Phone number to use for testing (E.164 format)",
|
|
98
|
+
"required": false,
|
|
99
|
+
"sensitive": false
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|