PluginProbe ʕ •ᴥ•ʔ
AI Engine – The Chatbot, AI Framework & MCP for WordPress / 0.6.7
AI Engine – The Chatbot, AI Framework & MCP for WordPress v0.6.7
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
598 lines
1 <?php
2
3 class Meow_MWAI_Modules_Chatbot {
4 private $core = null;
5 private $namespace = 'ai-engine/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 $casuallyFineTuned = boolval( $atts['casually_fined_tuned'] );
269 $promptEnding = addslashes( trim( $atts['prompt_ending'] ) );
270 $completionEnding = addslashes( trim( $atts['completion_ending'] ) );
271 if ( $casuallyFineTuned ) {
272 $promptEnding = "\\n\\n===\\n\\n";
273 $completionEnding = "\\n\\n";
274 }
275
276 // OpenAI Parameters
277 $model = $atts['model'];
278 $temperature = $atts['temperature'];
279 $maxTokens = $atts['max_tokens'];
280 $apiKey = $atts['api_key'];
281
282 // Named functions
283 $onSentClickFn = "mwai_{$id}_onSendClick";
284 $addReplyFn = "mwai_{$id}_addReply";
285 $initChatBotFn = "mwai_{$id}_initChatBot";
286 $setButtonTextFn = "mwai_{$id}_setButtonText";
287
288 // Variables
289 $apiUrl = get_rest_url( null, $mode === 'images' ? 'ai-engine/v1/imagesbot' : 'ai-engine/v1/chat' );
290 $onGoingPrompt = "mwai_{$id}_onGoingPrompt";
291 $memorizedChat = "mwai_{$id}_memorizedChat";
292 $baseClasses = "mwai-chat";
293 $baseClasses .= ( $window ? " mwai-window" : "" );
294 $baseClasses .= ( !$window && $fullscreen ? " mwai-fullscreen" : "" );
295 $baseClasses .= ( $style === 'chatgpt' ? " mwai-chatgpt" : "" );
296 $baseClasses .= ( $window && !empty( $icon_position ) ? (" mwai-" . $icon_position) : "" );
297
298 // Output CSS
299 ob_start();
300 $style_content = "";
301 if ( $style === 'chatgpt' ) {
302 $style_content = $this->chatgpt_style( $id, $style );
303 }
304 echo apply_filters( 'mwai_chatbot_style', $style_content, $id );
305
306 // Output HTML & CSS
307 $chatStyles = $this->core->get_option( 'shortcode_chat_styles' );
308 $iconUrl = MWAI_URL . '/images/chat-green.svg';
309 if ( !empty( $icon ) ) {
310 $iconUrl = $icon;
311 }
312 else if ( !empty( $chatStyles ) && isset( $chatStyles['avatar'] ) ) {
313 $url = $chatStyles['avatar'];
314 $iconUrl = $this->core->isUrl( $url ) ? $url : (MWAI_URL . 'images/' . $chatStyles['avatar']);
315 }
316 ?>
317 <div id="mwai-chat-<?= $id ?>" class="<?= $baseClasses ?>">
318 <?php if ( $window ) { ?>
319 <div class="mwai-open-button">
320 <img width="64" height="64" src="<?= $iconUrl ?>" />
321 </div>
322 <div class="mwai-header">
323 <?php if ( $fullscreen ) { ?>
324 <div class="mwai-resize-button"></div>
325 <?php } ?>
326 <div class="mwai-close-button"></div>
327 </div>
328 <?php } ?>
329 <div class="mwai-content">
330 <div class="mwai-conversation">
331 </div>
332 <div class="mwai-input">
333 <textarea rows="1" placeholder="<?= $textInputPlaceholder ?>"></textarea>
334 <button><span><?= $textSend ?></span></button>
335 </div>
336 </div>
337 </div>
338
339 <script>
340 (function () {
341 let <?= $onGoingPrompt ?> = '<?= $context ?>' + '\n\n';
342 let isMobile = window.matchMedia("only screen and (max-width: 760px)").matches;
343 let isWindow = <?= $window ? 'true' : 'false' ?>;
344 let isFullscreen = <?= $fullscreen ? 'true' : 'false' ?>;
345 let mode = '<?= $mode ?>';
346 let memorizeChat = <?= $memorizeChat ? 'true' : 'false' ?>;
347 let <?= $memorizedChat ?> = [];
348
349 // Set button text
350 function <?= $setButtonTextFn ?>() {
351 let input = document.querySelector('#mwai-chat-<?= $id ?> .mwai-input textarea');
352 let button = document.querySelector('#mwai-chat-<?= $id ?> .mwai-input button');
353 if (<?= $memorizedChat ?>.length < 2) {
354 button.innerHTML = '<span><?= $textSend ?></span>';
355 }
356 else if (!input.value.length) {
357 button.innerHTML = '<span><?= $textClear ?></span>';
358 }
359 else {
360 button.innerHTML = '<span><?= $textSend ?></span>';
361 }
362 }
363
364 // Push the reply in the conversation
365 function <?= $addReplyFn ?>(text, type = 'user') {
366 var conversation = document.querySelector('#mwai-chat-<?= $id ?> .mwai-conversation');
367
368 if (memorizeChat) {
369 <?= $memorizedChat ?>.push({ text, type });
370 localStorage.setItem('mwai-chat-<?= $id ?>', JSON.stringify(<?= $memorizedChat ?>));
371 }
372
373 // If text is array, then it's image URLs. Let's create a simple gallery in HTML in $text.
374 if (Array.isArray(text)) {
375 var newText = '<div class="mwai-gallery">';
376 for (var i = 0; i < text.length; i++) {
377 newText += '<a href="' + text[i] + '" target="_blank"><img src="' + text[i] + '" />';
378 }
379 text = newText + '</div>';
380 }
381
382 var mwaiClasses = 'mwai-reply';
383 if (type === 'ai') {
384 mwaiClasses += ' mwai-ai';
385 }
386 else if (type === 'system') {
387 mwaiClasses += ' mwai-system';
388 }
389 else {
390 mwaiClasses += ' mwai-user';
391 }
392 var html = '<div class="' + mwaiClasses + '">';
393 if (type === 'ai') {
394 html += '<span class="mwai-name"><?= $aiName ?></span>';
395 }
396 else if (type === 'system') {
397 html += '<span class="mwai-name"><?= $sysName ?></span>';
398 }
399 else {
400 html += '<span class="mwai-name"><?= $userName ?></span>';
401 }
402 html += '<span class="mwai-text">' + text + '</span>';
403 html += '</div>';
404 conversation.innerHTML += html;
405 conversation.scrollTop = conversation.scrollHeight;
406 <?= $setButtonTextFn ?>();
407
408 // Syntax coloring
409 if (typeof hljs !== 'undefined') {
410 document.querySelectorAll('pre code').forEach((el) => {
411 hljs.highlightElement(el);
412 });
413 }
414 }
415
416 // Function to request the completion
417 function <?= $onSentClickFn ?>() {
418 let input = document.querySelector('#mwai-chat-<?= $id ?> .mwai-input textarea');
419 let inputText = input.value.trim();
420
421 // Reset the conversation if empty
422 if (inputText === '') {
423 <?= $onGoingPrompt ?> = '<?= $context ?>' + '\n\n';
424 document.querySelector('#mwai-chat-<?= $id ?> .mwai-conversation').innerHTML = '';
425 localStorage.removeItem('mwai-chat-<?= $id ?>');
426 <?= $memorizedChat ?> = [];
427 <?= $addReplyFn ?>('<?= $startSentence ?>', 'ai');
428 return;
429 }
430
431 // Disable the button
432 var button = document.querySelector('#mwai-chat-<?= $id ?> .mwai-input button');
433 button.disabled = true;
434
435 // Add the user reply
436 <?= $addReplyFn ?>(inputText, 'user');
437 <?= $onGoingPrompt ?> += '<?= $userName ?>' + inputText + '\n';
438 input.value = '';
439 input.setAttribute('rows', 1);
440 input.disabled = true;
441
442 // Let's build the prompt depending on the "system"
443 <?= $onGoingPrompt ?> += '<?= $aiName ?>';
444 let prompt = <?= $onGoingPrompt ?>;
445 if (<?= $casuallyFineTuned ? 1 : 0 ?>) {
446 prompt = inputText + '<?= $promptEnding ?>';
447 }
448
449 // Prompt for the images
450 const data = mode === 'images' ? {
451 env: '<?= $env ?>',
452 session: '<?= $sessionId ?>',
453 prompt: inputText,
454 maxResults: <?= $maxResults ?>,
455 model: '<?= $atts['model'] ?>',
456 apiKey: '<?= $atts['api_key'] ?>',
457 // Prompt for the chat
458 } : {
459 env: '<?= $env ?>',
460 session: '<?= $sessionId ?>',
461 prompt: prompt,
462 userName: '<?= $userName ?>',
463 aiName: '<?= $aiName ?>',
464 model: '<?= $model ?>',
465 temperature: '<?= $temperature ?>',
466 maxTokens: '<?= $maxTokens ?>',
467 stop: '<?= $completionEnding ?>',
468 maxResults: '<?= $maxResults ?>',
469 apiKey: '<?= $apiKey ?>',
470 };
471 console.log('[BOT] Sent: ', data);
472 fetch('<?= $apiUrl ?>', { method: 'POST', headers: {
473 'Content-Type': 'application/json',
474 'X-WP-Nonce': '<?= $rest_nonce ?>'
475 },
476 body: JSON.stringify(data)
477 })
478 .then(response => response.json())
479 .then(data => {
480 console.log('[BOT] Recv: ', data);
481 if (!data.success) {
482 <?= $addReplyFn ?>(data.message, 'system');
483 }
484 else {
485 <?= $addReplyFn ?>(data.images ? data.images : data.html, 'ai');
486 <?= $onGoingPrompt ?> += data.answer + '\n';
487 }
488 button.disabled = false;
489 input.disabled = false;
490
491 // Only focus only on desktop (to avoid the mobile keyboard to kick-in)
492 if (!isMobile) {
493 input.focus();
494 }
495 })
496 .catch(error => {
497 console.error(error);
498 button.disabled = false;
499 input.disabled = false;
500 });
501 }
502
503 // Keep the textarea height in sync with the content
504 function mwaiSetTextAreaHeight(textarea, lines) {
505 var rows = textarea.getAttribute('rows');
506 if (lines !== rows) {
507 textarea.setAttribute('rows', lines > 5 ? 5 : lines);
508 }
509 }
510
511 // Init the chatbot
512 function <?= $initChatBotFn ?>() {
513 var input = document.querySelector('#mwai-chat-<?= $id ?> .mwai-input textarea');
514 var button = document.querySelector('#mwai-chat-<?= $id ?> .mwai-input button');
515
516 input.addEventListener('keypress', (event) => {
517 let text = event.target.value;
518 if (event.keyCode === 13 && !text.length && !event.shiftKey) {
519 event.preventDefault();
520 return;
521 }
522 if (event.keyCode === 13 && text.length && !event.shiftKey) {
523 <?= $onSentClickFn ?>();
524 }
525 });
526 input.addEventListener('keydown', (event) => {
527 var rows = input.getAttribute('rows');
528 if (event.keyCode === 13 && event.shiftKey) {
529 var lines = input.value.split('\n').length + 1;
530 mwaiSetTextAreaHeight(input, lines);
531 }
532 });
533 input.addEventListener('keyup', (event) => {
534 var rows = input.getAttribute('rows');
535 var lines = input.value.split('\n').length ;
536 mwaiSetTextAreaHeight(input, lines);
537 <?= $setButtonTextFn ?>();
538 });
539
540 button.addEventListener('click', (event) => {
541 <?= $onSentClickFn ?>();
542 });
543
544 // If window, add event listener to mwai-open-button and mwai-close-button
545 if ( isWindow ) {
546 var openButton = document.querySelector('#mwai-chat-<?= $id ?> .mwai-open-button');
547 openButton.addEventListener('click', (event) => {
548 var chat = document.querySelector('#mwai-chat-<?= $id ?>');
549 chat.classList.add('mwai-open');
550 // Only focus only on desktop (to avoid the mobile keyboard to kick-in)
551 if (!isMobile) {
552 input.focus();
553 }
554 });
555 var closeButton = document.querySelector('#mwai-chat-<?= $id ?> .mwai-close-button');
556 closeButton.addEventListener('click', (event) => {
557 var chat = document.querySelector('#mwai-chat-<?= $id ?>');
558 chat.classList.remove('mwai-open');
559 });
560 if (isFullscreen) {
561 var resizeButton = document.querySelector('#mwai-chat-<?= $id ?> .mwai-resize-button');
562 resizeButton.addEventListener('click', (event) => {
563 var chat = document.querySelector('#mwai-chat-<?= $id ?>');
564 chat.classList.toggle('mwai-fullscreen');
565 });
566 }
567 }
568
569 // Get back the previous chat if any for the same ID
570 var chatHistory = [];
571 if (memorizeChat) {
572 chatHistory = localStorage.getItem('mwai-chat-<?= $id ?>');
573 if (chatHistory) {
574 chatHistory = JSON.parse(chatHistory);
575 chatHistory = chatHistory.filter(x => x && x.text && x.type);
576 chatHistory.forEach(x => { <?= $addReplyFn ?>(x.text, x.type) });
577 }
578 else {
579 chatHistory = [];
580 }
581 }
582 if (chatHistory.length === 0) {
583 <?= $addReplyFn ?>('<?= $startSentence ?>', 'ai');
584 }
585 }
586
587 // Let's go totally meoooow on this!
588 <?= $initChatBotFn ?>();
589 })();
590 </script>
591
592 <?php
593 $output = ob_get_contents();
594 ob_end_clean();
595 $output = apply_filters( 'mwai_chatbot', $output, $atts );
596 return $output;
597 }
598 }