PluginProbe ʕ •ᴥ•ʔ
AI Engine – The Chatbot, AI Framework & MCP for WordPress / 0.8.3
AI Engine – The Chatbot, AI Framework & MCP for WordPress v0.8.3
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
603 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 add_action( 'wp_footer', array( $this, 'inject_chat' ) );
18 }
19
20 // Only for test now, but later we should probably import the JS/CSS
21 if ( $this->core->get_option( 'shortcode_chat_syntax_highlighting' ) ) {
22 wp_enqueue_script( 'mwai_chatbot',
23 '//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js', [], null, false );
24 wp_enqueue_style( 'mwai_chatbot',
25 '//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/stackoverflow-dark.min.css' );
26 }
27
28 if ( $this->core->get_option( 'shortcode_chat_styles' ) ) {
29 add_filter( 'mwai_chatbot_style', [ $this, 'apply_chat_styles' ], 10, 2 );
30 }
31
32 }
33
34 function rest_api_init() {
35 try {
36 register_rest_route( $this->namespace, '/chat', array(
37 'methods' => 'POST',
38 'callback' => array( $this, 'rest_chat' ),
39 'permission_callback' => '__return_true'
40 ) );
41 register_rest_route( $this->namespace, '/imagesbot', array(
42 'methods' => 'POST',
43 'callback' => array( $this, 'rest_imagesbot' ),
44 'permission_callback' => '__return_true'
45 ) );
46 }
47 catch ( Exception $e ) {
48 var_dump( $e );
49 }
50 }
51
52 function chatgpt_style( $id ) {
53 $css = file_get_contents( MWAI_PATH . '/classes/modules/chatbot-chatgpt.css' );
54 $css = str_replace( '#mwai-chat-id', "#mwai-chat-{$id}", $css );
55 return "<style>" . $css . "</style>";
56 }
57
58 function rest_chat( $request ) {
59 try {
60 $params = $request->get_json_params();
61 $session = $params['session'];
62 $env = $params['env'];
63 $prompt = $params['prompt'];
64 $model = $params['model'];
65 $temperature = $params['temperature'];
66 $maxTokens = intval( $params['maxTokens'] );
67 $apiKey = $params['apiKey'];
68 $stop = $params['stop'];
69 $query = new Meow_MWAI_QueryText( $prompt, 1024 );
70 if ( $model ) {
71 $query->setModel( $model );
72 }
73 if ( $temperature ) {
74 $query->setTemperature( $temperature );
75 }
76 if ( $maxTokens ) {
77 $query->setMaxTokens( $maxTokens );
78 }
79 if ( $stop ) {
80 $query->setStop( $stop );
81 }
82 if ( $apiKey ) {
83 $query->setApiKey( $apiKey );
84 }
85 if ( $env ) {
86 $query->setEnv( $env );
87 }
88 if ( $session ) {
89 $query->setSession( $session );
90 }
91 $answer = $this->core->ai->run( $query );
92 $rawText = $answer->result;
93 $html = apply_filters( 'mwai_chatbot_answer', $rawText );
94 $html = $this->core->markdown_to_html( $rawText );
95 return new WP_REST_Response([ 'success' => true, 'answer' => $rawText,
96 'html' => $html, 'usage' => $answer->usage ], 200 );
97 }
98 catch ( Exception $e ) {
99 return new WP_REST_Response([ 'success' => false, 'message' => $e->getMessage() ], 500 );
100 }
101 }
102
103 function rest_imagesbot( $request ) {
104 try {
105 $params = $request->get_json_params();
106 $session = $params['session'];
107 $env = $params['env'];
108 $prompt = $params['prompt'];
109 $maxResults = $params['maxResults'];
110 $apiKey = $params['apiKey'];
111 $query = new Meow_MWAI_QueryImage( $prompt );
112 if ( $maxResults ) {
113 $query->setMaxResults( $maxResults );
114 }
115 if ( $apiKey ) {
116 $query->setApiKey( $apiKey );
117 }
118 if ( $env ) {
119 $query->setEnv( $env );
120 }
121 if ( $session ) {
122 $query->setSession( $session );
123 }
124 $answer = $this->core->ai->run( $query );
125 return new WP_REST_Response([ 'success' => true, 'images' => $answer->results, 'usage' => $answer->usage ], 200 );
126 }
127 catch ( Exception $e ) {
128 return new WP_REST_Response([ 'success' => false, 'message' => $e->getMessage() ], 500 );
129 }
130 }
131
132 function apply_chat_styles( $css, $chatbotId ) {
133 $chatStyles = $this->core->get_option( 'shortcode_chat_styles' );
134 return preg_replace_callback( '/--mwai-(\w+):\s*([^;]+);/', function ( $matches ) use ($chatStyles ) {
135 if( isset( $chatStyles[$matches[1]] ) ) {
136 return "--mwai-" . $matches[1] . ": " . $chatStyles[$matches[1]] . ";";
137 }
138 return $matches[0];
139 }, $css );
140 }
141
142 function inject_chat() {
143 $params = $this->core->get_option( 'shortcode_chat_params' );
144 echo $this->chat( $params );
145 }
146
147 function imageschat( $atts ) {
148 $atts['mode'] = 'images';
149 return $this->chat( $atts );
150 }
151
152 function getCurrentUser() {
153 if ( is_user_logged_in() ) {
154 return wp_get_current_user();
155 }
156 return null;
157 }
158
159 function handlePlaceholders( $data ) {
160 if ( strpos( $data, '{' ) === false ) {
161 return $data;
162 }
163 $placeholders_meta = [ '{FIRST_NAME}', '{LAST_NAME}' ];
164 $placeholders_data = [ '{USER_LOGIN}', '{DISPLAY_NAME}' ];
165 $user = $this->getCurrentUser();
166 if ( $user ) {
167 foreach ( $placeholders_meta as $placeholder ) {
168 if ( strpos( $data, $placeholder ) === false ) { continue; }
169 $lcPlaceholder = substr( strtolower( $placeholder ), 1, -1 );
170 $value = get_user_meta( $user->ID, $lcPlaceholder, true );
171 $data = str_replace( $placeholder, $value, $data );
172 }
173 foreach ( $placeholders_data as $placeholder ) {
174 if ( strpos( $data, $placeholder ) === false ) { continue; }
175 $lcPlaceholder = substr( strtolower( $placeholder ), 1, -1 );
176 $value = $user->data->$lcPlaceholder;
177 $data = str_replace( $placeholder, $value, $data );
178 }
179 }
180 return $data;
181 }
182
183 function formatUserName( $userName ) {
184 // Default avatar
185 if ( empty( $userName ) ) {
186 $user = $this->getCurrentUser();
187 if ( $user ) {
188 // Gravatar
189 $userName = '<div class="mwai-avatar"><img src="' . get_avatar_url( $user->user_email ) . '" /></div>';
190 }
191 else {
192 // Default avatar
193 $userName = '<div class="mwai-avatar mwai-svg"><img src="' . MWAI_URL . '/images/avatar-user.svg" /></div>';
194 }
195 }
196 // Custom avatar
197 else if ( $this->core->isUrl( $userName ) ) {
198 $userName = '<div class="mwai-avatar"><img src="' . $userName . '" /></div>';
199 }
200 // Placeholders
201 else {
202 $userName = $this->handlePlaceholders( $userName );
203 }
204 return $userName;
205 }
206
207 function formatAiName( $aiName ) {
208 // Default avatar
209 if ( empty( $aiName ) ) {
210 $aiName = '<div class="mwai-avatar mwai-svg"><img src="' . MWAI_URL . '/images/avatar-ai.svg" /></div>';
211 }
212 // Custom avatar
213 else if ( $this->core->isUrl( $aiName ) ) {
214 $aiName = '<div class="mwai-avatar"><img src="' . $aiName . '" /></div>';
215 }
216 return $aiName;
217 }
218
219 function chat( $atts ) {
220 // Use the core default parameters, or the user default parameters
221 $override = $this->core->get_option( 'shortcode_chat_params_override' );
222 $defaults_params = $override ? $this->core->get_option( 'shortcode_chat_params' ) :
223 $this->core->get_option( 'shortcode_chat_default_params' );
224
225 // Give a chance to modify the default parameters one last time
226 $defaults = apply_filters( 'mwai_chatbot_params_defaults', $defaults_params );
227
228 // Make sure all the mandatory params are set
229 foreach ( $this->core->defaultChatbotParams as $key => $value ) {
230 if ( !isset( $defaults[$key] ) ) {
231 $defaults[$key] = $value;
232 }
233 }
234
235 // Override with the shortcode, and before/after filters
236 $atts = apply_filters( 'mwai_chatbot_params_before', $atts );
237 $atts = shortcode_atts( $defaults, $atts );
238 $atts = apply_filters( 'mwai_chatbot_params', $atts );
239
240 // UI Parameters
241 $aiName = addslashes( trim($atts['ai_name']) );
242 $userName = addslashes( trim($atts['user_name']) );
243 $sysName = addslashes( trim($atts['sys_name']) );
244 $context = addslashes( $atts['context'] );
245 $context = preg_replace( '/\v+/', "\\n", $context );
246 $textSend = addslashes( trim( $atts['text_send'] ) );
247 $textClear = addslashes( trim( $atts['text_clear'] ) );
248 $textInputPlaceholder = addslashes( trim( $atts['text_input_placeholder'] ) );
249 $startSentence = addslashes( trim( $atts['start_sentence'] ) );
250 $window = filter_var( $atts['window'], FILTER_VALIDATE_BOOLEAN );
251 $fullscreen = filter_var( $atts['fullscreen'], FILTER_VALIDATE_BOOLEAN );
252 $icon = addslashes( trim($atts['icon']) );
253 $iconText = trim($atts['icon_text']);
254 $iconPosition = addslashes( trim($atts['icon_position']) );
255 $style = $atts['style'];
256
257 // Validade & Enhance UI Parameters
258 $aiName = $this->formatAiName( $aiName );
259 $userName = $this->formatUserName( $userName );
260
261 // Chatbot System Parameters
262 $id = empty( $atts['id'] ) ? uniqid() : $atts['id'];
263 $memorizeChat = !empty( $atts['id'] );
264 $id = preg_replace( '/[^a-zA-Z0-9]/', '', $id );
265 $env = $atts['env'];
266 $mode = $atts['mode'];
267 $maxResults = $atts['max_results'];
268 $sessionId = $this->core->get_session_id();
269 $rest_nonce = wp_create_nonce( 'wp_rest' );
270 $casuallyFineTuned = boolval( $atts['casually_fine_tuned'] );
271 $promptEnding = addslashes( trim( $atts['prompt_ending'] ) );
272 $completionEnding = addslashes( trim( $atts['completion_ending'] ) );
273 if ( $casuallyFineTuned ) {
274 $promptEnding = "\\n\\n===\\n\\n";
275 $completionEnding = "\\n\\n";
276 }
277
278 // OpenAI Parameters
279 $model = $atts['model'];
280 $temperature = $atts['temperature'];
281 $maxTokens = $atts['max_tokens'];
282 $apiKey = $atts['api_key'];
283
284 // Named functions
285 $onSentClickFn = "mwai_{$id}_onSendClick";
286 $addReplyFn = "mwai_{$id}_addReply";
287 $initChatBotFn = "mwai_{$id}_initChatBot";
288 $setButtonTextFn = "mwai_{$id}_setButtonText";
289
290 // Variables
291 $apiUrl = get_rest_url( null, $mode === 'images' ? 'ai-chatbot/v1/imagesbot' : 'ai-chatbot/v1/chat' );
292 $onGoingPrompt = "mwai_{$id}_onGoingPrompt";
293 $memorizedChat = "mwai_{$id}_memorizedChat";
294 $baseClasses = "mwai-chat";
295 $baseClasses .= ( $window ? " mwai-window" : "" );
296 $baseClasses .= ( !$window && $fullscreen ? " mwai-fullscreen" : "" );
297 $baseClasses .= ( $style === 'chatgpt' ? " mwai-chatgpt" : "" );
298 $baseClasses .= ( $window && !empty( $iconPosition ) ? (" mwai-" . $iconPosition) : "" );
299
300 // Output CSS
301 ob_start();
302 $style_content = "";
303 if ( $style === 'chatgpt' ) {
304 $style_content = $this->chatgpt_style( $id, $style );
305 }
306 echo apply_filters( 'mwai_chatbot_style', $style_content, $id );
307
308 // Output HTML & CSS
309 $chatStyles = $this->core->get_option( 'shortcode_chat_styles' );
310 $iconUrl = MWAI_URL . '/images/chat-green.svg';
311 if ( !empty( $icon ) ) {
312 $iconUrl = $icon;
313 }
314 else if ( !empty( $chatStyles ) && isset( $chatStyles['icon'] ) ) {
315 $url = $chatStyles['icon'];
316 $iconUrl = $this->core->isUrl( $url ) ? $url : (MWAI_URL . 'images/' . $chatStyles['icon']);
317 }
318 ?>
319 <div id="mwai-chat-<?= $id ?>" class="<?= $baseClasses ?>">
320 <?php if ( $window ) { ?>
321 <div class="mwai-open-button">
322 <?php if ( !empty( $iconText ) ) { ?>
323 <div class="mwai-icon-text"><?= $iconText ?></div>
324 <?php } ?>
325 <img width="64" height="64" src="<?= $iconUrl ?>" />
326 </div>
327 <div class="mwai-header">
328 <?php if ( $fullscreen ) { ?>
329 <div class="mwai-resize-button"></div>
330 <?php } ?>
331 <div class="mwai-close-button"></div>
332 </div>
333 <?php } ?>
334 <div class="mwai-content">
335 <div class="mwai-conversation">
336 </div>
337 <div class="mwai-input">
338 <textarea rows="1" placeholder="<?= $textInputPlaceholder ?>"></textarea>
339 <button><span><?= $textSend ?></span></button>
340 </div>
341 </div>
342 </div>
343
344 <script>
345 (function () {
346 let <?= $onGoingPrompt ?> = '<?= $context ?>' + '\n\n';
347 let isMobile = window.matchMedia("only screen and (max-width: 760px)").matches;
348 let isWindow = <?= $window ? 'true' : 'false' ?>;
349 let isFullscreen = <?= $fullscreen ? 'true' : 'false' ?>;
350 let mode = '<?= $mode ?>';
351 let memorizeChat = <?= $memorizeChat ? 'true' : 'false' ?>;
352 let <?= $memorizedChat ?> = [];
353
354 // Set button text
355 function <?= $setButtonTextFn ?>() {
356 let input = document.querySelector('#mwai-chat-<?= $id ?> .mwai-input textarea');
357 let button = document.querySelector('#mwai-chat-<?= $id ?> .mwai-input button');
358 if (<?= $memorizedChat ?>.length < 2) {
359 button.innerHTML = '<span><?= $textSend ?></span>';
360 }
361 else if (!input.value.length) {
362 button.innerHTML = '<span><?= $textClear ?></span>';
363 }
364 else {
365 button.innerHTML = '<span><?= $textSend ?></span>';
366 }
367 }
368
369 // Push the reply in the conversation
370 function <?= $addReplyFn ?>(text, type = 'user') {
371 var conversation = document.querySelector('#mwai-chat-<?= $id ?> .mwai-conversation');
372
373 if (memorizeChat) {
374 <?= $memorizedChat ?>.push({ text, type });
375 localStorage.setItem('mwai-chat-<?= $id ?>', JSON.stringify(<?= $memorizedChat ?>));
376 }
377
378 // If text is array, then it's image URLs. Let's create a simple gallery in HTML in $text.
379 if (Array.isArray(text)) {
380 var newText = '<div class="mwai-gallery">';
381 for (var i = 0; i < text.length; i++) {
382 newText += '<a href="' + text[i] + '" target="_blank"><img src="' + text[i] + '" />';
383 }
384 text = newText + '</div>';
385 }
386
387 var mwaiClasses = 'mwai-reply';
388 if (type === 'ai') {
389 mwaiClasses += ' mwai-ai';
390 }
391 else if (type === 'system') {
392 mwaiClasses += ' mwai-system';
393 }
394 else {
395 mwaiClasses += ' mwai-user';
396 }
397 var html = '<div class="' + mwaiClasses + '">';
398 if (type === 'ai') {
399 html += '<span class="mwai-name"><?= $aiName ?></span>';
400 }
401 else if (type === 'system') {
402 html += '<span class="mwai-name"><?= $sysName ?></span>';
403 }
404 else {
405 html += '<span class="mwai-name"><?= $userName ?></span>';
406 }
407 html += '<span class="mwai-text">' + text + '</span>';
408 html += '</div>';
409 conversation.innerHTML += html;
410 conversation.scrollTop = conversation.scrollHeight;
411 <?= $setButtonTextFn ?>();
412
413 // Syntax coloring
414 if (typeof hljs !== 'undefined') {
415 document.querySelectorAll('pre code').forEach((el) => {
416 hljs.highlightElement(el);
417 });
418 }
419 }
420
421 // Function to request the completion
422 function <?= $onSentClickFn ?>() {
423 let input = document.querySelector('#mwai-chat-<?= $id ?> .mwai-input textarea');
424 let inputText = input.value.trim();
425
426 // Reset the conversation if empty
427 if (inputText === '') {
428 <?= $onGoingPrompt ?> = '<?= $context ?>' + '\n\n';
429 document.querySelector('#mwai-chat-<?= $id ?> .mwai-conversation').innerHTML = '';
430 localStorage.removeItem('mwai-chat-<?= $id ?>');
431 <?= $memorizedChat ?> = [];
432 <?= $addReplyFn ?>('<?= $startSentence ?>', 'ai');
433 return;
434 }
435
436 // Disable the button
437 var button = document.querySelector('#mwai-chat-<?= $id ?> .mwai-input button');
438 button.disabled = true;
439
440 // Add the user reply
441 <?= $addReplyFn ?>(inputText, 'user');
442 <?= $onGoingPrompt ?> += '<?= $userName ?>' + inputText + '\n';
443 input.value = '';
444 input.setAttribute('rows', 1);
445 input.disabled = true;
446
447 // Let's build the prompt depending on the "system"
448 <?= $onGoingPrompt ?> += '<?= $aiName ?>';
449 let prompt = <?= $onGoingPrompt ?>;
450 if (<?= $casuallyFineTuned ? 1 : 0 ?>) {
451 prompt = inputText + '<?= $promptEnding ?>';
452 }
453
454 // Prompt for the images
455 const data = mode === 'images' ? {
456 env: '<?= $env ?>',
457 session: '<?= $sessionId ?>',
458 prompt: inputText,
459 maxResults: <?= $maxResults ?>,
460 model: '<?= $atts['model'] ?>',
461 apiKey: '<?= $atts['api_key'] ?>',
462 // Prompt for the chat
463 } : {
464 env: '<?= $env ?>',
465 session: '<?= $sessionId ?>',
466 prompt: prompt,
467 userName: '<?= $userName ?>',
468 aiName: '<?= $aiName ?>',
469 model: '<?= $model ?>',
470 temperature: '<?= $temperature ?>',
471 maxTokens: '<?= $maxTokens ?>',
472 stop: '<?= $completionEnding ?>',
473 maxResults: '<?= $maxResults ?>',
474 apiKey: '<?= $apiKey ?>',
475 };
476 console.log('[BOT] Sent: ', data);
477 fetch('<?= $apiUrl ?>', { method: 'POST', headers: {
478 'Content-Type': 'application/json',
479 'X-WP-Nonce': '<?= $rest_nonce ?>'
480 },
481 body: JSON.stringify(data)
482 })
483 .then(response => response.json())
484 .then(data => {
485 console.log('[BOT] Recv: ', data);
486 if (!data.success) {
487 <?= $addReplyFn ?>(data.message, 'system');
488 }
489 else {
490 <?= $addReplyFn ?>(data.images ? data.images : data.html, 'ai');
491 <?= $onGoingPrompt ?> += data.answer + '\n';
492 }
493 button.disabled = false;
494 input.disabled = false;
495
496 // Only focus only on desktop (to avoid the mobile keyboard to kick-in)
497 if (!isMobile) {
498 input.focus();
499 }
500 })
501 .catch(error => {
502 console.error(error);
503 button.disabled = false;
504 input.disabled = false;
505 });
506 }
507
508 // Keep the textarea height in sync with the content
509 function mwaiSetTextAreaHeight(textarea, lines) {
510 var rows = textarea.getAttribute('rows');
511 if (lines !== rows) {
512 textarea.setAttribute('rows', lines > 5 ? 5 : lines);
513 }
514 }
515
516 // Init the chatbot
517 function <?= $initChatBotFn ?>() {
518 var input = document.querySelector('#mwai-chat-<?= $id ?> .mwai-input textarea');
519 var button = document.querySelector('#mwai-chat-<?= $id ?> .mwai-input button');
520
521 input.addEventListener('keypress', (event) => {
522 let text = event.target.value;
523 if (event.keyCode === 13 && !text.length && !event.shiftKey) {
524 event.preventDefault();
525 return;
526 }
527 if (event.keyCode === 13 && text.length && !event.shiftKey) {
528 <?= $onSentClickFn ?>();
529 }
530 });
531 input.addEventListener('keydown', (event) => {
532 var rows = input.getAttribute('rows');
533 if (event.keyCode === 13 && event.shiftKey) {
534 var lines = input.value.split('\n').length + 1;
535 mwaiSetTextAreaHeight(input, lines);
536 }
537 });
538 input.addEventListener('keyup', (event) => {
539 var rows = input.getAttribute('rows');
540 var lines = input.value.split('\n').length ;
541 mwaiSetTextAreaHeight(input, lines);
542 <?= $setButtonTextFn ?>();
543 });
544
545 button.addEventListener('click', (event) => {
546 <?= $onSentClickFn ?>();
547 });
548
549 // If window, add event listener to mwai-open-button and mwai-close-button
550 if ( isWindow ) {
551 var openButton = document.querySelector('#mwai-chat-<?= $id ?> .mwai-open-button');
552 openButton.addEventListener('click', (event) => {
553 var chat = document.querySelector('#mwai-chat-<?= $id ?>');
554 chat.classList.add('mwai-open');
555 // Only focus only on desktop (to avoid the mobile keyboard to kick-in)
556 if (!isMobile) {
557 input.focus();
558 }
559 });
560 var closeButton = document.querySelector('#mwai-chat-<?= $id ?> .mwai-close-button');
561 closeButton.addEventListener('click', (event) => {
562 var chat = document.querySelector('#mwai-chat-<?= $id ?>');
563 chat.classList.remove('mwai-open');
564 });
565 if (isFullscreen) {
566 var resizeButton = document.querySelector('#mwai-chat-<?= $id ?> .mwai-resize-button');
567 resizeButton.addEventListener('click', (event) => {
568 var chat = document.querySelector('#mwai-chat-<?= $id ?>');
569 chat.classList.toggle('mwai-fullscreen');
570 });
571 }
572 }
573
574 // Get back the previous chat if any for the same ID
575 var chatHistory = [];
576 if (memorizeChat) {
577 chatHistory = localStorage.getItem('mwai-chat-<?= $id ?>');
578 if (chatHistory) {
579 chatHistory = JSON.parse(chatHistory);
580 chatHistory = chatHistory.filter(x => x && x.text && x.type);
581 chatHistory.forEach(x => { <?= $addReplyFn ?>(x.text, x.type) });
582 }
583 else {
584 chatHistory = [];
585 }
586 }
587 if (chatHistory.length === 0) {
588 <?= $addReplyFn ?>('<?= $startSentence ?>', 'ai');
589 }
590 }
591
592 // Let's go totally meoooow on this!
593 <?= $initChatBotFn ?>();
594 })();
595 </script>
596
597 <?php
598 $output = ob_get_contents();
599 ob_end_clean();
600 $output = apply_filters( 'mwai_chatbot', $output, $atts );
601 return $output;
602 }
603 }