search_brave( $query, $count, $api_key, $base_url, ); break; case "tavily": $results = $this->search_tavily( $query, $count, $api_key, $base_url, ); break; case "serper": $results = $this->search_serper( $query, $count, $api_key, $base_url, ); break; case "9router": default: $results = $this->search_9router( $query, $count, $api_key, $base_url, ); break; } if (is_wp_error($results)) { return $results; } if (empty($results)) { return []; // No results found } // Cache results for 1 hour to prevent redundant API calls set_transient($cache_key, $results, HOUR_IN_SECONDS); return $results; } /** * Driver: 9Router Proxy (Generic OpenAI-style search endpoint) */ private function search_9router($query, $count, $api_key, $base_url) { $url = !empty($base_url) ? $base_url : "http://localhost:20128/v1/search"; $body = [ "model" => "gemini", // generic "query" => $query, "search_type" => "web", "max_results" => absint($count), ]; $response = wp_remote_post($url, [ "headers" => [ "Content-Type" => "application/json", "Authorization" => "Bearer " . $api_key, ], "body" => wp_json_encode($body), "timeout" => 15, ]); if (is_wp_error($response)) { return $response; } $http_code = wp_remote_retrieve_response_code($response); $body_response = json_decode(wp_remote_retrieve_body($response), true); if (200 !== $http_code) { return new WP_Error( "search_error", "9Router Search Error: " . ($body_response["error"]["message"] ?? "Unknown"), ); } $formatted = []; if ( !empty($body_response["data"]) && is_array($body_response["data"]) ) { foreach ($body_response["data"] as $result) { $formatted[] = [ "title" => $result["title"] ?? "", "url" => $result["url"] ?? "", "description" => $result["content"] ?? ($result["description"] ?? ""), ]; } } return $formatted; } /** * Driver: Tavily API */ private function search_tavily($query, $count, $api_key, $base_url) { $url = !empty($base_url) ? $base_url : "https://api.tavily.com/search"; $body = [ "api_key" => $api_key, "query" => $query, "search_depth" => "basic", "max_results" => absint($count), ]; $response = wp_remote_post($url, [ "headers" => ["Content-Type" => "application/json"], "body" => wp_json_encode($body), "timeout" => 15, ]); if (is_wp_error($response)) { return $response; } $http_code = wp_remote_retrieve_response_code($response); $body_response = json_decode(wp_remote_retrieve_body($response), true); if (200 !== $http_code) { return new WP_Error( "search_error", "Tavily Search Error: " . ($body_response["detail"] ?? "Unknown"), ); } $formatted = []; if ( !empty($body_response["results"]) && is_array($body_response["results"]) ) { foreach ($body_response["results"] as $result) { $formatted[] = [ "title" => $result["title"] ?? "", "url" => $result["url"] ?? "", "description" => $result["content"] ?? "", ]; } } return $formatted; } /** * Driver: Serper.dev */ private function search_serper($query, $count, $api_key, $base_url) { $url = !empty($base_url) ? $base_url : "https://google.serper.dev/search"; $body = [ "q" => $query, "num" => absint($count), ]; $response = wp_remote_post($url, [ "headers" => [ "Content-Type" => "application/json", "X-API-KEY" => $api_key, ], "body" => wp_json_encode($body), "timeout" => 15, ]); if (is_wp_error($response)) { return $response; } $http_code = wp_remote_retrieve_response_code($response); $body_response = json_decode(wp_remote_retrieve_body($response), true); if (200 !== $http_code) { return new WP_Error( "search_error", "Serper Search Error: " . ($body_response["message"] ?? "Unknown"), ); } $formatted = []; if ( !empty($body_response["organic"]) && is_array($body_response["organic"]) ) { foreach ($body_response["organic"] as $result) { $formatted[] = [ "title" => $result["title"] ?? "", "url" => $result["link"] ?? "", "description" => $result["snippet"] ?? "", ]; } } return $formatted; } /** * Driver: Brave Search API */ private function search_brave($query, $count, $api_key, $base_url) { $base = !empty($base_url) ? $base_url : "https://api.search.brave.com/res/v1/web/search"; $url = add_query_arg( [ "q" => urlencode($query), "count" => absint($count), "text_decorations" => 0, "spellcheck" => 1, ], $base, ); $response = wp_remote_get($url, [ "headers" => [ "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_response = json_decode(wp_remote_retrieve_body($response), true); if (200 !== $http_code) { return new WP_Error( "search_error", "Brave Search Error: " . ($body_response["message"] ?? "Unknown"), ); } $formatted = []; if ( !empty($body_response["web"]["results"]) && is_array($body_response["web"]["results"]) ) { foreach ($body_response["web"]["results"] as $result) { $formatted[] = [ "title" => $result["title"] ?? "", "url" => $result["url"] ?? "", "description" => $result["description"] ?? "", ]; } } return $formatted; } /** * 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; } }