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