PluginProbe ʕ •ᴥ•ʔ
AI Engine – The Chatbot, AI Framework & MCP for WordPress / 1.9.92
AI Engine – The Chatbot, AI Framework & MCP for WordPress v1.9.92
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 / rest.php
ai-engine / classes Last commit date
engines 2 years ago modules 2 years ago queries 2 years ago admin.php 2 years ago api.php 2 years ago core.php 2 years ago init.php 3 years ago reply.php 2 years ago rest.php 2 years ago
rest.php
948 lines
1 <?php
2
3 class Meow_MWAI_Rest
4 {
5 private $core = null;
6 private $namespace = 'mwai/v1';
7
8 public function __construct( $core ) {
9 $this->core = $core;
10 add_action( 'rest_api_init', array( $this, 'rest_init' ) );
11 }
12
13 function rest_init() {
14 try {
15 // Settings Endpoints
16 register_rest_route( $this->namespace, '/settings/update', array(
17 'methods' => 'POST',
18 'permission_callback' => [ $this->core, 'can_access_settings' ],
19 'callback' => [ $this, 'rest_settings_update' ],
20 ) );
21 register_rest_route( $this->namespace, '/settings/list', array(
22 'methods' => 'GET',
23 'permission_callback' => [ $this->core, 'can_access_settings' ],
24 'callback' => [ $this, 'rest_settings_list' ],
25 ) );
26 register_rest_route( $this->namespace, '/settings/reset', array(
27 'methods' => 'POST',
28 'permission_callback' => [ $this->core, 'can_access_settings' ],
29 'callback' => [ $this, 'rest_settings_reset' ],
30 ) );
31 register_rest_route( $this->namespace, '/settings/chatbots', array(
32 'methods' => ['GET', 'POST'],
33 'permission_callback' => [ $this->core, 'can_access_settings' ],
34 'callback' => [ $this, 'rest_settings_chatbots' ],
35 ) );
36 register_rest_route( $this->namespace, '/settings/themes', array(
37 'methods' => ['GET', 'POST'],
38 'permission_callback' => [ $this->core, 'can_access_settings' ],
39 'callback' => [ $this, 'rest_settings_themes' ],
40 ) );
41
42 // System Endpoints
43 register_rest_route( $this->namespace, '/system/logs/list', array(
44 'methods' => 'POST',
45 'permission_callback' => [ $this->core, 'can_access_settings' ],
46 'callback' => [ $this, 'rest_system_logs_list' ],
47 ) );
48 register_rest_route( $this->namespace, '/system/logs/delete', array(
49 'methods' => 'POST',
50 'permission_callback' => [ $this->core, 'can_access_settings' ],
51 'callback' => [ $this, 'rest_system_logs_delete' ],
52 ) );
53 register_rest_route( $this->namespace, '/system/logs/meta', array(
54 'methods' => 'POST',
55 'permission_callback' => [ $this->core, 'can_access_settings' ],
56 'callback' => [ $this, 'rest_system_logs_meta_get' ],
57 ) );
58 register_rest_route( $this->namespace, '/system/templates', array(
59 'methods' => 'POST',
60 'permission_callback' => [ $this->core, 'can_access_features' ],
61 'callback' => [ $this, 'rest_system_templates_save' ],
62 ) );
63 register_rest_route( $this->namespace, '/system/templates', array(
64 'methods' => 'GET',
65 'permission_callback' => [ $this->core, 'can_access_features' ],
66 'callback' => [ $this, 'rest_system_templates_get' ],
67 ) );
68
69 // AI Endpoints
70 register_rest_route( $this->namespace, '/ai/completions', array(
71 'methods' => 'POST',
72 'permission_callback' => [ $this->core, 'can_access_features' ],
73 'callback' => [ $this, 'rest_ai_completions' ],
74 ) );
75 register_rest_route( $this->namespace, '/ai/images', array(
76 'methods' => 'POST',
77 'permission_callback' => [ $this->core, 'can_access_features' ],
78 'callback' => [ $this, 'rest_ai_images' ],
79 ) );
80 register_rest_route( $this->namespace, '/ai/copilot', array(
81 'methods' => 'POST',
82 'permission_callback' => [ $this->core, 'can_access_features' ],
83 'callback' => [ $this, 'rest_ai_copilot' ],
84 ) );
85
86 register_rest_route( $this->namespace, '/ai/magic_wand', array(
87 'methods' => 'POST',
88 'callback' => [ $this, 'rest_ai_magic_wand' ],
89 'permission_callback' => [ $this->core, 'can_access_features' ],
90 ) );
91 register_rest_route( $this->namespace, '/ai/moderate', array(
92 'methods' => 'POST',
93 'permission_callback' => [ $this->core, 'can_access_settings' ],
94 'callback' => [ $this, 'rest_ai_moderate' ],
95 ) );
96 register_rest_route( $this->namespace, '/ai/transcribe', array(
97 'methods' => 'POST',
98 'permission_callback' => [ $this->core, 'can_access_settings' ],
99 'callback' => [ $this, 'rest_ai_transcribe' ],
100 ) );
101
102 // Helpers Endpoints
103 register_rest_route( $this->namespace, '/helpers/update_post_title', array(
104 'methods' => 'POST',
105 'permission_callback' => [ $this->core, 'can_access_features' ],
106 'callback' => [ $this, 'rest_helpers_update_title' ],
107 ) );
108 register_rest_route( $this->namespace, '/helpers/update_post_excerpt', array(
109 'methods' => 'POST',
110 'permission_callback' => [ $this->core, 'can_access_features' ],
111 'callback' => [ $this, 'rest_helpers_update_excerpt' ],
112 ) );
113 register_rest_route( $this->namespace, '/helpers/create_post', array(
114 'methods' => 'POST',
115 'permission_callback' => [ $this->core, 'can_access_features' ],
116 'callback' => [ $this, 'rest_helpers_create_post' ],
117 ) );
118 register_rest_route( $this->namespace, '/helpers/create_image', array(
119 'methods' => 'POST',
120 'permission_callback' => [ $this->core, 'can_access_features' ],
121 'callback' => [ $this, 'rest_helpers_create_images' ],
122 ) );
123 register_rest_route( $this->namespace, '/helpers/count_posts', array(
124 'methods' => 'GET',
125 'permission_callback' => [ $this->core, 'can_access_features' ],
126 'callback' => [ $this, 'rest_helpers_count_posts' ],
127 ) );
128 register_rest_route( $this->namespace, '/helpers/post_types', array(
129 'methods' => 'GET',
130 'permission_callback' => [ $this->core, 'can_access_features' ],
131 'callback' => [ $this, 'rest_helpers_post_types' ],
132 ) );
133 register_rest_route( $this->namespace, '/helpers/post_content', array(
134 'methods' => 'GET',
135 'permission_callback' => [ $this->core, 'can_access_features' ],
136 'callback' => [ $this, 'rest_helpers_post_content' ],
137 ) );
138
139 // OpenAI Endpoints
140 register_rest_route( $this->namespace, '/openai/files/list', array(
141 'methods' => 'GET',
142 'permission_callback' => [ $this->core, 'can_access_settings' ],
143 'callback' => [ $this, 'rest_openai_files_get' ],
144 ) );
145 register_rest_route( $this->namespace, '/openai/files/upload', array(
146 'methods' => 'POST',
147 'permission_callback' => [ $this->core, 'can_access_settings' ],
148 'callback' => [ $this, 'rest_openai_files_upload' ],
149 ) );
150 register_rest_route( $this->namespace, '/openai/files/delete', array(
151 'methods' => 'POST',
152 'permission_callback' => [ $this->core, 'can_access_settings' ],
153 'callback' => [ $this, 'rest_openai_files_delete' ],
154 ) );
155 register_rest_route( $this->namespace, '/openai/files/download', array(
156 'methods' => 'POST',
157 'permission_callback' => [ $this->core, 'can_access_settings' ],
158 'callback' => [ $this, 'rest_openai_files_download' ],
159 ) );
160 register_rest_route( $this->namespace, '/openai/files/finetune', array(
161 'methods' => 'POST',
162 'permission_callback' => [ $this->core, 'can_access_settings' ],
163 'callback' => [ $this, 'rest_openai_files_finetune' ],
164 ) );
165 register_rest_route( $this->namespace, '/openai/finetunes/list_deleted', array(
166 'methods' => 'GET',
167 'permission_callback' => [ $this->core, 'can_access_settings' ],
168 'callback' => [ $this, 'rest_openai_deleted_finetunes_get' ],
169 ) );
170
171 // register_rest_route( $this->namespace, '/openai/models', array(
172 // 'methods' => 'GET',
173 // 'permission_callback' => [ $this->core, 'can_access_settings' ],
174 // 'callback' => [ $this, 'rest_openai_models_get' ],
175 // ) );
176
177 register_rest_route( $this->namespace, '/openai/finetunes/list', array(
178 'methods' => 'GET',
179 'permission_callback' => [ $this->core, 'can_access_settings' ],
180 'callback' => [ $this, 'rest_openai_finetunes_get' ],
181 ) );
182 register_rest_route( $this->namespace, '/openai/finetunes/delete', array(
183 'methods' => 'POST',
184 'permission_callback' => [ $this->core, 'can_access_settings' ],
185 'callback' => [ $this, 'rest_openai_finetunes_delete' ],
186 ) );
187 register_rest_route( $this->namespace, '/openai/finetunes/cancel', array(
188 'methods' => 'POST',
189 'permission_callback' => [ $this->core, 'can_access_settings' ],
190 'callback' => [ $this, 'rest_openai_finetunes_cancel' ],
191 ) );
192 register_rest_route( $this->namespace, '/openai/incidents', array(
193 'methods' => 'GET',
194 'permission_callback' => [ $this->core, 'can_access_settings' ],
195 'callback' => [ $this, 'rest_openai_incidents' ],
196 ) );
197 }
198 catch ( Exception $e ) {
199 var_dump( $e );
200 }
201 }
202
203 function rest_settings_list() {
204 return new WP_REST_Response( [
205 'success' => true,
206 'options' => $this->core->get_all_options()
207 ], 200 );
208 }
209
210 function rest_settings_update( $request ) {
211 try {
212 $params = $request->get_json_params();
213 $value = $params['options'];
214 $options = $this->core->update_options( $value );
215 $success = !!$options;
216 $message = __( $success ? 'OK' : "Could not update options.", 'ai-engine' );
217 return new WP_REST_Response([ 'success' => $success, 'message' => $message, 'options' => $options ], 200 );
218 }
219 catch ( Exception $e ) {
220 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
221 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
222 }
223 }
224
225 function rest_settings_reset() {
226 try {
227 $options = $this->core->reset_options();
228 $success = !!$options;
229 $message = __( $success ? 'OK' : "Could not reset options.", 'ai-engine' );
230 return new WP_REST_Response([ 'success' => $success, 'message' => $message, 'options' => $options ], 200 );
231 }
232 catch ( Exception $e ) {
233 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
234 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
235 }
236 }
237
238 function createValidationResult( $result = true, $message = null) {
239 $message = $message ? $message : __( 'OK', 'ai-engine' );
240 return [ 'result' => $result, 'message' => $message ];
241 }
242
243 function validate_updated_option( $option_name ) {
244 $option_checkbox = get_option( 'mwai_option_checkbox', false );
245 $option_text = get_option( 'mwai_option_text', 'Default' );
246 if ( $option_checkbox === '' )
247 update_option( 'mwai_option_checkbox', false );
248 if ( $option_text === '' )
249 update_option( 'mwai_option_text', 'Default' );
250 return $this->createValidationResult();
251 }
252
253 function rest_ai_completions( $request ) {
254 try {
255 $params = $request->get_json_params();
256 $prompt = $params['prompt'];
257 $query = new Meow_MWAI_Query_Text( $prompt );
258 $query->injectParams( $params );
259
260 // Handle streaming
261 $stream = $params['stream'] ?? false;
262 $streamCallback = null;
263 if ( $stream ) {
264 $streamCallback = function( $reply ) {
265 //$raw = _wp_specialchars( $reply, ENT_NOQUOTES, 'UTF-8', true );
266 $raw = $reply;
267 $this->core->stream_push( [ 'type' => 'live', 'data' => $raw ] );
268 if ( ob_get_level() > 0 ) {
269 ob_flush();
270 }
271 flush();
272 };
273 header( 'Cache-Control: no-cache' );
274 header( 'Content-Type: text/event-stream' );
275 header( 'X-Accel-Buffering: no' ); // This is useful to disable buffering in nginx through headers.
276 ob_implicit_flush( true );
277 ob_end_flush();
278 }
279
280 // Process Reply
281 $reply = $this->core->ai->run( $query, $streamCallback );
282 $restRes = [
283 'success' => true,
284 'data' => $reply->result,
285 'usage' => $reply->usage
286 ];
287 if ( $stream ) {
288 $this->core->stream_push( [ 'type' => 'end', 'data' => json_encode( $restRes ) ] );
289 die();
290 }
291 return new WP_REST_Response( $restRes, 200 );
292 }
293 catch ( Exception $e ) {
294 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
295 if ( $stream ) {
296 $this->core->stream_push( [ 'type' => 'error', 'data' => $message ] );
297 }
298 else {
299 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
300 }
301 }
302 }
303
304 function rest_ai_images( $request ) {
305 try {
306 $params = $request->get_json_params();
307 $prompt = $params['prompt'];
308 $query = new Meow_MWAI_Query_Image( $prompt );
309 $query->injectParams( $params );
310 $reply = $this->core->ai->run( $query );
311 return new WP_REST_Response([ 'success' => true, 'data' => $reply->results, 'usage' => $reply->usage ], 200 );
312 }
313 catch ( Exception $e ) {
314 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
315 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
316 }
317 }
318
319 function rest_ai_magic_wand( $request ) {
320 try {
321 $params = $request->get_json_params();
322 $action = isset( $params['action'] ) ? $params['action'] : null;
323 $data = isset( $params['data'] ) ? $params['data'] : null;
324 if ( empty( $data ) || empty( $action ) ) {
325 return new WP_REST_Response([ 'success' => false, 'message' => "An action and some data are required." ], 500 );
326 }
327 $postId = isset( $data['postId'] ) ? $data['postId'] : null;
328 $text = isset( $data['text'] ) ? $data['text'] : null;
329 $selectedText = isset( $data['selectedText'] ) ? $data['selectedText'] : null;
330
331 // NOTE: As soon as we have a wide range of usages and possibilities,
332 // let's refactor this into a nice and extensible UI/API.
333 $query = new Meow_MWAI_Query_Text( "", 1024 );
334 $query->setEnv( 'admin-tools' );
335 // TODO: We should also use the envId (as the model belongs to it)
336 $model = $this->core->get_option( 'ai_default_model' );
337 if ( !empty( $model ) ) {
338 $query->setModel( $model );
339 }
340 $mode = 'replace';
341
342 $language = "";
343 $keepLanguage = "";
344 if ( !empty( $postId ) ) {
345 $language = $this->core->get_post_language( $postId );
346 $keepLanguage = " Ensure the reply is in the same language as the original text ({$language}).";
347 }
348
349 if ( $action === 'correctText' ) {
350 $query->setPrompt( "Correct the typos and grammar mistakes in this text without altering its content. Return only the corrected text, without explanations or additional content.{$keepLanguage}\n\n" . $text );
351 }
352 else if ( $action === 'enhanceText' ) {
353 $query->setPrompt( "Enhance this text by eliminating redundancies, utilizing a more suitable vocabulary, and refining its structure. Provide only the revised text, without explanations or any additional content.{$keepLanguage}\n\n" . $text );
354 }
355 else if ( $action === 'longerText' ) {
356 $query->setPrompt( "Expand the subsequent text to a minimum of three times its original length, integrating relevant and accurate information to enrich its content. If the text is a story, amplify its charm by elaborating on essential aspects, enhancing readability, and creating a sense of engagement for the reader. Maintain consistency in tone and vocabulary throughout the expansion process.{$keepLanguage}\n\n" . $text );
357 }
358 else if ( $action === 'shorterText' ) {
359 $query->setPrompt( "Condense the following text by reducing its length to half, while retaining the core elements of the original narrative. Focus on maintaining the essence of the story and its key details.{$keepLanguage}\n\n" . $text );
360 }
361 else if ( $action === 'suggestSynonyms' ) {
362 $mode = 'suggest';
363 $query->setPrompt( "Provide a synonym or rephrase the given word or sentence while retaining the original meaning and preserving the initial and final punctuation. Offer only the resulting word or expression, without additional context. If a suitable synonym or alternative cannot be identified, ensure that a creative response is still provided.{$keepLanguage}\n\n" . $selectedText );
364 $query->setTemperature( 1 );
365 $query->setMaxResults( 5 );
366 }
367 else if ( $action === 'translateText' ) {
368 $query->setPrompt( "Translate the text into {$language}, preserving the tone, mood, and nuance, while staying as true as possible to the original meaning. Provide only the translated text, without any additional content.\n\n" . $text );
369 }
370 else if ( $action === 'suggestExcerpts' ) {
371 $text = $this->core->getCleanPostContent( $postId );
372 $query->setPrompt( "Craft a clear, SEO-optimized introduction for the following text, using 120 to 170 characters. Ensure the introduction is concise and relevant, without including any URLs.{$keepLanguage}\n\n" . $text );
373 $query->setMaxResults( 5 );
374 }
375 else if ( $action === 'suggestTitles' ) {
376 $text = $this->core->getCleanPostContent( $postId );
377 $query->setPrompt( "Generate a concise, SEO-optimized title for the following text, without using quotes or any other formatting. Focus on clarity and relevance to the content.{$keepLanguage}\n\n" . $text );
378 $query->setMaxResults( 5 );
379 }
380 $reply = $this->core->ai->run( $query );
381 return new WP_REST_Response([ 'success' => true, 'data' => [
382 'mode' => $mode,
383 'result' => $reply->result,
384 'results' => $reply->results
385 ] ], 200 );
386 }
387 catch ( Exception $e ) {
388 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
389 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
390 }
391 }
392
393 function rest_ai_copilot( $request ) {
394 try {
395 $params = $request->get_json_params();
396 $action = sanitize_text_field( $params['action'] );
397 $prompt = sanitize_text_field( $params['prompt'] );
398 if ( empty( $action ) || empty( $prompt ) ) {
399 return new WP_REST_Response([ 'success' => false, 'message' => "Copilot needs an action and a prompt." ], 500 );
400 }
401 $query = new Meow_MWAI_Query_Text( $prompt, 2048 );
402 $query->setEnv( 'admin-tools' );
403 // TODO: We should also use the envId (as the model belongs to it)
404 $model = $this->core->get_option( 'ai_default_model' );
405 if ( !empty( $model ) ) {
406 $query->setModel( $model );
407 }
408 $reply = $this->core->ai->run( $query );
409 return new WP_REST_Response([ 'success' => true, 'data' => $reply->result ], 200 );
410 }
411 catch ( Exception $e ) {
412 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
413 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
414 }
415 }
416
417 function rest_helpers_update_title( $request ) {
418 try {
419 $params = $request->get_json_params();
420 $title = sanitize_text_field( $params['title'] );
421 $postId = intval( $params['postId'] );
422 $post = get_post( $postId );
423 if ( !$post ) {
424 throw new Exception( 'There is no post with this ID.' );
425 }
426 $post->post_title = $title;
427 //$post->post_name = sanitize_title( $title );
428 wp_update_post( $post );
429 return new WP_REST_Response([ 'success' => true, 'message' => "Title updated." ], 200 );
430 }
431 catch ( Exception $e ) {
432 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
433 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
434 }
435 }
436
437 function rest_helpers_update_excerpt( $request ) {
438 try {
439 $params = $request->get_json_params();
440 $excerpt = sanitize_text_field( $params['excerpt'] );
441 $postId = intval( $params['postId'] );
442 $post = get_post( $postId );
443 if ( !$post ) {
444 throw new Exception( 'There is no post with this ID.' );
445 }
446 $post->post_excerpt = $excerpt;
447 wp_update_post( $post );
448 return new WP_REST_Response([ 'success' => true, 'message' => "Excerpt updated." ], 200 );
449 }
450 catch ( Exception $e ) {
451 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
452 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
453 }
454 }
455
456 function rest_helpers_create_post( $request ) {
457 try {
458 $params = $request->get_json_params();
459 $title = sanitize_text_field( $params['title'] );
460 $content = sanitize_textarea_field( $params['content'] );
461 $excerpt = sanitize_text_field( $params['excerpt'] );
462 $postType = sanitize_text_field( $params['postType'] );
463 $post = new stdClass();
464 $post->post_title = $title;
465 $post->post_excerpt = $excerpt;
466 $post->post_content = $content;
467 $post->post_status = 'draft';
468 $post->post_type = isset( $postType ) ? $postType : 'post';
469 $post->post_content = $this->core->markdown_to_html( $post->post_content );
470 $postId = wp_insert_post( $post );
471 return new WP_REST_Response([ 'success' => true, 'postId' => $postId ], 200 );
472 }
473 catch ( Exception $e ) {
474 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
475 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
476 }
477 }
478
479 function image_download( $url ) {
480 $args = array( 'timeout' => 60, );
481 $response = wp_remote_get( $url, $args );
482 if ( is_wp_error( $response ) ) {
483 throw new Exception( $response->get_error_message() );
484 }
485 $output = wp_remote_retrieve_body( $response );
486 if ( is_wp_error( $output ) ) {
487 throw new Exception( $output->get_error_message() );
488 }
489 return $output;
490 }
491
492 function rest_helpers_create_images( $request ) {
493 try {
494 $params = $request->get_json_params();
495 $title = sanitize_text_field( $params['title'] );
496 $caption = sanitize_text_field( $params['caption'] );
497 $alt = sanitize_text_field( $params['alt'] );
498 $description = sanitize_text_field( $params['description'] );
499 $url = $params['url'];
500 $filename = sanitize_text_field( $params['filename'] );
501 $image_data = $this->image_download( $url );
502 if ( !$image_data ) {
503 throw new Exception( 'Could not download the image.' );
504 }
505 $upload_dir = wp_upload_dir();
506 if ( empty( $filename ) ) {
507 $filename = basename( $url );
508 }
509 $wp_filetype = wp_check_filetype( $filename );
510 if ( wp_mkdir_p( $upload_dir['path'] ) ) {
511 $file = $upload_dir['path'] . '/' . $filename;
512 }
513 else {
514 $file = $upload_dir['basedir'] . '/' . $filename;
515 }
516
517 // Make sure the file is unique, if not, add a number to the end of the file before the extension
518 $i = 1;
519 $parts = pathinfo( $file );
520 while ( file_exists( $file ) ) {
521 $file = $parts['dirname'] . '/' . $parts['filename'] . '-' . $i . '.' . $parts['extension'];
522 $i++;
523 }
524
525 // Write the file
526 file_put_contents( $file, $image_data );
527 $attachment = [
528 'post_mime_type' => $wp_filetype['type'],
529 'post_title' => $title,
530 'post_content' => $description,
531 'post_excerpt' => $caption,
532 'post_status' => 'inherit'
533 ];
534 // Register the file as a Media Library attachment
535 $attachmentId = wp_insert_attachment( $attachment, $file );
536 require_once( ABSPATH . 'wp-admin/includes/image.php' );
537 $attachment_data = wp_generate_attachment_metadata( $attachmentId, $file );
538 wp_update_attachment_metadata( $attachmentId, $attachment_data );
539 update_post_meta( $attachmentId, '_wp_attachment_image_alt', $alt );
540 return new WP_REST_Response([ 'success' => true, 'attachmentId' => $attachmentId ], 200 );
541 }
542 catch ( Exception $e ) {
543 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
544 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
545 }
546 }
547
548 function rest_openai_files_get() {
549 try {
550 $envId = isset( $_GET['envId'] ) ? $_GET['envId'] : null;
551 $openai = new Meow_MWAI_Engines_OpenAI( $this->core, $envId );
552 $files = $openai->listFiles();
553 return new WP_REST_Response([ 'success' => true, 'files' => $files ], 200 );
554 }
555 catch ( Exception $e ) {
556 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
557 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
558 }
559 }
560
561 // function rest_openai_models_get() {
562 // try {
563 // $openai = new Meow_MWAI_Engines_OpenAI( $this->core );
564 // $finetunes = $openai->listModels();
565 // return new WP_REST_Response([ 'success' => true, 'finetunes' => $finetunes ], 200 );
566 // }
567 // catch ( Exception $e ) {
568 // $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
569 // return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
570 // }
571 // }
572
573 function rest_openai_deleted_finetunes_get() {
574 try {
575 $envId = isset( $_GET['envId'] ) ? $_GET['envId'] : null;
576 $legacy = isset( $_GET['legacy'] ) ? $_GET['legacy'] === 'true' : false;
577 $openai = new Meow_MWAI_Engines_OpenAI( $this->core, $envId );
578 $finetunes = $openai->listDeletedFineTunes( $legacy );
579 return new WP_REST_Response([ 'success' => true, 'finetunes' => $finetunes ], 200 );
580 }
581 catch ( Exception $e ) {
582 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
583 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
584 }
585 }
586
587 function rest_openai_finetunes_get() {
588 try {
589 $envId = isset( $_GET['envId'] ) ? $_GET['envId'] : null;
590 $legacy = isset( $_GET['legacy'] ) ? $_GET['legacy'] === 'true' : false;
591 $openai = new Meow_MWAI_Engines_OpenAI( $this->core, $envId );
592 $finetunes = $openai->listFineTunes( $legacy );
593 return new WP_REST_Response([ 'success' => true, 'finetunes' => $finetunes ], 200 );
594 }
595 catch ( Exception $e ) {
596 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
597 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
598 }
599 }
600
601 function rest_openai_files_upload( $request ) {
602 try {
603 $params = $request->get_json_params();
604 $envId = $params['envId'];;
605 $filename = sanitize_text_field( $params['filename'] );
606 $data = $params['data'];
607 $openai = new Meow_MWAI_Engines_OpenAI( $this->core, $envId );
608 $file = $openai->uploadFile( $filename, $data );
609 return new WP_REST_Response([ 'success' => true, 'file' => $file ], 200 );
610 }
611 catch ( Exception $e ) {
612 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
613 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
614 }
615 }
616
617 function rest_openai_files_delete( $request ) {
618 try {
619 $params = $request->get_json_params();
620 $envId = $params['envId'];;
621 $fileId = $params['fileId'];
622 $openai = new Meow_MWAI_Engines_OpenAI( $this->core, $envId );
623 $openai->deleteFile( $fileId );
624 return new WP_REST_Response([ 'success' => true ], 200 );
625 }
626 catch ( Exception $e ) {
627 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
628 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
629 }
630 }
631
632 function rest_openai_finetunes_cancel( $request ) {
633 try {
634 $params = $request->get_json_params();
635 $envId = $params['envId'];;
636 $finetuneId = $params['finetuneId'];
637 $openai = new Meow_MWAI_Engines_OpenAI( $this->core, $envId );
638 $openai->cancelFineTune( $finetuneId );
639 return new WP_REST_Response([ 'success' => true ], 200 );
640 }
641 catch ( Exception $e ) {
642 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
643 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
644 }
645 }
646
647 function rest_openai_finetunes_delete( $request ) {
648 try {
649 $params = $request->get_json_params();
650 $envId = $params['envId'];;
651 $modelId = $params['modelId'];
652 $openai = new Meow_MWAI_Engines_OpenAI( $this->core, $envId );
653 $openai->deleteFineTune( $modelId );
654 return new WP_REST_Response([ 'success' => true ], 200 );
655 }
656 catch ( Exception $e ) {
657 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
658 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
659 }
660 }
661
662 function rest_openai_files_download( $request ) {
663 try {
664 $params = $request->get_json_params();
665 $envId = $params['envId'];;
666 $fileId = $params['fileId'];
667 $openai = new Meow_MWAI_Engines_OpenAI( $this->core, $envId );
668 $data = $openai->downloadFile( $fileId );
669 return new WP_REST_Response([ 'success' => true, 'data' => $data ], 200 );
670 }
671 catch ( Exception $e ) {
672 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
673 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
674 }
675 }
676
677 function rest_openai_files_finetune( $request ) {
678 try {
679 $params = $request->get_json_params();
680 $envId = $params['envId'];;
681 $fileId = $params['fileId'];
682 $model = $params['model'];
683 $suffix = $params['suffix'];
684 $hyperparams = [
685 "nEpochs" => $params['nEpochs'],
686 "batchSize" => $params['batchSize']
687 ];
688 $openai = new Meow_MWAI_Engines_OpenAI( $this->core, $envId );
689 $finetune = $openai->fineTuneFile( $fileId, $model, $suffix, $hyperparams );
690 return new WP_REST_Response([ 'success' => true, 'finetune' => $finetune ], 200 );
691 }
692 catch ( Exception $e ) {
693 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
694 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
695 }
696 }
697
698 function rest_openai_incidents() {
699 try {
700 $transient = get_transient( 'mwai_openai_incidents' );
701 if ( $transient ) {
702 return new WP_REST_Response([ 'success' => true, 'incidents' => $transient ], 200 );
703 }
704 $openai = new Meow_MWAI_Engines_OpenAI( $this->core );
705 $incidents = $openai->getIncidents();
706 set_transient( 'mwai_openai_incidents', $incidents, 60 * 10 );
707 return new WP_REST_Response([ 'success' => true, 'incidents' => $incidents ], 200 );
708 }
709 catch ( Exception $e ) {
710 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
711 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
712 }
713 }
714
715 function rest_helpers_count_posts( $request ) {
716 try {
717 $params = $request->get_query_params();
718 $postType = $params['postType'];
719 $postStatus = $params['postStatus'];
720 $postStatus = !empty( $params['postStatus'] ) ? explode( ',', $postStatus ) : [ 'publish' ];
721 $count = wp_count_posts( $postType );
722 $count = array_sum( array_intersect_key( (array)$count, array_flip( $postStatus ) ) );
723 return new WP_REST_Response([ 'success' => true, 'count' => $count ], 200 );
724 }
725 catch ( Exception $e ) {
726 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
727 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
728 }
729 }
730
731 function rest_helpers_post_content( $request ) {
732 try {
733 $params = $request->get_query_params();
734 $offset = (int)$params['offset'];
735 $postType = $params['postType'];
736 $postStatus = $params['postStatus'];
737 $postStatus = !empty( $params['postStatus'] ) ? explode( ',', $postStatus ) : [ 'publish' ];
738 $postId = (int)$params['postId'];
739
740 $post = null;
741 if ( !empty( $postId ) ) {
742 $post = get_post( $postId );
743 if ( $post->post_status !== 'publish' && $post->post_status !== 'future'
744 && $post->post_status !== 'draft' && $post->post_status !== 'private' ) {
745 $post = null;
746 }
747 }
748 else {
749 $posts = get_posts( [
750 'posts_per_page' => 1,
751 'post_type' => $postType,
752 'offset' => $offset,
753 'post_status' => $postStatus,
754 ] );
755 $post = count( $posts ) === 0 ? null : $posts[0];
756 }
757 if ( !$post ) {
758 return new WP_REST_Response([ 'success' => false, 'message' => 'Post not found' ], 404 );
759 }
760 $cleanPost = $this->core->getCleanPost( $post );
761 return new WP_REST_Response([ 'success' => true, 'content' => $cleanPost['content'],
762 'checksum' => $cleanPost['checksum'], 'language' => $cleanPost['language'], 'excerpt' => $cleanPost['excerpt'],
763 'postId' => $cleanPost['postId'], 'title' => $cleanPost['title'], 'url' => $cleanPost['url'] ], 200 );
764 }
765 catch ( Exception $e ) {
766 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
767 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
768 }
769 }
770
771 function rest_system_templates_get( $request ) {
772 try {
773 $params = $request->get_query_params();
774 $category = $params['category'];
775 $templates = [];
776 $templates_option = get_option( 'mwai_templates', [] );
777 if ( !is_array( $templates_option ) ) {
778 update_option( 'mwai_templates', [] );
779 }
780 $categories = array_column( $templates_option, 'category' );
781 $index = array_search( $category, $categories );
782 $templates = [];
783 if ( $index !== false ) {
784 $templates = $templates_option[$index]['templates'];
785 }
786 return new WP_REST_Response([ 'success' => true, 'templates' => $templates ], 200 );
787 }
788 catch ( Exception $e ) {
789 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
790 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
791 }
792 }
793
794 function rest_system_templates_save( $request ) {
795 try {
796 $params = $request->get_json_params();
797 $category = $params['category'];
798 $templates = $params['templates'];
799 $templates_option = get_option( 'mwai_templates', [] );
800 $categories = array_column( $templates_option, 'category' );
801 $index = array_search( $category, $categories );
802 if ( $index !== false && $index >= 0 ) {
803 $templates_option[$index]['templates'] = $templates;
804 }
805 else {
806 $group = [ 'category' => $category, 'templates' => $templates ];
807 $templates_option[] = $group;
808 }
809
810 update_option( 'mwai_templates', $templates_option );
811 return new WP_REST_Response([ 'success' => true ], 200 );
812 }
813 catch ( Exception $e ) {
814 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
815 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
816 }
817 }
818
819 function rest_system_logs_list( $request ) {
820 try {
821 $params = $request->get_json_params();
822 $offset = $params['offset'];
823 $limit = $params['limit'];
824 $filters = $params['filters'];
825 $sort = $params['sort'];
826 $logs = apply_filters( 'mwai_stats_logs', [], $offset, $limit, $filters, $sort );
827 return new WP_REST_Response([ 'success' => true, 'total' => $logs['total'], 'logs' => $logs['rows'] ], 200 );
828 }
829 catch ( Exception $e ) {
830 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
831 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
832 }
833 }
834
835 function rest_system_logs_delete( $request ) {
836 try {
837 $params = $request->get_json_params();
838 $logIds = $params['logIds'];
839 $success = apply_filters( 'mwai_stats_logs_delete', true, $logIds );
840 return new WP_REST_Response([ 'success' => $success ], 200 );
841 }
842 catch ( Exception $e ) {
843 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
844 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
845 }
846 }
847
848 function rest_system_logs_meta_get( $request ) {
849 try {
850 $params = $request->get_json_params();
851 $logId = $params['logId'];
852 $metaKeys = $params['metaKeys'];
853 $data = apply_filters( 'mwai_stats_logs_meta', [], $logId, $metaKeys );
854 return new WP_REST_Response([ 'success' => true, 'data' => $data ], 200 );
855 }
856 catch ( Exception $e ) {
857 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
858 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
859 }
860 }
861
862 function rest_ai_moderate( $request ) {
863 try {
864 $params = $request->get_json_params();
865 $envId = $params['envId'];
866 $text = $params['text'];
867 if ( !$text ) {
868 return new WP_REST_Response([ 'success' => false, 'message' => 'Text not found.' ], 404 );
869 }
870 $openai = new Meow_MWAI_Engines_OpenAI( $this->core, $envId );
871 $results = $openai->moderate( $text );
872 return new WP_REST_Response([ 'success' => true, 'results' => $results ], 200 );
873 }
874 catch ( Exception $e ) {
875 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
876 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
877 }
878
879 }
880
881 function rest_ai_transcribe( $request ) {
882 try {
883 $params = $request->get_json_params();
884 $query = new Meow_MWAI_Query_Transcribe();
885 $query->injectParams( $params );
886 $query->setEnv('admin-tools');
887 $reply = $this->core->ai->run( $query );
888 return new WP_REST_Response([ 'success' => true, 'data' => $reply->result ], 200 );
889 }
890 catch ( Exception $e ) {
891 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
892 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
893 }
894 }
895
896 function rest_helpers_post_types() {
897 try {
898 $postTypes = $this->core->getPostTypes();
899 return new WP_REST_Response([ 'success' => true, 'postTypes' => $postTypes ], 200 );
900 }
901 catch ( Exception $e ) {
902 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
903 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
904 }
905 }
906
907 function rest_settings_themes( $request ) {
908 try {
909 $method = $request->get_method();
910 if ( $method === 'GET' ) {
911 $themes = $this->core->getThemes();
912 return new WP_REST_Response([ 'success' => true, 'themes' => $themes ], 200 );
913 }
914 else if ( $method === 'POST' ) {
915 $params = $request->get_json_params();
916 $themes = $params['themes'];
917 $themes = $this->core->updateThemes( $themes );
918 return new WP_REST_Response([ 'success' => true, 'themes' => $themes ], 200 );
919 }
920 }
921 catch ( Exception $e ) {
922 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
923 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
924 }
925 }
926
927 function rest_settings_chatbots( $request ) {
928 try {
929 $method = $request->get_method();
930 if ( $method === 'GET' ) {
931 $chatbots = $this->core->getChatbots();
932 return new WP_REST_Response([ 'success' => true, 'chatbots' => $chatbots ], 200 );
933 }
934 else if ( $method === 'POST' ) {
935 $params = $request->get_json_params();
936 $chatbots = $params['chatbots'];
937 $chatbots = $this->core->updateChatbots( $chatbots );
938 return new WP_REST_Response([ 'success' => true, 'chatbots' => $chatbots ], 200 );
939 }
940 return new WP_REST_Response([ 'success' => false, 'message' => 'Method not allowed' ], 405 );
941 }
942 catch ( Exception $e ) {
943 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
944 return new WP_REST_Response([ 'success' => false, 'message' => $message ], 500 );
945 }
946 }
947 }
948