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 @@ +, + * outputFileType?: string, * outputMimeType?: string, * outputSchema?: array, + * outputMediaOrientation?: string, + * outputMediaAspectRatio?: string, * customOptions?: array * } * @@ -56,8 +61,11 @@ 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_OUTPUT_MEDIA_ORIENTATION = 'outputMediaOrientation'; + public const KEY_OUTPUT_MEDIA_ASPECT_RATIO = 'outputMediaAspectRatio'; public const KEY_CUSTOM_OPTIONS = 'customOptions'; /** @@ -125,6 +133,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. */ @@ -135,6 +148,16 @@ class ModelConfig extends AbstractDataTransferObject */ protected ?array $outputSchema = null; + /** + * @var MediaOrientationEnum|null Output media orientation. + */ + 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. */ @@ -470,6 +493,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. * @@ -526,6 +573,61 @@ 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 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. * @@ -641,6 +743,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.', @@ -650,6 +757,16 @@ 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_OUTPUT_MEDIA_ASPECT_RATIO => [ + 'type' => 'string', + 'pattern' => '^\d+:\d+$', + 'description' => 'Output media aspect ratio.', + ], self::KEY_CUSTOM_OPTIONS => [ 'type' => 'object', 'additionalProperties' => true, @@ -730,6 +847,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; } @@ -738,6 +859,14 @@ 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; + } + + if ($this->outputMediaAspectRatio !== null) { + $data[self::KEY_OUTPUT_MEDIA_ASPECT_RATIO] = $this->outputMediaAspectRatio; + } + $data[self::KEY_CUSTOM_OPTIONS] = $this->customOptions; return $data; @@ -809,6 +938,10 @@ public static function fromArray(array $array): self }, $array[self::KEY_TOOLS])); } + if (isset($array[self::KEY_OUTPUT_FILE_TYPE])) { + $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]); } @@ -817,6 +950,14 @@ 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_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]); } 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()); }