Files
wp-agentic-writer/includes/class-brave-search-api.php
Dwindi Ramadhana d2c10756ab Add AI writing assistant plugin with local backend, brave search, and image generation support
- Implement local backend AI provider with Ollama integration
- Add Brave Search API integration for real-time search suggestions
- Add image generation manager with multiple AI providers
- Create hybrid provider system with local/cloud fallback
- Add comprehensive settings UI with provider management
- Implement Gutenberg sidebar with writing assistance controls
- Add SEO schema generation for AI-generated content
- Multiple provider support: OpenRouter, local backend, Codex
2026-05-17 10:48:05 +07:00

155 lines
4.0 KiB
PHP

<?php
/**
* Brave Search API Integration
*
* Handles fetching web search results for models that do not natively support web search
*
* @package WP_Agentic_Writer
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class WP_Agentic_Writer_Brave_Search_API {
/**
* Brave Search REST API Endpoint
*
* @var string
*/
private $api_endpoint = 'https://api.search.brave.com/res/v1/web/search';
/**
* Get singleton instance.
*
* @since 0.1.0
* @return WP_Agentic_Writer_Brave_Search_API
*/
public static function get_instance() {
static $instance = null;
if ( null === $instance ) {
$instance = new self();
}
return $instance;
}
/**
* Perform a web search.
*
* @since 0.1.0
* @param string $query Required. The user's search query.
* @param int $count Optional. Number of results to return. Default 3.
* @return array|WP_Error Array of formatted search results, or WP_Error on failure.
*/
public function search( $query, $count = 3 ) {
$settings = get_option( 'wp_agentic_writer_settings', array() );
$api_key = $settings['brave_search_api_key'] ?? '';
if ( empty( $api_key ) ) {
return new WP_Error(
'brave_api_key_missing',
__( 'Brave Search API Key is missing. Please configure it in WP Agentic Writer settings.', 'wp-agentic-writer' )
);
}
// Check cache first to prevent burning API limits on identical subsequent queries
$cache_key = 'wpaw_brave_search_' . md5( $query . '_' . $count );
$cached_results = get_transient( $cache_key );
if ( false !== $cached_results ) {
return $cached_results;
}
$url = add_query_arg(
array(
'q' => urlencode( $query ),
'count' => absint( $count ),
'text_decorations' => 0, // Disable HTML tags in descriptions
'spellcheck' => 1,
),
$this->api_endpoint
);
$response = wp_remote_get(
$url,
array(
'headers' => array(
'Accept' => 'application/json',
'Accept-Encoding' => 'gzip',
'X-Subscription-Token' => $api_key,
),
'timeout' => 15,
)
);
if ( is_wp_error( $response ) ) {
return $response;
}
$http_code = wp_remote_retrieve_response_code( $response );
$body = json_decode( wp_remote_retrieve_body( $response ), true );
if ( 200 !== $http_code ) {
return new WP_Error(
'brave_api_error',
sprintf(
/* translators: %1$d is HTTP status code, %2$s is error message */
__( 'Brave Search API Error %1$d: %2$s', 'wp-agentic-writer' ),
$http_code,
$body['message'] ?? __( 'Unknown Error', 'wp-agentic-writer' )
)
);
}
if ( empty( $body['web']['results'] ) ) {
return array(); // No results found
}
$formatted_results = array();
foreach ( $body['web']['results'] as $result ) {
$formatted_results[] = array(
'title' => $result['title'] ?? '',
'url' => $result['url'] ?? '',
'description' => $result['description'] ?? '',
);
}
// Cache results for 1 hour to prevent redundant API calls
set_transient( $cache_key, $formatted_results, HOUR_IN_SECONDS );
return $formatted_results;
}
/**
* Formats search results into a markdown context block for LLM System Prompt injection.
*
* @since 0.1.0
* @param array $results Search results array.
* @param string $query Original query.
* @return string Formatted markdown context string.
*/
public function format_results_for_llm( $results, $query ) {
if ( empty( $results ) || is_wp_error( $results ) ) {
return "No reliable web search results found for: {$query}";
}
$markdown = "## LIVE WEB SEARCH CONTEXT\n";
$markdown .= "> You successfully searched the internet for: \"{$query}\"\n";
$markdown .= "> Please incorporate the following real-time data into your answer:\n\n";
$counter = 1;
foreach ( $results as $item ) {
$markdown .= "{$counter}. **{$item['title']}**\n";
$markdown .= " URL: {$item['url']}\n";
$markdown .= " Summary: {$item['description']}\n\n";
$counter++;
}
$markdown .= "---------------------------\n";
return $markdown;
}
}