PluginProbe ʕ •ᴥ•ʔ
AI Engine – The Chatbot, AI Framework & MCP for WordPress / 2.8.4
AI Engine – The Chatbot, AI Framework & MCP for WordPress v2.8.4
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 / wand.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 search.php 1 year ago security.php 1 year ago tasks.php 1 year ago wand.php 1 year ago
wand.php
379 lines
1 <?php
2
3 class Meow_MWAI_Modules_Wand
4 {
5 private $core;
6
7 public static $features = [
8 'correctText' => [
9 'label' => 'Correct Text',
10 'sublabel' => 'Grammar & Spelling',
11 'arguments' => ['postId', 'text'],
12 'where' => 'blockContext',
13 'group' => 'first'
14 ],
15 'enhanceText' => [
16 'label' => 'Enhance Text',
17 'sublabel' => 'Readibility & Quality',
18 'arguments' => ['postId', 'text'],
19 'where' => 'blockContext',
20 'group' => 'first'
21 ],
22 'longerText' => [
23 'label' => 'Longer Text',
24 'sublabel' => 'Readibility',
25 'arguments' => ['postId', 'text'],
26 'where' => 'blockContext',
27 'group' => 'first'
28 ],
29 'shorterText' => [
30 'label' => 'Shorter Text',
31 'sublabel' => 'Readibility',
32 'arguments' => ['postId', 'text'],
33 'where' => 'blockContext',
34 'group' => 'first'
35 ],
36 'translateText' => [
37 'label' => 'Translate Text',
38 'sublabel' => 'To Post Language',
39 'arguments' => ['postId', 'text', 'language'],
40 'where' => 'blockContext',
41 'group' => 'first'
42 ],
43 'translateSection' => [
44 'label' => 'Translate Post',
45 'sublabel' => 'To Post Language',
46 'arguments' => ['postId', 'text', 'context'],
47 'where' => 'postContext', // We should probably handle this dynamically on the front-side
48 'group' => 'first' // This is random
49 ],
50 'suggestSynonyms' => [
51 'label' => 'Suggest Synonyms',
52 'sublabel' => 'For Selected Words',
53 'arguments' => ['postId', 'text', 'selectedText'],
54 'where' => 'blockContext',
55 'group' => 'second'
56 ],
57 'generateImage' => [
58 'label' => 'Generate Image',
59 'sublabel' => 'For This Text',
60 'arguments' => ['postId', 'text'],
61 'where' => 'blockContext',
62 'group' => 'third'
63 ],
64 'suggestExcerpts' => [
65 'label' => 'Suggest Excerpts',
66 'sublabel' => 'Generate SEO-Optimized Excerpts',
67 'arguments' => ['postId'],
68 'where' => 'postActions'
69 ],
70 'suggestTitles' => [
71 'label' => 'Suggest Titles',
72 'sublabel' => 'Generate SEO-Optimized Titles',
73 'arguments' => ['postId'],
74 'where' => 'postActions'
75 ]
76 ];
77
78 public function __construct( $core )
79 {
80 $this->core = $core;
81 $this->register_filters();
82 }
83
84 private function register_filters()
85 {
86 foreach ( self::$features as $action => $feature ) {
87 add_filter( 'mwai_magic_wand_' . $action, [ $this, 'action_' . $action ], 10, 2 );
88 }
89 }
90
91 /**
92 * Common method to process text actions (e.g., correct, enhance, lengthen, shorten text).
93 *
94 * @param array $arguments The arguments provided for the action.
95 * @param string $messagePrefix The prefix for the message to be set in the query.
96 * @return array The result of the text processing.
97 */
98 private function processTextAction( $arguments, $messagePrefix )
99 {
100 $postId = $arguments['postId'];
101 $isJson = isset( $arguments['json'] ) && !empty( $arguments['json'] );
102 $blockType = isset( $arguments['blockType'] ) ? $arguments['blockType'] : null;
103
104 if ( $isJson ) {
105 // Handle structured JSON data for complex blocks
106 $jsonData = $arguments['json'];
107 $text = json_encode( $jsonData, JSON_PRETTY_PRINT );
108
109 // Add specific instructions for JSON handling
110 $jsonInstructions = "\n\nIMPORTANT: The input is JSON data. You must return ONLY valid JSON (no markdown, no code blocks, no explanations). Return the EXACT SAME JSON structure, only modifying the text content within it.";
111
112 if ( $blockType === 'core/list' ) {
113 $jsonInstructions .= " This is a list with 'type' and 'items' fields. Return: {\"type\": \"list\", \"items\": [...modified items...]}";
114 } elseif ( $blockType === 'core/table' ) {
115 $jsonInstructions .= " This is a table with 'type' and 'rows' fields. Each row has a 'cells' array. Return: {\"type\": \"table\", \"rows\": [{\"cells\": [...modified cells...]}, ...]}";
116 }
117
118 $messagePrefix .= $jsonInstructions;
119 } else {
120 // Handle regular text
121 $text = $arguments['text'];
122 }
123
124 $query = new Meow_MWAI_Query_Text( "", 1024 );
125 $query->set_scope( 'admin-tools' );
126 $language = $keepLanguage = "";
127 if ( !empty( $postId ) ) {
128 $language = $this->core->get_post_language( $postId );
129 $keepLanguage = " Ensure the reply is in the same language as the original text ({$language}).";
130 }
131 $query->set_message( $messagePrefix . $keepLanguage . "\n\n" . $text );
132 $reply = $this->core->run_query( $query );
133
134 $result = $reply->result;
135 $responseType = 'text';
136
137 // If we sent JSON, we must get JSON back
138 if ( $isJson ) {
139 // First, try to extract JSON from markdown code blocks if present
140 $jsonPattern = '/```(?:json)?\s*\n?(.+?)\n?```/s';
141 if ( preg_match( $jsonPattern, $result, $matches ) ) {
142 $result = trim( $matches[1] );
143 }
144
145 // Now parse the JSON
146 $parsedJson = json_decode( $result, true );
147 if ( json_last_error() === JSON_ERROR_NONE ) {
148 // Validate that the JSON has the expected structure
149 if ( $blockType === 'core/list' && isset( $parsedJson['type'] ) && $parsedJson['type'] === 'list' && isset( $parsedJson['items'] ) ) {
150 $result = $parsedJson;
151 $responseType = 'json';
152 } elseif ( $blockType === 'core/table' && isset( $parsedJson['type'] ) && $parsedJson['type'] === 'table' && isset( $parsedJson['rows'] ) ) {
153 $result = $parsedJson;
154 $responseType = 'json';
155 } else {
156 // JSON is valid but doesn't match expected structure
157 error_log( 'AI Engine: JSON response does not match expected structure for block type: ' . $blockType );
158 throw new Exception( 'Invalid JSON structure returned by AI' );
159 }
160 } else {
161 // JSON parsing failed
162 error_log( 'AI Engine: Failed to parse AI response as JSON. Error: ' . json_last_error_msg() );
163 error_log( 'AI Engine: Raw response: ' . $result );
164 throw new Exception( 'AI did not return valid JSON' );
165 }
166 }
167
168 return [
169 'mode' => 'replace',
170 'type' => $responseType,
171 'result' => $result,
172 'results' => $reply->results
173 ];
174 }
175
176 /**
177 * Handles the correction of text by checking and correcting grammatical errors.
178 */
179 public function action_correctText( $value, $arguments )
180 {
181 $prompt = apply_filters( 'mwai_prompt_correctText', "Correct the typos and grammar mistakes in this text without altering its content. Ensure the reply is in the same language as the original text.\n\n", $arguments );
182 return $this->processTextAction( $arguments, $prompt );
183 }
184
185 /**
186 * Enhances the text's readability and quality.
187 */
188 public function action_enhanceText( $value, $arguments )
189 {
190 $prompt = apply_filters( 'mwai_prompt_enhanceText', "Enhance this text by improving readability and quality, using a more suitable vocabulary, and refining its structure.\n\n", $arguments );
191 return $this->processTextAction( $arguments, $prompt );
192 }
193
194 /**
195 * Lengthens the text to improve readability.
196 */
197 public function action_longerText( $value, $arguments ) {
198 $prompt = apply_filters( 'mwai_prompt_longerText', "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.\n\n", $arguments );
199 return $this->processTextAction( $arguments, $prompt );
200 }
201
202 /**
203 * Shortens the text to improve readability.
204 */
205 public function action_shorterText( $value, $arguments ) {
206 $prompt = apply_filters( 'mwai_prompt_shorterText', "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.\n\n", $arguments );
207 return $this->processTextAction( $arguments, $prompt );
208 }
209
210 /**
211 * Suggests synonyms for selected words in the text.
212 */
213 public function action_suggestSynonyms( $value, $arguments ) {
214 $postId = $arguments['postId'];
215 $selectedText = $arguments['selectedText'];
216 $query = new Meow_MWAI_Query_Text( "", 1024 );
217 $query->set_scope( 'admin-tools' );
218 $language = $keepLanguage = "";
219 if ( !empty( $postId ) ) {
220 $language = $this->core->get_post_language( $postId );
221 $keepLanguage = " Ensure the reply is in the same language as the original text ({$language}).";
222 }
223 $prompt = apply_filters( 'mwai_prompt_suggestSynonyms', "Provide 5 synonyms or 5 ways of rephrasing the given word or sentence while retaining the original meaning and preserving the initial and final punctuation and spacing if any. 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. Separate every suggestion with a new line, and that's it." . $keepLanguage . "\n\n", $arguments );
224 $query->set_message( $prompt . $selectedText );
225 $query->set_temperature( 1 );
226 $reply = $this->core->run_query( $query );
227 $lines = explode( "\n", $reply->result );
228 $results = [];
229 foreach ( $lines as $line ) {
230 if ( !empty( $line ) ) {
231 $results[] = $line;
232 }
233 }
234 return [
235 'mode' => 'suggest',
236 'type' => $reply->type,
237 'result' => $results[0] ?? '',
238 'results' => $results
239 ];
240 }
241
242 /**
243 * Generates an image relevant to the text.
244 */
245 public function action_generateImage( $value, $arguments ) {
246 global $mwai;
247 $postId = $arguments['postId'];
248 $text = $arguments['text'];
249 $prompt = apply_filters( 'mwai_prompt_generateImage', "Generate an image that is relevant to the following text:\n\n", $arguments );
250 $message = $prompt . $text;
251 $media = $mwai->imageQueryForMediaLibrary( $message, $params = [], $postId );
252 return [
253 'mode' => 'insertMedia',
254 'type' => 'image',
255 'media' => $media
256 ];
257 }
258
259 /**
260 * Translates the specified text of text to the target language.
261 *
262 * @param mixed $value Unused parameter
263 * @param array $arguments Contains postId, text, and context
264 * @return array Translation result
265 */
266 public function action_translateSection( $value, $arguments ) {
267 $postId = $arguments['postId'];
268 $text = $arguments['text'];
269
270 if (empty($text)) {
271 return [
272 'mode' => 'replace',
273 'type' => 'text',
274 'result' => '',
275 'results' => []
276 ];
277 }
278
279 $context = $arguments['context'];
280 $targetLanguage = $this->core->get_post_language($postId);
281 $query = new Meow_MWAI_Query_Text("", 1024);
282 $query->set_scope('admin-tools');
283 $prompt = "Translate the following section into {$targetLanguage}:\n\n" .
284 "[SECTION TO TRANSLATE]\n{$text}\n[END SECTION TO TRANSLATE]\n\n" .
285 "Translation guidelines:\n" .
286 "1. Maintain the original tone, mood, and nuance.\n" .
287 "2. Preserve the intended meaning as accurately as possible.\n" .
288 "3. Ensure the translation fits seamlessly within the broader context.\n" .
289 "4. Use appropriate idiomatic expressions in the target language when applicable.\n" .
290 "5. Maintain any formatting or special characters present in the original text.\n\n" .
291 "Broader context (for reference only, do not translate):\n\n" .
292 "[CONTEXT]\n{$context}\n[END CONTEXT]\n\n" .
293 "Provide only the translated section, between the markers [TRANSLATED SECTION] and [END TRANSLATED SECTION], without any additional content. Do not include the markers [TRANSLATED SECTION] and [END TRANSLATED SECTION] in your reply!\n\n";
294 $prompt = apply_filters('mwai_prompt_translateSection', $prompt, $arguments);
295 $query->set_message($prompt);
296 $reply = $this->core->run_query($query);
297
298 // Clean up the result, just in case...
299 $result = $reply->result;
300 $result = str_replace('[TRANSLATED SECTION]', '', $result);
301 $result = str_replace('[END TRANSLATED SECTION]', '', $result);
302 $result = trim($result);
303 $results = [];
304 foreach ($reply->results as $r) {
305 $r = str_replace('[TRANSLATED SECTION]', '', $r);
306 $r = str_replace('[END TRANSLATED SECTION]', '', $r);
307 $r = trim($r);
308 $results[] = $r;
309 }
310
311 return [
312 'mode' => 'replace',
313 'type' => $reply->type,
314 'result' => $result,
315 'results' => $results
316 ];
317 }
318
319 /**
320 * Translates the text to the specified language.
321 */
322 public function action_translateText( $value, $arguments ) {
323 $postId = $arguments['postId'];
324 $text = $arguments['text'];
325 $language = $this->core->get_post_language( $postId );
326 $query = new Meow_MWAI_Query_Text( "", 1024 );
327 $query->set_scope( 'admin-tools' );
328 $prompt = apply_filters( 'mwai_prompt_translateText', "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", $arguments );
329 $query->set_message( $prompt . $text );
330 $reply = $this->core->run_query( $query );
331 return [
332 'mode' => 'replace',
333 'type' => $reply->type,
334 'result' => $reply->result,
335 'results' => $reply->results
336 ];
337 }
338
339 /**
340 * Suggests SEO-optimized excerpts for the text.
341 */
342 public function action_suggestExcerpts( $value, $arguments ) {
343 $postId = $arguments['postId'];
344 $text = $this->core->get_post_content( $postId );
345 $query = new Meow_MWAI_Query_Text( "", 1024 );
346 $query->set_scope( 'admin-tools' );
347 $prompt = apply_filters( 'mwai_prompt_suggestExcerpts', "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.\n\n", $arguments );
348 $query->set_message( $prompt . $text );
349 $query->set_max_results( 5 );
350 $reply = $this->core->run_query( $query );
351 return [
352 'mode' => 'suggest',
353 'type' => $reply->type,
354 'result' => $reply->result,
355 'results' => $reply->results
356 ];
357 }
358
359 /**
360 * Suggests SEO-optimized titles for the text.
361 */
362 public function action_suggestTitles( $value, $arguments ) {
363 $postId = $arguments['postId'];
364 $text = $this->core->get_post_content( $postId );
365 $query = new Meow_MWAI_Query_Text( "", 1024 );
366 $query->set_scope( 'admin-tools' );
367 $prompt = apply_filters( 'mwai_prompt_suggestTitles', "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.\n\n", $arguments );
368 $query->set_message( $prompt . $text );
369 $query->set_max_results( 5 );
370 $reply = $this->core->run_query( $query );
371 return [
372 'mode' => 'suggest',
373 'type' => $reply->type,
374 'result' => $reply->result,
375 'results' => $reply->results
376 ];
377 }
378 }
379