Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/wp-includes/ai-client.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
*/

use WordPress\AiClient\AiClient;
use WordPress\AiClient\Messages\DTO\Message;
use WordPress\AiClient\Messages\DTO\MessagePart;

/**
* Returns whether AI features are supported in the current environment.
Expand Down Expand Up @@ -55,6 +57,6 @@ function wp_supports_ai(): bool {
* conversations. Default null.
* @return WP_AI_Client_Prompt_Builder The prompt builder instance.
*/
function wp_ai_client_prompt( $prompt = null ) {
function wp_ai_client_prompt( $prompt = null ): WP_AI_Client_Prompt_Builder {
return new WP_AI_Client_Prompt_Builder( AiClient::defaultRegistry(), $prompt );
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public function clear(): bool {
* @param mixed $default_value Default value to return for keys that do not exist.
* @return array<string, mixed> A list of key => value pairs.
*/
public function getMultiple( $keys, $default_value = null ) {
public function getMultiple( $keys, $default_value = null ): array {
/**
* Keys array.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,15 @@ class WP_AI_Client_HTTP_Client implements ClientInterface, ClientWithOptionsInte
* Response factory instance.
*
* @since 7.0.0
* @var ResponseFactoryInterface
*/
private $response_factory;
private ResponseFactoryInterface $response_factory;

/**
* Stream factory instance.
*
* @since 7.0.0
* @var StreamFactoryInterface
*/
private $stream_factory;
private StreamFactoryInterface $stream_factory;

/**
* Constructor.
Expand Down
19 changes: 17 additions & 2 deletions src/wp-includes/ai-client/class-wp-ai-client-prompt-builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -190,14 +190,29 @@ public function __construct( ProviderRegistry $registry, $prompt = null ) {
$this->error = $this->exception_to_wp_error( $e );
}

$default_timeout = 30.0;

/**
* Filters the default request timeout in seconds for AI Client HTTP requests.
*
* @since 7.0.0
*
* @param int $default_timeout The default timeout in seconds.
* @param float $default_timeout The default timeout in seconds.
*/
$default_timeout = (int) apply_filters( 'wp_ai_client_default_request_timeout', 30 );
$filtered_default_timeout = apply_filters( 'wp_ai_client_default_request_timeout', $default_timeout );
if ( is_numeric( $filtered_default_timeout ) && (float) $filtered_default_timeout >= 0.0 ) {
$default_timeout = (float) $filtered_default_timeout;
} else {
_doing_it_wrong(
__METHOD__,
sprintf(
/* translators: %s: wp_ai_client_default_request_timeout */
__( 'The %s filter must return a non-negative number.' ),
'<code>wp_ai_client_default_request_timeout</code>'
),
'7.0.0'
);
}

$this->builder->usingRequestOptions(
RequestOptions::fromArray(
Expand Down
72 changes: 67 additions & 5 deletions tests/phpunit/tests/ai-client/wpAiClientPromptBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -192,15 +192,64 @@ public function test_constructor_sets_default_request_timeout() {
}

/**
* Test that the constructor allows overriding the default request timeout.
* Test that the constructor allows overriding the default request timeout with a valid value.
*
* @ticket 64591
* @ticket 65094
*
* @dataProvider data_valid_request_timeout_overrides
*
* @param mixed $input The timeout value returned by the filter.
* @param float $expected The expected timeout stored on the request options.
*/
public function test_constructor_allows_overriding_request_timeout_with_valid_timeout( $input, float $expected ) {
add_filter(
'wp_ai_client_default_request_timeout',
static function () use ( $input ) {
return $input;
}
);

$builder = new WP_AI_Client_Prompt_Builder( AiClient::defaultRegistry() );

/** @var RequestOptions $request_options */
$request_options = $this->get_wrapped_prompt_builder_property_value( $builder, 'requestOptions' );

$this->assertInstanceOf( RequestOptions::class, $request_options );
$this->assertSame( $expected, $request_options->getTimeout() );
}

/**
* Data provider for {@see self::test_constructor_allows_overriding_request_timeout_with_valid_timeout()}.
*
* @return array<string, array{0: mixed, 1: float}>
*/
public function test_constructor_allows_overriding_request_timeout() {
public function data_valid_request_timeout_overrides(): array {
return array(
'float' => array( 45.5, 45.5 ),
'integer' => array( 67, 67.0 ),
'string' => array( '20', 20.0 ),
'infinity' => array( INF, INF ),
'zero' => array( 0.0, 0.0 ),
);
}

/**
* Test that the constructor disallows overriding the default request timeout with an invalid value.
*
* @ticket 65094
*
* @dataProvider data_invalid_request_timeouts
*
* @expectedIncorrectUsage WP_AI_Client_Prompt_Builder::__construct
*
* @param mixed $timeout The invalid timeout value returned by the filter.
*/
public function test_constructor_disallows_overriding_with_invalid_request_timeout( $timeout ) {
add_filter(
'wp_ai_client_default_request_timeout',
static function () {
return 45;
static function () use ( $timeout ) {
return $timeout;
}
);

Expand All @@ -210,7 +259,20 @@ static function () {
$request_options = $this->get_wrapped_prompt_builder_property_value( $builder, 'requestOptions' );

$this->assertInstanceOf( RequestOptions::class, $request_options );
$this->assertSame( 45.0, $request_options->getTimeout() );
$this->assertSame( 30.0, $request_options->getTimeout() );
}

/**
* Data provider for {@see self::test_constructor_disallows_overriding_with_invalid_request_timeout()}.
*
* @return array<string, array{0: mixed}>
*/
public function data_invalid_request_timeouts(): array {
return array(
'negative number' => array( -1 ),
Comment thread
westonruter marked this conversation as resolved.
'array' => array( array() ),
'null' => array( null ),
);
Comment thread
westonruter marked this conversation as resolved.
}

/**
Expand Down
Loading