encryption = $encryption; } /** * {@inheritDoc} */ public function complete( string $prompt, int $max_tokens = 600 ): string { $api_key = $this->get_api_key(); if ( empty( $api_key ) ) { throw new AIProviderException( esc_html__( 'Gemini API key is not configured.', 'ai-discoverability-kit' ) ); } $body = array( 'contents' => array( array( 'parts' => array( array( 'text' => $prompt ), ), ), ), 'generationConfig' => array( 'maxOutputTokens' => $max_tokens, ), ); $endpoint = self::ENDPOINT_BASE . '?key=' . $api_key; $response = wp_remote_post( $endpoint, array( 'timeout' => 45, 'headers' => array( 'Content-Type' => 'application/json', ), 'body' => wp_json_encode( $body ), ) ); if ( is_wp_error( $response ) ) { throw new AIProviderException( esc_html( $response->get_error_message() ) ); } $status = wp_remote_retrieve_response_code( $response ); $body = json_decode( wp_remote_retrieve_body( $response ), true ); if ( 200 !== $status ) { $error_msg = $body['error']['message'] ?? __( 'Unknown Gemini API error.', 'ai-discoverability-kit' ); throw new AIProviderException( esc_html( $error_msg ) ); } return trim( $body['candidates'][0]['content']['parts'][0]['text'] ?? '' ); } /** * {@inheritDoc} */ public function validate_api_key(): bool { $api_key = $this->get_api_key(); if ( empty( $api_key ) ) { return false; } try { $body = array( 'contents' => array( array( 'parts' => array( array( 'text' => 'hi' ), ), ), ), 'generationConfig' => array( 'maxOutputTokens' => 5, ), ); $response = wp_remote_post( self::ENDPOINT_BASE . '?key=' . $api_key, array( 'timeout' => 15, 'headers' => array( 'Content-Type' => 'application/json' ), 'body' => wp_json_encode( $body ), ) ); if ( is_wp_error( $response ) ) { return false; } $body = json_decode( wp_remote_retrieve_body( $response ), true ); return isset( $body['candidates'] ) && is_array( $body['candidates'] ); } catch ( \Exception $e ) { return false; } } /** * {@inheritDoc} */ public function get_provider_name(): string { return 'gemini'; } /** * {@inheritDoc} */ public function estimate_cost_usd( int $input_tokens, int $output_tokens ): float { return ( $input_tokens / 1000 * self::INPUT_COST_PER_1K ) + ( $output_tokens / 1000 * self::OUTPUT_COST_PER_1K ); } /** * Get the decrypted API key. * * @return string Decrypted API key, or empty string if not set. */ private function get_api_key(): string { $encrypted = get_option( 'aicommerce_gemini_api_key', '' ); if ( empty( $encrypted ) ) { return ''; } return $this->encryption->decrypt( $encrypted ); } }