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