From 48a4c79c27e83ae51656636375c551c3b01f05c3 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Sat, 9 Aug 2025 15:00:47 -0500 Subject: [PATCH 1/5] Include outputFileType param for model config. --- src/Providers/Models/DTO/ModelConfig.php | 49 ++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/Providers/Models/DTO/ModelConfig.php b/src/Providers/Models/DTO/ModelConfig.php index eb072b4..964b685 100644 --- a/src/Providers/Models/DTO/ModelConfig.php +++ b/src/Providers/Models/DTO/ModelConfig.php @@ -6,6 +6,7 @@ use InvalidArgumentException; use WordPress\AiClient\Common\AbstractDataTransferObject; +use WordPress\AiClient\Files\Enums\FileTypeEnum; use WordPress\AiClient\Messages\Enums\ModalityEnum; use WordPress\AiClient\Tools\DTO\Tool; @@ -56,6 +57,7 @@ class ModelConfig extends AbstractDataTransferObject public const KEY_LOGPROBS = 'logprobs'; public const KEY_TOP_LOGPROBS = 'topLogprobs'; public const KEY_TOOLS = 'tools'; + public const KEY_OUTPUT_FILE_TYPE = 'outputFileType'; public const KEY_OUTPUT_MIME_TYPE = 'outputMimeType'; public const KEY_OUTPUT_SCHEMA = 'outputSchema'; public const KEY_CUSTOM_OPTIONS = 'customOptions'; @@ -125,6 +127,11 @@ class ModelConfig extends AbstractDataTransferObject */ protected ?array $tools = null; + /** + * @var FileTypeEnum|null Output file type. + */ + protected ?FileTypeEnum $outputFileType = null; + /** * @var string|null Output MIME type. */ @@ -470,6 +477,30 @@ public function getTools(): ?array return $this->tools; } + /** + * Sets the output file type. + * + * @since n.e.x.t + * + * @param FileTypeEnum $outputFileType The output file type. + */ + public function setOutputFileType(FileTypeEnum $outputFileType): void + { + $this->outputFileType = $outputFileType; + } + + /** + * Gets the output file type. + * + * @since n.e.x.t + * + * @return FileTypeEnum|null The output file type. + */ + public function getOutputFileType(): ?FileTypeEnum + { + return $this->outputFileType; + } + /** * Sets the output MIME type. * @@ -641,6 +672,11 @@ public static function getJsonSchema(): array 'items' => Tool::getJsonSchema(), 'description' => 'Tools available to the model.', ], + self::KEY_OUTPUT_FILE_TYPE => [ + 'type' => 'string', + 'enum' => FileTypeEnum::getValues(), + 'description' => 'Output file type.', + ], self::KEY_OUTPUT_MIME_TYPE => [ 'type' => 'string', 'description' => 'Output MIME type.', @@ -730,6 +766,10 @@ static function (ModalityEnum $modality): string { }, $this->tools); } + if ($this->outputFileType !== null) { + $data[self::KEY_OUTPUT_FILE_TYPE] = $this->outputFileType->value; + } + if ($this->outputMimeType !== null) { $data[self::KEY_OUTPUT_MIME_TYPE] = $this->outputMimeType; } @@ -809,6 +849,15 @@ public static function fromArray(array $array): self }, $array[self::KEY_TOOLS])); } + if (isset($array[self::KEY_OUTPUT_FILE_TYPE])) { + if (!is_string($array[self::KEY_OUTPUT_FILE_TYPE])) { + throw new InvalidArgumentException( + 'Output file type must be a string.' + ); + } + $config->setOutputFileType(FileTypeEnum::from($array[self::KEY_OUTPUT_FILE_TYPE])); + } + if (isset($array[self::KEY_OUTPUT_MIME_TYPE])) { $config->setOutputMimeType($array[self::KEY_OUTPUT_MIME_TYPE]); } From 65351a7cda3e5201135d0ad2867a189bb4369af9 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Sat, 9 Aug 2025 15:02:25 -0500 Subject: [PATCH 2/5] Fix missing entry in array shape. --- src/Providers/Models/DTO/ModelConfig.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Providers/Models/DTO/ModelConfig.php b/src/Providers/Models/DTO/ModelConfig.php index 964b685..8d6dd56 100644 --- a/src/Providers/Models/DTO/ModelConfig.php +++ b/src/Providers/Models/DTO/ModelConfig.php @@ -35,6 +35,7 @@ * logprobs?: bool, * topLogprobs?: int, * tools?: list, + * outputFileType?: string, * outputMimeType?: string, * outputSchema?: array, * customOptions?: array @@ -850,11 +851,6 @@ public static function fromArray(array $array): self } if (isset($array[self::KEY_OUTPUT_FILE_TYPE])) { - if (!is_string($array[self::KEY_OUTPUT_FILE_TYPE])) { - throw new InvalidArgumentException( - 'Output file type must be a string.' - ); - } $config->setOutputFileType(FileTypeEnum::from($array[self::KEY_OUTPUT_FILE_TYPE])); } From a6a83cb391af300328546a384ce865aa3fa740c0 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Sat, 9 Aug 2025 15:05:32 -0500 Subject: [PATCH 3/5] Add MediaOrientationEnum and include outputMediaOrientation param for model config. --- src/Files/Enums/MediaOrientationEnum.php | 43 ++++++++++++++++++++++ src/Providers/Models/DTO/ModelConfig.php | 45 ++++++++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 src/Files/Enums/MediaOrientationEnum.php diff --git a/src/Files/Enums/MediaOrientationEnum.php b/src/Files/Enums/MediaOrientationEnum.php new file mode 100644 index 0000000..cf12f79 --- /dev/null +++ b/src/Files/Enums/MediaOrientationEnum.php @@ -0,0 +1,43 @@ +, + * outputMediaOrientation?: string, * customOptions?: array * } * @@ -61,6 +63,7 @@ class ModelConfig extends AbstractDataTransferObject public const KEY_OUTPUT_FILE_TYPE = 'outputFileType'; public const KEY_OUTPUT_MIME_TYPE = 'outputMimeType'; public const KEY_OUTPUT_SCHEMA = 'outputSchema'; + public const KEY_OUTPUT_MEDIA_ORIENTATION = 'outputMediaOrientation'; public const KEY_CUSTOM_OPTIONS = 'customOptions'; /** @@ -143,6 +146,11 @@ class ModelConfig extends AbstractDataTransferObject */ protected ?array $outputSchema = null; + /** + * @var MediaOrientationEnum|null Output media orientation. + */ + protected ?MediaOrientationEnum $outputMediaOrientation = null; + /** * @var array Custom provider-specific options. */ @@ -558,6 +566,30 @@ public function getOutputSchema(): ?array return $this->outputSchema; } + /** + * Sets the output media orientation. + * + * @since n.e.x.t + * + * @param MediaOrientationEnum $outputMediaOrientation The output media orientation. + */ + public function setOutputMediaOrientation(MediaOrientationEnum $outputMediaOrientation): void + { + $this->outputMediaOrientation = $outputMediaOrientation; + } + + /** + * Gets the output media orientation. + * + * @since n.e.x.t + * + * @return MediaOrientationEnum|null The output media orientation. + */ + public function getOutputMediaOrientation(): ?MediaOrientationEnum + { + return $this->outputMediaOrientation; + } + /** * Sets a single custom option. * @@ -687,6 +719,11 @@ public static function getJsonSchema(): array 'additionalProperties' => true, 'description' => 'Output schema (JSON schema).', ], + self::KEY_OUTPUT_MEDIA_ORIENTATION => [ + 'type' => 'string', + 'enum' => MediaOrientationEnum::getValues(), + 'description' => 'Output media orientation.', + ], self::KEY_CUSTOM_OPTIONS => [ 'type' => 'object', 'additionalProperties' => true, @@ -779,6 +816,10 @@ static function (ModalityEnum $modality): string { $data[self::KEY_OUTPUT_SCHEMA] = $this->outputSchema; } + if ($this->outputMediaOrientation !== null) { + $data[self::KEY_OUTPUT_MEDIA_ORIENTATION] = $this->outputMediaOrientation->value; + } + $data[self::KEY_CUSTOM_OPTIONS] = $this->customOptions; return $data; @@ -862,6 +903,10 @@ public static function fromArray(array $array): self $config->setOutputSchema($array[self::KEY_OUTPUT_SCHEMA]); } + if (isset($array[self::KEY_OUTPUT_MEDIA_ORIENTATION])) { + $config->setOutputMediaOrientation(MediaOrientationEnum::from($array[self::KEY_OUTPUT_MEDIA_ORIENTATION])); + } + if (isset($array[self::KEY_CUSTOM_OPTIONS])) { $config->setCustomOptions($array[self::KEY_CUSTOM_OPTIONS]); } From b92d28c2961b964666f535c30f2b03343d2d7984 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Sat, 9 Aug 2025 15:11:06 -0500 Subject: [PATCH 4/5] Include outputMediaAspectRatio param for model config. --- src/Providers/Models/DTO/ModelConfig.php | 51 ++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/Providers/Models/DTO/ModelConfig.php b/src/Providers/Models/DTO/ModelConfig.php index 454ae52..7d84e63 100644 --- a/src/Providers/Models/DTO/ModelConfig.php +++ b/src/Providers/Models/DTO/ModelConfig.php @@ -40,6 +40,7 @@ * outputMimeType?: string, * outputSchema?: array, * outputMediaOrientation?: string, + * outputMediaAspectRatio?: string, * customOptions?: array * } * @@ -64,6 +65,7 @@ class ModelConfig extends AbstractDataTransferObject public const KEY_OUTPUT_MIME_TYPE = 'outputMimeType'; public const KEY_OUTPUT_SCHEMA = 'outputSchema'; public const KEY_OUTPUT_MEDIA_ORIENTATION = 'outputMediaOrientation'; + public const KEY_OUTPUT_MEDIA_ASPECT_RATIO = 'outputMediaAspectRatio'; public const KEY_CUSTOM_OPTIONS = 'customOptions'; /** @@ -151,6 +153,11 @@ class ModelConfig extends AbstractDataTransferObject */ protected ?MediaOrientationEnum $outputMediaOrientation = null; + /** + * @var string|null Output media aspect ratio (e.g. 3:2, 16:9). + */ + protected ?string $outputMediaAspectRatio = null; + /** * @var array Custom provider-specific options. */ @@ -590,6 +597,37 @@ public function getOutputMediaOrientation(): ?MediaOrientationEnum return $this->outputMediaOrientation; } + /** + * Sets the output media aspect ratio. + * + * If set, this supersedes the output media orientation, as it is a more specific configuration. + * + * @since n.e.x.t + * + * @param string $outputMediaAspectRatio The output media aspect ratio (e.g. 3:2, 16:9). + */ + public function setOutputMediaAspectRatio(string $outputMediaAspectRatio): void + { + if (!preg_match('/^\d+:\d+$/', $outputMediaAspectRatio)) { + throw new InvalidArgumentException( + 'Output media aspect ratio must be in the format "width:height" (e.g. 3:2, 16:9).' + ); + } + $this->outputMediaAspectRatio = $outputMediaAspectRatio; + } + + /** + * Gets the output media aspect ratio. + * + * @since n.e.x.t + * + * @return string|null The output media aspect ratio (e.g. 3:2, 16:9). + */ + public function getOutputMediaAspectRatio(): ?string + { + return $this->outputMediaAspectRatio; + } + /** * Sets a single custom option. * @@ -724,6 +762,11 @@ public static function getJsonSchema(): array 'enum' => MediaOrientationEnum::getValues(), 'description' => 'Output media orientation.', ], + self::KEY_OUTPUT_MEDIA_ASPECT_RATIO => [ + 'type' => 'string', + 'pattern' => '^\d+:\d+$', + 'description' => 'Output media aspect ratio.', + ], self::KEY_CUSTOM_OPTIONS => [ 'type' => 'object', 'additionalProperties' => true, @@ -820,6 +863,10 @@ static function (ModalityEnum $modality): string { $data[self::KEY_OUTPUT_MEDIA_ORIENTATION] = $this->outputMediaOrientation->value; } + if ($this->outputMediaAspectRatio !== null) { + $data[self::KEY_OUTPUT_MEDIA_ASPECT_RATIO] = $this->outputMediaAspectRatio; + } + $data[self::KEY_CUSTOM_OPTIONS] = $this->customOptions; return $data; @@ -907,6 +954,10 @@ public static function fromArray(array $array): self $config->setOutputMediaOrientation(MediaOrientationEnum::from($array[self::KEY_OUTPUT_MEDIA_ORIENTATION])); } + if (isset($array[self::KEY_OUTPUT_MEDIA_ASPECT_RATIO])) { + $config->setOutputMediaAspectRatio($array[self::KEY_OUTPUT_MEDIA_ASPECT_RATIO]); + } + if (isset($array[self::KEY_CUSTOM_OPTIONS])) { $config->setCustomOptions($array[self::KEY_CUSTOM_OPTIONS]); } From be95110c1bee035cfc8c8316ed359a3cfb06cab7 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Sat, 9 Aug 2025 15:17:00 -0500 Subject: [PATCH 5/5] Add test coverage for new model config params. --- .../Providers/Models/DTO/ModelConfigTest.php | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tests/unit/Providers/Models/DTO/ModelConfigTest.php b/tests/unit/Providers/Models/DTO/ModelConfigTest.php index 2a4ef07..b109703 100644 --- a/tests/unit/Providers/Models/DTO/ModelConfigTest.php +++ b/tests/unit/Providers/Models/DTO/ModelConfigTest.php @@ -6,6 +6,8 @@ use JsonSerializable; use PHPUnit\Framework\TestCase; +use WordPress\AiClient\Files\Enums\FileTypeEnum; +use WordPress\AiClient\Files\Enums\MediaOrientationEnum; use WordPress\AiClient\Messages\Enums\ModalityEnum; use WordPress\AiClient\Providers\Models\DTO\ModelConfig; use WordPress\AiClient\Tools\DTO\Tool; @@ -53,8 +55,11 @@ public function testDefaultConstructor(): void $this->assertNull($config->getLogprobs()); $this->assertNull($config->getTopLogprobs()); $this->assertNull($config->getTools()); + $this->assertNull($config->getOutputFileType()); $this->assertNull($config->getOutputMimeType()); $this->assertNull($config->getOutputSchema()); + $this->assertNull($config->getOutputMediaOrientation()); + $this->assertNull($config->getOutputMediaAspectRatio()); $this->assertEquals([], $config->getCustomOptions()); } @@ -138,6 +143,18 @@ public function testSettersAndGetters(): void $config->setOutputSchema($outputSchema); $this->assertEquals($outputSchema, $config->getOutputSchema()); + // Test output file type + $config->setOutputFileType(FileTypeEnum::inline()); + $this->assertEquals(FileTypeEnum::inline(), $config->getOutputFileType()); + + // Test output media orientation + $config->setOutputMediaOrientation(MediaOrientationEnum::landscape()); + $this->assertEquals(MediaOrientationEnum::landscape(), $config->getOutputMediaOrientation()); + + // Test output media aspect ratio + $config->setOutputMediaAspectRatio('4:3'); + $this->assertEquals('4:3', $config->getOutputMediaAspectRatio()); + // Test custom options $customOptions = ['custom_param' => 'value', 'another_param' => 123]; $config->setCustomOptions($customOptions); @@ -173,8 +190,11 @@ public function testGetJsonSchema(): void ModelConfig::KEY_LOGPROBS, ModelConfig::KEY_TOP_LOGPROBS, ModelConfig::KEY_TOOLS, + ModelConfig::KEY_OUTPUT_FILE_TYPE, ModelConfig::KEY_OUTPUT_MIME_TYPE, ModelConfig::KEY_OUTPUT_SCHEMA, + ModelConfig::KEY_OUTPUT_MEDIA_ORIENTATION, + ModelConfig::KEY_OUTPUT_MEDIA_ASPECT_RATIO, ModelConfig::KEY_CUSTOM_OPTIONS ]; @@ -190,6 +210,9 @@ public function testGetJsonSchema(): void $this->assertEquals('boolean', $schema['properties'][ModelConfig::KEY_LOGPROBS]['type']); $this->assertEquals('string', $schema['properties'][ModelConfig::KEY_OUTPUT_MIME_TYPE]['type']); $this->assertEquals('object', $schema['properties'][ModelConfig::KEY_OUTPUT_SCHEMA]['type']); + $this->assertEquals('string', $schema['properties'][ModelConfig::KEY_OUTPUT_FILE_TYPE]['type']); + $this->assertEquals('string', $schema['properties'][ModelConfig::KEY_OUTPUT_MEDIA_ORIENTATION]['type']); + $this->assertEquals('string', $schema['properties'][ModelConfig::KEY_OUTPUT_MEDIA_ASPECT_RATIO]['type']); $this->assertEquals('object', $schema['properties'][ModelConfig::KEY_CUSTOM_OPTIONS]['type']); // Check constraints @@ -223,8 +246,11 @@ public function testToArrayAllProperties(): void $config->setLogprobs(true); $config->setTopLogprobs(10); $config->setTools([$tool]); + $config->setOutputFileType(FileTypeEnum::remote()); $config->setOutputMimeType('application/json'); $config->setOutputSchema(['type' => 'object']); + $config->setOutputMediaOrientation(MediaOrientationEnum::portrait()); + $config->setOutputMediaAspectRatio('9:16'); $config->setCustomOptions(['key' => 'value']); $array = $config->toArray(); @@ -243,8 +269,11 @@ public function testToArrayAllProperties(): void $this->assertTrue($array[ModelConfig::KEY_LOGPROBS]); $this->assertEquals(10, $array[ModelConfig::KEY_TOP_LOGPROBS]); $this->assertCount(1, $array[ModelConfig::KEY_TOOLS]); + $this->assertEquals('remote', $array[ModelConfig::KEY_OUTPUT_FILE_TYPE]); $this->assertEquals('application/json', $array[ModelConfig::KEY_OUTPUT_MIME_TYPE]); $this->assertEquals(['type' => 'object'], $array[ModelConfig::KEY_OUTPUT_SCHEMA]); + $this->assertEquals('portrait', $array[ModelConfig::KEY_OUTPUT_MEDIA_ORIENTATION]); + $this->assertEquals('9:16', $array[ModelConfig::KEY_OUTPUT_MEDIA_ASPECT_RATIO]); $this->assertEquals(['key' => 'value'], $array[ModelConfig::KEY_CUSTOM_OPTIONS]); } @@ -320,6 +349,9 @@ public function testFromArrayAllProperties(): void ], ModelConfig::KEY_OUTPUT_MIME_TYPE => 'application/json', ModelConfig::KEY_OUTPUT_SCHEMA => ['type' => 'array', 'items' => ['type' => 'string']], + ModelConfig::KEY_OUTPUT_FILE_TYPE => 'inline', + ModelConfig::KEY_OUTPUT_MEDIA_ORIENTATION => 'landscape', + ModelConfig::KEY_OUTPUT_MEDIA_ASPECT_RATIO => '16:9', ModelConfig::KEY_CUSTOM_OPTIONS => ['custom' => true] ]; @@ -343,6 +375,9 @@ public function testFromArrayAllProperties(): void $this->assertCount(1, $config->getTools()); $this->assertEquals('application/json', $config->getOutputMimeType()); $this->assertEquals(['type' => 'array', 'items' => ['type' => 'string']], $config->getOutputSchema()); + $this->assertEquals(FileTypeEnum::inline(), $config->getOutputFileType()); + $this->assertEquals(MediaOrientationEnum::landscape(), $config->getOutputMediaOrientation()); + $this->assertEquals('16:9', $config->getOutputMediaAspectRatio()); $this->assertEquals(['custom' => true], $config->getCustomOptions()); } @@ -374,6 +409,9 @@ public function testArrayRoundTrip(): void $original->setMaxTokens(1500); $original->setStopSequences(['END', 'STOP']); $original->setLogprobs(true); + $original->setOutputFileType(FileTypeEnum::inline()); + $original->setOutputMediaOrientation(MediaOrientationEnum::square()); + $original->setOutputMediaAspectRatio('1:1'); $original->setCustomOptions(['test' => 'value']); $array = $original->toArray(); @@ -384,6 +422,9 @@ public function testArrayRoundTrip(): void $this->assertEquals($original->getMaxTokens(), $restored->getMaxTokens()); $this->assertEquals($original->getStopSequences(), $restored->getStopSequences()); $this->assertEquals($original->getLogprobs(), $restored->getLogprobs()); + $this->assertEquals($original->getOutputFileType(), $restored->getOutputFileType()); + $this->assertEquals($original->getOutputMediaOrientation(), $restored->getOutputMediaOrientation()); + $this->assertEquals($original->getOutputMediaAspectRatio(), $restored->getOutputMediaAspectRatio()); $this->assertEquals($original->getCustomOptions(), $restored->getCustomOptions()); }