Skip to content
Open
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
117 changes: 94 additions & 23 deletions src/Providers/DTO/ProviderMetadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,16 @@
*
* @since 0.1.0
*
* @phpstan-type ProviderMetadataArgsShape array{
* description?: ?string,
* type?: ProviderTypeEnum,
* credentialsUrl?: ?string,
* authenticationMethod?: ?RequestAuthenticationMethod
* }
* @phpstan-type ProviderMetadataArrayShape array{
* id: string,
* name: string,
* description?: ?string,
* type: string,
* credentialsUrl?: ?string,
* authenticationMethod?: ?string
Expand All @@ -30,6 +37,7 @@ class ProviderMetadata extends AbstractDataTransferObject
{
public const KEY_ID = 'id';
public const KEY_NAME = 'name';
public const KEY_DESCRIPTION = 'description';
public const KEY_TYPE = 'type';
public const KEY_CREDENTIALS_URL = 'credentialsUrl';
public const KEY_AUTHENTICATION_METHOD = 'authenticationMethod';
Expand All @@ -44,6 +52,11 @@ class ProviderMetadata extends AbstractDataTransferObject
*/
protected string $name;

/**
* @var string|null The provider's description.
*/
protected ?string $description;

/**
* @var ProviderTypeEnum The provider type.
*/
Expand All @@ -62,26 +75,51 @@ class ProviderMetadata extends AbstractDataTransferObject
/**
* Constructor.
*
* Accepts either an array of arguments or legacy positional parameters
* for backwards compatibility.
*
* @since 0.1.0
*
* @param string $id The provider's unique identifier.
* @param string $name The provider's display name.
* @param ProviderTypeEnum $type The provider type.
* @param string|null $credentialsUrl The URL where users can get credentials.
* @param RequestAuthenticationMethod|null $authenticationMethod The authentication method.
*/
public function __construct(
string $id,
string $name,
ProviderTypeEnum $type,
?string $credentialsUrl = null,
?RequestAuthenticationMethod $authenticationMethod = null
) {
* @param string $id The provider's unique identifier.
* @param string $name The provider's display name.
* @param ProviderMetadataArgsShape|ProviderTypeEnum $args {
* Optional. Provider metadata arguments, or a ProviderTypeEnum for backwards compatibility.
*
* @type string|null $description The provider's description.
* @type ProviderTypeEnum $type The provider type. Default cloud.
* @type string|null $credentialsUrl The URL where users can get credentials.
* @type RequestAuthenticationMethod|null $authenticationMethod The authentication method.
* }
*/
public function __construct(string $id, string $name, $args = [])
{
// Capture all arguments before any parameter is modified.
$allArgs = func_get_args();

$this->id = $id;
$this->name = $name;
$this->type = $type;
$this->credentialsUrl = $credentialsUrl;
$this->authenticationMethod = $authenticationMethod;

// Backwards compatibility: accept old-style positional arguments.
if ($args instanceof ProviderTypeEnum) {
$args = [
self::KEY_TYPE => $allArgs[2],
];
if (isset($allArgs[3])) {
$args[self::KEY_CREDENTIALS_URL] = $allArgs[3];
}
if (isset($allArgs[4])) {
$args[self::KEY_AUTHENTICATION_METHOD] = $allArgs[4];
}
if (isset($allArgs[5])) {
$args[self::KEY_DESCRIPTION] = $allArgs[5];
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This last one is unnecessary. It was never possible in the old way to pass a description anyway. We should not add support for it in the wrong way that we want to discourage anyway.

}

/** @var ProviderMetadataArgsShape $args */
$this->description = $args[self::KEY_DESCRIPTION] ?? null;
$this->type = $args[self::KEY_TYPE] ?? ProviderTypeEnum::cloud();
$this->credentialsUrl = $args[self::KEY_CREDENTIALS_URL] ?? null;
$this->authenticationMethod = $args[self::KEY_AUTHENTICATION_METHOD] ?? null;
}

/**
Expand All @@ -108,6 +146,18 @@ public function getName(): string
return $this->name;
}

/**
* Gets the provider's description.
*
* @since 0.5.0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

n.e.x.t - please double check that throughout the PR

*
* @return string|null The provider description.
*/
public function getDescription(): ?string
{
return $this->description;
}

/**
* Gets the provider type.
*
Expand Down Expand Up @@ -162,6 +212,10 @@ public static function getJsonSchema(): array
'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(),
Expand All @@ -177,7 +231,7 @@ public static function getJsonSchema(): array
'description' => 'The authentication method.',
],
],
'required' => [self::KEY_ID, self::KEY_NAME, self::KEY_TYPE],
'required' => [self::KEY_ID, self::KEY_NAME],
];
}

Expand All @@ -193,6 +247,7 @@ public function toArray(): array
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,
Expand All @@ -206,16 +261,32 @@ public function toArray(): array
*/
public static function fromArray(array $array): self
{
static::validateFromArrayData($array, [self::KEY_ID, self::KEY_NAME, self::KEY_TYPE]);
static::validateFromArrayData($array, [self::KEY_ID, self::KEY_NAME]);

$args = [];

if (isset($array[self::KEY_DESCRIPTION])) {
$args[self::KEY_DESCRIPTION] = $array[self::KEY_DESCRIPTION];
}

if (isset($array[self::KEY_TYPE])) {
$args[self::KEY_TYPE] = ProviderTypeEnum::from($array[self::KEY_TYPE]);
}

if (isset($array[self::KEY_CREDENTIALS_URL])) {
$args[self::KEY_CREDENTIALS_URL] = $array[self::KEY_CREDENTIALS_URL];
}

if (isset($array[self::KEY_AUTHENTICATION_METHOD])) {
$args[self::KEY_AUTHENTICATION_METHOD] = RequestAuthenticationMethod::from(
$array[self::KEY_AUTHENTICATION_METHOD]
);
}

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
$args
);
}
}
2 changes: 1 addition & 1 deletion tests/mocks/MockAbstractProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ protected static function createModel(
*/
protected static function createProviderMetadata(): ProviderMetadata
{
return static::$mockProviderMetadata ?? new ProviderMetadata('mock-provider', 'Mock Provider', '1.0.0');
return static::$mockProviderMetadata ?? new ProviderMetadata('mock-provider', 'Mock Provider');
}

/**
Expand Down
2 changes: 1 addition & 1 deletion tests/mocks/MockNoAuthProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class MockNoAuthProvider implements ProviderInterface
*/
public static function metadata(): ProviderMetadata
{
return new ProviderMetadata('no-auth', 'No Auth Provider', ProviderTypeEnum::server());
return new ProviderMetadata('no-auth', 'No Auth Provider', ['type' => ProviderTypeEnum::server()]);
}

/**
Expand Down
5 changes: 1 addition & 4 deletions tests/mocks/MockProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
use WordPress\AiClient\Providers\Contracts\ProviderAvailabilityInterface;
use WordPress\AiClient\Providers\Contracts\ProviderInterface;
use WordPress\AiClient\Providers\DTO\ProviderMetadata;
use WordPress\AiClient\Providers\Enums\ProviderTypeEnum;
use WordPress\AiClient\Providers\Http\Enums\RequestAuthenticationMethod;
use WordPress\AiClient\Providers\Models\Contracts\ModelInterface;
use WordPress\AiClient\Providers\Models\DTO\ModelConfig;
Expand Down Expand Up @@ -38,9 +37,7 @@ public static function metadata(): ProviderMetadata
return new ProviderMetadata(
'mock',
'Mock Provider',
ProviderTypeEnum::cloud(),
null,
RequestAuthenticationMethod::apiKey()
['authenticationMethod' => RequestAuthenticationMethod::apiKey()]
);
}

Expand Down
13 changes: 4 additions & 9 deletions tests/traits/MockModelCreationTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
use WordPress\AiClient\Messages\DTO\MessagePart;
use WordPress\AiClient\Messages\DTO\ModelMessage;
use WordPress\AiClient\Providers\DTO\ProviderMetadata;
use WordPress\AiClient\Providers\Enums\ProviderTypeEnum;
use WordPress\AiClient\Providers\Models\Contracts\ModelInterface;
use WordPress\AiClient\Providers\Models\DTO\ModelConfig;
use WordPress\AiClient\Providers\Models\DTO\ModelMetadata;
Expand Down Expand Up @@ -56,8 +55,7 @@ protected function createTestResult(string $content = 'Test response'): Generati

$providerMetadata = new ProviderMetadata(
'mock',
'Mock Provider',
ProviderTypeEnum::cloud()
'Mock Provider'
);
$modelMetadata = new ModelMetadata(
'mock-model',
Expand Down Expand Up @@ -128,8 +126,7 @@ protected function createMockTextGenerationModel(

$providerMetadata = new ProviderMetadata(
'mock',
'Mock Provider',
ProviderTypeEnum::cloud()
'Mock Provider'
);

return new class (
Expand Down Expand Up @@ -195,8 +192,7 @@ protected function createMockImageGenerationModel(

$providerMetadata = new ProviderMetadata(
'mock',
'Mock Provider',
ProviderTypeEnum::cloud()
'Mock Provider'
);

return new class (
Expand Down Expand Up @@ -259,8 +255,7 @@ protected function createMockUnsupportedModel(string $modelId = 'unsupported-mod
$mockMetadata = $this->createMock(ModelMetadata::class);
$mockProviderMetadata = new ProviderMetadata(
'mock',
'Mock Provider',
ProviderTypeEnum::cloud()
'Mock Provider'
);

$mockMetadata->expects($this->any())
Expand Down
24 changes: 8 additions & 16 deletions tests/unit/Builders/PromptBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
use WordPress\AiClient\Messages\Enums\ModalityEnum;
use WordPress\AiClient\Providers\DTO\ProviderMetadata;
use WordPress\AiClient\Providers\DTO\ProviderModelsMetadata;
use WordPress\AiClient\Providers\Enums\ProviderTypeEnum;
use WordPress\AiClient\Providers\Models\Contracts\ModelInterface;
use WordPress\AiClient\Providers\Models\DTO\ModelConfig;
use WordPress\AiClient\Providers\Models\DTO\ModelMetadata;
Expand Down Expand Up @@ -58,7 +57,7 @@ class PromptBuilderTest extends TestCase
*/
private function createTestProviderMetadata(): ProviderMetadata
{
return new ProviderMetadata('test-provider', 'Test Provider', ProviderTypeEnum::cloud());
return new ProviderMetadata('test-provider', 'Test Provider');
}

/**
Expand Down Expand Up @@ -91,8 +90,7 @@ private function createSpeechGenerationModel(ModelMetadata $metadata, Generative
{
$providerMetadata = new ProviderMetadata(
'mock-provider',
'Mock Provider',
ProviderTypeEnum::cloud()
'Mock Provider'
);

return new class (
Expand Down Expand Up @@ -154,8 +152,7 @@ private function createTextToSpeechModel(ModelMetadata $metadata, GenerativeAiRe
{
$providerMetadata = new ProviderMetadata(
'mock-provider',
'Mock Provider',
ProviderTypeEnum::cloud()
'Mock Provider'
);

return new class (
Expand Down Expand Up @@ -660,20 +657,17 @@ public function testUsingModelPreferenceWithProviderTupleSelectsModel(): void

$firstProviderMetadata = new ProviderMetadata(
'first-provider',
'First Provider',
ProviderTypeEnum::cloud()
'First Provider'
);

$preferredProviderMetadata = new ProviderMetadata(
'preferred-provider',
'Preferred Provider',
ProviderTypeEnum::cloud()
'Preferred Provider'
);

$otherProviderMetadata = new ProviderMetadata(
'other-provider',
'Other Provider',
ProviderTypeEnum::cloud()
'Other Provider'
);

$this->registry->expects($this->once())
Expand Down Expand Up @@ -1904,8 +1898,7 @@ public function testGenerateTextThrowsExceptionWhenNoCandidates(): void

$providerMetadata = new ProviderMetadata(
'mock-provider',
'Mock Provider',
ProviderTypeEnum::cloud()
'Mock Provider'
);

$model = new class (
Expand Down Expand Up @@ -2093,8 +2086,7 @@ public function testGenerateTextsThrowsExceptionWhenNoTextGenerated(): void

$providerMetadata = new ProviderMetadata(
'mock-provider',
'Mock Provider',
ProviderTypeEnum::cloud()
'Mock Provider'
);

$model = new class (
Expand Down
3 changes: 1 addition & 2 deletions tests/unit/Operations/DTO/GenerativeAiOperationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ private function createTestProviderMetadata(): ProviderMetadata
{
return new ProviderMetadata(
'test-provider',
'Test Provider',
ProviderTypeEnum::cloud()
'Test Provider'
);
}

Expand Down
5 changes: 2 additions & 3 deletions tests/unit/Providers/AbstractProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
use WordPress\AiClient\Providers\Contracts\ModelMetadataDirectoryInterface;
use WordPress\AiClient\Providers\Contracts\ProviderAvailabilityInterface;
use WordPress\AiClient\Providers\DTO\ProviderMetadata;
use WordPress\AiClient\Providers\Enums\ProviderTypeEnum;
use WordPress\AiClient\Providers\Models\Contracts\ModelInterface;
use WordPress\AiClient\Providers\Models\DTO\ModelConfig;
use WordPress\AiClient\Providers\Models\DTO\ModelMetadata;
Expand Down Expand Up @@ -176,7 +175,7 @@ protected static function createModel(
}
protected static function createProviderMetadata(): ProviderMetadata
{
return new ProviderMetadata('mock-provider-1', 'Mock Provider 1', ProviderTypeEnum::cloud());
return new ProviderMetadata('mock-provider-1', 'Mock Provider 1');
}
protected static function createProviderAvailability(): ProviderAvailabilityInterface
{
Expand All @@ -197,7 +196,7 @@ protected static function createModel(
}
protected static function createProviderMetadata(): ProviderMetadata
{
return new ProviderMetadata('mock-provider-2', 'Mock Provider 2', ProviderTypeEnum::cloud());
return new ProviderMetadata('mock-provider-2', 'Mock Provider 2');
}
protected static function createProviderAvailability(): ProviderAvailabilityInterface
{
Expand Down
Loading
Loading