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