diff --git a/.release-please-manifest.json b/.release-please-manifest.json index e42b9af..8f918e4 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "5.11.0" + ".": "5.12.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 0cfcc15..5088d53 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 57 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runwayml/runwayml-264e9b264bae2f906e06f33a5af492e19580bcd192f6094cfdb534fcbf70f5bc.yml -openapi_spec_hash: 30ac92dee6f88c19ea1cdc174b05a260 -config_hash: 6bdea3c3109ee75952f779d566c229ea +configured_endpoints: 59 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runwayml/runwayml-a31e62dafc005582320d354e7aed335c8df690338ca539c055aa4a5637b9ad3b.yml +openapi_spec_hash: ab95f9ae7163b960171e68f4ff95da4e +config_hash: 95e64e640428abd4184a48762d9fd5f8 diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e78108..1cb8f58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## 5.12.0 (2026-07-23) + +Full Changelog: [v5.11.0...v5.12.0](https://github.com/runwayml/sdk-python/compare/v5.11.0...v5.12.0) + +### Features + +* **api:** add Model Router image and audio generation ([e9f38d4](https://github.com/runwayml/sdk-python/commit/e9f38d40cf90be9e1e0775e50db76bef1aac1969)) +* **api:** expose generate image and audio endpoints ([d19bc95](https://github.com/runwayml/sdk-python/commit/d19bc9510ae78e7be4c257703e0e06e068eef0a7)) + + +### Bug Fixes + +* **client:** make generate.image and generate.audio responses awaitable ([d4900ac](https://github.com/runwayml/sdk-python/commit/d4900aca61dbb0ee983331aba287ac0930e975ac)) + + +### Chores + +* **openapi:** keep generate.video SDK schema task-only ([4b6e6c4](https://github.com/runwayml/sdk-python/commit/4b6e6c4abf38ae0cad30ba73acbf7f03401e00ac)) + ## 5.11.0 (2026-07-21) Full Changelog: [v5.10.0...v5.11.0](https://github.com/runwayml/sdk-python/compare/v5.10.0...v5.11.0) diff --git a/api.md b/api.md index 6bb94e6..5c23a57 100644 --- a/api.md +++ b/api.md @@ -169,6 +169,30 @@ Methods: - client.generate.video.create(\*\*params) -> VideoCreateResponse +## Image + +Types: + +```python +from runwayml.types.generate import ImageCreateResponse +``` + +Methods: + +- client.generate.image.create(\*\*params) -> ImageCreateResponse + +## Audio + +Types: + +```python +from runwayml.types.generate import AudioCreateResponse +``` + +Methods: + +- client.generate.audio.create(\*\*params) -> AudioCreateResponse + # Routers Types: diff --git a/pyproject.toml b/pyproject.toml index 2ee47e8..7fd7a0c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "runwayml" -version = "5.11.0" +version = "5.12.0" description = "The official Python library for the runwayml API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/runwayml/_version.py b/src/runwayml/_version.py index e20c282..480bb51 100644 --- a/src/runwayml/_version.py +++ b/src/runwayml/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "runwayml" -__version__ = "5.11.0" # x-release-please-version +__version__ = "5.12.0" # x-release-please-version diff --git a/src/runwayml/resources/generate/__init__.py b/src/runwayml/resources/generate/__init__.py index a52fcf1..60ca843 100644 --- a/src/runwayml/resources/generate/__init__.py +++ b/src/runwayml/resources/generate/__init__.py @@ -1,5 +1,21 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +from .audio import ( + AudioResource, + AsyncAudioResource, + AudioResourceWithRawResponse, + AsyncAudioResourceWithRawResponse, + AudioResourceWithStreamingResponse, + AsyncAudioResourceWithStreamingResponse, +) +from .image import ( + ImageResource, + AsyncImageResource, + ImageResourceWithRawResponse, + AsyncImageResourceWithRawResponse, + ImageResourceWithStreamingResponse, + AsyncImageResourceWithStreamingResponse, +) from .video import ( VideoResource, AsyncVideoResource, @@ -24,6 +40,18 @@ "AsyncVideoResourceWithRawResponse", "VideoResourceWithStreamingResponse", "AsyncVideoResourceWithStreamingResponse", + "ImageResource", + "AsyncImageResource", + "ImageResourceWithRawResponse", + "AsyncImageResourceWithRawResponse", + "ImageResourceWithStreamingResponse", + "AsyncImageResourceWithStreamingResponse", + "AudioResource", + "AsyncAudioResource", + "AudioResourceWithRawResponse", + "AsyncAudioResourceWithRawResponse", + "AudioResourceWithStreamingResponse", + "AsyncAudioResourceWithStreamingResponse", "GenerateResource", "AsyncGenerateResource", "GenerateResourceWithRawResponse", diff --git a/src/runwayml/resources/generate/audio.py b/src/runwayml/resources/generate/audio.py new file mode 100644 index 0000000..8be60f6 --- /dev/null +++ b/src/runwayml/resources/generate/audio.py @@ -0,0 +1,198 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from runwayml.lib.polling import ( + NewTaskCreatedResponse, + AsyncNewTaskCreatedResponse, + create_waitable_resource, + create_async_waitable_resource, +) + +from ..._types import Body, Query, Headers, NotGiven, not_given +from ..._utils import maybe_transform, async_maybe_transform +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ..._base_client import make_request_options +from ...types.generate import audio_create_params +from ...types.generate.audio_create_response import AudioCreateResponse + +__all__ = ["AudioResource", "AsyncAudioResource"] + + +class AudioResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> AudioResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/runwayml/sdk-python#accessing-raw-response-data-eg-headers + """ + return AudioResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AudioResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/runwayml/sdk-python#with_streaming_response + """ + return AudioResourceWithStreamingResponse(self) + + def create( + self, + *, + config_id: str, + input: audio_create_params.Input, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> NewTaskCreatedResponse: + """ + Start an audio generation task using a saved Model Router config instead of + naming a model. Set input.type to speech to speak promptText verbatim, or audio + to generate audio described by promptText. + + Args: + config_id: The slug of a saved Model Router config to route this request with. + + input: Model-agnostic audio generation input. The router selects a model and maps these + options to it. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/v1/generate/audio", + body=maybe_transform( + { + "config_id": config_id, + "input": input, + }, + audio_create_params.AudioCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=create_waitable_resource(AudioCreateResponse, self._client), + ) + + +class AsyncAudioResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncAudioResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/runwayml/sdk-python#accessing-raw-response-data-eg-headers + """ + return AsyncAudioResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncAudioResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/runwayml/sdk-python#with_streaming_response + """ + return AsyncAudioResourceWithStreamingResponse(self) + + async def create( + self, + *, + config_id: str, + input: audio_create_params.Input, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AsyncNewTaskCreatedResponse: + """ + Start an audio generation task using a saved Model Router config instead of + naming a model. Set input.type to speech to speak promptText verbatim, or audio + to generate audio described by promptText. + + Args: + config_id: The slug of a saved Model Router config to route this request with. + + input: Model-agnostic audio generation input. The router selects a model and maps these + options to it. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/v1/generate/audio", + body=await async_maybe_transform( + { + "config_id": config_id, + "input": input, + }, + audio_create_params.AudioCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=create_async_waitable_resource(AudioCreateResponse, self._client), + ) + + +class AudioResourceWithRawResponse: + def __init__(self, audio: AudioResource) -> None: + self._audio = audio + + self.create = to_raw_response_wrapper( + audio.create, + ) + + +class AsyncAudioResourceWithRawResponse: + def __init__(self, audio: AsyncAudioResource) -> None: + self._audio = audio + + self.create = async_to_raw_response_wrapper( + audio.create, + ) + + +class AudioResourceWithStreamingResponse: + def __init__(self, audio: AudioResource) -> None: + self._audio = audio + + self.create = to_streamed_response_wrapper( + audio.create, + ) + + +class AsyncAudioResourceWithStreamingResponse: + def __init__(self, audio: AsyncAudioResource) -> None: + self._audio = audio + + self.create = async_to_streamed_response_wrapper( + audio.create, + ) diff --git a/src/runwayml/resources/generate/generate.py b/src/runwayml/resources/generate/generate.py index 02d0cbc..6081263 100644 --- a/src/runwayml/resources/generate/generate.py +++ b/src/runwayml/resources/generate/generate.py @@ -2,6 +2,22 @@ from __future__ import annotations +from .audio import ( + AudioResource, + AsyncAudioResource, + AudioResourceWithRawResponse, + AsyncAudioResourceWithRawResponse, + AudioResourceWithStreamingResponse, + AsyncAudioResourceWithStreamingResponse, +) +from .image import ( + ImageResource, + AsyncImageResource, + ImageResourceWithRawResponse, + AsyncImageResourceWithRawResponse, + ImageResourceWithStreamingResponse, + AsyncImageResourceWithStreamingResponse, +) from .video import ( VideoResource, AsyncVideoResource, @@ -21,6 +37,14 @@ class GenerateResource(SyncAPIResource): def video(self) -> VideoResource: return VideoResource(self._client) + @cached_property + def image(self) -> ImageResource: + return ImageResource(self._client) + + @cached_property + def audio(self) -> AudioResource: + return AudioResource(self._client) + @cached_property def with_raw_response(self) -> GenerateResourceWithRawResponse: """ @@ -46,6 +70,14 @@ class AsyncGenerateResource(AsyncAPIResource): def video(self) -> AsyncVideoResource: return AsyncVideoResource(self._client) + @cached_property + def image(self) -> AsyncImageResource: + return AsyncImageResource(self._client) + + @cached_property + def audio(self) -> AsyncAudioResource: + return AsyncAudioResource(self._client) + @cached_property def with_raw_response(self) -> AsyncGenerateResourceWithRawResponse: """ @@ -74,6 +106,14 @@ def __init__(self, generate: GenerateResource) -> None: def video(self) -> VideoResourceWithRawResponse: return VideoResourceWithRawResponse(self._generate.video) + @cached_property + def image(self) -> ImageResourceWithRawResponse: + return ImageResourceWithRawResponse(self._generate.image) + + @cached_property + def audio(self) -> AudioResourceWithRawResponse: + return AudioResourceWithRawResponse(self._generate.audio) + class AsyncGenerateResourceWithRawResponse: def __init__(self, generate: AsyncGenerateResource) -> None: @@ -83,6 +123,14 @@ def __init__(self, generate: AsyncGenerateResource) -> None: def video(self) -> AsyncVideoResourceWithRawResponse: return AsyncVideoResourceWithRawResponse(self._generate.video) + @cached_property + def image(self) -> AsyncImageResourceWithRawResponse: + return AsyncImageResourceWithRawResponse(self._generate.image) + + @cached_property + def audio(self) -> AsyncAudioResourceWithRawResponse: + return AsyncAudioResourceWithRawResponse(self._generate.audio) + class GenerateResourceWithStreamingResponse: def __init__(self, generate: GenerateResource) -> None: @@ -92,6 +140,14 @@ def __init__(self, generate: GenerateResource) -> None: def video(self) -> VideoResourceWithStreamingResponse: return VideoResourceWithStreamingResponse(self._generate.video) + @cached_property + def image(self) -> ImageResourceWithStreamingResponse: + return ImageResourceWithStreamingResponse(self._generate.image) + + @cached_property + def audio(self) -> AudioResourceWithStreamingResponse: + return AudioResourceWithStreamingResponse(self._generate.audio) + class AsyncGenerateResourceWithStreamingResponse: def __init__(self, generate: AsyncGenerateResource) -> None: @@ -100,3 +156,11 @@ def __init__(self, generate: AsyncGenerateResource) -> None: @cached_property def video(self) -> AsyncVideoResourceWithStreamingResponse: return AsyncVideoResourceWithStreamingResponse(self._generate.video) + + @cached_property + def image(self) -> AsyncImageResourceWithStreamingResponse: + return AsyncImageResourceWithStreamingResponse(self._generate.image) + + @cached_property + def audio(self) -> AsyncAudioResourceWithStreamingResponse: + return AsyncAudioResourceWithStreamingResponse(self._generate.audio) diff --git a/src/runwayml/resources/generate/image.py b/src/runwayml/resources/generate/image.py new file mode 100644 index 0000000..05cefd7 --- /dev/null +++ b/src/runwayml/resources/generate/image.py @@ -0,0 +1,196 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from runwayml.lib.polling import ( + NewTaskCreatedResponse, + AsyncNewTaskCreatedResponse, + create_waitable_resource, + create_async_waitable_resource, +) + +from ..._types import Body, Query, Headers, NotGiven, not_given +from ..._utils import maybe_transform, async_maybe_transform +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ..._base_client import make_request_options +from ...types.generate import image_create_params +from ...types.generate.image_create_response import ImageCreateResponse + +__all__ = ["ImageResource", "AsyncImageResource"] + + +class ImageResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> ImageResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/runwayml/sdk-python#accessing-raw-response-data-eg-headers + """ + return ImageResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> ImageResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/runwayml/sdk-python#with_streaming_response + """ + return ImageResourceWithStreamingResponse(self) + + def create( + self, + *, + config_id: str, + input: image_create_params.Input, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> NewTaskCreatedResponse: + """ + Start an image generation task using a saved Model Router config instead of + naming a model. + + Args: + config_id: The slug of a saved Model Router config to route this request with. + + input: Model-agnostic image generation input. The router selects a model and maps these + options to it. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/v1/generate/image", + body=maybe_transform( + { + "config_id": config_id, + "input": input, + }, + image_create_params.ImageCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=create_waitable_resource(ImageCreateResponse, self._client), + ) + + +class AsyncImageResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncImageResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/runwayml/sdk-python#accessing-raw-response-data-eg-headers + """ + return AsyncImageResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncImageResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/runwayml/sdk-python#with_streaming_response + """ + return AsyncImageResourceWithStreamingResponse(self) + + async def create( + self, + *, + config_id: str, + input: image_create_params.Input, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AsyncNewTaskCreatedResponse: + """ + Start an image generation task using a saved Model Router config instead of + naming a model. + + Args: + config_id: The slug of a saved Model Router config to route this request with. + + input: Model-agnostic image generation input. The router selects a model and maps these + options to it. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/v1/generate/image", + body=await async_maybe_transform( + { + "config_id": config_id, + "input": input, + }, + image_create_params.ImageCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=create_async_waitable_resource(ImageCreateResponse, self._client), + ) + + +class ImageResourceWithRawResponse: + def __init__(self, image: ImageResource) -> None: + self._image = image + + self.create = to_raw_response_wrapper( + image.create, + ) + + +class AsyncImageResourceWithRawResponse: + def __init__(self, image: AsyncImageResource) -> None: + self._image = image + + self.create = async_to_raw_response_wrapper( + image.create, + ) + + +class ImageResourceWithStreamingResponse: + def __init__(self, image: ImageResource) -> None: + self._image = image + + self.create = to_streamed_response_wrapper( + image.create, + ) + + +class AsyncImageResourceWithStreamingResponse: + def __init__(self, image: AsyncImageResource) -> None: + self._image = image + + self.create = async_to_streamed_response_wrapper( + image.create, + ) diff --git a/src/runwayml/resources/generate/video.py b/src/runwayml/resources/generate/video.py index 3750712..ecf7cec 100644 --- a/src/runwayml/resources/generate/video.py +++ b/src/runwayml/resources/generate/video.py @@ -23,7 +23,7 @@ ) from ..._base_client import make_request_options from ...types.generate import video_create_params -from ...types.generate.video_create_response import RoutedVideoTaskCreated +from ...types.generate.video_create_response import VideoCreateResponse __all__ = ["VideoResource", "AsyncVideoResource"] @@ -64,6 +64,9 @@ def create( Start a video generation task using a saved Model Router config instead of naming a model. + The SDK does not expose dry-run for this endpoint yet — use the HTTP API with + ``dry_run=True`` if you need a routing preview without creating a task. + Args: config_id: The slug of a saved Model Router config to route this request with. @@ -90,7 +93,7 @@ def create( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=create_waitable_resource(RoutedVideoTaskCreated, self._client), + cast_to=create_waitable_resource(VideoCreateResponse, self._client), ) @@ -130,6 +133,9 @@ async def create( Start a video generation task using a saved Model Router config instead of naming a model. + The SDK does not expose dry-run for this endpoint yet — use the HTTP API with + ``dry_run=True`` if you need a routing preview without creating a task. + Args: config_id: The slug of a saved Model Router config to route this request with. @@ -156,7 +162,7 @@ async def create( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=create_async_waitable_resource(RoutedVideoTaskCreated, self._client), + cast_to=create_async_waitable_resource(VideoCreateResponse, self._client), ) diff --git a/src/runwayml/types/generate/__init__.py b/src/runwayml/types/generate/__init__.py index 809aa0d..721aead 100644 --- a/src/runwayml/types/generate/__init__.py +++ b/src/runwayml/types/generate/__init__.py @@ -2,5 +2,9 @@ from __future__ import annotations +from .audio_create_params import AudioCreateParams as AudioCreateParams +from .image_create_params import ImageCreateParams as ImageCreateParams from .video_create_params import VideoCreateParams as VideoCreateParams +from .audio_create_response import AudioCreateResponse as AudioCreateResponse +from .image_create_response import ImageCreateResponse as ImageCreateResponse from .video_create_response import VideoCreateResponse as VideoCreateResponse diff --git a/src/runwayml/types/generate/audio_create_params.py b/src/runwayml/types/generate/audio_create_params.py new file mode 100644 index 0000000..c5f8b12 --- /dev/null +++ b/src/runwayml/types/generate/audio_create_params.py @@ -0,0 +1,160 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union, Iterable +from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict + +from ..._utils import PropertyInfo + +__all__ = [ + "AudioCreateParams", + "Input", + "InputReferenceAudio", + "InputVoice", + "InputVoicePreset", + "InputVoiceReferenceAudio", +] + + +class AudioCreateParams(TypedDict, total=False): + config_id: Required[Annotated[str, PropertyInfo(alias="configId")]] + """The slug of a saved Model Router config to route this request with.""" + + input: Required[Input] + """Model-agnostic audio generation input. + + The router selects a model and maps these options to it. + """ + + +class InputReferenceAudio(TypedDict, total=False): + uri: Required[str] + """A HTTPS URL.""" + + +class InputVoicePreset(TypedDict, total=False): + """A preset voice.""" + + preset_id: Required[ + Annotated[ + Literal[ + "Maya", + "Arjun", + "Serene", + "Bernard", + "Billy", + "Mark", + "Clint", + "Mabel", + "Chad", + "Leslie", + "Eleanor", + "Elias", + "Elliot", + "Grungle", + "Brodie", + "Sandra", + "Kirk", + "Kylie", + "Lara", + "Lisa", + "Malachi", + "Marlene", + "Martin", + "Miriam", + "Monster", + "Paula", + "Pip", + "Rusty", + "Ragnar", + "Xylar", + "Maggie", + "Jack", + "Katie", + "Noah", + "James", + "Rina", + "Ella", + "Mariah", + "Frank", + "Claudia", + "Niki", + "Vincent", + "Kendrick", + "Myrna", + "Tom", + "Wanda", + "Benjamin", + "Kiana", + "Rachel", + ], + PropertyInfo(alias="presetId"), + ] + ] + """A Runway preset voice id. + + Choosing a preset routes only to models that support preset voices. + """ + + type: Required[Literal["preset"]] + + +class InputVoiceReferenceAudio(TypedDict, total=False): + """Clone a voice from a reference audio clip, then speak promptText in that voice. + + Routes only to models that support voice cloning. + """ + + audio_uri: Required[Annotated[str, PropertyInfo(alias="audioUri")]] + """A HTTPS URL.""" + + type: Required[Literal["reference-audio"]] + + +InputVoice: TypeAlias = Union[InputVoicePreset, InputVoiceReferenceAudio] + + +class Input(TypedDict, total=False): + """Model-agnostic audio generation input. + + The router selects a model and maps these options to it. + """ + + prompt_text: Required[Annotated[str, PropertyInfo(alias="promptText")]] + """For `speech`, the words to speak. + + For `audio`, a description of the desired output. + """ + + type: Required[Literal["speech", "audio"]] + """ + How promptText is interpreted: `speech` speaks it verbatim as a script; `audio` + treats it as a description of the desired audio, which may combine speech, + music, ambience, and sound effects. + """ + + duration: float + """Desired output duration in seconds for `audio` generation. + + Models that cannot honor an explicit duration are excluded. + """ + + loop: bool + """When true, the `audio` output is designed to loop seamlessly. + + Models without loop support are excluded. + """ + + reference_audios: Annotated[Iterable[InputReferenceAudio], PropertyInfo(alias="referenceAudios")] + """ + Optional reference audio clips guiding `audio` generation, for models that + support them. Reference each clip in promptText as @Audio1, @Audio2, and @Audio3 + in order. + """ + + voice: InputVoice + """The voice to speak with. + + When omitted, models that support a default voice remain eligible. + """ diff --git a/src/runwayml/types/generate/audio_create_response.py b/src/runwayml/types/generate/audio_create_response.py new file mode 100644 index 0000000..ebce1ce --- /dev/null +++ b/src/runwayml/types/generate/audio_create_response.py @@ -0,0 +1,83 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["AudioCreateResponse", "Routing", "RoutingEstimatedCost", "RoutingResolvedInput", "RoutingResolvedSettings"] + + +class RoutingEstimatedCost(BaseModel): + """Estimated cost, computed against current pricing.""" + + credits: float + """Estimated cost of the generation in credits.""" + + +class RoutingResolvedInput(BaseModel): + """Request-side defaults resolved for the routing response. + + Not necessarily identical to prepared model options. + """ + + type: Literal["speech", "audio"] + """The prompt mode the router routed for.""" + + voice: Literal["preset", "reference-audio", "default", "none"] + """ + How the selected model resolves the voice: the requested preset or + reference-audio clone, the model default for voiceless speech, or none for + general audio. + """ + + +class RoutingResolvedSettings(BaseModel): + """The resolved config settings the router used for this request.""" + + optimize_for: Literal["cost", "latency", "quality"] = FieldInfo(alias="optimizeFor") + """ + The single optimization preference the config selected, used as the soft + weighting when scoring eligible models. + """ + + price_ceiling: Optional[float] = FieldInfo(alias="priceCeiling", default=None) + """ + The applied maximum credits per generation for this request’s modality, or null + if the config sets no ceiling. + """ + + +class Routing(BaseModel): + """Metadata describing which model the router selected and why.""" + + config_id: str = FieldInfo(alias="configId") + """The slug of the router config that was applied to this request.""" + + estimated_cost: RoutingEstimatedCost = FieldInfo(alias="estimatedCost") + """Estimated cost, computed against current pricing.""" + + model: str + """The public name of the model the router selected.""" + + provider: str + """The provider of the selected model.""" + + resolved_input: RoutingResolvedInput = FieldInfo(alias="resolvedInput") + """Request-side defaults resolved for the routing response. + + Not necessarily identical to prepared model options. + """ + + resolved_settings: RoutingResolvedSettings = FieldInfo(alias="resolvedSettings") + """The resolved config settings the router used for this request.""" + + +class AudioCreateResponse(BaseModel): + id: str + """The ID of the created task. Poll GET /v1/tasks/:id for the result.""" + + routing: Routing + """Metadata describing which model the router selected and why.""" diff --git a/src/runwayml/types/generate/image_create_params.py b/src/runwayml/types/generate/image_create_params.py new file mode 100644 index 0000000..5ac1a88 --- /dev/null +++ b/src/runwayml/types/generate/image_create_params.py @@ -0,0 +1,83 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Iterable +from typing_extensions import Literal, Required, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["ImageCreateParams", "Input", "InputContentModeration", "InputReferenceImage"] + + +class ImageCreateParams(TypedDict, total=False): + config_id: Required[Annotated[str, PropertyInfo(alias="configId")]] + """The slug of a saved Model Router config to route this request with.""" + + input: Required[Input] + """Model-agnostic image generation input. + + The router selects a model and maps these options to it. + """ + + +class InputContentModeration(TypedDict, total=False): + """Settings that affect the behavior of the content moderation system.""" + + public_figure_threshold: Annotated[Literal["auto", "low"], PropertyInfo(alias="publicFigureThreshold")] + """ + When set to `low`, the content moderation system will be less strict about + preventing generations that include recognizable public figures. + """ + + +class InputReferenceImage(TypedDict, total=False): + uri: Required[str] + """A HTTPS URL.""" + + +class Input(TypedDict, total=False): + """Model-agnostic image generation input. + + The router selects a model and maps these options to it. + """ + + prompt_text: Required[Annotated[str, PropertyInfo(alias="promptText")]] + """A text prompt describing the desired image.""" + + aspect_ratio: Annotated[ + Literal["16:9", "9:16", "1:1", "4:3", "3:4", "21:9", "2:3", "3:2", "4:5", "5:4"], + PropertyInfo(alias="aspectRatio"), + ] + """Desired aspect ratio. + + Models that do not support the requested aspect are excluded. + """ + + content_moderation: Annotated[InputContentModeration, PropertyInfo(alias="contentModeration")] + """Settings that affect the behavior of the content moderation system.""" + + output_count: Annotated[int, PropertyInfo(alias="outputCount")] + """Number of images to generate (1–10). + + Models that cannot produce the exact count are excluded and cost scales with + this value. + """ + + reference_images: Annotated[Iterable[InputReferenceImage], PropertyInfo(alias="referenceImages")] + """Optional reference images for models that support them. + + Tags are assigned per model when omitted. + """ + + resolution: Literal["1k", "2k", "4k"] + """Desired megapixel tier. + + Models that do not support the requested tier are excluded. + """ + + seed: int + """A seed for reproducible generation. + + Only gen4_image and gen4_image_turbo accept this field. + """ diff --git a/src/runwayml/types/generate/image_create_response.py b/src/runwayml/types/generate/image_create_response.py new file mode 100644 index 0000000..fb415da --- /dev/null +++ b/src/runwayml/types/generate/image_create_response.py @@ -0,0 +1,85 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["ImageCreateResponse", "Routing", "RoutingEstimatedCost", "RoutingResolvedInput", "RoutingResolvedSettings"] + + +class RoutingEstimatedCost(BaseModel): + """Estimated cost, computed against current pricing.""" + + credits: float + """Estimated cost of the generation in credits.""" + + +class RoutingResolvedInput(BaseModel): + """Request-side defaults resolved for the routing response. + + Not necessarily identical to prepared model options. + """ + + aspect_ratio: str = FieldInfo(alias="aspectRatio") + """Aspect ratio used for routing display.""" + + ratio: str + """ + Concrete output ratio derived from aspectRatio and resolution for the selected + model. + """ + + resolution: str + """Megapixel tier used for routing display.""" + + +class RoutingResolvedSettings(BaseModel): + """The resolved config settings the router used for this request.""" + + optimize_for: Literal["cost", "latency", "quality"] = FieldInfo(alias="optimizeFor") + """ + The single optimization preference the config selected, used as the soft + weighting when scoring eligible models. + """ + + price_ceiling: Optional[float] = FieldInfo(alias="priceCeiling", default=None) + """ + The applied maximum credits per generation for this request’s modality, or null + if the config sets no ceiling. + """ + + +class Routing(BaseModel): + """Metadata describing which model the router selected and why.""" + + config_id: str = FieldInfo(alias="configId") + """The slug of the router config that was applied to this request.""" + + estimated_cost: RoutingEstimatedCost = FieldInfo(alias="estimatedCost") + """Estimated cost, computed against current pricing.""" + + model: str + """The public name of the model the router selected.""" + + provider: str + """The provider of the selected model.""" + + resolved_input: RoutingResolvedInput = FieldInfo(alias="resolvedInput") + """Request-side defaults resolved for the routing response. + + Not necessarily identical to prepared model options. + """ + + resolved_settings: RoutingResolvedSettings = FieldInfo(alias="resolvedSettings") + """The resolved config settings the router used for this request.""" + + +class ImageCreateResponse(BaseModel): + id: str + """The ID of the created task. Poll GET /v1/tasks/:id for the result.""" + + routing: Routing + """Metadata describing which model the router selected and why.""" diff --git a/src/runwayml/types/generate/video_create_params.py b/src/runwayml/types/generate/video_create_params.py index e2b8ef2..1c9d81a 100644 --- a/src/runwayml/types/generate/video_create_params.py +++ b/src/runwayml/types/generate/video_create_params.py @@ -32,13 +32,6 @@ class VideoCreateParams(TypedDict, total=False): Fields are optional; the router selects a model and maps these options to it. """ - dry_run: Annotated[bool, PropertyInfo(alias="dryRun")] - """ - When true, run the full routing pipeline and return the decision and estimated - cost without generating. No task is created, nothing is billed, and no asset is - produced. - """ - class InputContentModeration(TypedDict, total=False): """Settings that affect the behavior of the content moderation system.""" diff --git a/src/runwayml/types/generate/video_create_response.py b/src/runwayml/types/generate/video_create_response.py index 24fd33b..0624cc1 100644 --- a/src/runwayml/types/generate/video_create_response.py +++ b/src/runwayml/types/generate/video_create_response.py @@ -1,113 +1,23 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Union, Optional -from typing_extensions import Literal, Annotated, TypeAlias +from typing import Optional +from typing_extensions import Literal from pydantic import Field as FieldInfo -from ..._utils import PropertyInfo from ..._models import BaseModel -__all__ = [ - "VideoCreateResponse", - "RoutedVideoTaskCreated", - "RoutedVideoTaskCreatedRouting", - "RoutedVideoTaskCreatedRoutingEstimatedCost", - "RoutedVideoTaskCreatedRoutingResolvedInput", - "RoutedVideoTaskCreatedRoutingResolvedSettings", - "RoutedVideoDryRun", - "RoutedVideoDryRunRouting", - "RoutedVideoDryRunRoutingEstimatedCost", - "RoutedVideoDryRunRoutingResolvedInput", - "RoutedVideoDryRunRoutingResolvedSettings", -] - - -class RoutedVideoTaskCreatedRoutingEstimatedCost(BaseModel): - """Estimated cost, computed against current pricing.""" - - credits: float - """Estimated cost of the generation in credits.""" - - -class RoutedVideoTaskCreatedRoutingResolvedInput(BaseModel): - """Request-side defaults resolved for the routing response. - - Not necessarily identical to prepared model options. - """ +__all__ = ["VideoCreateResponse", "Routing", "RoutingEstimatedCost", "RoutingResolvedInput", "RoutingResolvedSettings"] - duration: float - """Duration in seconds used for routing display (request value or router default).""" - - ratio: str - """Concrete output ratio derived from aspectRatio (e.g. - - "1280:720"), or the router default. - """ - resolution: str - """Resolution tier from the request, or the router default when omitted.""" - - -class RoutedVideoTaskCreatedRoutingResolvedSettings(BaseModel): - """The resolved config settings the router used for this request.""" - - optimize_for: Literal["cost", "latency", "quality"] = FieldInfo(alias="optimizeFor") - """ - The single optimization preference the config selected, used as the soft - weighting when scoring eligible models. - """ - - price_ceiling: Optional[float] = FieldInfo(alias="priceCeiling", default=None) - """ - The applied maximum credits per generation for this request’s modality, or null - if the config sets no ceiling. - """ - - -class RoutedVideoTaskCreatedRouting(BaseModel): - """Metadata describing which model the router selected and why.""" - - config_id: str = FieldInfo(alias="configId") - """The slug of the router config that was applied to this request.""" - - estimated_cost: RoutedVideoTaskCreatedRoutingEstimatedCost = FieldInfo(alias="estimatedCost") - """Estimated cost, computed against current pricing.""" - - model: str - """The public name of the model the router selected.""" - - provider: str - """The provider of the selected model.""" - - resolved_input: RoutedVideoTaskCreatedRoutingResolvedInput = FieldInfo(alias="resolvedInput") - """Request-side defaults resolved for the routing response. - - Not necessarily identical to prepared model options. - """ - - resolved_settings: RoutedVideoTaskCreatedRoutingResolvedSettings = FieldInfo(alias="resolvedSettings") - """The resolved config settings the router used for this request.""" - - -class RoutedVideoTaskCreated(BaseModel): - id: str - """The ID of the created task. Poll GET /v1/tasks/:id for the result.""" - - dry_run: Literal[False] = FieldInfo(alias="dryRun") - - routing: RoutedVideoTaskCreatedRouting - """Metadata describing which model the router selected and why.""" - - -class RoutedVideoDryRunRoutingEstimatedCost(BaseModel): +class RoutingEstimatedCost(BaseModel): """Estimated cost, computed against current pricing.""" credits: float """Estimated cost of the generation in credits.""" -class RoutedVideoDryRunRoutingResolvedInput(BaseModel): +class RoutingResolvedInput(BaseModel): """Request-side defaults resolved for the routing response. Not necessarily identical to prepared model options. @@ -126,7 +36,7 @@ class RoutedVideoDryRunRoutingResolvedInput(BaseModel): """Resolution tier from the request, or the router default when omitted.""" -class RoutedVideoDryRunRoutingResolvedSettings(BaseModel): +class RoutingResolvedSettings(BaseModel): """The resolved config settings the router used for this request.""" optimize_for: Literal["cost", "latency", "quality"] = FieldInfo(alias="optimizeFor") @@ -142,13 +52,13 @@ class RoutedVideoDryRunRoutingResolvedSettings(BaseModel): """ -class RoutedVideoDryRunRouting(BaseModel): +class Routing(BaseModel): """Metadata describing which model the router selected and why.""" config_id: str = FieldInfo(alias="configId") """The slug of the router config that was applied to this request.""" - estimated_cost: RoutedVideoDryRunRoutingEstimatedCost = FieldInfo(alias="estimatedCost") + estimated_cost: RoutingEstimatedCost = FieldInfo(alias="estimatedCost") """Estimated cost, computed against current pricing.""" model: str @@ -157,23 +67,19 @@ class RoutedVideoDryRunRouting(BaseModel): provider: str """The provider of the selected model.""" - resolved_input: RoutedVideoDryRunRoutingResolvedInput = FieldInfo(alias="resolvedInput") + resolved_input: RoutingResolvedInput = FieldInfo(alias="resolvedInput") """Request-side defaults resolved for the routing response. Not necessarily identical to prepared model options. """ - resolved_settings: RoutedVideoDryRunRoutingResolvedSettings = FieldInfo(alias="resolvedSettings") + resolved_settings: RoutingResolvedSettings = FieldInfo(alias="resolvedSettings") """The resolved config settings the router used for this request.""" -class RoutedVideoDryRun(BaseModel): - dry_run: Literal[True] = FieldInfo(alias="dryRun") +class VideoCreateResponse(BaseModel): + id: str + """The ID of the created task. Poll GET /v1/tasks/:id for the result.""" - routing: RoutedVideoDryRunRouting + routing: Routing """Metadata describing which model the router selected and why.""" - - -VideoCreateResponse: TypeAlias = Annotated[ - Union[RoutedVideoTaskCreated, RoutedVideoDryRun], PropertyInfo(discriminator="dry_run") -] diff --git a/src/runwayml/types/organization_retrieve_usage_response.py b/src/runwayml/types/organization_retrieve_usage_response.py index 53971c4..549c750 100644 --- a/src/runwayml/types/organization_retrieve_usage_response.py +++ b/src/runwayml/types/organization_retrieve_usage_response.py @@ -1,14 +1,20 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import datetime -from typing import List +from typing import List, Optional from typing_extensions import Literal from pydantic import Field as FieldInfo from .._models import BaseModel -__all__ = ["OrganizationRetrieveUsageResponse", "Result", "ResultUsedCredit"] +__all__ = [ + "OrganizationRetrieveUsageResponse", + "Result", + "ResultUsedCredit", + "ResultsByAPIKey", + "ResultsByAPIKeyUsedCredit", +] class ResultUsedCredit(BaseModel): @@ -84,6 +90,18 @@ class Result(BaseModel): """The credits used per model for the given date.""" +class ResultsByAPIKeyUsedCredit(BaseModel): + amount: int + + api_key_id: str = FieldInfo(alias="apiKeyId") + + +class ResultsByAPIKey(BaseModel): + date: datetime.date + + used_credits: List[ResultsByAPIKeyUsedCredit] = FieldInfo(alias="usedCredits") + + class OrganizationRetrieveUsageResponse(BaseModel): models: List[ Literal[ @@ -142,3 +160,9 @@ class OrganizationRetrieveUsageResponse(BaseModel): """The list of models with usage during the queried time range.""" results: List[Result] + + api_keys: Optional[List[str]] = FieldInfo(alias="apiKeys", default=None) + """Reserved for future use.""" + + results_by_api_key: Optional[List[ResultsByAPIKey]] = FieldInfo(alias="resultsByApiKey", default=None) + """Reserved for future use.""" diff --git a/src/runwayml/types/router_create_params.py b/src/runwayml/types/router_create_params.py index cc393ae..b10a7b3 100644 --- a/src/runwayml/types/router_create_params.py +++ b/src/runwayml/types/router_create_params.py @@ -50,7 +50,7 @@ class SettingsMaxCreditsPerGeneration(TypedDict, total=False): class SettingsModels(TypedDict, total=False): """ - When mode is allow_new_except, ids are excluded; when allowlist_only, ids are the only allowed values. Each id must be a known public video model name (unknown ids are rejected on create/update). + When mode is allow_new_except, ids are excluded; when allowlist_only, ids are the only allowed values. Each id must be a known public video or image model name (unknown ids are rejected on create/update). """ ids: Required[SequenceNotStr[str]] @@ -75,8 +75,8 @@ class Settings(TypedDict, total=False): models: SettingsModels """ When mode is allow_new_except, ids are excluded; when allowlist_only, ids are - the only allowed values. Each id must be a known public video model name - (unknown ids are rejected on create/update). + the only allowed values. Each id must be a known public video or image model + name (unknown ids are rejected on create/update). """ optimize_for: Annotated[Literal["cost", "latency", "quality"], PropertyInfo(alias="optimizeFor")] diff --git a/src/runwayml/types/router_create_response.py b/src/runwayml/types/router_create_response.py index 75c7a94..2d1d33d 100644 --- a/src/runwayml/types/router_create_response.py +++ b/src/runwayml/types/router_create_response.py @@ -26,7 +26,7 @@ class SettingsMaxCreditsPerGeneration(BaseModel): class SettingsModels(BaseModel): """ - When mode is allow_new_except, ids are excluded; when allowlist_only, ids are the only allowed values. Each id must be a known public video model name (unknown ids are rejected on create/update). + When mode is allow_new_except, ids are excluded; when allowlist_only, ids are the only allowed values. Each id must be a known public video or image model name (unknown ids are rejected on create/update). """ ids: List[str] @@ -49,8 +49,8 @@ class Settings(BaseModel): models: Optional[SettingsModels] = None """ When mode is allow_new_except, ids are excluded; when allowlist_only, ids are - the only allowed values. Each id must be a known public video model name - (unknown ids are rejected on create/update). + the only allowed values. Each id must be a known public video or image model + name (unknown ids are rejected on create/update). """ optimize_for: Optional[Literal["cost", "latency", "quality"]] = FieldInfo(alias="optimizeFor", default=None) diff --git a/src/runwayml/types/router_list_response.py b/src/runwayml/types/router_list_response.py index c465ef1..2e7e3c0 100644 --- a/src/runwayml/types/router_list_response.py +++ b/src/runwayml/types/router_list_response.py @@ -26,7 +26,7 @@ class SettingsMaxCreditsPerGeneration(BaseModel): class SettingsModels(BaseModel): """ - When mode is allow_new_except, ids are excluded; when allowlist_only, ids are the only allowed values. Each id must be a known public video model name (unknown ids are rejected on create/update). + When mode is allow_new_except, ids are excluded; when allowlist_only, ids are the only allowed values. Each id must be a known public video or image model name (unknown ids are rejected on create/update). """ ids: List[str] @@ -49,8 +49,8 @@ class Settings(BaseModel): models: Optional[SettingsModels] = None """ When mode is allow_new_except, ids are excluded; when allowlist_only, ids are - the only allowed values. Each id must be a known public video model name - (unknown ids are rejected on create/update). + the only allowed values. Each id must be a known public video or image model + name (unknown ids are rejected on create/update). """ optimize_for: Optional[Literal["cost", "latency", "quality"]] = FieldInfo(alias="optimizeFor", default=None) diff --git a/src/runwayml/types/router_retrieve_response.py b/src/runwayml/types/router_retrieve_response.py index 84882b0..571c31b 100644 --- a/src/runwayml/types/router_retrieve_response.py +++ b/src/runwayml/types/router_retrieve_response.py @@ -26,7 +26,7 @@ class SettingsMaxCreditsPerGeneration(BaseModel): class SettingsModels(BaseModel): """ - When mode is allow_new_except, ids are excluded; when allowlist_only, ids are the only allowed values. Each id must be a known public video model name (unknown ids are rejected on create/update). + When mode is allow_new_except, ids are excluded; when allowlist_only, ids are the only allowed values. Each id must be a known public video or image model name (unknown ids are rejected on create/update). """ ids: List[str] @@ -49,8 +49,8 @@ class Settings(BaseModel): models: Optional[SettingsModels] = None """ When mode is allow_new_except, ids are excluded; when allowlist_only, ids are - the only allowed values. Each id must be a known public video model name - (unknown ids are rejected on create/update). + the only allowed values. Each id must be a known public video or image model + name (unknown ids are rejected on create/update). """ optimize_for: Optional[Literal["cost", "latency", "quality"]] = FieldInfo(alias="optimizeFor", default=None) diff --git a/src/runwayml/types/router_update_params.py b/src/runwayml/types/router_update_params.py index c658374..f2a3628 100644 --- a/src/runwayml/types/router_update_params.py +++ b/src/runwayml/types/router_update_params.py @@ -40,7 +40,7 @@ class SettingsMaxCreditsPerGeneration(TypedDict, total=False): class SettingsModels(TypedDict, total=False): """ - When mode is allow_new_except, ids are excluded; when allowlist_only, ids are the only allowed values. Each id must be a known public video model name (unknown ids are rejected on create/update). + When mode is allow_new_except, ids are excluded; when allowlist_only, ids are the only allowed values. Each id must be a known public video or image model name (unknown ids are rejected on create/update). """ ids: Required[SequenceNotStr[str]] @@ -65,8 +65,8 @@ class Settings(TypedDict, total=False): models: SettingsModels """ When mode is allow_new_except, ids are excluded; when allowlist_only, ids are - the only allowed values. Each id must be a known public video model name - (unknown ids are rejected on create/update). + the only allowed values. Each id must be a known public video or image model + name (unknown ids are rejected on create/update). """ optimize_for: Annotated[Literal["cost", "latency", "quality"], PropertyInfo(alias="optimizeFor")] diff --git a/src/runwayml/types/router_update_response.py b/src/runwayml/types/router_update_response.py index 01c607f..a421b05 100644 --- a/src/runwayml/types/router_update_response.py +++ b/src/runwayml/types/router_update_response.py @@ -26,7 +26,7 @@ class SettingsMaxCreditsPerGeneration(BaseModel): class SettingsModels(BaseModel): """ - When mode is allow_new_except, ids are excluded; when allowlist_only, ids are the only allowed values. Each id must be a known public video model name (unknown ids are rejected on create/update). + When mode is allow_new_except, ids are excluded; when allowlist_only, ids are the only allowed values. Each id must be a known public video or image model name (unknown ids are rejected on create/update). """ ids: List[str] @@ -49,8 +49,8 @@ class Settings(BaseModel): models: Optional[SettingsModels] = None """ When mode is allow_new_except, ids are excluded; when allowlist_only, ids are - the only allowed values. Each id must be a known public video model name - (unknown ids are rejected on create/update). + the only allowed values. Each id must be a known public video or image model + name (unknown ids are rejected on create/update). """ optimize_for: Optional[Literal["cost", "latency", "quality"]] = FieldInfo(alias="optimizeFor", default=None) diff --git a/tests/api_resources/generate/test_audio.py b/tests/api_resources/generate/test_audio.py new file mode 100644 index 0000000..d35e73b --- /dev/null +++ b/tests/api_resources/generate/test_audio.py @@ -0,0 +1,146 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from runwayml import RunwayML, AsyncRunwayML +from tests.utils import assert_matches_type +from runwayml.types.generate import AudioCreateResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestAudio: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_create(self, client: RunwayML) -> None: + audio = client.generate.audio.create( + config_id="n6_", + input={ + "prompt_text": "x", + "type": "speech", + }, + ) + assert_matches_type(AudioCreateResponse, audio, path=["response"]) + + @parametrize + def test_method_create_with_all_params(self, client: RunwayML) -> None: + audio = client.generate.audio.create( + config_id="n6_", + input={ + "prompt_text": "x", + "type": "speech", + "duration": 0.5, + "loop": True, + "reference_audios": [{"uri": "https://example.com/file"}], + "voice": { + "preset_id": "Maya", + "type": "preset", + }, + }, + ) + assert_matches_type(AudioCreateResponse, audio, path=["response"]) + + @parametrize + def test_raw_response_create(self, client: RunwayML) -> None: + response = client.generate.audio.with_raw_response.create( + config_id="n6_", + input={ + "prompt_text": "x", + "type": "speech", + }, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + audio = response.parse() + assert_matches_type(AudioCreateResponse, audio, path=["response"]) + + @parametrize + def test_streaming_response_create(self, client: RunwayML) -> None: + with client.generate.audio.with_streaming_response.create( + config_id="n6_", + input={ + "prompt_text": "x", + "type": "speech", + }, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + audio = response.parse() + assert_matches_type(AudioCreateResponse, audio, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncAudio: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_create(self, async_client: AsyncRunwayML) -> None: + audio = await async_client.generate.audio.create( + config_id="n6_", + input={ + "prompt_text": "x", + "type": "speech", + }, + ) + assert_matches_type(AudioCreateResponse, audio, path=["response"]) + + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncRunwayML) -> None: + audio = await async_client.generate.audio.create( + config_id="n6_", + input={ + "prompt_text": "x", + "type": "speech", + "duration": 0.5, + "loop": True, + "reference_audios": [{"uri": "https://example.com/file"}], + "voice": { + "preset_id": "Maya", + "type": "preset", + }, + }, + ) + assert_matches_type(AudioCreateResponse, audio, path=["response"]) + + @parametrize + async def test_raw_response_create(self, async_client: AsyncRunwayML) -> None: + response = await async_client.generate.audio.with_raw_response.create( + config_id="n6_", + input={ + "prompt_text": "x", + "type": "speech", + }, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + audio = await response.parse() + assert_matches_type(AudioCreateResponse, audio, path=["response"]) + + @parametrize + async def test_streaming_response_create(self, async_client: AsyncRunwayML) -> None: + async with async_client.generate.audio.with_streaming_response.create( + config_id="n6_", + input={ + "prompt_text": "x", + "type": "speech", + }, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + audio = await response.parse() + assert_matches_type(AudioCreateResponse, audio, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/generate/test_image.py b/tests/api_resources/generate/test_image.py new file mode 100644 index 0000000..886edbc --- /dev/null +++ b/tests/api_resources/generate/test_image.py @@ -0,0 +1,124 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from runwayml import RunwayML, AsyncRunwayML +from tests.utils import assert_matches_type +from runwayml.types.generate import ImageCreateResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestImage: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_create(self, client: RunwayML) -> None: + image = client.generate.image.create( + config_id="n6_", + input={"prompt_text": "x"}, + ) + assert_matches_type(ImageCreateResponse, image, path=["response"]) + + @parametrize + def test_method_create_with_all_params(self, client: RunwayML) -> None: + image = client.generate.image.create( + config_id="n6_", + input={ + "prompt_text": "x", + "aspect_ratio": "16:9", + "content_moderation": {"public_figure_threshold": "auto"}, + "output_count": 1, + "reference_images": [{"uri": "https://example.com/file"}], + "resolution": "1k", + "seed": 0, + }, + ) + assert_matches_type(ImageCreateResponse, image, path=["response"]) + + @parametrize + def test_raw_response_create(self, client: RunwayML) -> None: + response = client.generate.image.with_raw_response.create( + config_id="n6_", + input={"prompt_text": "x"}, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + image = response.parse() + assert_matches_type(ImageCreateResponse, image, path=["response"]) + + @parametrize + def test_streaming_response_create(self, client: RunwayML) -> None: + with client.generate.image.with_streaming_response.create( + config_id="n6_", + input={"prompt_text": "x"}, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + image = response.parse() + assert_matches_type(ImageCreateResponse, image, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncImage: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_create(self, async_client: AsyncRunwayML) -> None: + image = await async_client.generate.image.create( + config_id="n6_", + input={"prompt_text": "x"}, + ) + assert_matches_type(ImageCreateResponse, image, path=["response"]) + + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncRunwayML) -> None: + image = await async_client.generate.image.create( + config_id="n6_", + input={ + "prompt_text": "x", + "aspect_ratio": "16:9", + "content_moderation": {"public_figure_threshold": "auto"}, + "output_count": 1, + "reference_images": [{"uri": "https://example.com/file"}], + "resolution": "1k", + "seed": 0, + }, + ) + assert_matches_type(ImageCreateResponse, image, path=["response"]) + + @parametrize + async def test_raw_response_create(self, async_client: AsyncRunwayML) -> None: + response = await async_client.generate.image.with_raw_response.create( + config_id="n6_", + input={"prompt_text": "x"}, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + image = await response.parse() + assert_matches_type(ImageCreateResponse, image, path=["response"]) + + @parametrize + async def test_streaming_response_create(self, async_client: AsyncRunwayML) -> None: + async with async_client.generate.image.with_streaming_response.create( + config_id="n6_", + input={"prompt_text": "x"}, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + image = await response.parse() + assert_matches_type(ImageCreateResponse, image, path=["response"]) + + assert cast(Any, response.is_closed) is True