PluginProbe ʕ •ᴥ•ʔ
AI Engine – The Chatbot, AI Framework & MCP for WordPress / 2.6.3
AI Engine – The Chatbot, AI Framework & MCP for WordPress v2.6.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 / discussions.php
ai-engine / classes / modules Last commit date
advisor.php 2 years ago chatbot.php 1 year ago discussions.php 1 year ago files.php 1 year ago gdpr.php 1 year ago security.php 1 year ago tasks.php 2 years ago wand.php 1 year ago
discussions.php
357 lines
1 <?php
2
3 class Meow_MWAI_Modules_Discussions {
4 private $wpdb = null;
5 private $core = null;
6 public $table_chats = null;
7 private $db_check = false;
8 private $namespace_admin = 'mwai/v1';
9 private $namespace_ui = 'mwai-ui/v1';
10
11 public function __construct() {
12 global $wpdb;
13 global $mwai_core;
14 $this->core = $mwai_core;
15 $this->wpdb = $wpdb;
16 $this->table_chats = $wpdb->prefix . 'mwai_chats';
17
18 if ( $this->core->get_option( 'chatbot_discussions' ) ) {
19 add_filter( 'mwai_chatbot_reply', [ $this, 'chatbot_reply' ], 10, 4 );
20 add_action( 'rest_api_init', [ $this, 'rest_api_init' ] );
21 }
22 }
23
24 public function rest_api_init() {
25
26 // Admin
27 register_rest_route( $this->namespace_admin, '/discussions/list', [
28 'methods' => 'POST',
29 'callback' => [ $this, 'rest_discussions_list' ],
30 'permission_callback' => [ $this->core, 'can_access_settings' ],
31 ] );
32 register_rest_route( $this->namespace_admin, '/discussions/delete', [
33 'methods' => 'POST',
34 'callback' => [ $this, 'rest_discussions_delete' ],
35 'permission_callback' => [ $this->core, 'can_access_settings' ],
36 ] );
37
38 // UI
39 register_rest_route( $this->namespace_ui, '/discussions/list', [
40 'methods' => 'POST',
41 'callback' => [ $this, 'rest_discussions_ui_list' ],
42 'permission_callback' => '__return_true'
43 ] );
44 }
45
46 function rest_discussions_list( $request ) {
47 try {
48 $params = $request->get_json_params();
49 $offset = $params['offset'];
50 $limit = $params['limit'];
51 $filters = $params['filters'];
52 $sort = $params['sort'];
53 $chats = $this->chats_query( [], $offset, $limit, $filters, $sort );
54 return new WP_REST_Response([ 'success' => true, 'total' => $chats['total'], 'chats' => $chats['rows'] ], 200 );
55 }
56 catch ( Exception $e ) {
57 return new WP_REST_Response([ 'success' => false, 'message' => $e->getMessage() ], 500 );
58 }
59 }
60
61 function rest_discussions_ui_list( $request ) {
62 try {
63 $params = $request->get_json_params();
64 $offset = isset( $params['offset'] ) ? $params['offset'] : 0;
65 $limit = isset( $params['limit'] ) ? $params['limit'] : 10;
66 $botId = isset( $params['botId'] ) ? $params['botId'] : null;
67 $customId = isset( $params['customId'] ) ? $params['customId'] : null;
68
69 if ( !is_null( $customId ) ) {
70 $botId = $customId;
71 }
72
73 if ( is_null( $botId ) ) {
74 return new WP_REST_Response([ 'success' => false, 'message' => "Bot ID is required." ], 200 );
75 }
76
77 $userId = get_current_user_id();
78 if ( !$userId ) {
79 return new WP_REST_Response([ 'success' => false, 'message' => "You need to be connected." ], 200 );
80 }
81 $filters = [
82 [ 'accessor' => 'user', 'value' => $userId ],
83 [ 'accessor' => 'botId', 'value' => $botId ],
84 ];
85 $chats = $this->chats_query( [], $offset, $limit, $filters );
86 return new WP_REST_Response([ 'success' => true, 'total' => $chats['total'], 'chats' => $chats['rows'] ], 200 );
87 }
88 catch ( Exception $e ) {
89 return new WP_REST_Response([ 'success' => false, 'message' => $e->getMessage() ], 500 );
90 }
91 }
92
93 function rest_discussions_delete( $request ) {
94 try {
95 $params = $request->get_json_params();
96 $chatsIds = $params['chatIds'];
97 if ( is_array( $chatsIds ) ) {
98 if ( count( $chatsIds ) === 0 ) {
99 $this->wpdb->query( "TRUNCATE TABLE $this->table_chats" );
100 }
101 foreach( $chatsIds as $chatId ) {
102 $this->wpdb->delete( $this->table_chats, [ 'chatId' => $chatId ] );
103 }
104 }
105 return new WP_REST_Response([ 'success' => true ], 200 );
106 }
107 catch ( Exception $e ) {
108 return new WP_REST_Response([ 'success' => false, 'message' => $e->getMessage() ], 500 );
109 }
110 }
111
112 // Get latest discussion for the given parameter
113 function get_discussion( $botId, $chatId ) {
114 $this->check_db();
115 $chat = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT *
116 FROM $this->table_chats
117 WHERE chatId = %s AND botId = %s", $chatId, $botId
118 ), ARRAY_A );
119 if ( $chat ) {
120 $chat['messages'] = json_decode( $chat['messages'] );
121 return $chat;
122 }
123 return null;
124 }
125
126 function chats_query( $chats = [], $offset = 0, $limit = null, $filters = null, $sort = null ) {
127 $this->check_db();
128 $offset = !empty( $offset ) ? intval( $offset ) : 0;
129 $limit = !empty( $limit ) ? intval( $limit ) : 5;
130 $filters = !empty( $filters ) ? $filters : [];
131 $this->core->sanitize_sort( $sort, 'updated', 'DESC' );
132 $query = "SELECT * FROM $this->table_chats";
133
134 // Filters
135 if ( is_array( $filters ) ) {
136 $where = array();
137 foreach ( $filters as $filter ) {
138 if ( $filter['accessor'] === 'user' ) {
139 $value = esc_sql( $filter['value'] );
140 if ( is_null( $value ) || $value === '' ) {
141 continue;
142 }
143 $isIP = filter_var( $value, FILTER_VALIDATE_IP );
144 if ( $isIP ) {
145 $where[] = "ip = '{$value}'";
146 }
147 else {
148 $where[] = "userId = '{$value}'";
149 }
150 }
151 if ( $filter['accessor'] === 'botId' ) {
152 $value = esc_sql( $filter['value'] );
153 if ( is_null( $value ) || $value === '' ) {
154 continue;
155 }
156 $where[] = "botId = '{$value}'";
157 }
158 if ( $filter['accessor'] === 'preview' ) {
159 $value = $filter['value'];
160 if ( empty( $value ) ) {
161 continue;
162 }
163 $where[] = "messages LIKE '%{$value}%'";
164 }
165 }
166 if ( count( $where ) > 0 ) {
167 $query .= " WHERE " . implode( " AND ", $where );
168 }
169 }
170
171 // Count based on this query
172 $chats['total'] = $this->wpdb->get_var( "SELECT COUNT(*) FROM ($query) AS t" );
173
174 // Order by
175 $query .= " ORDER BY " . esc_sql( $sort['accessor'] ) . " " . esc_sql( $sort['by'] );
176
177 // Limits
178 if ( $limit > 0 ) {
179 $query .= " LIMIT $offset, $limit";
180 }
181
182 $chats['rows'] = $this->wpdb->get_results( $query, ARRAY_A );
183 return $chats;
184 }
185
186 public function chatbot_reply( $rawText, $query, $params, $extra ) {
187 global $mwai_core;
188 $userIp = $mwai_core->get_ip_address();
189 $userId = $mwai_core->get_user_id();
190 $botId = isset( $params['botId'] ) ? $params['botId'] : null;
191 $chatId = $this->core->fix_chat_id( $query, $params );
192 $customId = isset( $params['customId'] ) ? $params['customId'] : null;
193 $threadId = $query instanceof Meow_MWAI_Query_Assistant ? $query->threadId : null;
194 $storeId = $query instanceof Meow_MWAI_Query_Assistant ? $query->storeId : null;
195 $now = date( 'Y-m-d H:i:s' );
196
197 if ( !empty( $customId ) ) {
198 $botId = $customId;
199 }
200 $newMessage = isset( $params['newMessage'] ) ? $params['newMessage'] : $query->get_message();
201
202 // If there is a file for "Vision", add it to the message
203 if ( isset( $query->filePurpose ) && $query->filePurpose === 'vision' && isset( $query->file ) ) {
204 $newMessage = "![Uploaded Image]({$query->file})\n" . $newMessage;
205 }
206
207 //$chatId = hash( 'sha256', $userIp . $userId . $clientChatId );
208 $this->check_db();
209 $chat = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT *
210 FROM $this->table_chats
211 WHERE chatId = %s", $chatId
212 )
213 );
214 $messageExtra = [
215 'embeddings' => isset( $extra['embeddings'] ) ? $extra['embeddings'] : null
216 ];
217 $chatExtra = [
218 'session' => $query->session,
219 'model' => $query->model,
220 ];
221 if ( !empty( $query->temperature ) ) {
222 $chatExtra['temperature'] = $query->temperature;
223 }
224 if ( !empty( $query->context ) ) {
225 $chatExtra['context'] = $query->context;
226 }
227 if ( $query instanceof Meow_MWAI_Query_Assistant ) {
228 $chatExtra['assistantId'] = $query->assistantId;
229 $chatExtra['threadId'] = $query->threadId;
230 $chatExtra['storeId'] = $query->storeId;
231 }
232 if ( $chat ) {
233 $chat->messages = json_decode( $chat->messages );
234 $chat->messages[] = [ 'role' => 'user', 'content' => $newMessage ];
235 $chat->messages[] = [ 'role' => 'assistant', 'content' => $rawText, 'extra' => $messageExtra ];
236 $chat->messages = json_encode( $chat->messages );
237 $this->wpdb->update( $this->table_chats, [
238 'userId' => $userId,
239 'messages' => $chat->messages,
240 'updated' => $now
241 ], [ 'id' => $chat->id ] );
242 }
243 else {
244 $chat = [
245 'userId' => $userId,
246 'ip' => $userIp,
247 'messages' => json_encode( [
248 [ 'role' => 'user', 'content' => $newMessage ],
249 [ 'role' => 'assistant', 'content' => $rawText, 'extra' => $messageExtra ]
250 ] ),
251 'extra' => json_encode( $chatExtra ),
252 'botId' => $botId,
253 'chatId' => $chatId,
254 'threadId' => $threadId,
255 'storeId' => $storeId,
256 'created' => $now,
257 'updated' => $now
258 ];
259 $this->wpdb->insert( $this->table_chats, $chat );
260 }
261 return $rawText;
262 }
263
264 function format_messages( $json, $format = 'html' ) {
265 $html = '';
266 if ( $format === 'html' ) {
267 try {
268 $conversation = json_decode( $json, true );
269 if ( json_last_error() !== JSON_ERROR_NONE ) {
270 return 'Invalid JSON format';
271 }
272 foreach ( $conversation as $message ) {
273 $role = ucfirst( $message['role'] );
274 $html .= '<p><strong>' . htmlspecialchars( $role ) . ':</strong> ' . htmlspecialchars( $message['content'] ) . '</p>';
275 }
276 }
277 catch ( Exception $e ) {
278 error_log( $e->getMessage() );
279 return 'Error while formatting the message';
280 }
281 }
282 $html = apply_filters( 'mwai_discussion_format_messages', $html, $json, $format );
283 return $html;
284 }
285
286 function check_db() {
287 if ( $this->db_check ) {
288 return true;
289 }
290 $this->db_check = !( strtolower(
291 $this->wpdb->get_var( "SHOW TABLES LIKE '$this->table_chats'" ) ) != strtolower( $this->table_chats )
292 );
293 if ( !$this->db_check ) {
294 $this->create_db();
295 $this->db_check = !( strtolower(
296 $this->wpdb->get_var( "SHOW TABLES LIKE '$this->table_chats'" ) ) != strtolower( $this->table_chats )
297 );
298 }
299
300 // LATER: REMOVE THIS AFTER SEPTEMBER 2023
301 // Make sure the column "userId" and "ip "exist in the $this->table_chats table
302 $this->db_check = $this->db_check && $this->wpdb->get_var( "SHOW COLUMNS FROM $this->table_chats LIKE 'userId'" );
303 if ( !$this->db_check ) {
304 $this->wpdb->query( "ALTER TABLE $this->table_chats ADD COLUMN userId BIGINT(20) NULL" );
305 $this->wpdb->query( "ALTER TABLE $this->table_chats ADD COLUMN ip VARCHAR(64) NULL" );
306 $this->wpdb->query( "ALTER TABLE $this->table_chats ADD COLUMN botId VARCHAR(64) NULL" );
307 $this->db_check = true;
308 }
309
310 // LATER: REMOVE THIS AFTER JANUARY 2024
311 $this->db_check = $this->db_check && $this->wpdb->get_var( "SHOW COLUMNS FROM $this->table_chats LIKE 'threadId'" );
312 if ( !$this->db_check ) {
313 $this->wpdb->query( "ALTER TABLE $this->table_chats ADD COLUMN threadId VARCHAR(64) NULL" );
314 $this->db_check = true;
315 }
316
317 // LATER: REMOVE THIS AFTER SEPTEMBER 2024
318 $this->db_check = $this->db_check && $this->wpdb->get_var( "SHOW COLUMNS FROM $this->table_chats LIKE 'storeId'" );
319 if ( !$this->db_check ) {
320 $this->wpdb->query( "ALTER TABLE $this->table_chats ADD COLUMN storeId VARCHAR(64) NULL" );
321 $this->db_check = true;
322 }
323
324 // LATER: REMOVE THIS AFTER SEPTEMBER 2024
325 $this->db_check = $this->db_check && $this->wpdb->get_var( "SHOW COLUMNS FROM $this->table_chats LIKE 'extra'" );
326 if ( $this->db_check ) {
327 $column = $this->wpdb->get_row( "SHOW COLUMNS FROM $this->table_chats WHERE Field = 'extra'" );
328 if ( $column->Type === 'text' ) {
329 $this->wpdb->query( "ALTER TABLE $this->table_chats MODIFY COLUMN extra LONGTEXT" );
330 }
331 }
332
333 return $this->db_check;
334 }
335
336 function create_db() {
337 $charset_collate = $this->wpdb->get_charset_collate();
338 $sqlLogs = "CREATE TABLE $this->table_chats (
339 id BIGINT(20) NOT NULL AUTO_INCREMENT,
340 userId BIGINT(20) NULL,
341 ip VARCHAR(64) NULL,
342 messages TEXT NOT NULL NULL,
343 extra LONGTEXT NOT NULL NULL,
344 botId VARCHAR(64) NULL,
345 chatId VARCHAR(64) NOT NULL,
346 threadId VARCHAR(64) NULL,
347 storeId VARCHAR(64) NULL,
348 created DATETIME NOT NULL,
349 updated DATETIME NOT NULL,
350 PRIMARY KEY (id),
351 INDEX chatId (chatId)
352 ) $charset_collate;";
353 require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
354 dbDelta( $sqlLogs );
355 }
356
357 }