WooCommerce Code Reference

Connection.php

Source code

<?php

namespace Automattic\WooCommerce\Blocks\AI;

use Automattic\Jetpack\Connection\Client;
use Jetpack_Options;
use WP_Error;
use WpOrg\Requests\Exception;
use WpOrg\Requests\Requests;

/**
 * Class Connection
 */
class Connection {
	const TEXT_COMPLETION_API_URL = 'https://public-api.wordpress.com/wpcom/v2/text-completion';
	const MODEL                   = 'gpt-3.5-turbo-1106';

	/**
	 * The post request.
	 *
	 * @param string $token The JWT token.
	 * @param string $prompt The prompt to send to the API.
	 * @param int    $timeout The timeout for the request.
	 * @param string $response_format The response format.
	 *
	 * @return mixed
	 */
	public function fetch_ai_response( $token, $prompt, $timeout = 15, $response_format = null ) {
		if ( $token instanceof \WP_Error ) {
			return $token;
		}

		$body = array(
			'feature' => 'woocommerce_blocks_patterns',
			'prompt'  => $prompt,
			'token'   => $token,
			'model'   => self::MODEL,
		);

		if ( $response_format ) {
			$body['response_format'] = $response_format;
		}

		$response = wp_remote_post(
			self::TEXT_COMPLETION_API_URL,
			array(
				'body'    => $body,
				'timeout' => $timeout,
			)
		);

		if ( is_wp_error( $response ) ) {
			return new \WP_Error( $response->get_error_code(), esc_html__( 'Failed to connect with the AI endpoint: try again later.', 'woocommerce' ), $response->get_error_message() );
		}

		$body = wp_remote_retrieve_body( $response );

		return json_decode( $body, true );
	}

	/**
	 * Fetch the AI responses in parallel using the given token and prompts.
	 *
	 * @param string $token The JWT token.
	 * @param array  $prompts The prompts to send to the API.
	 * @param int    $timeout The timeout for the request.
	 * @param string $response_format The response format.
	 *
	 * @return array|WP_Error The responses or a WP_Error object.
	 */
	public function fetch_ai_responses( $token, array $prompts, $timeout = 15, $response_format = null ) {
		if ( $token instanceof \WP_Error ) {
			return $token;
		}

		$requests = array();
		foreach ( $prompts as $prompt ) {
			$data = array(
				'feature' => 'woocommerce_blocks_patterns',
				'prompt'  => $prompt,
				'token'   => $token,
				'model'   => self::MODEL,
			);

			if ( $response_format ) {
				$data['response_format'] = $response_format;
			}

			$requests[] = array(
				'url'     => self::TEXT_COMPLETION_API_URL,
				'type'    => 'POST',
				'headers' => array( 'Content-Type' => 'application/json; charset=utf-8' ),
				'data'    => wp_json_encode( $data ),
			);
		}

		$responses = Requests::request_multiple( $requests, array( 'timeout' => $timeout ) );

		$processed_responses = array();

		foreach ( $responses as $key => $response ) {
			if ( is_wp_error( $response ) || is_a( $response, Exception::class ) ) {
				return new WP_Error( 'failed-to-connect-with-the-ai-endpoint', esc_html__( 'Failed to connect with the AI endpoint: try again later.', 'woocommerce' ) );
			}

			$processed_responses[ $key ] = json_decode( $response->body, true );
		}

		return $processed_responses;
	}

	/**
	 * Return the site ID.
	 *
	 * @return integer|\WP_Error The site ID or a WP_Error object.
	 */
	public function get_site_id() {
		if ( ! class_exists( Jetpack_Options::class ) ) {
			return new \WP_Error( 'site-id-error', esc_html__( 'Failed to fetch the site ID: try again later.', 'woocommerce' ) );
		}

		$site_id = Jetpack_Options::get_option( 'id' );

		if ( ! $site_id ) {
			return new \WP_Error( 'site-id-error', esc_html__( 'Failed to fetch the site ID: The site is not registered.', 'woocommerce' ) );
		}

		return $site_id;
	}

	/**
	 * Fetch the JWT token.
	 *
	 * @param integer $site_id The site ID.
	 *
	 * @return string|\WP_Error The JWT token or a WP_Error object.
	 */
	public function get_jwt_token( $site_id ) {
		if ( is_wp_error( $site_id ) ) {
			return $site_id;
		}

		$request = Client::wpcom_json_api_request_as_user(
			sprintf( '/sites/%d/jetpack-openai-query/jwt', $site_id ),
			'2',
			array(
				'method'  => 'POST',
				'headers' => array( 'Content-Type' => 'application/json; charset=utf-8' ),
			)
		);

		$response = json_decode( wp_remote_retrieve_body( $request ) );

		if ( $response instanceof \WP_Error ) {
			return new \WP_Error( $response->get_error_code(), esc_html__( 'Failed to generate the JWT token', 'woocommerce' ), $response->get_error_message() );
		}

		if ( ! isset( $response->token ) ) {
			return new \WP_Error( 'failed-to-retrieve-jwt-token', esc_html__( 'Failed to retrieve the JWT token: Try again later.', 'woocommerce' ) );
		}

		return $response->token;
	}
}