Skip to content

Commit 97f9662

Browse files
committed
AI: Update PHP AI Client package to 1.2.1.
This package update allows registered providers to have a description, and it fixes an issue with Redis compatibility. Props jason_the_adams, laurisaarni. See #64591. git-svn-id: https://develop.svn.wordpress.org/trunk@61776 602fd350-edb4-49c9-b593-d223f7449a82
1 parent 0d52263 commit 97f9662

5 files changed

Lines changed: 80 additions & 9 deletions

File tree

src/wp-includes/php-ai-client/src/AiClient.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ class AiClient
8484
/**
8585
* @var string The version of the AI Client.
8686
*/
87-
public const VERSION = '1.1.0';
87+
public const VERSION = '1.2.1';
8888
/**
8989
* @var ProviderRegistry|null The default provider registry instance.
9090
*/

src/wp-includes/php-ai-client/src/Providers/DTO/ProviderMetadata.php

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@
1313
* unique identifier, display name, and type (cloud, server, or client).
1414
*
1515
* @since 0.1.0
16+
* @since 1.2.0 Added optional description property.
1617
*
1718
* @phpstan-type ProviderMetadataArrayShape array{
1819
* id: string,
1920
* name: string,
21+
* description?: ?string,
2022
* type: string,
2123
* credentialsUrl?: ?string,
2224
* authenticationMethod?: ?string
@@ -28,6 +30,7 @@ class ProviderMetadata extends AbstractDataTransferObject
2830
{
2931
public const KEY_ID = 'id';
3032
public const KEY_NAME = 'name';
33+
public const KEY_DESCRIPTION = 'description';
3134
public const KEY_TYPE = 'type';
3235
public const KEY_CREDENTIALS_URL = 'credentialsUrl';
3336
public const KEY_AUTHENTICATION_METHOD = 'authenticationMethod';
@@ -39,6 +42,10 @@ class ProviderMetadata extends AbstractDataTransferObject
3942
* @var string The provider's display name.
4043
*/
4144
protected string $name;
45+
/**
46+
* @var string|null The provider's description.
47+
*/
48+
protected ?string $description;
4249
/**
4350
* @var ProviderTypeEnum The provider type.
4451
*/
@@ -55,17 +62,20 @@ class ProviderMetadata extends AbstractDataTransferObject
5562
* Constructor.
5663
*
5764
* @since 0.1.0
65+
* @since 1.2.0 Added optional $description parameter.
5866
*
5967
* @param string $id The provider's unique identifier.
6068
* @param string $name The provider's display name.
6169
* @param ProviderTypeEnum $type The provider type.
6270
* @param string|null $credentialsUrl The URL where users can get credentials.
6371
* @param RequestAuthenticationMethod|null $authenticationMethod The authentication method.
72+
* @param string|null $description The provider's description.
6473
*/
65-
public function __construct(string $id, string $name, ProviderTypeEnum $type, ?string $credentialsUrl = null, ?RequestAuthenticationMethod $authenticationMethod = null)
74+
public function __construct(string $id, string $name, ProviderTypeEnum $type, ?string $credentialsUrl = null, ?RequestAuthenticationMethod $authenticationMethod = null, ?string $description = null)
6675
{
6776
$this->id = $id;
6877
$this->name = $name;
78+
$this->description = $description;
6979
$this->type = $type;
7080
$this->credentialsUrl = $credentialsUrl;
7181
$this->authenticationMethod = $authenticationMethod;
@@ -92,6 +102,17 @@ public function getName(): string
92102
{
93103
return $this->name;
94104
}
105+
/**
106+
* Gets the provider's description.
107+
*
108+
* @since 1.2.0
109+
*
110+
* @return string|null The provider description.
111+
*/
112+
public function getDescription(): ?string
113+
{
114+
return $this->description;
115+
}
95116
/**
96117
* Gets the provider type.
97118
*
@@ -129,30 +150,33 @@ public function getAuthenticationMethod(): ?RequestAuthenticationMethod
129150
* {@inheritDoc}
130151
*
131152
* @since 0.1.0
153+
* @since 1.2.0 Added description to schema.
132154
*/
133155
public static function getJsonSchema(): array
134156
{
135-
return ['type' => 'object', 'properties' => [self::KEY_ID => ['type' => 'string', 'description' => 'The provider\'s unique identifier.'], self::KEY_NAME => ['type' => 'string', 'description' => 'The provider\'s display name.'], self::KEY_TYPE => ['type' => 'string', 'enum' => ProviderTypeEnum::getValues(), 'description' => 'The provider type (cloud, server, or client).'], self::KEY_CREDENTIALS_URL => ['type' => 'string', 'description' => 'The URL where users can get credentials.'], self::KEY_AUTHENTICATION_METHOD => ['type' => ['string', 'null'], 'enum' => array_merge(RequestAuthenticationMethod::getValues(), [null]), 'description' => 'The authentication method.']], 'required' => [self::KEY_ID, self::KEY_NAME, self::KEY_TYPE]];
157+
return ['type' => 'object', 'properties' => [self::KEY_ID => ['type' => 'string', 'description' => 'The provider\'s unique identifier.'], self::KEY_NAME => ['type' => 'string', 'description' => 'The provider\'s display name.'], self::KEY_DESCRIPTION => ['type' => 'string', 'description' => 'The provider\'s description.'], self::KEY_TYPE => ['type' => 'string', 'enum' => ProviderTypeEnum::getValues(), 'description' => 'The provider type (cloud, server, or client).'], self::KEY_CREDENTIALS_URL => ['type' => 'string', 'description' => 'The URL where users can get credentials.'], self::KEY_AUTHENTICATION_METHOD => ['type' => ['string', 'null'], 'enum' => array_merge(RequestAuthenticationMethod::getValues(), [null]), 'description' => 'The authentication method.']], 'required' => [self::KEY_ID, self::KEY_NAME, self::KEY_TYPE]];
136158
}
137159
/**
138160
* {@inheritDoc}
139161
*
140162
* @since 0.1.0
163+
* @since 1.2.0 Added description to output.
141164
*
142165
* @return ProviderMetadataArrayShape
143166
*/
144167
public function toArray(): array
145168
{
146-
return [self::KEY_ID => $this->id, self::KEY_NAME => $this->name, self::KEY_TYPE => $this->type->value, self::KEY_CREDENTIALS_URL => $this->credentialsUrl, self::KEY_AUTHENTICATION_METHOD => $this->authenticationMethod ? $this->authenticationMethod->value : null];
169+
return [self::KEY_ID => $this->id, self::KEY_NAME => $this->name, self::KEY_DESCRIPTION => $this->description, self::KEY_TYPE => $this->type->value, self::KEY_CREDENTIALS_URL => $this->credentialsUrl, self::KEY_AUTHENTICATION_METHOD => $this->authenticationMethod ? $this->authenticationMethod->value : null];
147170
}
148171
/**
149172
* {@inheritDoc}
150173
*
151174
* @since 0.1.0
175+
* @since 1.2.0 Added description support.
152176
*/
153177
public static function fromArray(array $array): self
154178
{
155179
static::validateFromArrayData($array, [self::KEY_ID, self::KEY_NAME, self::KEY_TYPE]);
156-
return new self($array[self::KEY_ID], $array[self::KEY_NAME], ProviderTypeEnum::from($array[self::KEY_TYPE]), $array[self::KEY_CREDENTIALS_URL] ?? null, isset($array[self::KEY_AUTHENTICATION_METHOD]) ? RequestAuthenticationMethod::from($array[self::KEY_AUTHENTICATION_METHOD]) : null);
180+
return new self($array[self::KEY_ID], $array[self::KEY_NAME], ProviderTypeEnum::from($array[self::KEY_TYPE]), $array[self::KEY_CREDENTIALS_URL] ?? null, isset($array[self::KEY_AUTHENTICATION_METHOD]) ? RequestAuthenticationMethod::from($array[self::KEY_AUTHENTICATION_METHOD]) : null, $array[self::KEY_DESCRIPTION] ?? null);
157181
}
158182
}

src/wp-includes/php-ai-client/src/Providers/Http/Enums/RequestAuthenticationMethod.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ class RequestAuthenticationMethod extends AbstractEnum
2727
* @since 0.4.0
2828
*
2929
* @return class-string<RequestAuthenticationInterface&WithArrayTransformationInterface> The implementation class.
30+
*
31+
* @phpstan-ignore missingType.generics
3032
*/
3133
public function getImplementationClass(): string
3234
{

src/wp-includes/php-ai-client/src/Providers/Http/HttpTransporter.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ private function convertFromPsr7Response(ResponseInterface $psr7Response): Respo
260260
return new Response(
261261
$psr7Response->getStatusCode(),
262262
$psr7Response->getHeaders(),
263+
// @phpstan-ignore-line
263264
$body === '' ? null : $body
264265
);
265266
}

src/wp-includes/php-ai-client/src/Providers/Models/DTO/SupportedOption.php

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
namespace WordPress\AiClient\Providers\Models\DTO;
55

66
use WordPress\AiClient\Common\AbstractDataTransferObject;
7+
use WordPress\AiClient\Common\AbstractEnum;
78
use WordPress\AiClient\Common\Exception\InvalidArgumentException;
89
use WordPress\AiClient\Providers\Models\Enums\OptionEnum;
910
/**
@@ -78,19 +79,62 @@ public function isSupportedValue($value): bool
7879
}
7980
// If the value is an array, consider it a set (i.e. order doesn't matter).
8081
if (is_array($value)) {
81-
sort($value);
82+
$normalizedValue = self::normalizeArrayForComparison($value);
8283
foreach ($this->supportedValues as $supportedValue) {
8384
if (!is_array($supportedValue)) {
8485
continue;
8586
}
86-
sort($supportedValue);
87-
if ($value === $supportedValue) {
87+
$normalizedSupported = self::normalizeArrayForComparison($supportedValue);
88+
if ($normalizedValue === $normalizedSupported) {
8889
return \true;
8990
}
9091
}
9192
return \false;
9293
}
93-
return in_array($value, $this->supportedValues, \true);
94+
$normalizedValue = self::normalizeValue($value);
95+
foreach ($this->supportedValues as $supportedValue) {
96+
if (self::normalizeValue($supportedValue) === $normalizedValue) {
97+
return \true;
98+
}
99+
}
100+
return \false;
101+
}
102+
/**
103+
* Normalizes an AbstractEnum instance to its string value.
104+
*
105+
* This ensures comparisons work correctly even after deserialization
106+
* (e.g. Redis/Memcached object cache), where AbstractEnum singletons
107+
* are reconstructed as separate instances.
108+
*
109+
* @since 1.2.1
110+
*
111+
* @param mixed $value The value to normalize.
112+
* @return mixed The normalized value.
113+
*/
114+
private static function normalizeValue($value)
115+
{
116+
if ($value instanceof AbstractEnum) {
117+
return $value->value;
118+
}
119+
return $value;
120+
}
121+
/**
122+
* Normalizes and sorts an array for comparison.
123+
*
124+
* Maps each element through normalizeValue() and sorts the result,
125+
* ensuring consistent comparison regardless of element order or
126+
* AbstractEnum instance identity.
127+
*
128+
* @since 1.2.1
129+
*
130+
* @param array<mixed> $items The array to normalize.
131+
* @return array<mixed> The normalized, sorted array.
132+
*/
133+
private static function normalizeArrayForComparison(array $items): array
134+
{
135+
$normalized = array_map([self::class, 'normalizeValue'], $items);
136+
sort($normalized);
137+
return $normalized;
94138
}
95139
/**
96140
* Gets the supported values for this option.

0 commit comments

Comments
 (0)