1
+ import {
2
+ ActionExample ,
3
+ generateText ,
4
+ HandlerCallback ,
5
+ IAgentRuntime ,
6
+ Memory ,
7
+ ModelClass ,
8
+ State ,
9
+ type Action ,
10
+ } from "@elizaos/core" ;
11
+ import twilio from 'twilio' ;
12
+
13
+ export const sendSmsAction : Action = {
14
+ name : "SendSms" ,
15
+ similes : [
16
+ "SendSms"
17
+ ] ,
18
+ validate : async ( _runtime : IAgentRuntime , _message : Memory ) => {
19
+ return true ;
20
+ } ,
21
+ description :
22
+ "Send SMS to the mobile number provided by the user" ,
23
+ handler : async (
24
+ _runtime : IAgentRuntime ,
25
+ _message : Memory ,
26
+ _state : State ,
27
+ _options :{ [ key :string ] : unknown } ,
28
+ _callback : HandlerCallback ,
29
+ ) : Promise < boolean > => {
30
+ // Check if environment variables are set
31
+ const accountSid = process . env . TWILIO_ACCOUNT_SID ;
32
+ const authToken = process . env . TWILIO_AUTH_TOKEN ;
33
+
34
+ console . log ( "CHECK _message: " , _message . content . text ) ;
35
+
36
+ if ( ! accountSid || ! authToken ) {
37
+ console . error ( 'TWILIO_ACCOUNT_SID or TWILIO_AUTH_TOKEN is not set' ) ;
38
+ return false ;
39
+ }
40
+
41
+ // Extract the mobile number from the message
42
+ const mobileNumberRegex = / (?: \+ | 0 0 ) ( \d { 1 , 3 } ) \s ? ( \d { 3 , 5 } ) \s ? ( \d { 4 , 10 } ) / ; // This regex matches numbers like +1 123 4567890 or 001 123 4567890
43
+ const text = ( _message . content as { text ?: string } ) ?. text || '' ;
44
+ const matches = text . match ( mobileNumberRegex ) ;
45
+
46
+ const messageRegex = / ( [ ' " ] ) ( .* ?) \1/ ;
47
+ const messageMatch = text . match ( messageRegex ) ;
48
+
49
+ let mobileNumberProvidedByUser = null ;
50
+ let messageToSendFromUser = null ;
51
+
52
+ if ( messageMatch ) {
53
+ messageToSendFromUser = messageMatch [ 2 ] ;
54
+ }
55
+ if ( matches ) {
56
+ // Combine the parts of the number into a single string, removing spaces and plus signs
57
+ mobileNumberProvidedByUser = `+${ matches [ 1 ] } ${ matches [ 2 ] } ${ matches [ 3 ] } ` ;
58
+ } else {
59
+ const alternativeMobileNumberRegex = / \b ( \d { 3 } ) [ - . ] ? ( \d { 3 } ) [ - . ] ? ( \d { 4 } ) \b / ; // For formats like 123-456-7890 or 123.456.7890
60
+ if ( ! mobileNumberProvidedByUser ) {
61
+ const alternativeMatches = text . match ( alternativeMobileNumberRegex ) ;
62
+ if ( alternativeMatches ) {
63
+ mobileNumberProvidedByUser = `${ alternativeMatches [ 1 ] } ${ alternativeMatches [ 2 ] } ${ alternativeMatches [ 3 ] } ` ;
64
+ }
65
+ }
66
+ }
67
+
68
+ const twilioNumber = process . env . TWILIO_PHONE_NUMBER ; // Your Twilio phone number
69
+
70
+ console . log ( 'check target mobile number: ' , mobileNumberProvidedByUser ) ;
71
+ console . log ( 'check messageToSendFromUser: ' , messageToSendFromUser ) ;
72
+ console . log ( 'check twilioNumber: ' , twilioNumber ) ;
73
+
74
+ if ( ! twilioNumber ) {
75
+ console . error ( 'Twilio phone number is missing' ) ;
76
+
77
+ _callback ( {
78
+ text : `Sorry there was an issue send sms, please try again later` ,
79
+ } ) ;
80
+ return false ;
81
+ }
82
+
83
+ const recentMessages = `Extract the phone number from the user recent messages ${ _state . recentMessages } ` ;
84
+
85
+ if ( ! mobileNumberProvidedByUser ) {
86
+ console . error ( 'Mobile number is missing will try to get the phone number or mobile number from recent messages' ) ;
87
+
88
+ mobileNumberProvidedByUser = await generateText (
89
+ {
90
+ runtime : _runtime ,
91
+ context : recentMessages ,
92
+ modelClass : ModelClass . SMALL ,
93
+ stop : [ "\n" ] ,
94
+ customSystemPrompt : "only extract the message that the user intend to send and only get the last one"
95
+ }
96
+ ) ;
97
+ }
98
+
99
+ if ( ! mobileNumberProvidedByUser ) {
100
+ console . error ( 'Mobile number is missing' ) ;
101
+
102
+ _callback ( {
103
+ text : `Sorry, there was an issue send sms, please try again later` ,
104
+ } ) ;
105
+ return false ;
106
+ }
107
+
108
+ const recentUserMessages = `Extract the message intended for SMS or text: ${ _state . recentMessages } ` ;
109
+
110
+ if ( ! messageToSendFromUser ) {
111
+ console . error ( 'messageToSendFromUser is missing will try to get the user message from recent messages' ) ;
112
+
113
+ messageToSendFromUser = await generateText (
114
+ {
115
+ runtime : _runtime ,
116
+ context : recentUserMessages ,
117
+ modelClass : ModelClass . SMALL ,
118
+ stop : [ "\n" ]
119
+ }
120
+ ) ;
121
+ }
122
+
123
+ if ( messageToSendFromUser == null ) {
124
+ console . error ( 'messageToSendFromUser is empty or null' ) ;
125
+
126
+ _callback ( {
127
+ text : `Sorry there was an issue sending the WhatsApp message, please try again later` ,
128
+ } ) ;
129
+ return false ;
130
+ }
131
+
132
+ try {
133
+ // Initialize Twilio client
134
+ const client = twilio ( accountSid , authToken ) ;
135
+
136
+ // Send the SMS
137
+ const message = await client . messages . create ( {
138
+ body : messageToSendFromUser , // The message body
139
+ to : mobileNumberProvidedByUser , // The recipient's phone number
140
+ from : twilioNumber , // Your Twilio phone number
141
+ } ) ;
142
+
143
+ console . log ( "message body: " , message ) ;
144
+
145
+ const messageFromAgent = `SMS sent successfully to ${ mobileNumberProvidedByUser } ` ;
146
+
147
+ // Call the callback to notify the user
148
+ _callback ( {
149
+ text : messageFromAgent ,
150
+ } ) ;
151
+
152
+ return true ;
153
+ } catch ( error ) {
154
+ console . error ( 'Failed to send SMS:' , error ) ;
155
+ _callback ( {
156
+ text : `Failed to send SMS to ${ mobileNumberProvidedByUser } ` ,
157
+ } ) ;
158
+ return false ;
159
+ }
160
+ } ,
161
+ examples : [
162
+ [
163
+ {
164
+ user : "{{user1}}" ,
165
+ content : { text : "please send my message via sms to target mobile number" } ,
166
+ } ,
167
+ {
168
+ user : "{{user2}}" ,
169
+ content : { text : "" , action : "SEND_SMS" } ,
170
+ } ,
171
+ ] ,
172
+ ] as ActionExample [ ] [ ] ,
173
+ } as Action ;
0 commit comments