Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "2.1.0"
".": "2.2.0"
}
8 changes: 4 additions & 4 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 123
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-fadefdc7c7e30df47c09df323669b242ff90ee08e51f304175ace5274e0aab49.yml
openapi_spec_hash: 6d20f639d9ff8a097a34962da6218231
config_hash: 902654e60f5d659f2bfcfd903e17c46d
configured_endpoints: 136
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-d64cf80d2ebddf175c5578f68226a3d5bbd3f7fd8d62ccac2205f3fc05a355ee.yml
openapi_spec_hash: d51e0d60d0c536f210b597a211bc5af0
config_hash: e7c42016df9c6bd7bd6ff15101b9bc9b
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Changelog

## 2.2.0 (2025-10-06)

Full Changelog: [v2.1.0...v2.2.0](https://github.com/openai/openai-python/compare/v2.1.0...v2.2.0)

### Features

* **api:** dev day 2025 launches ([38ac009](https://github.com/openai/openai-python/commit/38ac0093ebb3419b1e2280d0dc2d26c74a2bbbec))


### Bug Fixes

* **client:** add chatkit to beta resource ([de3e561](https://github.com/openai/openai-python/commit/de3e5619d0a85b17906a9416039ef309e820dc0f))

## 2.1.0 (2025-10-02)

Full Changelog: [v2.0.1...v2.1.0](https://github.com/openai/openai-python/compare/v2.0.1...v2.1.0)
Expand Down
26 changes: 26 additions & 0 deletions api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1139,3 +1139,29 @@ Methods:
Methods:

- <code title="get /containers/{container_id}/files/{file_id}/content">client.containers.files.content.<a href="./src/openai/resources/containers/files/content.py">retrieve</a>(file_id, \*, container_id) -> HttpxBinaryResponseContent</code>

# Videos

Types:

```python
from openai.types import (
Video,
VideoCreateError,
VideoModel,
VideoSeconds,
VideoSize,
VideoDeleteResponse,
)
```

Methods:

- <code title="post /videos">client.videos.<a href="./src/openai/resources/videos.py">create</a>(\*\*<a href="src/openai/types/video_create_params.py">params</a>) -> <a href="./src/openai/types/video.py">Video</a></code>
- <code title="get /videos/{video_id}">client.videos.<a href="./src/openai/resources/videos.py">retrieve</a>(video_id) -> <a href="./src/openai/types/video.py">Video</a></code>
- <code title="get /videos">client.videos.<a href="./src/openai/resources/videos.py">list</a>(\*\*<a href="src/openai/types/video_list_params.py">params</a>) -> <a href="./src/openai/types/video.py">SyncConversationCursorPage[Video]</a></code>
- <code title="delete /videos/{video_id}">client.videos.<a href="./src/openai/resources/videos.py">delete</a>(video_id) -> <a href="./src/openai/types/video_delete_response.py">VideoDeleteResponse</a></code>
- <code title="get /videos/{video_id}/content">client.videos.<a href="./src/openai/resources/videos.py">download_content</a>(video_id, \*\*<a href="src/openai/types/video_download_content_params.py">params</a>) -> HttpxBinaryResponseContent</code>
- <code title="post /videos/{video_id}/remix">client.videos.<a href="./src/openai/resources/videos.py">remix</a>(video_id, \*\*<a href="src/openai/types/video_remix_params.py">params</a>) -> <a href="./src/openai/types/video.py">Video</a></code>
- <code>client.videos.<a href="./src/openai/resources/videos.py">create_and_poll</a>(\*args) -> Video</code>

22 changes: 22 additions & 0 deletions examples/video.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env -S poetry run python

import asyncio

from openai import AsyncOpenAI

client = AsyncOpenAI()


async def main() -> None:
video = await client.videos.create_and_poll(
model="sora-2",
prompt="A video of the words 'Thank you' in sparkling letters",
)

if video.status == "completed":
print("Video successfully completed: ", video)
else:
print("Video creation failed. Status: ", video.status)


asyncio.run(main())
1 change: 1 addition & 0 deletions helpers.md
Original file line number Diff line number Diff line change
Expand Up @@ -514,4 +514,5 @@ client.beta.vector_stores.files.upload_and_poll(...)
client.beta.vector_stores.files.create_and_poll(...)
client.beta.vector_stores.file_batches.create_and_poll(...)
client.beta.vector_stores.file_batches.upload_and_poll(...)
client.videos.create_and_poll(...)
```
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "openai"
version = "2.1.0"
version = "2.2.0"
description = "The official Python library for the openai API"
dynamic = ["readme"]
license = "Apache-2.0"
Expand Down
1 change: 1 addition & 0 deletions src/openai/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ def _reset_client() -> None: # type: ignore[reportUnusedFunction]
files as files,
images as images,
models as models,
videos as videos,
batches as batches,
uploads as uploads,
realtime as realtime,
Expand Down
38 changes: 38 additions & 0 deletions src/openai/_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
files,
images,
models,
videos,
batches,
uploads,
realtime,
Expand All @@ -59,6 +60,7 @@
from .resources.files import Files, AsyncFiles
from .resources.images import Images, AsyncImages
from .resources.models import Models, AsyncModels
from .resources.videos import Videos, AsyncVideos
from .resources.batches import Batches, AsyncBatches
from .resources.webhooks import Webhooks, AsyncWebhooks
from .resources.beta.beta import Beta, AsyncBeta
Expand Down Expand Up @@ -288,6 +290,12 @@ def containers(self) -> Containers:

return Containers(self)

@cached_property
def videos(self) -> Videos:
from .resources.videos import Videos

return Videos(self)

@cached_property
def with_raw_response(self) -> OpenAIWithRawResponse:
return OpenAIWithRawResponse(self)
Expand Down Expand Up @@ -633,6 +641,12 @@ def containers(self) -> AsyncContainers:

return AsyncContainers(self)

@cached_property
def videos(self) -> AsyncVideos:
from .resources.videos import AsyncVideos

return AsyncVideos(self)

@cached_property
def with_raw_response(self) -> AsyncOpenAIWithRawResponse:
return AsyncOpenAIWithRawResponse(self)
Expand Down Expand Up @@ -883,6 +897,12 @@ def containers(self) -> containers.ContainersWithRawResponse:

return ContainersWithRawResponse(self._client.containers)

@cached_property
def videos(self) -> videos.VideosWithRawResponse:
from .resources.videos import VideosWithRawResponse

return VideosWithRawResponse(self._client.videos)


class AsyncOpenAIWithRawResponse:
_client: AsyncOpenAI
Expand Down Expand Up @@ -998,6 +1018,12 @@ def containers(self) -> containers.AsyncContainersWithRawResponse:

return AsyncContainersWithRawResponse(self._client.containers)

@cached_property
def videos(self) -> videos.AsyncVideosWithRawResponse:
from .resources.videos import AsyncVideosWithRawResponse

return AsyncVideosWithRawResponse(self._client.videos)


class OpenAIWithStreamedResponse:
_client: OpenAI
Expand Down Expand Up @@ -1113,6 +1139,12 @@ def containers(self) -> containers.ContainersWithStreamingResponse:

return ContainersWithStreamingResponse(self._client.containers)

@cached_property
def videos(self) -> videos.VideosWithStreamingResponse:
from .resources.videos import VideosWithStreamingResponse

return VideosWithStreamingResponse(self._client.videos)


class AsyncOpenAIWithStreamedResponse:
_client: AsyncOpenAI
Expand Down Expand Up @@ -1228,6 +1260,12 @@ def containers(self) -> containers.AsyncContainersWithStreamingResponse:

return AsyncContainersWithStreamingResponse(self._client.containers)

@cached_property
def videos(self) -> videos.AsyncVideosWithStreamingResponse:
from .resources.videos import AsyncVideosWithStreamingResponse

return AsyncVideosWithStreamingResponse(self._client.videos)


Client = OpenAI

Expand Down
8 changes: 8 additions & 0 deletions src/openai/_module_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from .resources.files import Files
from .resources.images import Images
from .resources.models import Models
from .resources.videos import Videos
from .resources.batches import Batches
from .resources.webhooks import Webhooks
from .resources.beta.beta import Beta
Expand Down Expand Up @@ -72,6 +73,12 @@ def __load__(self) -> Models:
return _load_client().models


class VideosProxy(LazyProxy["Videos"]):
@override
def __load__(self) -> Videos:
return _load_client().videos


class BatchesProxy(LazyProxy["Batches"]):
@override
def __load__(self) -> Batches:
Expand Down Expand Up @@ -151,6 +158,7 @@ def __load__(self) -> Conversations:
evals: Evals = EvalsProxy().__as_proxied__()
images: Images = ImagesProxy().__as_proxied__()
models: Models = ModelsProxy().__as_proxied__()
videos: Videos = VideosProxy().__as_proxied__()
batches: Batches = BatchesProxy().__as_proxied__()
uploads: Uploads = UploadsProxy().__as_proxied__()
webhooks: Webhooks = WebhooksProxy().__as_proxied__()
Expand Down
2 changes: 1 addition & 1 deletion src/openai/_version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

__title__ = "openai"
__version__ = "2.1.0" # x-release-please-version
__version__ = "2.2.0" # x-release-please-version
14 changes: 14 additions & 0 deletions src/openai/resources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@
ModelsWithStreamingResponse,
AsyncModelsWithStreamingResponse,
)
from .videos import (
Videos,
AsyncVideos,
VideosWithRawResponse,
AsyncVideosWithRawResponse,
VideosWithStreamingResponse,
AsyncVideosWithStreamingResponse,
)
from .batches import (
Batches,
AsyncBatches,
Expand Down Expand Up @@ -212,4 +220,10 @@
"AsyncContainersWithRawResponse",
"ContainersWithStreamingResponse",
"AsyncContainersWithStreamingResponse",
"Videos",
"AsyncVideos",
"VideosWithRawResponse",
"AsyncVideosWithRawResponse",
"VideosWithStreamingResponse",
"AsyncVideosWithStreamingResponse",
]
14 changes: 14 additions & 0 deletions src/openai/resources/beta/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@
BetaWithStreamingResponse,
AsyncBetaWithStreamingResponse,
)
from .chatkit import (
ChatKit,
AsyncChatKit,
ChatKitWithRawResponse,
AsyncChatKitWithRawResponse,
ChatKitWithStreamingResponse,
AsyncChatKitWithStreamingResponse,
)
from .threads import (
Threads,
AsyncThreads,
Expand All @@ -26,6 +34,12 @@
)

__all__ = [
"ChatKit",
"AsyncChatKit",
"ChatKitWithRawResponse",
"AsyncChatKitWithRawResponse",
"ChatKitWithStreamingResponse",
"AsyncChatKitWithStreamingResponse",
"Assistants",
"AsyncAssistants",
"AssistantsWithRawResponse",
Expand Down
32 changes: 32 additions & 0 deletions src/openai/resources/beta/beta.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@
AsyncAssistantsWithStreamingResponse,
)
from ..._resource import SyncAPIResource, AsyncAPIResource
from .chatkit.chatkit import (
ChatKit,
AsyncChatKit,
ChatKitWithRawResponse,
AsyncChatKitWithRawResponse,
ChatKitWithStreamingResponse,
AsyncChatKitWithStreamingResponse,
)
from .threads.threads import (
Threads,
AsyncThreads,
Expand All @@ -38,6 +46,10 @@ def chat(self) -> Chat:
def realtime(self) -> Realtime:
return Realtime(self._client)

@cached_property
def chatkit(self) -> ChatKit:
return ChatKit(self._client)

@cached_property
def assistants(self) -> Assistants:
return Assistants(self._client)
Expand Down Expand Up @@ -75,6 +87,10 @@ def chat(self) -> AsyncChat:
def realtime(self) -> AsyncRealtime:
return AsyncRealtime(self._client)

@cached_property
def chatkit(self) -> AsyncChatKit:
return AsyncChatKit(self._client)

@cached_property
def assistants(self) -> AsyncAssistants:
return AsyncAssistants(self._client)
Expand Down Expand Up @@ -107,6 +123,10 @@ class BetaWithRawResponse:
def __init__(self, beta: Beta) -> None:
self._beta = beta

@cached_property
def chatkit(self) -> ChatKitWithRawResponse:
return ChatKitWithRawResponse(self._beta.chatkit)

Comment on lines 107 to +129

Choose a reason for hiding this comment

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

P1 Badge Expose chatkit property on Beta resource

The new ChatKit client is only referenced in the wrapper classes, but Beta/AsyncBeta no longer define a chatkit property. Any call such as client.beta.chatkit or client.beta.with_raw_response.chatkit will raise AttributeError because self._beta.chatkit does not exist. As a result the ChatKit API added in this release is unreachable and the accompanying tests will fail. Define @cached_property accessors on both Beta and AsyncBeta that return ChatKit/AsyncChatKit before using them in the wrappers.

Useful? React with 👍 / 👎.

@cached_property
def assistants(self) -> AssistantsWithRawResponse:
return AssistantsWithRawResponse(self._beta.assistants)
Expand All @@ -120,6 +140,10 @@ class AsyncBetaWithRawResponse:
def __init__(self, beta: AsyncBeta) -> None:
self._beta = beta

@cached_property
def chatkit(self) -> AsyncChatKitWithRawResponse:
return AsyncChatKitWithRawResponse(self._beta.chatkit)

@cached_property
def assistants(self) -> AsyncAssistantsWithRawResponse:
return AsyncAssistantsWithRawResponse(self._beta.assistants)
Expand All @@ -133,6 +157,10 @@ class BetaWithStreamingResponse:
def __init__(self, beta: Beta) -> None:
self._beta = beta

@cached_property
def chatkit(self) -> ChatKitWithStreamingResponse:
return ChatKitWithStreamingResponse(self._beta.chatkit)

@cached_property
def assistants(self) -> AssistantsWithStreamingResponse:
return AssistantsWithStreamingResponse(self._beta.assistants)
Expand All @@ -146,6 +174,10 @@ class AsyncBetaWithStreamingResponse:
def __init__(self, beta: AsyncBeta) -> None:
self._beta = beta

@cached_property
def chatkit(self) -> AsyncChatKitWithStreamingResponse:
return AsyncChatKitWithStreamingResponse(self._beta.chatkit)

@cached_property
def assistants(self) -> AsyncAssistantsWithStreamingResponse:
return AsyncAssistantsWithStreamingResponse(self._beta.assistants)
Expand Down
Loading