PluginProbe ʕ •ᴥ•ʔ
AI Engine – The Chatbot, AI Framework & MCP for WordPress / 0.7.1
AI Engine – The Chatbot, AI Framework & MCP for WordPress v0.7.1
3.5.7 3.5.6 3.5.5 3.5.4 3.5.3 3.5.2 3.5.1 3.5.0 3.4.9 3.4.8 3.4.7 0.2.1 1.6.91 0.2.2 1.6.92 0.2.3 1.6.93 0.2.4 1.6.94 0.2.5 1.6.95 0.2.6 1.6.96 0.2.7 1.6.97 0.2.8 1.6.98 0.2.9 1.6.99 0.3.0 1.7.0 0.3.1 1.7.1 0.3.2 1.7.2 0.3.3 1.7.3 0.3.4 1.7.4 0.3.5 1.7.5 0.3.6 1.7.6 0.4.0 1.7.7 0.4.1 1.7.8 0.4.2 1.7.9 0.4.3 1.8.0 0.4.4 1.8.1 0.4.5 1.8.2 0.4.6 1.8.3 0.4.7 1.8.4 0.4.8 1.8.5 0.4.9 1.8.6 0.5.0 1.8.7 0.5.1 1.8.8 0.5.2 1.8.9 0.5.3 1.9.0 0.5.4 1.9.1 0.5.5 1.9.2 0.5.6 1.9.3 0.5.7 1.9.4 0.5.8 1.9.5 0.5.9 1.9.6 0.6.0 1.9.7 0.6.1 1.9.8 0.6.2 1.9.81 0.6.3 1.9.82 0.6.4 1.9.83 0.6.5 1.9.84 0.6.6 1.9.85 0.6.7 1.9.86 0.6.8 1.9.87 0.6.9 1.9.88 0.7.0 1.9.89 0.7.1 1.9.90 0.7.2 1.9.91 0.7.3 1.9.92 0.7.4 1.9.93 0.7.5 1.9.94 0.7.6 1.9.95 0.7.7 1.9.96 0.7.8 1.9.97 0.7.9 1.9.98 0.8.0 1.9.99 0.8.1 2.0.0 0.8.2 2.0.1 0.8.3 2.0.2 0.8.4 2.0.3 0.8.5 2.0.4 0.8.6 2.0.5 0.8.7 2.0.6 0.8.8 2.0.7 0.8.9 2.0.8 0.9.0 2.0.9 0.9.2 2.1.0 0.9.3 2.1.1 0.9.4 2.1.2 0.9.5 2.1.3 0.9.6 2.1.4 0.9.7 2.1.5 0.9.8 2.1.6 0.9.81 2.1.7 0.9.82 2.1.8 0.9.83 2.1.9 0.9.84 2.2.0 0.9.85 2.2.1 0.9.86 2.2.2 0.9.87 2.2.3 0.9.88 2.2.4 0.9.89 2.2.5 0.9.9 2.2.51 0.9.91 2.2.52 0.9.92 2.2.53 0.9.93 2.2.54 0.9.94 2.2.56 0.9.95 2.2.57 0.9.96 2.2.6 0.9.97 2.2.60 0.9.98 2.2.61 0.9.99 2.2.62 1.0.0 2.2.63 1.0.01 2.2.70 1.0.1 2.2.80 1.0.2 2.2.81 1.0.3 2.2.90 1.0.4 2.2.91 1.0.5 2.2.92 1.0.6 2.2.93 1.0.7 2.2.94 1.0.8 2.2.95 1.0.9 2.3.0 1.1.0 2.3.1 1.1.1 2.3.2 1.1.2 2.3.3 1.1.3 2.3.4 1.1.4 2.3.5 1.1.5 2.3.6 1.1.6 2.3.7 1.1.7 2.3.8 1.1.8 2.3.9 1.1.9 2.4.0 1.2.0 2.4.1 1.2.1 2.4.2 1.2.2 2.4.3 1.2.21 2.4.4 1.2.3 2.4.5 1.2.30 2.4.6 1.3.0 2.4.7 1.3.1 2.4.8 1.3.2 2.4.9 1.3.3 2.5.0 1.3.31 2.5.1 1.3.32 2.5.2 1.3.33 2.5.3 1.3.34 2.5.4 1.3.35 2.5.5 1.3.36 2.5.6 1.3.37 2.5.7 1.3.38 2.5.8 1.3.39 2.5.9 1.3.40 2.6.0 1.3.41 2.6.1 1.3.42 2.6.2 1.3.43 2.6.3 1.3.44 2.6.5 1.3.45 2.6.6 1.3.46 2.6.7 1.3.47 2.6.8 1.3.48 2.6.9 1.3.49 2.7.0 1.3.50 2.7.1 1.3.51 2.7.2 1.3.52 2.7.3 1.3.53 2.7.4 1.3.54 2.7.5 1.3.56 2.7.6 1.3.57 2.7.7 1.3.58 2.7.8 1.3.59 2.7.9 1.3.60 2.8.0 1.3.61 2.8.1 1.3.62 2.8.2 1.3.63 2.8.3 1.3.64 2.8.4 1.3.65 2.8.5 1.3.66 2.8.6 1.3.67 2.8.7 1.3.68 2.8.8 1.3.69 2.8.9 1.3.70 2.9.0 1.3.71 2.9.1 1.3.72 2.9.2 1.3.73 2.9.3 1.3.74 2.9.4 1.3.75 2.9.5 1.3.76 2.9.6 1.3.77 2.9.7 1.3.78 2.9.8 1.3.79 2.9.9 1.3.80 3.0.0 1.3.81 3.0.1 1.3.82 3.0.2 1.3.83 3.0.3 1.3.84 3.0.4 1.3.85 3.0.5 1.3.86 3.0.6 1.3.87 3.0.7 1.3.88 3.0.8 1.3.89 3.0.9 1.3.90 3.1.0 1.3.91 3.1.1 1.3.92 3.1.2 1.3.93 3.1.3 1.3.94 3.1.4 1.3.95 3.1.5 1.3.96 3.1.6 1.3.97 3.1.7 1.3.98 3.1.8 1.3.99 3.1.9 1.4.0 3.2.0 1.4.1 3.2.1 1.4.2 3.2.2 1.4.3 3.2.3 1.4.4 3.2.4 1.4.5 3.2.5 1.4.6 3.2.6 1.4.7 3.2.7 1.4.8 3.2.8 1.4.9 3.2.9 1.5.0 3.3.0 1.5.1 3.3.1 1.5.2 3.3.2 1.5.3 3.3.3 1.5.4 3.3.4 1.5.5 3.3.5 1.5.6 3.3.6 1.5.7 3.3.7 1.5.8 3.3.8 1.5.9 3.3.9 1.6.0 3.4.0 1.6.1 3.4.1 1.6.2 3.4.2 1.6.3 3.4.3 1.6.5 3.4.4 1.6.51 3.4.5 1.6.52 3.4.6 1.6.53 1.6.54 1.6.55 1.6.56 1.6.57 1.6.58 1.6.59 1.6.60 1.6.61 1.6.62 1.6.63 1.6.64 1.6.65 1.6.66 1.6.67 1.6.68 trunk 1.6.69 0.0.1 1.6.70 0.0.2 1.6.71 0.0.3 1.6.72 0.0.4 1.6.73 0.0.5 1.6.74 0.0.6 1.6.75 0.0.7 1.6.76 0.0.8 1.6.77 0.0.9 1.6.78 0.1.0 1.6.79 0.1.1 1.6.81 0.1.2 1.6.82 0.1.3 1.6.83 0.1.4 1.6.84 0.1.5 1.6.85 0.1.6 1.6.86 0.1.7 1.6.87 0.1.8 1.6.88 0.1.9 1.6.89 0.2.0 1.6.90
ai-engine / classes / modules / chatbot.php
ai-engine / classes / modules Last commit date
assistants.php 3 years ago chatbot-chatgpt.css 3 years ago chatbot-chatgpt.scss 3 years ago chatbot.php 3 years ago
chatbot.php
599 lines
1 <?php
2
3 class Meow_MWAI_Modules_Chatbot {
4 private $core = null;
5 private $namespace = 'ai-chatbot/v1';
6
7 public function __construct() {
8 global $mwai_core;
9 $this->core = $mwai_core;
10 if ( is_admin() ) { return; }
11 add_shortcode( 'mwai_chat', array( $this, 'chat' ) );
12 add_shortcode( 'mwai_chatbot', array( $this, 'chat' ) );
13 add_shortcode( 'mwai_imagesbot', array( $this, 'imageschat' ) );
14 add_action( 'rest_api_init', array( $this, 'rest_api_init' ) );
15 if ( $this->core->get_option( 'shortcode_chat_inject' ) ) {
16 add_action( 'wp_body_open', array( $this, 'inject_chat' ) );
17 }
18
19 // Only for test now, but later we should probably import the JS/CSS
20 if ( $this->core->get_option( 'shortcode_chat_syntax_highlighting' ) ) {
21 wp_enqueue_script( 'mwai_chatbot',
22 '//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js', [], null, false );
23 wp_enqueue_style( 'mwai_chatbot',
24 '//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/stackoverflow-dark.min.css' );
25 }
26
27 if ( $this->core->get_option( 'shortcode_chat_styles' ) ) {
28 add_filter( 'mwai_chatbot_style', [ $this, 'apply_chat_styles' ], 10, 2 );
29 }
30
31 }
32
33 function rest_api_init() {
34 try {
35 register_rest_route( $this->namespace, '/chat', array(
36 'methods' => 'POST',
37 'callback' => array( $this, 'rest_chat' ),
38 'permission_callback' => '__return_true'
39 ) );
40 register_rest_route( $this->namespace, '/imagesbot', array(
41 'methods' => 'POST',
42 'callback' => array( $this, 'rest_imagesbot' ),
43 'permission_callback' => '__return_true'
44 ) );
45 }
46 catch ( Exception $e ) {
47 var_dump( $e );
48 }
49 }
50
51 function chatgpt_style( $id ) {
52 $css = file_get_contents( MWAI_PATH . '/classes/modules/chatbot-chatgpt.css' );
53 $css = str_replace( '#mwai-chat-id', "#mwai-chat-{$id}", $css );
54 return "<style>" . $css . "</style>";
55 }
56
57 function rest_chat( $request ) {
58 try {
59 $params = $request->get_json_params();
60 $session = $params['session'];
61 $env = $params['env'];
62 $prompt = $params['prompt'];
63 $model = $params['model'];
64 $temperature = $params['temperature'];
65 $maxTokens = intval( $params['maxTokens'] );
66 $apiKey = $params['apiKey'];
67 $stop = $params['stop'];
68 $query = new Meow_MWAI_QueryText( $prompt, 1024 );
69 if ( $model ) {
70 $query->setModel( $model );
71 }
72 if ( $temperature ) {
73 $query->setTemperature( $temperature );
74 }
75 if ( $maxTokens ) {
76 $query->setMaxTokens( $maxTokens );
77 }
78 if ( $stop ) {
79 $query->setStop( $stop );
80 }
81 if ( $apiKey ) {
82 $query->setApiKey( $apiKey );
83 }
84 if ( $env ) {
85 $query->setEnv( $env );
86 }
87 if ( $session ) {
88 $query->setSession( $session );
89 }
90 $answer = $this->core->ai->run( $query );
91 $rawText = $answer->result;
92 $html = apply_filters( 'mwai_chatbot_answer', $rawText );
93 $html = $this->core->markdown_to_html( $rawText );
94 return new WP_REST_Response([ 'success' => true, 'answer' => $rawText,
95 'html' => $html, 'usage' => $answer->usage ], 200 );
96 }
97 catch ( Exception $e ) {
98 return new WP_REST_Response([ 'success' => false, 'message' => $e->getMessage() ], 500 );
99 }
100 }
101
102 function rest_imagesbot( $request ) {
103 try {
104 $params = $request->get_json_params();
105 $session = $params['session'];
106 $env = $params['env'];
107 $prompt = $params['prompt'];
108 $maxResults = $params['maxResults'];
109 $apiKey = $params['apiKey'];
110 $query = new Meow_MWAI_QueryImage( $prompt );
111 if ( $maxResults ) {
112 $query->setMaxResults( $maxResults );
113 }
114 if ( $apiKey ) {
115 $query->setApiKey( $apiKey );
116 }
117 if ( $env ) {
118 $query->setEnv( $env );
119 }
120 if ( $session ) {
121 $query->setSession( $session );
122 }
123 $answer = $this->core->ai->run( $query );
124 return new WP_REST_Response([ 'success' => true, 'images' => $answer->results, 'usage' => $answer->usage ], 200 );
125 }
126 catch ( Exception $e ) {
127 return new WP_REST_Response([ 'success' => false, 'message' => $e->getMessage() ], 500 );
128 }
129 }
130
131 function apply_chat_styles( $css, $chatbotId ) {
132 $chatStyles = $this->core->get_option( 'shortcode_chat_styles' );
133 return preg_replace_callback( '/--mwai-(\w+):\s*([^;]+);/', function ( $matches ) use ($chatStyles ) {
134 if( isset( $chatStyles[$matches[1]] ) ) {
135 return "--mwai-" . $matches[1] . ": " . $chatStyles[$matches[1]] . ";";
136 }
137 return $matches[0];
138 }, $css );
139 }
140
141 function inject_chat() {
142 $params = $this->core->get_option( 'shortcode_chat_params' );
143 echo $this->chat( $params );
144 }
145
146 function imageschat( $atts ) {
147 $atts['mode'] = 'images';
148 return $this->chat( $atts );
149 }
150
151 function getCurrentUser() {
152 if ( is_user_logged_in() ) {
153 return wp_get_current_user();
154 }
155 return null;
156 }
157
158 function handlePlaceholders( $data ) {
159 if ( strpos( $data, '{' ) === false ) {
160 return $data;
161 }
162 $placeholders_meta = [ '{FIRST_NAME}', '{LAST_NAME}' ];
163 $placeholders_data = [ '{USER_LOGIN}', '{DISPLAY_NAME}' ];
164 $user = $this->getCurrentUser();
165 if ( $user ) {
166 foreach ( $placeholders_meta as $placeholder ) {
167 if ( strpos( $data, $placeholder ) === false ) { continue; }
168 $lcPlaceholder = substr( strtolower( $placeholder ), 1, -1 );
169 $value = get_user_meta( $user->ID, $lcPlaceholder, true );
170 $data = str_replace( $placeholder, $value, $data );
171 }
172 foreach ( $placeholders_data as $placeholder ) {
173 if ( strpos( $data, $placeholder ) === false ) { continue; }
174 $lcPlaceholder = substr( strtolower( $placeholder ), 1, -1 );
175 $value = $user->data->$lcPlaceholder;
176 $data = str_replace( $placeholder, $value, $data );
177 }
178 }
179 return $data;
180 }
181
182 function formatUserName( $userName ) {
183 // Default avatar
184 if ( empty( $userName ) ) {
185 $user = $this->getCurrentUser();
186 if ( $user ) {
187 // Gravatar
188 $userName = '<div class="mwai-avatar"><img src="' . get_avatar_url( $user->user_email ) . '" /></div>';
189 }
190 else {
191 // Default avatar
192 $userName = '<div class="mwai-avatar mwai-svg"><img src="' . MWAI_URL . '/images/avatar-user.svg" /></div>';
193 }
194 }
195 // Custom avatar
196 else if ( $this->core->isUrl( $userName ) ) {
197 $userName = '<div class="mwai-avatar"><img src="' . $userName . '" /></div>';
198 }
199 // Placeholders
200 else {
201 $userName = $this->handlePlaceholders( $userName );
202 }
203 return $userName;
204 }
205
206 function formatAiName( $aiName ) {
207 // Default avatar
208 if ( empty( $aiName ) ) {
209 $aiName = '<div class="mwai-avatar mwai-svg"><img src="' . MWAI_URL . '/images/avatar-ai.svg" /></div>';
210 }
211 // Custom avatar
212 else if ( $this->core->isUrl( $aiName ) ) {
213 $aiName = '<div class="mwai-avatar"><img src="' . $aiName . '" /></div>';
214 }
215 return $aiName;
216 }
217
218 function chat( $atts ) {
219 // Use the core default parameters, or the user default parameters
220 $override = $this->core->get_option( 'shortcode_chat_params_override' );
221 $defaults_params = $override ? $this->core->get_option( 'shortcode_chat_params' ) :
222 $this->core->get_option( 'shortcode_chat_default_params' );
223
224 // Give a chance to modify the default parameters one last time
225 $defaults = apply_filters( 'mwai_chatbot_params_defaults', $defaults_params );
226
227 // Make sure all the mandatory params are set
228 foreach ( $this->core->defaultChatbotParams as $key => $value ) {
229 if ( !isset( $defaults[$key] ) ) {
230 $defaults[$key] = $value;
231 }
232 }
233
234 // Override with the shortcode, and before/after filters
235 $atts = apply_filters( 'mwai_chatbot_params_before', $atts );
236 $atts = shortcode_atts( $defaults, $atts );
237 $atts = apply_filters( 'mwai_chatbot_params', $atts );
238
239 // UI Parameters
240 $aiName = addslashes( trim($atts['ai_name']) );
241 $userName = addslashes( trim($atts['user_name']) );
242 $sysName = addslashes( trim($atts['sys_name']) );
243 $context = addslashes( $atts['context'] );
244 $context = preg_replace( '/\v+/', "\\n", $context );
245 $textSend = addslashes( trim( $atts['text_send'] ) );
246 $textClear = addslashes( trim( $atts['text_clear'] ) );
247 $textInputPlaceholder = addslashes( trim( $atts['text_input_placeholder'] ) );
248 $startSentence = addslashes( trim( $atts['start_sentence'] ) );
249 $window = filter_var( $atts['window'], FILTER_VALIDATE_BOOLEAN );
250 $fullscreen = filter_var( $atts['fullscreen'], FILTER_VALIDATE_BOOLEAN );
251 $icon = addslashes( trim($atts['icon']) );
252 $icon_position = addslashes( trim($atts['icon_position']) );
253 $style = $atts['style'];
254
255 // Validade & Enhance UI Parameters
256 $aiName = $this->formatAiName( $aiName );
257 $userName = $this->formatUserName( $userName );
258
259 // Chatbot System Parameters
260 $id = empty( $atts['id'] ) ? uniqid() : $atts['id'];
261 $memorizeChat = !empty( $atts['id'] );
262 $id = preg_replace( '/[^a-zA-Z0-9]/', '', $id );
263 $env = $atts['env'];
264 $mode = $atts['mode'];
265 $maxResults = $atts['max_results'];
266 $sessionId = $this->core->get_session_id();
267 $rest_nonce = wp_create_nonce( 'wp_rest' );
268 $casuallyFineTunedPrevious = boolval( $atts['casually_fined_tuned'] );
269 $casuallyFineTuned = $casuallyFineTunedPrevious ? true : boolval( $atts['casually_fine_tuned'] );
270 $promptEnding = addslashes( trim( $atts['prompt_ending'] ) );
271 $completionEnding = addslashes( trim( $atts['completion_ending'] ) );
272 if ( $casuallyFineTuned ) {
273 $promptEnding = "\\n\\n===\\n\\n";
274 $completionEnding = "\\n\\n";
275 }
276
277 // OpenAI Parameters
278 $model = $atts['model'];
279 $temperature = $atts['temperature'];
280 $maxTokens = $atts['max_tokens'];
281 $apiKey = $atts['api_key'];
282
283 // Named functions
284 $onSentClickFn = "mwai_{$id}_onSendClick";
285 $addReplyFn = "mwai_{$id}_addReply";
286 $initChatBotFn = "mwai_{$id}_initChatBot";
287 $setButtonTextFn = "mwai_{$id}_setButtonText";
288
289 // Variables
290 $apiUrl = get_rest_url( null, $mode === 'images' ? 'ai-chatbot/v1/imagesbot' : 'ai-chatbot/v1/chat' );
291 $onGoingPrompt = "mwai_{$id}_onGoingPrompt";
292 $memorizedChat = "mwai_{$id}_memorizedChat";
293 $baseClasses = "mwai-chat";
294 $baseClasses .= ( $window ? " mwai-window" : "" );
295 $baseClasses .= ( !$window && $fullscreen ? " mwai-fullscreen" : "" );
296 $baseClasses .= ( $style === 'chatgpt' ? " mwai-chatgpt" : "" );
297 $baseClasses .= ( $window && !empty( $icon_position ) ? (" mwai-" . $icon_position) : "" );
298
299 // Output CSS
300 ob_start();
301 $style_content = "";
302 if ( $style === 'chatgpt' ) {
303 $style_content = $this->chatgpt_style( $id, $style );
304 }
305 echo apply_filters( 'mwai_chatbot_style', $style_content, $id );
306
307 // Output HTML & CSS
308 $chatStyles = $this->core->get_option( 'shortcode_chat_styles' );
309 $iconUrl = MWAI_URL . '/images/chat-green.svg';
310 if ( !empty( $icon ) ) {
311 $iconUrl = $icon;
312 }
313 else if ( !empty( $chatStyles ) && isset( $chatStyles['avatar'] ) ) {
314 $url = $chatStyles['avatar'];
315 $iconUrl = $this->core->isUrl( $url ) ? $url : (MWAI_URL . 'images/' . $chatStyles['avatar']);
316 }
317 ?>
318 <div id="mwai-chat-<?= $id ?>" class="<?= $baseClasses ?>">
319 <?php if ( $window ) { ?>
320 <div class="mwai-open-button">
321 <img width="64" height="64" src="<?= $iconUrl ?>" />
322 </div>
323 <div class="mwai-header">
324 <?php if ( $fullscreen ) { ?>
325 <div class="mwai-resize-button"></div>
326 <?php } ?>
327 <div class="mwai-close-button"></div>
328 </div>
329 <?php } ?>
330 <div class="mwai-content">
331 <div class="mwai-conversation">
332 </div>
333 <div class="mwai-input">
334 <textarea rows="1" placeholder="<?= $textInputPlaceholder ?>"></textarea>
335 <button><span><?= $textSend ?></span></button>
336 </div>
337 </div>
338 </div>
339
340 <script>
341 (function () {
342 let <?= $onGoingPrompt ?> = '<?= $context ?>' + '\n\n';
343 let isMobile = window.matchMedia("only screen and (max-width: 760px)").matches;
344 let isWindow = <?= $window ? 'true' : 'false' ?>;
345 let isFullscreen = <?= $fullscreen ? 'true' : 'false' ?>;
346 let mode = '<?= $mode ?>';
347 let memorizeChat = <?= $memorizeChat ? 'true' : 'false' ?>;
348 let <?= $memorizedChat ?> = [];
349
350 // Set button text
351 function <?= $setButtonTextFn ?>() {
352 let input = document.querySelector('#mwai-chat-<?= $id ?> .mwai-input textarea');
353 let button = document.querySelector('#mwai-chat-<?= $id ?> .mwai-input button');
354 if (<?= $memorizedChat ?>.length < 2) {
355 button.innerHTML = '<span><?= $textSend ?></span>';
356 }
357 else if (!input.value.length) {
358 button.innerHTML = '<span><?= $textClear ?></span>';
359 }
360 else {
361 button.innerHTML = '<span><?= $textSend ?></span>';
362 }
363 }
364
365 // Push the reply in the conversation
366 function <?= $addReplyFn ?>(text, type = 'user') {
367 var conversation = document.querySelector('#mwai-chat-<?= $id ?> .mwai-conversation');
368
369 if (memorizeChat) {
370 <?= $memorizedChat ?>.push({ text, type });
371 localStorage.setItem('mwai-chat-<?= $id ?>', JSON.stringify(<?= $memorizedChat ?>));
372 }
373
374 // If text is array, then it's image URLs. Let's create a simple gallery in HTML in $text.
375 if (Array.isArray(text)) {
376 var newText = '<div class="mwai-gallery">';
377 for (var i = 0; i < text.length; i++) {
378 newText += '<a href="' + text[i] + '" target="_blank"><img src="' + text[i] + '" />';
379 }
380 text = newText + '</div>';
381 }
382
383 var mwaiClasses = 'mwai-reply';
384 if (type === 'ai') {
385 mwaiClasses += ' mwai-ai';
386 }
387 else if (type === 'system') {
388 mwaiClasses += ' mwai-system';
389 }
390 else {
391 mwaiClasses += ' mwai-user';
392 }
393 var html = '<div class="' + mwaiClasses + '">';
394 if (type === 'ai') {
395 html += '<span class="mwai-name"><?= $aiName ?></span>';
396 }
397 else if (type === 'system') {
398 html += '<span class="mwai-name"><?= $sysName ?></span>';
399 }
400 else {
401 html += '<span class="mwai-name"><?= $userName ?></span>';
402 }
403 html += '<span class="mwai-text">' + text + '</span>';
404 html += '</div>';
405 conversation.innerHTML += html;
406 conversation.scrollTop = conversation.scrollHeight;
407 <?= $setButtonTextFn ?>();
408
409 // Syntax coloring
410 if (typeof hljs !== 'undefined') {
411 document.querySelectorAll('pre code').forEach((el) => {
412 hljs.highlightElement(el);
413 });
414 }
415 }
416
417 // Function to request the completion
418 function <?= $onSentClickFn ?>() {
419 let input = document.querySelector('#mwai-chat-<?= $id ?> .mwai-input textarea');
420 let inputText = input.value.trim();
421
422 // Reset the conversation if empty
423 if (inputText === '') {
424 <?= $onGoingPrompt ?> = '<?= $context ?>' + '\n\n';
425 document.querySelector('#mwai-chat-<?= $id ?> .mwai-conversation').innerHTML = '';
426 localStorage.removeItem('mwai-chat-<?= $id ?>');
427 <?= $memorizedChat ?> = [];
428 <?= $addReplyFn ?>('<?= $startSentence ?>', 'ai');
429 return;
430 }
431
432 // Disable the button
433 var button = document.querySelector('#mwai-chat-<?= $id ?> .mwai-input button');
434 button.disabled = true;
435
436 // Add the user reply
437 <?= $addReplyFn ?>(inputText, 'user');
438 <?= $onGoingPrompt ?> += '<?= $userName ?>' + inputText + '\n';
439 input.value = '';
440 input.setAttribute('rows', 1);
441 input.disabled = true;
442
443 // Let's build the prompt depending on the "system"
444 <?= $onGoingPrompt ?> += '<?= $aiName ?>';
445 let prompt = <?= $onGoingPrompt ?>;
446 if (<?= $casuallyFineTuned ? 1 : 0 ?>) {
447 prompt = inputText + '<?= $promptEnding ?>';
448 }
449
450 // Prompt for the images
451 const data = mode === 'images' ? {
452 env: '<?= $env ?>',
453 session: '<?= $sessionId ?>',
454 prompt: inputText,
455 maxResults: <?= $maxResults ?>,
456 model: '<?= $atts['model'] ?>',
457 apiKey: '<?= $atts['api_key'] ?>',
458 // Prompt for the chat
459 } : {
460 env: '<?= $env ?>',
461 session: '<?= $sessionId ?>',
462 prompt: prompt,
463 userName: '<?= $userName ?>',
464 aiName: '<?= $aiName ?>',
465 model: '<?= $model ?>',
466 temperature: '<?= $temperature ?>',
467 maxTokens: '<?= $maxTokens ?>',
468 stop: '<?= $completionEnding ?>',
469 maxResults: '<?= $maxResults ?>',
470 apiKey: '<?= $apiKey ?>',
471 };
472 console.log('[BOT] Sent: ', data);
473 fetch('<?= $apiUrl ?>', { method: 'POST', headers: {
474 'Content-Type': 'application/json',
475 'X-WP-Nonce': '<?= $rest_nonce ?>'
476 },
477 body: JSON.stringify(data)
478 })
479 .then(response => response.json())
480 .then(data => {
481 console.log('[BOT] Recv: ', data);
482 if (!data.success) {
483 <?= $addReplyFn ?>(data.message, 'system');
484 }
485 else {
486 <?= $addReplyFn ?>(data.images ? data.images : data.html, 'ai');
487 <?= $onGoingPrompt ?> += data.answer + '\n';
488 }
489 button.disabled = false;
490 input.disabled = false;
491
492 // Only focus only on desktop (to avoid the mobile keyboard to kick-in)
493 if (!isMobile) {
494 input.focus();
495 }
496 })
497 .catch(error => {
498 console.error(error);
499 button.disabled = false;
500 input.disabled = false;
501 });
502 }
503
504 // Keep the textarea height in sync with the content
505 function mwaiSetTextAreaHeight(textarea, lines) {
506 var rows = textarea.getAttribute('rows');
507 if (lines !== rows) {
508 textarea.setAttribute('rows', lines > 5 ? 5 : lines);
509 }
510 }
511
512 // Init the chatbot
513 function <?= $initChatBotFn ?>() {
514 var input = document.querySelector('#mwai-chat-<?= $id ?> .mwai-input textarea');
515 var button = document.querySelector('#mwai-chat-<?= $id ?> .mwai-input button');
516
517 input.addEventListener('keypress', (event) => {
518 let text = event.target.value;
519 if (event.keyCode === 13 && !text.length && !event.shiftKey) {
520 event.preventDefault();
521 return;
522 }
523 if (event.keyCode === 13 && text.length && !event.shiftKey) {
524 <?= $onSentClickFn ?>();
525 }
526 });
527 input.addEventListener('keydown', (event) => {
528 var rows = input.getAttribute('rows');
529 if (event.keyCode === 13 && event.shiftKey) {
530 var lines = input.value.split('\n').length + 1;
531 mwaiSetTextAreaHeight(input, lines);
532 }
533 });
534 input.addEventListener('keyup', (event) => {
535 var rows = input.getAttribute('rows');
536 var lines = input.value.split('\n').length ;
537 mwaiSetTextAreaHeight(input, lines);
538 <?= $setButtonTextFn ?>();
539 });
540
541 button.addEventListener('click', (event) => {
542 <?= $onSentClickFn ?>();
543 });
544
545 // If window, add event listener to mwai-open-button and mwai-close-button
546 if ( isWindow ) {
547 var openButton = document.querySelector('#mwai-chat-<?= $id ?> .mwai-open-button');
548 openButton.addEventListener('click', (event) => {
549 var chat = document.querySelector('#mwai-chat-<?= $id ?>');
550 chat.classList.add('mwai-open');
551 // Only focus only on desktop (to avoid the mobile keyboard to kick-in)
552 if (!isMobile) {
553 input.focus();
554 }
555 });
556 var closeButton = document.querySelector('#mwai-chat-<?= $id ?> .mwai-close-button');
557 closeButton.addEventListener('click', (event) => {
558 var chat = document.querySelector('#mwai-chat-<?= $id ?>');
559 chat.classList.remove('mwai-open');
560 });
561 if (isFullscreen) {
562 var resizeButton = document.querySelector('#mwai-chat-<?= $id ?> .mwai-resize-button');
563 resizeButton.addEventListener('click', (event) => {
564 var chat = document.querySelector('#mwai-chat-<?= $id ?>');
565 chat.classList.toggle('mwai-fullscreen');
566 });
567 }
568 }
569
570 // Get back the previous chat if any for the same ID
571 var chatHistory = [];
572 if (memorizeChat) {
573 chatHistory = localStorage.getItem('mwai-chat-<?= $id ?>');
574 if (chatHistory) {
575 chatHistory = JSON.parse(chatHistory);
576 chatHistory = chatHistory.filter(x => x && x.text && x.type);
577 chatHistory.forEach(x => { <?= $addReplyFn ?>(x.text, x.type) });
578 }
579 else {
580 chatHistory = [];
581 }
582 }
583 if (chatHistory.length === 0) {
584 <?= $addReplyFn ?>('<?= $startSentence ?>', 'ai');
585 }
586 }
587
588 // Let's go totally meoooow on this!
589 <?= $initChatBotFn ?>();
590 })();
591 </script>
592
593 <?php
594 $output = ob_get_contents();
595 ob_end_clean();
596 $output = apply_filters( 'mwai_chatbot', $output, $atts );
597 return $output;
598 }
599 }