PluginProbe
WPBot – AI ChatBot for Live Support, Lead Generation, WordPress Automation, AI Services / 8.8.0
WPBot – AI ChatBot for Live Support, Lead Generation, WordPress Automation, AI Services v8.8.0
8.8.0 8.7.9 8.7.8 8.7.7 8.7.6 8.7.5 8.7.4 8.7.3 8.7.2 8.7.1 8.7.0 8.6.9 8.6.8 8.6.7 8.6.6 8.6.5 8.6.4 8.6.2 8.6.1 8.6.0 8.5.9 8.5.8 8.5.7 8.5.6 8.5.5 All 536 releases
← All changes | includes/integration/gemini/qcld-bot-gemini.php +72 -24 8.6.0 → 8.8.0 View file →
@@ -131,8 +131,9 @@
131 131 if($gemini_enabled == '1') {
132 132 update_option('ai_enabled', 0);
133 133 update_option('qcld_openrouter_enabled', 0);
134 134 update_option('qcld_grok_enabled', 0);
135 + update_option('disable_wp_chatbot_site_search',1);
135 136
136 137 } else {
137 138 update_option('ai_enabled', 1);
138 139 }
@@ -182,11 +183,11 @@
182 183 $api_url = 'https://generativelanguage.googleapis.com/v1/models/' . $selected_model . ':generateContent';
183 184 $result = wp_remote_post($api_url, $args);
184 185 $result = json_decode(wp_remote_retrieve_body($result), true);
185 186 if( $result['error'] ?? false ) {
186 - wp_send_json( array( 'status' => 'error', 'msg' => esc_html__( $result['error']['message'], 'chatbot' ) ) );
187 + wp_send_json( array( 'status' => 'error', 'msg' => esc_html( $result['error']['message'] ) ) );
187 188 } elseif ( $result['candidates'] ?? false ) {
188 - wp_send_json( array( 'status' => 'success', 'msg' => esc_html__( $result['candidates'][0]['content']['parts'][0]['text'], 'chatbot' ) ) );
189 + wp_send_json( array( 'status' => 'success', 'msg' => esc_html( $result['candidates'][0]['content']['parts'][0]['text'] ) ) );
189 190 }
190 191
191 192 wp_die();
192 193
@@ -241,11 +242,33 @@
241 242 }
242 243
243 244 $Qcld_Parsedown = new Qcld_Parsedown();
244 245
246 + $is_playground = isset($_POST['is_ai_actions_playground']) && intval($_POST['is_ai_actions_playground']) === 1;
247 +
245 248 // Build context-aware content with system instructions
246 - $system_instructions = '';
247 - if ( get_option('gemeni_context_awareness_enabled') == '1' ) {
249 + $system_instructions = $is_playground ? 'You are a helpful AI assistant. You MUST strictly follow the interactive form instructions if the user asks for them.' : '';
250 +
251 + // AI Interactive Form
252 + if (get_option('enable_ai_interactive_form') == '1') {
253 + $saved_ai_forms = get_option('wpbot_ai_forms', array());
254 + if (!empty($saved_ai_forms) && is_array($saved_ai_forms)) {
255 + $system_instructions .= "\n\nYou must handle the following interactive forms when the user asks for them:\n";
256 + foreach ($saved_ai_forms as $form) {
257 + $system_instructions .= "\nForm Title: " . $form['title'] . "\nInstructions: " . $form['prompt'] . "\n";
258 + }
259 + $system_instructions .= "\n\nCRITICAL INSTRUCTIONS FOR INTERACTIVE FORMS:\n";
260 + $system_instructions .= "When a user triggers an interactive form, you must act as a step-by-step data collection agent.\n";
261 + $system_instructions .= "1. DO NOT ask all questions at once. Ask exactly ONE question at a time.\n";
262 + $system_instructions .= "2. Wait for the user's response before asking the next question.\n";
263 + $system_instructions .= "3. Once all necessary information is collected for the form, you MUST output a final JSON block summarizing the collected data. The keys inside the \"data\" object MUST be dynamically named based on the specific questions you asked during the form collection (e.g., \"Full Name\", \"Company Size\", \"Email\", etc.). The final JSON block must be wrapped EXACTLY in these delimiters:\n";
264 + $system_instructions .= "__AI_FORM_DATA__{ \"form_title\": \"<Form Title>\", \"data\": { \"Question 1\": \"Answer 1\", \"Question 2\": \"Answer 2\" } }__AI_FORM_DATA_END__\n";
265 + $system_instructions .= "Do not include any other text after this JSON block once the form is complete.\n";
266 + $system_instructions .= "4. If the user provides an invalid, irrelevant, or nonsensical answer to your question, DO NOT apologize or state that you lack information. Instead, respond with 'Invalid answer found' and ask the exact same question again.";
267 + }
268 + }
269 +
270 + if ( !$is_playground && get_option('gemeni_context_awareness_enabled') == '1' ) {
248 271 $site_name = get_bloginfo('name');
249 272 $site_desc = get_bloginfo('description');
250 273
251 274 // Get current page URL and title more reliably
@@ -329,12 +352,21 @@
329 352 if ( $current_url ) { $context_bits[] = 'URL: ' . $current_url; }
330 353 if ( $page_summary ) { $context_bits[] = 'Page summary: ' . $page_summary; }
331 354
332 355 if ( ! empty( $context_bits ) ) {
333 - $system_instructions = 'Context Information: ' . implode( '. ', $context_bits ) . '. Please use this context to provide more relevant and accurate responses.';
356 + if (!empty($system_instructions)) {
357 + $system_instructions .= "\n\nContext Information: " . implode( '. ', $context_bits ) . '. Please use this context to provide more relevant and accurate responses.';
358 + } else {
359 + $system_instructions = 'Context Information: ' . implode( '. ', $context_bits ) . '. Please use this context to provide more relevant and accurate responses.';
360 + }
334 361 }
335 362 }
336 363
364 + $action_prompt = !empty($_POST['action_prompt']) ? wp_unslash($_POST['action_prompt']) : '';
365 + if (!empty($action_prompt)) {
366 + $system_instructions .= "\n\nCRITICAL ACTIVE ACTION INSTRUCTION:\n" . $action_prompt;
367 + }
368 +
337 369 // RAG Integration
338 370 if (get_option('is_page_rag_enabled') == '1') {
339 371 $rag_context_text = Qcld_Bot_Rag::instance()->run_rag_search($keyword);
340 372 if (!empty($rag_context_text) && $rag_context_text != "No knowledge base found.") {
@@ -351,16 +383,14 @@
351 383 }
352 384
353 385 if ( ( get_option( 'page_suggestion_enabled' ) == '1' ) && count( $relevant_pagelink ) > 0 ) {
354 386 $relevant_post_link = maybe_unserialize( get_option( 'qlcd_wp_chatbot_relevant_post_link_openai' ) );
355 - // Always use get_locale() to avoid undefined function error
356 387 $locale = get_locale();
357 - if ( is_array( $relevant_post_link ) && isset( $relevant_post_link[ $locale ] ) && is_array( $relevant_post_link[ $locale ] ) ) {
388 + if ( !$is_playground && is_array( $relevant_post_link ) && isset( $relevant_post_link[ $locale ] ) && is_array( $relevant_post_link[ $locale ] ) ) {
358 389 $relevant_pagelinks = '<br><br><p><em>' . implode( '', $relevant_post_link[ $locale ] ) . '</em><p>' . implode( '</br>', $relevant_pagelink );
359 390 } else {
360 - // Fallback: try to use $locale, but check if key exists
361 391 $em_text = '';
362 - if ( is_array( $relevant_post_link ) && isset( $relevant_post_link[ $locale ] ) ) {
392 + if ( !$is_playground && is_array( $relevant_post_link ) && isset( $relevant_post_link[ $locale ] ) ) {
363 393 $em_text = is_array( $relevant_post_link[ $locale ] ) ? implode( '', $relevant_post_link[ $locale ] ) : $relevant_post_link[ $locale ];
364 394 }
365 395 $relevant_pagelinks = '<br><br><p><em>' . $em_text . '</em><p>' . implode( '</br>', $relevant_pagelink );
366 396 }
@@ -368,15 +398,12 @@
368 398 $relevant_pagelinks = '';
369 399 }
370 400
371 401 $selected_model = get_option('qcld_gemini_model') ? get_option('qcld_gemini_model') : 'gemini-2.5-flash';
372 - // Gemini API expects a different payload and endpoint
373 402 $api_url = 'https://generativelanguage.googleapis.com/v1/models/' . $selected_model . ':generateContent';
374 403
375 - // Build formatted messages with system instructions
376 404 $formatted_messages = [];
377 405
378 - // Add system instructions as first user message if context is enabled
379 406 if ( ! empty( $system_instructions ) ) {
380 407 $formatted_messages[] = [
381 408 'role' => 'user',
382 409 'parts' => [
@@ -383,9 +410,8 @@
383 410 ['text' => "[System Instructions] " . $system_instructions]
384 411 ]
385 412 ];
386 413
387 - // Add model response to acknowledge system instructions
388 414 $formatted_messages[] = [
389 415 'role' => 'model',
390 416 'parts' => [
391 417 ['text' => "I understand and will follow these instructions."]
@@ -391,22 +417,40 @@
391 417 ['text' => "I understand and will follow these instructions."]
392 418 ]
393 419 ];
394 420 }
421 +
422 + if (!empty($_POST['ai_history'])) {
423 + $parsed_history = json_decode(wp_unslash($_POST['ai_history']), true);
424 + if (is_array($parsed_history)) {
425 + foreach ($parsed_history as $h) {
426 + if (isset($h['role']) && isset($h['content'])) {
427 + $role = ($h['role'] === 'assistant') ? 'model' : 'user';
428 + $formatted_messages[] = [
429 + 'role' => $role,
430 + 'parts' => [
431 + ['text' => sanitize_text_field($h['content'])]
432 + ]
433 + ];
434 + }
435 + }
436 + }
437 + }
395 438
396 - // Add the actual user query
397 - $formatted_messages[] = [
398 - 'role' => 'user',
399 - 'parts' => [
400 - ['text' => $keyword]
401 - ]
402 - ];
439 + $last_msg = end($formatted_messages);
440 + if (!$last_msg || $last_msg['role'] !== 'user' || empty($last_msg['parts'][0]['text']) || $last_msg['parts'][0]['text'] !== $keyword) {
441 + $formatted_messages[] = [
442 + 'role' => 'user',
443 + 'parts' => [
444 + ['text' => $keyword]
445 + ]
446 + ];
447 + }
403 448
404 449 $data = array(
405 450 'contents' => $formatted_messages,
406 451 );
407 452
408 - // Use WordPress wp_remote_post for better error handling and consistency
409 453 $args = array(
410 454 'body' => json_encode($data),
411 455 'headers' => array(
412 456 'Content-Type' => 'application/json',
@@ -420,9 +464,8 @@
420 464 );
421 465
422 466 $result = wp_remote_post($api_url, $args);
423 467
424 - // Check for WordPress errors
425 468 if (is_wp_error($result)) {
426 469 $response['status'] = 'error';
427 470 $response['message'] = 'API request failed: ' . $result->get_error_message();
428 471 } else {
@@ -430,15 +473,20 @@
430 473 $response_body = wp_remote_retrieve_body($result);
431 474
432 475 if ($http_code === 200) {
433 476 $msg = json_decode($response_body);
434 - // Gemini API returns candidates[0]->content->parts[0]->text
435 477 if (
436 478 isset($msg->candidates[0]->content->parts[0]->text)
437 479 && !empty($msg->candidates[0]->content->parts[0]->text)
438 480 ) {
439 481 $response['status'] = 'success';
440 - $response['message'] = $Qcld_Parsedown->text( $msg->candidates[0]->content->parts[0]->text ) . $relevant_pagelinks;
482 + $reply_text = $Qcld_Parsedown->text( $msg->candidates[0]->content->parts[0]->text );
483 + if (strpos($reply_text, 'AI_FORM_DATA') !== false) {
484 + $reply_text = Qcld_WPBot_Common_Functions::format_and_save_ai_form_response($reply_text);
485 + $response['message'] = $reply_text;
486 + } else {
487 + $response['message'] = $reply_text . $relevant_pagelinks;
488 + }
441 489 } else {
442 490 $response['status'] = 'error';
443 491 $response['message'] = 'Invalid response format from Gemini API';
444 492 }