From 3c0004be014bc13e68885049eafb22c5a14648e9 Mon Sep 17 00:00:00 2001 From: Connor Tumbleson Date: Mon, 28 Jul 2025 10:38:04 -0400 Subject: [PATCH 1/5] wip: add containers --- .../Resources/ContainersContract.php | 48 ++++++++ src/Resources/Containers.php | 116 ++++++++++++++++++ src/Responses/Containers/DeleteContainer.php | 60 +++++++++ .../Containers/Objects/ExpiresAfter.php | 54 ++++++++ .../Containers/RetrieveContainer.php | 78 ++++++++++++ .../Resources/ContainersTestResource.php | 41 +++++++ 6 files changed, 397 insertions(+) create mode 100644 src/Contracts/Resources/ContainersContract.php create mode 100644 src/Resources/Containers.php create mode 100644 src/Responses/Containers/DeleteContainer.php create mode 100644 src/Responses/Containers/Objects/ExpiresAfter.php create mode 100644 src/Responses/Containers/RetrieveContainer.php create mode 100644 src/Testing/Resources/ContainersTestResource.php diff --git a/src/Contracts/Resources/ContainersContract.php b/src/Contracts/Resources/ContainersContract.php new file mode 100644 index 00000000..d3a71a71 --- /dev/null +++ b/src/Contracts/Resources/ContainersContract.php @@ -0,0 +1,48 @@ + $parameters + */ + public function create(array $parameters): CreateResponse; + + /** + * Retrieves a container with the given ID. + * + * @see https://platform.openai.com/docs/api-reference/containers/retrieveContainer + */ + public function retrieve(string $id): RetrieveContainer; + + /** + * Delete a container with the given ID. + * + * @see https://platform.openai.com/docs/api-reference/containers/deleteContainer + */ + public function delete(string $id): DeleteContainer; + + /** + * Returns a list of input items for a given response. + * + * @see https://platform.openai.com/docs/api-reference/responses/input-items + * + * @param array $parameters + */ + public function list(string $id, array $parameters = []): ListInputItems; +} diff --git a/src/Resources/Containers.php b/src/Resources/Containers.php new file mode 100644 index 00000000..a0443c9e --- /dev/null +++ b/src/Resources/Containers.php @@ -0,0 +1,116 @@ + $parameters + */ + public function create(array $parameters): CreateResponse + { + $this->ensureNotStreamed($parameters); + + $payload = Payload::create('responses', $parameters); + + /** @var Response $response */ + $response = $this->transporter->requestObject($payload); + + return CreateResponse::from($response->data(), $response->meta()); + } + + /** + * When you create a Response with stream set to true, + * the server will emit server-sent events to the client as the Response is generated. + * + * @see https://platform.openai.com/docs/api-reference/responses-streaming + * + * @param array $parameters + * @return StreamResponse + */ + public function createStreamed(array $parameters): StreamResponse + { + $parameters = $this->setStreamParameter($parameters); + + $payload = Payload::create('responses', $parameters); + + $response = $this->transporter->requestStream($payload); + + return new StreamResponse(CreateStreamedResponse::class, $response); + } + + /** + * Retrieves a container with the given ID. + * + * @see https://platform.openai.com/docs/api-reference/containers/retrieveContainer + */ + public function retrieve(string $id): RetrieveContainer + { + $payload = Payload::retrieve('containers', $id); + + /** @var Response $response */ + $response = $this->transporter->requestObject($payload); + + return RetrieveContainer::from($response->data(), $response->meta()); + } + + /** + * Delete a container with the given ID. + * + * @phpstan-import-type DeleteContainerType from DeleteContainer + * + * @see https://platform.openai.com/docs/api-reference/containers/deleteContainer + */ + public function delete(string $id): DeleteContainer + { + $payload = Payload::delete('containers', $id); + + /** @var Response $response */ + $response = $this->transporter->requestObject($payload); + + return DeleteContainer::from($response->data(), $response->meta()); + } + + /** + * Lists input items for a response with the given ID. + * + * @see https://platform.openai.com/docs/api-reference/responses/input-items + * + * @param array $parameters + */ + public function list(string $id, array $parameters = []): ListInputItems + { + $payload = Payload::list('responses/'.$id.'/input_items', $parameters); + + /** @var Response $response */ + $response = $this->transporter->requestObject($payload); + + return ListInputItems::from($response->data(), $response->meta()); + } +} diff --git a/src/Responses/Containers/DeleteContainer.php b/src/Responses/Containers/DeleteContainer.php new file mode 100644 index 00000000..c9bb5819 --- /dev/null +++ b/src/Responses/Containers/DeleteContainer.php @@ -0,0 +1,60 @@ + + */ +final class DeleteContainer implements ResponseContract, ResponseHasMetaInformationContract +{ + /** + * @use ArrayAccessible + */ + use ArrayAccessible; + + use Fakeable; + use HasMetaInformation; + + private function __construct( + public readonly string $id, + public readonly string $object, + public readonly bool $deleted, + private readonly MetaInformation $meta, + ) {} + + /** + * @param DeleteContainerType $attributes + */ + public static function from(array $attributes, MetaInformation $meta): self + { + return new self( + id: $attributes['id'], + object: $attributes['object'], + deleted: $attributes['deleted'], + meta: $meta, + ); + } + + /** + * {@inheritDoc} + */ + public function toArray(): array + { + return [ + 'id' => $this->id, + 'object' => $this->object, + 'deleted' => $this->deleted, + ]; + } +} diff --git a/src/Responses/Containers/Objects/ExpiresAfter.php b/src/Responses/Containers/Objects/ExpiresAfter.php new file mode 100644 index 00000000..06679b09 --- /dev/null +++ b/src/Responses/Containers/Objects/ExpiresAfter.php @@ -0,0 +1,54 @@ + + */ +final class ExpiresAfter implements ResponseContract +{ + /** + * @use ArrayAccessible + */ + use ArrayAccessible; + + use Fakeable; + + /** + * @param 'last_active_at' $anchor + */ + private function __construct( + public readonly string $anchor, + public readonly int $minutes, + ) {} + + /** + * @param ExpiresAfterType $attributes + */ + public static function from(array $attributes): self + { + return new self( + anchor: $attributes['anchor'], + minutes: $attributes['minutes'], + ); + } + + /** + * {@inheritDoc} + */ + public function toArray(): array + { + return [ + 'anchor' => $this->anchor, + 'minutes' => $this->minutes, + ]; + } +} diff --git a/src/Responses/Containers/RetrieveContainer.php b/src/Responses/Containers/RetrieveContainer.php new file mode 100644 index 00000000..d1ea9b0a --- /dev/null +++ b/src/Responses/Containers/RetrieveContainer.php @@ -0,0 +1,78 @@ + + */ +final class RetrieveContainer implements ResponseContract, ResponseHasMetaInformationContract +{ + /** + * @use ArrayAccessible + */ + use ArrayAccessible; + + use Fakeable; + use HasMetaInformation; + + /** + * @param 'container' $object + */ + private function __construct( + public readonly string $id, + public readonly string $object, + public readonly int $createdAt, + public readonly string $status, + public readonly ExpiresAfter $expiresAfter, + public readonly int $lastActiveAt, + public readonly string $name, + private readonly MetaInformation $meta, + ) {} + + /** + * @param RetrieveContainerType $attributes + */ + public static function from(array $attributes, MetaInformation $meta): self + { + return new self( + id: $attributes['id'], + object: $attributes['object'], + createdAt: $attributes['created_at'], + status: $attributes['status'], + expiresAfter: ExpiresAfter::from($attributes['expires_after']), + lastActiveAt: $attributes['last_active_at'], + name: $attributes['name'], + meta: $meta, + ); + } + + /** + * {@inheritDoc} + */ + public function toArray(): array + { + return [ + 'id' => $this->id, + 'object' => $this->object, + 'created_at' => $this->createdAt, + 'status' => $this->status, + 'expires_after' => $this->expiresAfter->toArray(), + 'last_active_at' => $this->lastActiveAt, + 'name' => $this->name, + ]; + } +} diff --git a/src/Testing/Resources/ContainersTestResource.php b/src/Testing/Resources/ContainersTestResource.php new file mode 100644 index 00000000..f3a961d4 --- /dev/null +++ b/src/Testing/Resources/ContainersTestResource.php @@ -0,0 +1,41 @@ +record(__FUNCTION__, func_get_args()); + } + + public function retrieve(string $id): RetrieveContainer + { + return $this->record(__FUNCTION__, func_get_args()); + } + + public function list(string $id, array $parameters = []): ListInputItems + { + return $this->record(__FUNCTION__, func_get_args()); + } + + public function delete(string $id): DeleteContainer + { + return $this->record(__FUNCTION__, func_get_args()); + } +} From 89e67917b3a0308f49534368c75f1159dafd6b06 Mon Sep 17 00:00:00 2001 From: Connor Tumbleson Date: Tue, 29 Jul 2025 07:13:51 -0400 Subject: [PATCH 2/5] chore: build out container api --- .../Resources/ContainersContract.php | 19 ++--- src/Resources/Containers.php | 66 +++++----------- src/Responses/Containers/CreateContainer.php | 78 +++++++++++++++++++ src/Responses/Containers/ListContainers.php | 78 +++++++++++++++++++ 4 files changed, 183 insertions(+), 58 deletions(-) create mode 100644 src/Responses/Containers/CreateContainer.php create mode 100644 src/Responses/Containers/ListContainers.php diff --git a/src/Contracts/Resources/ContainersContract.php b/src/Contracts/Resources/ContainersContract.php index d3a71a71..3066a58d 100644 --- a/src/Contracts/Resources/ContainersContract.php +++ b/src/Contracts/Resources/ContainersContract.php @@ -4,24 +4,21 @@ namespace OpenAI\Contracts\Resources; +use OpenAI\Responses\Containers\CreateContainer; use OpenAI\Responses\Containers\DeleteContainer; +use OpenAI\Responses\Containers\ListContainers; use OpenAI\Responses\Containers\RetrieveContainer; -use OpenAI\Responses\Responses\CreateResponse; -use OpenAI\Responses\Responses\ListInputItems; interface ContainersContract { /** - * Creates a model response. - * Provide text or image inputs to generate text or JSON outputs. - * Have the model call your own custom code or use built-in tools - * like web search or file search to use your own data as input for the model's response. + * Creates a container for use with the Code Interpreter tool. * - * @see https://platform.openai.com/docs/api-reference/responses/create + * @see https://platform.openai.com/docs/api-reference/containers/createContainers * * @param array $parameters */ - public function create(array $parameters): CreateResponse; + public function create(array $parameters): CreateContainer; /** * Retrieves a container with the given ID. @@ -38,11 +35,11 @@ public function retrieve(string $id): RetrieveContainer; public function delete(string $id): DeleteContainer; /** - * Returns a list of input items for a given response. + * List containers * - * @see https://platform.openai.com/docs/api-reference/responses/input-items + * @see https://platform.openai.com/docs/api-reference/containers/listContainers * * @param array $parameters */ - public function list(string $id, array $parameters = []): ListInputItems; + public function list(array $parameters = []): ListContainers; } diff --git a/src/Resources/Containers.php b/src/Resources/Containers.php index a0443c9e..65470c3b 100644 --- a/src/Resources/Containers.php +++ b/src/Resources/Containers.php @@ -5,64 +5,38 @@ namespace OpenAI\Resources; use OpenAI\Contracts\Resources\ContainersContract; +use OpenAI\Responses\Containers\CreateContainer; use OpenAI\Responses\Containers\DeleteContainer; +use OpenAI\Responses\Containers\ListContainers; use OpenAI\Responses\Containers\RetrieveContainer; -use OpenAI\Responses\Responses\CreateResponse; -use OpenAI\Responses\Responses\CreateStreamedResponse; -use OpenAI\Responses\Responses\ListInputItems; -use OpenAI\Responses\Responses\RetrieveResponse; -use OpenAI\Responses\StreamResponse; use OpenAI\ValueObjects\Transporter\Payload; use OpenAI\ValueObjects\Transporter\Response; /** - * @phpstan-import-type CreateResponseType from CreateResponse - * @phpstan-import-type RetrieveResponseType from RetrieveResponse - * @phpstan-import-type ListInputItemsType from ListInputItems + * @phpstan-import-type CreateContainerType from CreateContainer + * @phpstan-import-type RetrieveContainerType from RetrieveContainer + * @phpstan-import-type DeleteContainerType from DeleteContainer + * @phpstan-import-type ListContainersType from ListContainers */ final class Containers implements ContainersContract { use Concerns\Transportable; /** - * Creates a model response. Provide text or image inputs to generate text or JSON outputs. - * Have the model call your own custom code or use built-in tools like web search or file search - * to use your own data as input for the model's response. + * Creates a container for use with the Code Interpreter tool. * - * @see https://platform.openai.com/docs/api-reference/responses/create + * @see https://platform.openai.com/docs/api-reference/containers/createContainers * * @param array $parameters */ - public function create(array $parameters): CreateResponse + public function create(array $parameters): CreateContainer { - $this->ensureNotStreamed($parameters); + $payload = Payload::create('containers', $parameters); - $payload = Payload::create('responses', $parameters); - - /** @var Response $response */ + /** @var Response $response */ $response = $this->transporter->requestObject($payload); - return CreateResponse::from($response->data(), $response->meta()); - } - - /** - * When you create a Response with stream set to true, - * the server will emit server-sent events to the client as the Response is generated. - * - * @see https://platform.openai.com/docs/api-reference/responses-streaming - * - * @param array $parameters - * @return StreamResponse - */ - public function createStreamed(array $parameters): StreamResponse - { - $parameters = $this->setStreamParameter($parameters); - - $payload = Payload::create('responses', $parameters); - - $response = $this->transporter->requestStream($payload); - - return new StreamResponse(CreateStreamedResponse::class, $response); + return CreateContainer::from($response->data(), $response->meta()); } /** @@ -74,7 +48,7 @@ public function retrieve(string $id): RetrieveContainer { $payload = Payload::retrieve('containers', $id); - /** @var Response $response */ + /** @var Response $response */ $response = $this->transporter->requestObject($payload); return RetrieveContainer::from($response->data(), $response->meta()); @@ -83,8 +57,6 @@ public function retrieve(string $id): RetrieveContainer /** * Delete a container with the given ID. * - * @phpstan-import-type DeleteContainerType from DeleteContainer - * * @see https://platform.openai.com/docs/api-reference/containers/deleteContainer */ public function delete(string $id): DeleteContainer @@ -98,19 +70,19 @@ public function delete(string $id): DeleteContainer } /** - * Lists input items for a response with the given ID. + * List containers * - * @see https://platform.openai.com/docs/api-reference/responses/input-items + * @see https://platform.openai.com/docs/api-reference/containers/listContainers * * @param array $parameters */ - public function list(string $id, array $parameters = []): ListInputItems + public function list(array $parameters = []): ListContainers { - $payload = Payload::list('responses/'.$id.'/input_items', $parameters); + $payload = Payload::list('containers', $parameters); - /** @var Response $response */ + /** @var Response $response */ $response = $this->transporter->requestObject($payload); - return ListInputItems::from($response->data(), $response->meta()); + return ListContainers::from($response->data(), $response->meta()); } } diff --git a/src/Responses/Containers/CreateContainer.php b/src/Responses/Containers/CreateContainer.php new file mode 100644 index 00000000..8bbe8e54 --- /dev/null +++ b/src/Responses/Containers/CreateContainer.php @@ -0,0 +1,78 @@ + + */ +final class CreateContainer implements ResponseContract, ResponseHasMetaInformationContract +{ + /** + * @use ArrayAccessible + */ + use ArrayAccessible; + + use Fakeable; + use HasMetaInformation; + + /** + * @param 'container' $object + */ + private function __construct( + public readonly string $id, + public readonly string $object, + public readonly int $createdAt, + public readonly string $status, + public readonly ExpiresAfter $expiresAfter, + public readonly int $lastActiveAt, + public readonly string $name, + private readonly MetaInformation $meta, + ) {} + + /** + * @param CreateContainerType $attributes + */ + public static function from(array $attributes, MetaInformation $meta): self + { + return new self( + id: $attributes['id'], + object: $attributes['object'], + createdAt: $attributes['created_at'], + status: $attributes['status'], + expiresAfter: ExpiresAfter::from($attributes['expires_after']), + lastActiveAt: $attributes['last_active_at'], + name: $attributes['name'], + meta: $meta, + ); + } + + /** + * {@inheritDoc} + */ + public function toArray(): array + { + return [ + 'id' => $this->id, + 'object' => $this->object, + 'created_at' => $this->createdAt, + 'status' => $this->status, + 'expires_after' => $this->expiresAfter->toArray(), + 'last_active_at' => $this->lastActiveAt, + 'name' => $this->name, + ]; + } +} diff --git a/src/Responses/Containers/ListContainers.php b/src/Responses/Containers/ListContainers.php new file mode 100644 index 00000000..76d51a87 --- /dev/null +++ b/src/Responses/Containers/ListContainers.php @@ -0,0 +1,78 @@ + + */ +final class ListContainers implements ResponseContract, ResponseHasMetaInformationContract +{ + /** + * @use ArrayAccessible + */ + use ArrayAccessible; + + use Fakeable; + use HasMetaInformation; + + /** + * @param 'list' $object + * @param RetrieveContainer[] $data + */ + private function __construct( + public readonly string $object, + public readonly array $data, + public readonly ?string $firstId, + public readonly ?string $lastId, + public readonly bool $hasMore, + private readonly MetaInformation $meta, + ) {} + + /** + * @param ListContainersType $attributes + */ + public static function from(array $attributes, MetaInformation $meta): self + { + return new self( + object: $attributes['object'], + data: array_map( + fn (array $container): RetrieveContainer => RetrieveContainer::from($container, $meta), + $attributes['data'] + ), + firstId: $attributes['first_id'] ?? null, + lastId: $attributes['last_id'] ?? null, + hasMore: $attributes['has_more'], + meta: $meta, + ); + } + + /** + * {@inheritDoc} + */ + public function toArray(): array + { + return [ + 'object' => $this->object, + 'data' => array_map( + fn (RetrieveContainer $container): array => $container->toArray(), + $this->data + ), + 'first_id' => $this->firstId, + 'last_id' => $this->lastId, + 'has_more' => $this->hasMore, + ]; + } +} From 17d1ccd07e9cb784be2589d50b3c6f4f34e8f9f3 Mon Sep 17 00:00:00 2001 From: Connor Tumbleson Date: Tue, 29 Jul 2025 07:15:50 -0400 Subject: [PATCH 3/5] feat: build out client/resource for Containers --- src/Client.php | 11 +++++++++++ src/Testing/Resources/ContainersTestResource.php | 8 ++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/Client.php b/src/Client.php index fb019c2e..6a50eb35 100644 --- a/src/Client.php +++ b/src/Client.php @@ -14,6 +14,7 @@ use OpenAI\Resources\Batches; use OpenAI\Resources\Chat; use OpenAI\Resources\Completions; +use OpenAI\Resources\Containers; use OpenAI\Resources\Edits; use OpenAI\Resources\Embeddings; use OpenAI\Resources\Files; @@ -68,6 +69,16 @@ public function chat(): Chat return new Chat($this->transporter); } + /** + * Create and manage containers for use with the Code Interpreter tool. + * + * @see https://platform.openai.com/docs/api-reference/containers + */ + public function containers(): Containers + { + return new Containers($this->transporter); + } + /** * Get a vector representation of a given input that can be easily consumed by machine learning models and algorithms. * diff --git a/src/Testing/Resources/ContainersTestResource.php b/src/Testing/Resources/ContainersTestResource.php index f3a961d4..2c4d2ebd 100644 --- a/src/Testing/Resources/ContainersTestResource.php +++ b/src/Testing/Resources/ContainersTestResource.php @@ -4,10 +4,10 @@ use OpenAI\Contracts\Resources\ContainersContract; use OpenAI\Resources\Containers; +use OpenAI\Responses\Containers\CreateContainer; use OpenAI\Responses\Containers\DeleteContainer; +use OpenAI\Responses\Containers\ListContainers; use OpenAI\Responses\Containers\RetrieveContainer; -use OpenAI\Responses\Responses\CreateResponse; -use OpenAI\Responses\Responses\ListInputItems; use OpenAI\Testing\Resources\Concerns\Testable; final class ContainersTestResource implements ContainersContract @@ -19,7 +19,7 @@ public function resource(): string return Containers::class; } - public function create(array $parameters): CreateResponse + public function create(array $parameters): CreateContainer { return $this->record(__FUNCTION__, func_get_args()); } @@ -29,7 +29,7 @@ public function retrieve(string $id): RetrieveContainer return $this->record(__FUNCTION__, func_get_args()); } - public function list(string $id, array $parameters = []): ListInputItems + public function list(array $parameters = []): ListContainers { return $this->record(__FUNCTION__, func_get_args()); } From 67fa2040332aadd5bfded714b8118e2517aa3fda Mon Sep 17 00:00:00 2001 From: Connor Tumbleson Date: Tue, 29 Jul 2025 05:25:59 -0600 Subject: [PATCH 4/5] fix: correct typing --- src/Responses/Containers/CreateContainer.php | 2 +- src/Responses/Containers/RetrieveContainer.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Responses/Containers/CreateContainer.php b/src/Responses/Containers/CreateContainer.php index 8bbe8e54..8a224c5f 100644 --- a/src/Responses/Containers/CreateContainer.php +++ b/src/Responses/Containers/CreateContainer.php @@ -15,7 +15,7 @@ /** * @phpstan-import-type ExpiresAfterType from ExpiresAfter * - * @phpstan-type CreateContainerType array{id: string, object: 'container', created_at: int, status: string, expires_after: ExpiresAfter, last_active_at: int, name: string} + * @phpstan-type CreateContainerType array{id: string, object: 'container', created_at: int, status: string, expires_after: ExpiresAfterType, last_active_at: int, name: string} * * @implements ResponseContract */ diff --git a/src/Responses/Containers/RetrieveContainer.php b/src/Responses/Containers/RetrieveContainer.php index d1ea9b0a..f086eae7 100644 --- a/src/Responses/Containers/RetrieveContainer.php +++ b/src/Responses/Containers/RetrieveContainer.php @@ -15,7 +15,7 @@ /** * @phpstan-import-type ExpiresAfterType from ExpiresAfter * - * @phpstan-type RetrieveContainerType array{id: string, object: 'container', created_at: int, status: string, expires_after: ExpiresAfter, last_active_at: int, name: string} + * @phpstan-type RetrieveContainerType array{id: string, object: 'container', created_at: int, status: string, expires_after: ExpiresAfterType, last_active_at: int, name: string} * * @implements ResponseContract */ From bf658bf152a0a10f71cdf0451d5c76cb24846fe3 Mon Sep 17 00:00:00 2001 From: Connor Tumbleson Date: Tue, 29 Jul 2025 05:28:09 -0600 Subject: [PATCH 5/5] feat: add pest tests --- tests/Fixtures/Container.php | 76 ++++++++++++ tests/Resources/Containers.php | 117 ++++++++++++++++++ .../Responses/Containers/CreateContainer.php | 39 ++++++ .../Responses/Containers/DeleteContainer.php | 23 ++++ tests/Responses/Containers/ListContainers.php | 63 ++++++++++ .../Containers/Objects/ExpiresAfter.php | 27 ++++ .../Containers/RetrieveContainer.php | 39 ++++++ 7 files changed, 384 insertions(+) create mode 100644 tests/Fixtures/Container.php create mode 100644 tests/Resources/Containers.php create mode 100644 tests/Responses/Containers/CreateContainer.php create mode 100644 tests/Responses/Containers/DeleteContainer.php create mode 100644 tests/Responses/Containers/ListContainers.php create mode 100644 tests/Responses/Containers/Objects/ExpiresAfter.php create mode 100644 tests/Responses/Containers/RetrieveContainer.php diff --git a/tests/Fixtures/Container.php b/tests/Fixtures/Container.php new file mode 100644 index 00000000..8f2cc68d --- /dev/null +++ b/tests/Fixtures/Container.php @@ -0,0 +1,76 @@ + + */ +function containerResource(): array +{ + return [ + 'id' => 'container_abc123', + 'object' => 'container', + 'created_at' => 1690000000, + 'status' => 'active', + 'expires_after' => [ + 'anchor' => 'last_active_at', + 'minutes' => 60, + ], + 'last_active_at' => 1690001000, + 'name' => 'Test Container', + ]; +} + +/** + * @return array + */ +function createContainerResource(): array +{ + return containerResource(); +} + +/** + * @return array + */ +function retrieveContainerResource(): array +{ + return containerResource(); +} + +/** + * @return array + */ +function listContainersResource(): array +{ + return [ + 'object' => 'list', + 'data' => [ + containerResource(), + [ + 'id' => 'container_def456', + 'object' => 'container', + 'created_at' => 1690010000, + 'status' => 'active', + 'expires_after' => [ + 'anchor' => 'last_active_at', + 'minutes' => 120, + ], + 'last_active_at' => 1690011000, + 'name' => 'Another Test Container', + ], + ], + 'first_id' => 'container_abc123', + 'last_id' => 'container_def456', + 'has_more' => false, + ]; +} + +/** + * @return array + */ +function deleteContainerResource(): array +{ + return [ + 'id' => 'container_abc123', + 'object' => 'container', + 'deleted' => true, + ]; +} diff --git a/tests/Resources/Containers.php b/tests/Resources/Containers.php new file mode 100644 index 00000000..c456cd29 --- /dev/null +++ b/tests/Resources/Containers.php @@ -0,0 +1,117 @@ + 'Test Container', + ], \OpenAI\ValueObjects\Transporter\Response::from(createContainerResource(), metaHeaders())); + + $result = $client->containers()->create([ + 'name' => 'Test Container', + ]); + + expect($result) + ->toBeInstanceOf(CreateContainer::class) + ->id->toBe('container_abc123') + ->object->toBe('container') + ->createdAt->toBe(1690000000) + ->status->toBe('active') + ->expiresAfter->toBeInstanceOf(ExpiresAfter::class) + ->lastActiveAt->toBe(1690001000) + ->name->toBe('Test Container'); + + expect($result->expiresAfter) + ->anchor->toBe('last_active_at') + ->minutes->toBe(60); + + expect($result->meta()) + ->toBeInstanceOf(MetaInformation::class); +}); + +test('retrieve', function () { + $client = mockClient('GET', 'containers/container_abc123', [], + \OpenAI\ValueObjects\Transporter\Response::from(retrieveContainerResource(), metaHeaders())); + + $result = $client->containers()->retrieve('container_abc123'); + + expect($result) + ->toBeInstanceOf(RetrieveContainer::class) + ->id->toBe('container_abc123') + ->object->toBe('container') + ->createdAt->toBe(1690000000) + ->status->toBe('active') + ->expiresAfter->toBeInstanceOf(ExpiresAfter::class) + ->lastActiveAt->toBe(1690001000) + ->name->toBe('Test Container'); + + expect($result->expiresAfter) + ->anchor->toBe('last_active_at') + ->minutes->toBe(60); + + expect($result->meta()) + ->toBeInstanceOf(MetaInformation::class); +}); + +test('delete', function () { + $client = mockClient('DELETE', 'containers/container_abc123', [], + \OpenAI\ValueObjects\Transporter\Response::from(deleteContainerResource(), metaHeaders())); + + $result = $client->containers()->delete('container_abc123'); + + expect($result) + ->toBeInstanceOf(DeleteContainer::class) + ->id->toBe('container_abc123') + ->object->toBe('container') + ->deleted->toBe(true); + + expect($result->meta()) + ->toBeInstanceOf(MetaInformation::class); +}); + +test('list', function () { + $client = mockClient('GET', 'containers', [], + \OpenAI\ValueObjects\Transporter\Response::from(listContainersResource(), metaHeaders())); + + $result = $client->containers()->list(); + + expect($result) + ->toBeInstanceOf(ListContainers::class) + ->object->toBe('list') + ->data->toBeArray()->toHaveCount(2) + ->firstId->toBe('container_abc123') + ->lastId->toBe('container_def456') + ->hasMore->toBe(false); + + expect($result->data[0]) + ->toBeInstanceOf(RetrieveContainer::class) + ->id->toBe('container_abc123') + ->name->toBe('Test Container'); + + expect($result->data[1]) + ->toBeInstanceOf(RetrieveContainer::class) + ->id->toBe('container_def456') + ->name->toBe('Another Test Container'); + + expect($result->meta()) + ->toBeInstanceOf(MetaInformation::class); +}); + +test('list with parameters', function () { + $client = mockClient('GET', 'containers', ['limit' => 2], + \OpenAI\ValueObjects\Transporter\Response::from(listContainersResource(), metaHeaders())); + + $result = $client->containers()->list([ + 'limit' => 2, + ]); + + expect($result) + ->toBeInstanceOf(ListContainers::class) + ->object->toBe('list') + ->data->toBeArray()->toHaveCount(2); +}); diff --git a/tests/Responses/Containers/CreateContainer.php b/tests/Responses/Containers/CreateContainer.php new file mode 100644 index 00000000..7728a4a1 --- /dev/null +++ b/tests/Responses/Containers/CreateContainer.php @@ -0,0 +1,39 @@ +id->toBe('container_abc123') + ->object->toBe('container') + ->createdAt->toBe(1690000000) + ->status->toBe('active') + ->expiresAfter->toBeInstanceOf(ExpiresAfter::class) + ->lastActiveAt->toBe(1690001000) + ->name->toBe('Test Container'); + + expect($result->expiresAfter) + ->anchor->toBe('last_active_at') + ->minutes->toBe(60); +}); + +test('to array', function () { + $result = CreateContainer::from(createContainerResource(), meta()); + + expect($result->toArray()) + ->toBe([ + 'id' => 'container_abc123', + 'object' => 'container', + 'created_at' => 1690000000, + 'status' => 'active', + 'expires_after' => [ + 'anchor' => 'last_active_at', + 'minutes' => 60, + ], + 'last_active_at' => 1690001000, + 'name' => 'Test Container', + ]); +}); diff --git a/tests/Responses/Containers/DeleteContainer.php b/tests/Responses/Containers/DeleteContainer.php new file mode 100644 index 00000000..3cee846e --- /dev/null +++ b/tests/Responses/Containers/DeleteContainer.php @@ -0,0 +1,23 @@ +id->toBe('container_abc123') + ->object->toBe('container') + ->deleted->toBe(true); +}); + +test('to array', function () { + $result = DeleteContainer::from(deleteContainerResource(), meta()); + + expect($result->toArray()) + ->toBe([ + 'id' => 'container_abc123', + 'object' => 'container', + 'deleted' => true, + ]); +}); diff --git a/tests/Responses/Containers/ListContainers.php b/tests/Responses/Containers/ListContainers.php new file mode 100644 index 00000000..fe2d8580 --- /dev/null +++ b/tests/Responses/Containers/ListContainers.php @@ -0,0 +1,63 @@ +object->toBe('list') + ->data->toBeArray()->toHaveCount(2) + ->firstId->toBe('container_abc123') + ->lastId->toBe('container_def456') + ->hasMore->toBe(false); + + expect($result->data[0]) + ->toBeInstanceOf(RetrieveContainer::class) + ->id->toBe('container_abc123') + ->name->toBe('Test Container'); + + expect($result->data[1]) + ->toBeInstanceOf(RetrieveContainer::class) + ->id->toBe('container_def456') + ->name->toBe('Another Test Container'); +}); + +test('to array', function () { + $result = ListContainers::from(listContainersResource(), meta()); + + expect($result->toArray()) + ->toBe([ + 'object' => 'list', + 'data' => [ + [ + 'id' => 'container_abc123', + 'object' => 'container', + 'created_at' => 1690000000, + 'status' => 'active', + 'expires_after' => [ + 'anchor' => 'last_active_at', + 'minutes' => 60, + ], + 'last_active_at' => 1690001000, + 'name' => 'Test Container', + ], + [ + 'id' => 'container_def456', + 'object' => 'container', + 'created_at' => 1690010000, + 'status' => 'active', + 'expires_after' => [ + 'anchor' => 'last_active_at', + 'minutes' => 120, + ], + 'last_active_at' => 1690011000, + 'name' => 'Another Test Container', + ], + ], + 'first_id' => 'container_abc123', + 'last_id' => 'container_def456', + 'has_more' => false, + ]); +}); diff --git a/tests/Responses/Containers/Objects/ExpiresAfter.php b/tests/Responses/Containers/Objects/ExpiresAfter.php new file mode 100644 index 00000000..524d2bf0 --- /dev/null +++ b/tests/Responses/Containers/Objects/ExpiresAfter.php @@ -0,0 +1,27 @@ + 'last_active_at', + 'minutes' => 60, + ]); + + expect($result) + ->anchor->toBe('last_active_at') + ->minutes->toBe(60); +}); + +test('to array', function () { + $result = ExpiresAfter::from([ + 'anchor' => 'last_active_at', + 'minutes' => 60, + ]); + + expect($result->toArray()) + ->toBe([ + 'anchor' => 'last_active_at', + 'minutes' => 60, + ]); +}); diff --git a/tests/Responses/Containers/RetrieveContainer.php b/tests/Responses/Containers/RetrieveContainer.php new file mode 100644 index 00000000..0b35fa7f --- /dev/null +++ b/tests/Responses/Containers/RetrieveContainer.php @@ -0,0 +1,39 @@ +id->toBe('container_abc123') + ->object->toBe('container') + ->createdAt->toBe(1690000000) + ->status->toBe('active') + ->expiresAfter->toBeInstanceOf(ExpiresAfter::class) + ->lastActiveAt->toBe(1690001000) + ->name->toBe('Test Container'); + + expect($result->expiresAfter) + ->anchor->toBe('last_active_at') + ->minutes->toBe(60); +}); + +test('to array', function () { + $result = RetrieveContainer::from(retrieveContainerResource(), meta()); + + expect($result->toArray()) + ->toBe([ + 'id' => 'container_abc123', + 'object' => 'container', + 'created_at' => 1690000000, + 'status' => 'active', + 'expires_after' => [ + 'anchor' => 'last_active_at', + 'minutes' => 60, + ], + 'last_active_at' => 1690001000, + 'name' => 'Test Container', + ]); +});