diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 052d78b..8e76abb 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "4.18.0" + ".": "5.0.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 6e10a1c..0fd103d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 38 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runwayml/runwayml-10c9a846a0c356c45d6896a3f4c2c8058a13dc31374f75859044270418dd5f5a.yml -openapi_spec_hash: 8dda646a596bd23feda0d25eca7abbfd -config_hash: 6d8ca402de13857362ee587c404baca9 +configured_endpoints: 43 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runwayml/runwayml-e4103e353904891c1dfe59c4cfaefb536c0dc20ae0316f2c18bae77aa4e8d8c7.yml +openapi_spec_hash: 1ff35e9f88f6ed20b58ebdfaadc738c7 +config_hash: dbcc649d22e217f477258caee20c63d2 diff --git a/CHANGELOG.md b/CHANGELOG.md index 28573ec..70401ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## 5.0.0 (2026-06-10) + +Full Changelog: [v4.18.0...v5.0.0](https://github.com/runwayml/sdk-python/compare/v4.18.0...v5.0.0) + +### Features + +* **api:** Add new avatar and voice routes ([36d836d](https://github.com/runwayml/sdk-python/commit/36d836dfd28cadc7dbe0b956ce03a8243cd28e2f)) + + +### Bug Fixes + +* **api:** update the right config file this time ([0ddcaf5](https://github.com/runwayml/sdk-python/commit/0ddcaf5c418dda2139dbb5431703e49ba5f11c37)) + ## 4.18.0 (2026-06-05) Full Changelog: [v4.17.0...v4.18.0](https://github.com/runwayml/sdk-python/compare/v4.17.0...v4.18.0) diff --git a/api.md b/api.md index 45069e1..adfb5c7 100644 --- a/api.md +++ b/api.md @@ -166,6 +166,7 @@ from runwayml.types import ( AvatarRetrieveResponse, AvatarUpdateResponse, AvatarListResponse, + AvatarGetUsageResponse, ) ``` @@ -176,6 +177,21 @@ Methods: - client.avatars.update(id, \*\*params) -> AvatarUpdateResponse - client.avatars.list(\*\*params) -> SyncCursorPage[AvatarListResponse] - client.avatars.delete(id) -> None +- client.avatars.get_usage(\*\*params) -> AvatarGetUsageResponse + +# AvatarConversations + +Types: + +```python +from runwayml.types import AvatarConversationRetrieveResponse, AvatarConversationListResponse +``` + +Methods: + +- client.avatar_conversations.retrieve(id) -> AvatarConversationRetrieveResponse +- client.avatar_conversations.list(\*\*params) -> SyncCursorPage[AvatarConversationListResponse] +- client.avatar_conversations.delete(id) -> None # AvatarVideos @@ -227,6 +243,7 @@ Types: from runwayml.types import ( VoiceCreateResponse, VoiceRetrieveResponse, + VoiceUpdateResponse, VoiceListResponse, VoicePreviewResponse, ) @@ -236,6 +253,7 @@ Methods: - client.voices.create(\*\*params) -> VoiceCreateResponse - client.voices.retrieve(id) -> VoiceRetrieveResponse +- client.voices.update(id, \*\*params) -> VoiceUpdateResponse - client.voices.list(\*\*params) -> SyncCursorPage[VoiceListResponse] - client.voices.delete(id) -> None - client.voices.preview(\*\*params) -> VoicePreviewResponse diff --git a/pyproject.toml b/pyproject.toml index bff7f49..096471f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "runwayml" -version = "4.18.0" +version = "5.0.0" description = "The official Python library for the runwayml API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/runwayml/_client.py b/src/runwayml/_client.py index 348e902..e4ce04c 100644 --- a/src/runwayml/_client.py +++ b/src/runwayml/_client.py @@ -55,6 +55,7 @@ voice_isolation, speech_to_speech, realtime_sessions, + avatar_conversations, workflow_invocations, character_performance, ) @@ -77,6 +78,7 @@ from .resources.voice_isolation import VoiceIsolationResource, AsyncVoiceIsolationResource from .resources.speech_to_speech import SpeechToSpeechResource, AsyncSpeechToSpeechResource from .resources.realtime_sessions import RealtimeSessionsResource, AsyncRealtimeSessionsResource + from .resources.avatar_conversations import AvatarConversationsResource, AsyncAvatarConversationsResource from .resources.workflow_invocations import WorkflowInvocationsResource, AsyncWorkflowInvocationsResource from .resources.character_performance import CharacterPerformanceResource, AsyncCharacterPerformanceResource @@ -264,6 +266,12 @@ def avatars(self) -> AvatarsResource: return AvatarsResource(self) + @cached_property + def avatar_conversations(self) -> AvatarConversationsResource: + from .resources.avatar_conversations import AvatarConversationsResource + + return AvatarConversationsResource(self) + @cached_property def avatar_videos(self) -> AvatarVideosResource: from .resources.avatar_videos import AvatarVideosResource @@ -588,6 +596,12 @@ def avatars(self) -> AsyncAvatarsResource: return AsyncAvatarsResource(self) + @cached_property + def avatar_conversations(self) -> AsyncAvatarConversationsResource: + from .resources.avatar_conversations import AsyncAvatarConversationsResource + + return AsyncAvatarConversationsResource(self) + @cached_property def avatar_videos(self) -> AsyncAvatarVideosResource: from .resources.avatar_videos import AsyncAvatarVideosResource @@ -848,6 +862,12 @@ def avatars(self) -> avatars.AvatarsResourceWithRawResponse: return AvatarsResourceWithRawResponse(self._client.avatars) + @cached_property + def avatar_conversations(self) -> avatar_conversations.AvatarConversationsResourceWithRawResponse: + from .resources.avatar_conversations import AvatarConversationsResourceWithRawResponse + + return AvatarConversationsResourceWithRawResponse(self._client.avatar_conversations) + @cached_property def avatar_videos(self) -> avatar_videos.AvatarVideosResourceWithRawResponse: from .resources.avatar_videos import AvatarVideosResourceWithRawResponse @@ -993,6 +1013,12 @@ def avatars(self) -> avatars.AsyncAvatarsResourceWithRawResponse: return AsyncAvatarsResourceWithRawResponse(self._client.avatars) + @cached_property + def avatar_conversations(self) -> avatar_conversations.AsyncAvatarConversationsResourceWithRawResponse: + from .resources.avatar_conversations import AsyncAvatarConversationsResourceWithRawResponse + + return AsyncAvatarConversationsResourceWithRawResponse(self._client.avatar_conversations) + @cached_property def avatar_videos(self) -> avatar_videos.AsyncAvatarVideosResourceWithRawResponse: from .resources.avatar_videos import AsyncAvatarVideosResourceWithRawResponse @@ -1138,6 +1164,12 @@ def avatars(self) -> avatars.AvatarsResourceWithStreamingResponse: return AvatarsResourceWithStreamingResponse(self._client.avatars) + @cached_property + def avatar_conversations(self) -> avatar_conversations.AvatarConversationsResourceWithStreamingResponse: + from .resources.avatar_conversations import AvatarConversationsResourceWithStreamingResponse + + return AvatarConversationsResourceWithStreamingResponse(self._client.avatar_conversations) + @cached_property def avatar_videos(self) -> avatar_videos.AvatarVideosResourceWithStreamingResponse: from .resources.avatar_videos import AvatarVideosResourceWithStreamingResponse @@ -1283,6 +1315,12 @@ def avatars(self) -> avatars.AsyncAvatarsResourceWithStreamingResponse: return AsyncAvatarsResourceWithStreamingResponse(self._client.avatars) + @cached_property + def avatar_conversations(self) -> avatar_conversations.AsyncAvatarConversationsResourceWithStreamingResponse: + from .resources.avatar_conversations import AsyncAvatarConversationsResourceWithStreamingResponse + + return AsyncAvatarConversationsResourceWithStreamingResponse(self._client.avatar_conversations) + @cached_property def avatar_videos(self) -> avatar_videos.AsyncAvatarVideosResourceWithStreamingResponse: from .resources.avatar_videos import AsyncAvatarVideosResourceWithStreamingResponse diff --git a/src/runwayml/_version.py b/src/runwayml/_version.py index db2286f..527e88a 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__ = "4.18.0" # x-release-please-version +__version__ = "5.0.0" # x-release-please-version diff --git a/src/runwayml/resources/__init__.py b/src/runwayml/resources/__init__.py index 1aea4ab..257b9c5 100644 --- a/src/runwayml/resources/__init__.py +++ b/src/runwayml/resources/__init__.py @@ -152,6 +152,14 @@ RealtimeSessionsResourceWithStreamingResponse, AsyncRealtimeSessionsResourceWithStreamingResponse, ) +from .avatar_conversations import ( + AvatarConversationsResource, + AsyncAvatarConversationsResource, + AvatarConversationsResourceWithRawResponse, + AsyncAvatarConversationsResourceWithRawResponse, + AvatarConversationsResourceWithStreamingResponse, + AsyncAvatarConversationsResourceWithStreamingResponse, +) from .workflow_invocations import ( WorkflowInvocationsResource, AsyncWorkflowInvocationsResource, @@ -260,6 +268,12 @@ "AsyncAvatarsResourceWithRawResponse", "AvatarsResourceWithStreamingResponse", "AsyncAvatarsResourceWithStreamingResponse", + "AvatarConversationsResource", + "AsyncAvatarConversationsResource", + "AvatarConversationsResourceWithRawResponse", + "AsyncAvatarConversationsResourceWithRawResponse", + "AvatarConversationsResourceWithStreamingResponse", + "AsyncAvatarConversationsResourceWithStreamingResponse", "AvatarVideosResource", "AsyncAvatarVideosResource", "AvatarVideosResourceWithRawResponse", diff --git a/src/runwayml/resources/avatar_conversations.py b/src/runwayml/resources/avatar_conversations.py new file mode 100644 index 0000000..654db7e --- /dev/null +++ b/src/runwayml/resources/avatar_conversations.py @@ -0,0 +1,400 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Any, Union, cast +from datetime import datetime + +import httpx + +from ..types import avatar_conversation_list_params +from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given +from .._utils import path_template, 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 ..pagination import SyncCursorPage, AsyncCursorPage +from .._base_client import AsyncPaginator, make_request_options +from ..types.avatar_conversation_list_response import AvatarConversationListResponse +from ..types.avatar_conversation_retrieve_response import AvatarConversationRetrieveResponse + +__all__ = ["AvatarConversationsResource", "AsyncAvatarConversationsResource"] + + +class AvatarConversationsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> AvatarConversationsResourceWithRawResponse: + """ + 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 AvatarConversationsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AvatarConversationsResourceWithStreamingResponse: + """ + 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 AvatarConversationsResourceWithStreamingResponse(self) + + def retrieve( + self, + id: str, + *, + # 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, + ) -> AvatarConversationRetrieveResponse: + """ + Get detailed information about a specific conversation, including the transcript + and recording download URL when available. The conversation ID is the same value + returned when the realtime session was created. + + Args: + 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 + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return cast( + AvatarConversationRetrieveResponse, + self._get( + path_template("/v1/avatar_conversations/{id}", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast( + Any, AvatarConversationRetrieveResponse + ), # Union types cannot be passed in as arguments in the type system + ), + ) + + def list( + self, + *, + limit: int, + avatar: str | Omit = omit, + cursor: str | Omit = omit, + end_date: Union[str, datetime] | Omit = omit, + start_date: Union[str, datetime] | Omit = omit, + # 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, + ) -> SyncCursorPage[AvatarConversationListResponse]: + """ + List realtime avatar conversations for the authenticated user with cursor-based + pagination. Each conversation corresponds to a realtime session, and the + conversation ID matches the realtime session ID. Pass `avatar` to restrict + results to a single avatar. + + Args: + limit: The maximum number of items to return per page. + + avatar: Filter to conversations that used the given custom avatar. + + cursor: Cursor from a previous response for fetching the next page of results. + + end_date: Filter conversations created before this timestamp (exclusive). + + start_date: Filter conversations created on or after this timestamp (inclusive). + + 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._get_api_list( + "/v1/avatar_conversations", + page=SyncCursorPage[AvatarConversationListResponse], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "limit": limit, + "avatar": avatar, + "cursor": cursor, + "end_date": end_date, + "start_date": start_date, + }, + avatar_conversation_list_params.AvatarConversationListParams, + ), + ), + model=AvatarConversationListResponse, + ) + + def delete( + self, + id: str, + *, + # 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, + ) -> None: + """ + Delete a conversation and its associated data. + + Args: + 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 + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._delete( + path_template("/v1/avatar_conversations/{id}", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + +class AsyncAvatarConversationsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncAvatarConversationsResourceWithRawResponse: + """ + 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 AsyncAvatarConversationsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncAvatarConversationsResourceWithStreamingResponse: + """ + 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 AsyncAvatarConversationsResourceWithStreamingResponse(self) + + async def retrieve( + self, + id: str, + *, + # 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, + ) -> AvatarConversationRetrieveResponse: + """ + Get detailed information about a specific conversation, including the transcript + and recording download URL when available. The conversation ID is the same value + returned when the realtime session was created. + + Args: + 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 + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return cast( + AvatarConversationRetrieveResponse, + await self._get( + path_template("/v1/avatar_conversations/{id}", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast( + Any, AvatarConversationRetrieveResponse + ), # Union types cannot be passed in as arguments in the type system + ), + ) + + def list( + self, + *, + limit: int, + avatar: str | Omit = omit, + cursor: str | Omit = omit, + end_date: Union[str, datetime] | Omit = omit, + start_date: Union[str, datetime] | Omit = omit, + # 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, + ) -> AsyncPaginator[AvatarConversationListResponse, AsyncCursorPage[AvatarConversationListResponse]]: + """ + List realtime avatar conversations for the authenticated user with cursor-based + pagination. Each conversation corresponds to a realtime session, and the + conversation ID matches the realtime session ID. Pass `avatar` to restrict + results to a single avatar. + + Args: + limit: The maximum number of items to return per page. + + avatar: Filter to conversations that used the given custom avatar. + + cursor: Cursor from a previous response for fetching the next page of results. + + end_date: Filter conversations created before this timestamp (exclusive). + + start_date: Filter conversations created on or after this timestamp (inclusive). + + 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._get_api_list( + "/v1/avatar_conversations", + page=AsyncCursorPage[AvatarConversationListResponse], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "limit": limit, + "avatar": avatar, + "cursor": cursor, + "end_date": end_date, + "start_date": start_date, + }, + avatar_conversation_list_params.AvatarConversationListParams, + ), + ), + model=AvatarConversationListResponse, + ) + + async def delete( + self, + id: str, + *, + # 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, + ) -> None: + """ + Delete a conversation and its associated data. + + Args: + 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 + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._delete( + path_template("/v1/avatar_conversations/{id}", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + +class AvatarConversationsResourceWithRawResponse: + def __init__(self, avatar_conversations: AvatarConversationsResource) -> None: + self._avatar_conversations = avatar_conversations + + self.retrieve = to_raw_response_wrapper( + avatar_conversations.retrieve, + ) + self.list = to_raw_response_wrapper( + avatar_conversations.list, + ) + self.delete = to_raw_response_wrapper( + avatar_conversations.delete, + ) + + +class AsyncAvatarConversationsResourceWithRawResponse: + def __init__(self, avatar_conversations: AsyncAvatarConversationsResource) -> None: + self._avatar_conversations = avatar_conversations + + self.retrieve = async_to_raw_response_wrapper( + avatar_conversations.retrieve, + ) + self.list = async_to_raw_response_wrapper( + avatar_conversations.list, + ) + self.delete = async_to_raw_response_wrapper( + avatar_conversations.delete, + ) + + +class AvatarConversationsResourceWithStreamingResponse: + def __init__(self, avatar_conversations: AvatarConversationsResource) -> None: + self._avatar_conversations = avatar_conversations + + self.retrieve = to_streamed_response_wrapper( + avatar_conversations.retrieve, + ) + self.list = to_streamed_response_wrapper( + avatar_conversations.list, + ) + self.delete = to_streamed_response_wrapper( + avatar_conversations.delete, + ) + + +class AsyncAvatarConversationsResourceWithStreamingResponse: + def __init__(self, avatar_conversations: AsyncAvatarConversationsResource) -> None: + self._avatar_conversations = avatar_conversations + + self.retrieve = async_to_streamed_response_wrapper( + avatar_conversations.retrieve, + ) + self.list = async_to_streamed_response_wrapper( + avatar_conversations.list, + ) + self.delete = async_to_streamed_response_wrapper( + avatar_conversations.delete, + ) diff --git a/src/runwayml/resources/avatars.py b/src/runwayml/resources/avatars.py index fc00ef6..e6b1fc9 100644 --- a/src/runwayml/resources/avatars.py +++ b/src/runwayml/resources/avatars.py @@ -2,12 +2,13 @@ from __future__ import annotations -from typing import Any, Optional, cast +from typing import Any, Union, Optional, cast +from datetime import datetime from typing_extensions import Literal import httpx -from ..types import avatar_list_params, avatar_create_params, avatar_update_params +from ..types import avatar_list_params, avatar_create_params, avatar_update_params, avatar_get_usage_params from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property @@ -24,6 +25,7 @@ from ..types.avatar_create_response import AvatarCreateResponse from ..types.avatar_update_response import AvatarUpdateResponse from ..types.avatar_retrieve_response import AvatarRetrieveResponse +from ..types.avatar_get_usage_response import AvatarGetUsageResponse __all__ = ["AvatarsResource", "AsyncAvatarsResource"] @@ -312,6 +314,54 @@ def delete( cast_to=NoneType, ) + def get_usage( + self, + *, + end_date: Union[str, datetime], + start_date: Union[str, datetime], + # 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, + ) -> AvatarGetUsageResponse: + """ + Get aggregate usage statistics for avatar conversations, including total + duration, session counts, average duration, and a per-day breakdown. Per-day + buckets are keyed by UTC calendar date. The date range must not exceed 90 days. + + Args: + end_date: End of the date range in UTC (exclusive). Required. + + start_date: Start of the date range in UTC (inclusive). Required. + + 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._get( + "/v1/avatar_usage", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "end_date": end_date, + "start_date": start_date, + }, + avatar_get_usage_params.AvatarGetUsageParams, + ), + ), + cast_to=AvatarGetUsageResponse, + ) + class AsyncAvatarsResource(AsyncAPIResource): @cached_property @@ -597,6 +647,54 @@ async def delete( cast_to=NoneType, ) + async def get_usage( + self, + *, + end_date: Union[str, datetime], + start_date: Union[str, datetime], + # 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, + ) -> AvatarGetUsageResponse: + """ + Get aggregate usage statistics for avatar conversations, including total + duration, session counts, average duration, and a per-day breakdown. Per-day + buckets are keyed by UTC calendar date. The date range must not exceed 90 days. + + Args: + end_date: End of the date range in UTC (exclusive). Required. + + start_date: Start of the date range in UTC (inclusive). Required. + + 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._get( + "/v1/avatar_usage", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "end_date": end_date, + "start_date": start_date, + }, + avatar_get_usage_params.AvatarGetUsageParams, + ), + ), + cast_to=AvatarGetUsageResponse, + ) + class AvatarsResourceWithRawResponse: def __init__(self, avatars: AvatarsResource) -> None: @@ -617,6 +715,9 @@ def __init__(self, avatars: AvatarsResource) -> None: self.delete = to_raw_response_wrapper( avatars.delete, ) + self.get_usage = to_raw_response_wrapper( + avatars.get_usage, + ) class AsyncAvatarsResourceWithRawResponse: @@ -638,6 +739,9 @@ def __init__(self, avatars: AsyncAvatarsResource) -> None: self.delete = async_to_raw_response_wrapper( avatars.delete, ) + self.get_usage = async_to_raw_response_wrapper( + avatars.get_usage, + ) class AvatarsResourceWithStreamingResponse: @@ -659,6 +763,9 @@ def __init__(self, avatars: AvatarsResource) -> None: self.delete = to_streamed_response_wrapper( avatars.delete, ) + self.get_usage = to_streamed_response_wrapper( + avatars.get_usage, + ) class AsyncAvatarsResourceWithStreamingResponse: @@ -680,3 +787,6 @@ def __init__(self, avatars: AsyncAvatarsResource) -> None: self.delete = async_to_streamed_response_wrapper( avatars.delete, ) + self.get_usage = async_to_streamed_response_wrapper( + avatars.get_usage, + ) diff --git a/src/runwayml/resources/image_to_video.py b/src/runwayml/resources/image_to_video.py index 7cee6c5..695b11d 100644 --- a/src/runwayml/resources/image_to_video.py +++ b/src/runwayml/resources/image_to_video.py @@ -191,53 +191,6 @@ def create( """ ... - @overload - def create( - self, - *, - model: Literal["gen3a_turbo"], - prompt_image: Union[str, Iterable[image_to_video_create_params.Gen3aTurboPromptImagePromptImage]], - prompt_text: str, - content_moderation: image_to_video_create_params.Gen3aTurboContentModeration | Omit = omit, - duration: Literal[5, 10] | Omit = omit, - ratio: Literal["768:1280", "1280:768"] | Omit = omit, - seed: int | Omit = omit, - # 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: - """ - This endpoint will start a new task to generate a video from an image. - - Args: - prompt_image: A HTTPS URL. - - prompt_text: A non-empty string up to 1000 characters (measured in UTF-16 code units). This - should describe in detail what should appear in the output. - - content_moderation: Settings that affect the behavior of the content moderation system. - - duration: The duration of the output video in seconds. - - ratio: The resolution of the output video. - - seed: If unspecified, a random number is chosen. Varying the seed integer is a way to - get different results for the same other request parameters. Using the same seed - integer for an identical request will produce similar results. - - 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 - """ - ... - @overload def create( self, @@ -492,18 +445,16 @@ def create( @required_args( ["duration", "model", "prompt_image", "prompt_text", "ratio"], ["model", "prompt_image", "ratio"], - ["model", "prompt_image", "prompt_text"], ["model", "prompt_image"], ["duration", "model", "prompt_image", "ratio"], ) def create( self, *, - duration: int | Literal[4, 6, 8] | Literal[5, 10] | Literal[8] | Omit = omit, + duration: int | Literal[4, 6, 8] | Literal[8] | Omit = omit, model: Literal["gen4.5"] | Literal["gen4_turbo"] | Literal["veo3.1"] - | Literal["gen3a_turbo"] | Literal["veo3.1_fast"] | Literal["happyhorse_1_0"] | Literal["seedance2"] @@ -511,7 +462,6 @@ def create( | Literal["veo3"], prompt_image: Union[str, Iterable[image_to_video_create_params.Gen4_5PromptImagePromptImage]] | Union[str, Iterable[image_to_video_create_params.Gen4TurboPromptImagePromptImage]] - | Union[str, Iterable[image_to_video_create_params.Gen3aTurboPromptImagePromptImage]] | Union[str, Iterable[image_to_video_create_params.Seedance2PromptImagePromptImage]] | Union[str, Iterable[image_to_video_create_params.Veo3_1PromptImagePromptImage]] | Union[str, Iterable[image_to_video_create_params.Veo3_1FastPromptImagePromptImage]] @@ -520,7 +470,6 @@ def create( ratio: Literal["1280:720", "720:1280", "1104:832", "960:960", "832:1104", "1584:672"] | Literal["1280:720", "720:1280", "1104:832", "832:1104", "960:960", "1584:672"] | Literal["1280:720", "720:1280", "1080:1920", "1920:1080"] - | Literal["768:1280", "1280:768"] | Literal[ "992:432", "864:496", @@ -558,7 +507,6 @@ def create( | Omit = omit, content_moderation: image_to_video_create_params.Gen4_5ContentModeration | image_to_video_create_params.Gen4TurboContentModeration - | image_to_video_create_params.Gen3aTurboContentModeration | Omit = omit, seed: int | Omit = omit, audio: bool | Omit = omit, @@ -758,53 +706,6 @@ async def create( """ ... - @overload - async def create( - self, - *, - model: Literal["gen3a_turbo"], - prompt_image: Union[str, Iterable[image_to_video_create_params.Gen3aTurboPromptImagePromptImage]], - prompt_text: str, - content_moderation: image_to_video_create_params.Gen3aTurboContentModeration | Omit = omit, - duration: Literal[5, 10] | Omit = omit, - ratio: Literal["768:1280", "1280:768"] | Omit = omit, - seed: int | Omit = omit, - # 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: - """ - This endpoint will start a new task to generate a video from an image. - - Args: - prompt_image: A HTTPS URL. - - prompt_text: A non-empty string up to 1000 characters (measured in UTF-16 code units). This - should describe in detail what should appear in the output. - - content_moderation: Settings that affect the behavior of the content moderation system. - - duration: The duration of the output video in seconds. - - ratio: The resolution of the output video. - - seed: If unspecified, a random number is chosen. Varying the seed integer is a way to - get different results for the same other request parameters. Using the same seed - integer for an identical request will produce similar results. - - 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 - """ - ... - @overload async def create( self, @@ -1059,18 +960,16 @@ async def create( @required_args( ["duration", "model", "prompt_image", "prompt_text", "ratio"], ["model", "prompt_image", "ratio"], - ["model", "prompt_image", "prompt_text"], ["model", "prompt_image"], ["duration", "model", "prompt_image", "ratio"], ) async def create( self, *, - duration: int | Literal[4, 6, 8] | Literal[5, 10] | Literal[8] | Omit = omit, + duration: int | Literal[4, 6, 8] | Literal[8] | Omit = omit, model: Literal["gen4.5"] | Literal["gen4_turbo"] | Literal["veo3.1"] - | Literal["gen3a_turbo"] | Literal["veo3.1_fast"] | Literal["happyhorse_1_0"] | Literal["seedance2"] @@ -1078,7 +977,6 @@ async def create( | Literal["veo3"], prompt_image: Union[str, Iterable[image_to_video_create_params.Gen4_5PromptImagePromptImage]] | Union[str, Iterable[image_to_video_create_params.Gen4TurboPromptImagePromptImage]] - | Union[str, Iterable[image_to_video_create_params.Gen3aTurboPromptImagePromptImage]] | Union[str, Iterable[image_to_video_create_params.Seedance2PromptImagePromptImage]] | Union[str, Iterable[image_to_video_create_params.Veo3_1PromptImagePromptImage]] | Union[str, Iterable[image_to_video_create_params.Veo3_1FastPromptImagePromptImage]] @@ -1087,7 +985,6 @@ async def create( ratio: Literal["1280:720", "720:1280", "1104:832", "960:960", "832:1104", "1584:672"] | Literal["1280:720", "720:1280", "1104:832", "832:1104", "960:960", "1584:672"] | Literal["1280:720", "720:1280", "1080:1920", "1920:1080"] - | Literal["768:1280", "1280:768"] | Literal[ "992:432", "864:496", @@ -1125,7 +1022,6 @@ async def create( | Omit = omit, content_moderation: image_to_video_create_params.Gen4_5ContentModeration | image_to_video_create_params.Gen4TurboContentModeration - | image_to_video_create_params.Gen3aTurboContentModeration | Omit = omit, seed: int | Omit = omit, audio: bool | Omit = omit, diff --git a/src/runwayml/resources/video_to_video.py b/src/runwayml/resources/video_to_video.py index 8000675..f8f49c5 100644 --- a/src/runwayml/resources/video_to_video.py +++ b/src/runwayml/resources/video_to_video.py @@ -52,56 +52,6 @@ def with_streaming_response(self) -> VideoToVideoResourceWithStreamingResponse: """ return VideoToVideoResourceWithStreamingResponse(self) - @overload - def create( - self, - *, - model: Literal["gen4_aleph"], - prompt_text: str, - video_uri: str, - content_moderation: video_to_video_create_params.Gen4AlephContentModeration | Omit = omit, - ratio: Literal["1280:720", "720:1280", "1104:832", "960:960", "832:1104", "1584:672", "848:480", "640:480"] - | Omit = omit, - references: Iterable[video_to_video_create_params.Gen4AlephReference] | Omit = omit, - seed: int | Omit = omit, - # 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: - """ - This endpoint will start a new task to generate a video from a video. - - Args: - prompt_text: A non-empty string up to 1000 characters (measured in UTF-16 code units). This - should describe in detail what should appear in the output. - - video_uri: A HTTPS URL. - - content_moderation: Settings that affect the behavior of the content moderation system. - - ratio: Deprecated. This field is ignored. The resolution of the output video is - determined by the input video. - - references: An array of references. Currently up to one reference is supported. See - [our docs](/assets/inputs#images) on image inputs for more information. - - seed: If unspecified, a random number is chosen. Varying the seed integer is a way to - get different results for the same other request parameters. Using the same seed - integer for an identical request will produce similar results. - - 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 - """ - ... - @overload def create( self, @@ -109,9 +59,8 @@ def create( model: Literal["aleph2"], prompt_text: str, video_uri: str, - content_moderation: video_to_video_create_params.Aleph2ContentModeration | Omit = omit, - keyframes: Iterable[video_to_video_create_params.Aleph2Keyframe] | Omit = omit, - prompt_image: Iterable[video_to_video_create_params.Aleph2PromptImage] | Omit = omit, + content_moderation: video_to_video_create_params.Variant0ContentModeration | Omit = omit, + keyframes: Iterable[video_to_video_create_params.Variant0Keyframe] | Omit = omit, seed: int | Omit = omit, # 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. @@ -134,9 +83,6 @@ def create( keyframes: Timed guidance images placed at specific points in the input video. Up to 5 keyframes. - prompt_image: A list of up to 5 image keyframes for guiding the edit at specific points in the - video. - seed: If unspecified, a random number is chosen. Varying the seed integer is a way to get different results for the same other request parameters. Using the same seed integer for an identical request will produce similar results. @@ -300,14 +246,16 @@ def create( def create( self, *, - model: Literal["gen4_aleph"] | Literal["aleph2"] | Literal["seedance2"] | Literal["seedance2_fast"], + model: Literal["aleph2"] | Literal["seedance2"] | Literal["seedance2_fast"], prompt_text: str | Omit = omit, video_uri: str | Omit = omit, - content_moderation: video_to_video_create_params.Gen4AlephContentModeration - | video_to_video_create_params.Aleph2ContentModeration - | Omit = omit, - ratio: Literal["1280:720", "720:1280", "1104:832", "960:960", "832:1104", "1584:672", "848:480", "640:480"] - | Literal[ + content_moderation: video_to_video_create_params.Variant0ContentModeration | Omit = omit, + keyframes: Iterable[video_to_video_create_params.Variant0Keyframe] | Omit = omit, + seed: int | Omit = omit, + prompt_video: str | Omit = omit, + audio: bool | Omit = omit, + duration: int | Omit = omit, + ratio: Literal[ "992:432", "864:496", "752:560", @@ -342,19 +290,12 @@ def create( "720:1280", ] | Omit = omit, - references: Iterable[video_to_video_create_params.Gen4AlephReference] - | Iterable[video_to_video_create_params.Seedance2Reference] - | Iterable[video_to_video_create_params.Seedance2FastReference] - | Omit = omit, - seed: int | Omit = omit, - keyframes: Iterable[video_to_video_create_params.Aleph2Keyframe] | Omit = omit, - prompt_image: Iterable[video_to_video_create_params.Aleph2PromptImage] | Omit = omit, - prompt_video: str | Omit = omit, - audio: bool | Omit = omit, - duration: int | Omit = omit, reference_audio: Iterable[video_to_video_create_params.Seedance2ReferenceAudio] | Iterable[video_to_video_create_params.Seedance2FastReferenceAudio] | Omit = omit, + references: Iterable[video_to_video_create_params.Seedance2Reference] + | Iterable[video_to_video_create_params.Seedance2FastReference] + | Omit = omit, reference_videos: Iterable[video_to_video_create_params.Seedance2ReferenceVideo] | Iterable[video_to_video_create_params.Seedance2FastReferenceVideo] | Omit = omit, @@ -373,15 +314,14 @@ def create( "prompt_text": prompt_text, "video_uri": video_uri, "content_moderation": content_moderation, - "ratio": ratio, - "references": references, - "seed": seed, "keyframes": keyframes, - "prompt_image": prompt_image, + "seed": seed, "prompt_video": prompt_video, "audio": audio, "duration": duration, + "ratio": ratio, "reference_audio": reference_audio, + "references": references, "reference_videos": reference_videos, }, video_to_video_create_params.VideoToVideoCreateParams, @@ -415,56 +355,6 @@ def with_streaming_response(self) -> AsyncVideoToVideoResourceWithStreamingRespo """ return AsyncVideoToVideoResourceWithStreamingResponse(self) - @overload - async def create( - self, - *, - model: Literal["gen4_aleph"], - prompt_text: str, - video_uri: str, - content_moderation: video_to_video_create_params.Gen4AlephContentModeration | Omit = omit, - ratio: Literal["1280:720", "720:1280", "1104:832", "960:960", "832:1104", "1584:672", "848:480", "640:480"] - | Omit = omit, - references: Iterable[video_to_video_create_params.Gen4AlephReference] | Omit = omit, - seed: int | Omit = omit, - # 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: - """ - This endpoint will start a new task to generate a video from a video. - - Args: - prompt_text: A non-empty string up to 1000 characters (measured in UTF-16 code units). This - should describe in detail what should appear in the output. - - video_uri: A HTTPS URL. - - content_moderation: Settings that affect the behavior of the content moderation system. - - ratio: Deprecated. This field is ignored. The resolution of the output video is - determined by the input video. - - references: An array of references. Currently up to one reference is supported. See - [our docs](/assets/inputs#images) on image inputs for more information. - - seed: If unspecified, a random number is chosen. Varying the seed integer is a way to - get different results for the same other request parameters. Using the same seed - integer for an identical request will produce similar results. - - 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 - """ - ... - @overload async def create( self, @@ -472,9 +362,8 @@ async def create( model: Literal["aleph2"], prompt_text: str, video_uri: str, - content_moderation: video_to_video_create_params.Aleph2ContentModeration | Omit = omit, - keyframes: Iterable[video_to_video_create_params.Aleph2Keyframe] | Omit = omit, - prompt_image: Iterable[video_to_video_create_params.Aleph2PromptImage] | Omit = omit, + content_moderation: video_to_video_create_params.Variant0ContentModeration | Omit = omit, + keyframes: Iterable[video_to_video_create_params.Variant0Keyframe] | Omit = omit, seed: int | Omit = omit, # 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. @@ -497,9 +386,6 @@ async def create( keyframes: Timed guidance images placed at specific points in the input video. Up to 5 keyframes. - prompt_image: A list of up to 5 image keyframes for guiding the edit at specific points in the - video. - seed: If unspecified, a random number is chosen. Varying the seed integer is a way to get different results for the same other request parameters. Using the same seed integer for an identical request will produce similar results. @@ -663,14 +549,16 @@ async def create( async def create( self, *, - model: Literal["gen4_aleph"] | Literal["aleph2"] | Literal["seedance2"] | Literal["seedance2_fast"], + model: Literal["aleph2"] | Literal["seedance2"] | Literal["seedance2_fast"], prompt_text: str | Omit = omit, video_uri: str | Omit = omit, - content_moderation: video_to_video_create_params.Gen4AlephContentModeration - | video_to_video_create_params.Aleph2ContentModeration - | Omit = omit, - ratio: Literal["1280:720", "720:1280", "1104:832", "960:960", "832:1104", "1584:672", "848:480", "640:480"] - | Literal[ + content_moderation: video_to_video_create_params.Variant0ContentModeration | Omit = omit, + keyframes: Iterable[video_to_video_create_params.Variant0Keyframe] | Omit = omit, + seed: int | Omit = omit, + prompt_video: str | Omit = omit, + audio: bool | Omit = omit, + duration: int | Omit = omit, + ratio: Literal[ "992:432", "864:496", "752:560", @@ -705,19 +593,12 @@ async def create( "720:1280", ] | Omit = omit, - references: Iterable[video_to_video_create_params.Gen4AlephReference] - | Iterable[video_to_video_create_params.Seedance2Reference] - | Iterable[video_to_video_create_params.Seedance2FastReference] - | Omit = omit, - seed: int | Omit = omit, - keyframes: Iterable[video_to_video_create_params.Aleph2Keyframe] | Omit = omit, - prompt_image: Iterable[video_to_video_create_params.Aleph2PromptImage] | Omit = omit, - prompt_video: str | Omit = omit, - audio: bool | Omit = omit, - duration: int | Omit = omit, reference_audio: Iterable[video_to_video_create_params.Seedance2ReferenceAudio] | Iterable[video_to_video_create_params.Seedance2FastReferenceAudio] | Omit = omit, + references: Iterable[video_to_video_create_params.Seedance2Reference] + | Iterable[video_to_video_create_params.Seedance2FastReference] + | Omit = omit, reference_videos: Iterable[video_to_video_create_params.Seedance2ReferenceVideo] | Iterable[video_to_video_create_params.Seedance2FastReferenceVideo] | Omit = omit, @@ -736,15 +617,14 @@ async def create( "prompt_text": prompt_text, "video_uri": video_uri, "content_moderation": content_moderation, - "ratio": ratio, - "references": references, - "seed": seed, "keyframes": keyframes, - "prompt_image": prompt_image, + "seed": seed, "prompt_video": prompt_video, "audio": audio, "duration": duration, + "ratio": ratio, "reference_audio": reference_audio, + "references": references, "reference_videos": reference_videos, }, video_to_video_create_params.VideoToVideoCreateParams, diff --git a/src/runwayml/resources/voices.py b/src/runwayml/resources/voices.py index 39da22a..282fe06 100644 --- a/src/runwayml/resources/voices.py +++ b/src/runwayml/resources/voices.py @@ -7,7 +7,7 @@ import httpx -from ..types import voice_list_params, voice_create_params, voice_preview_params +from ..types import voice_list_params, voice_create_params, voice_update_params, voice_preview_params from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property @@ -22,6 +22,7 @@ from .._base_client import AsyncPaginator, make_request_options from ..types.voice_list_response import VoiceListResponse from ..types.voice_create_response import VoiceCreateResponse +from ..types.voice_update_response import VoiceUpdateResponse from ..types.voice_preview_response import VoicePreviewResponse from ..types.voice_retrieve_response import VoiceRetrieveResponse @@ -132,6 +133,57 @@ def retrieve( ), ) + def update( + self, + id: str, + *, + description: Optional[str] | Omit = omit, + name: str | Omit = omit, + # 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, + ) -> VoiceUpdateResponse: + """ + Update the name and/or description of a custom voice. + + Args: + description: An optional description of the voice. + + name: A name for the voice. + + 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 + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return cast( + VoiceUpdateResponse, + self._patch( + path_template("/v1/voices/{id}", id=id), + body=maybe_transform( + { + "description": description, + "name": name, + }, + voice_update_params.VoiceUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast( + Any, VoiceUpdateResponse + ), # Union types cannot be passed in as arguments in the type system + ), + ) + def list( self, *, @@ -366,6 +418,57 @@ async def retrieve( ), ) + async def update( + self, + id: str, + *, + description: Optional[str] | Omit = omit, + name: str | Omit = omit, + # 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, + ) -> VoiceUpdateResponse: + """ + Update the name and/or description of a custom voice. + + Args: + description: An optional description of the voice. + + name: A name for the voice. + + 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 + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return cast( + VoiceUpdateResponse, + await self._patch( + path_template("/v1/voices/{id}", id=id), + body=await async_maybe_transform( + { + "description": description, + "name": name, + }, + voice_update_params.VoiceUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast( + Any, VoiceUpdateResponse + ), # Union types cannot be passed in as arguments in the type system + ), + ) + def list( self, *, @@ -506,6 +609,9 @@ def __init__(self, voices: VoicesResource) -> None: self.retrieve = to_raw_response_wrapper( voices.retrieve, ) + self.update = to_raw_response_wrapper( + voices.update, + ) self.list = to_raw_response_wrapper( voices.list, ) @@ -527,6 +633,9 @@ def __init__(self, voices: AsyncVoicesResource) -> None: self.retrieve = async_to_raw_response_wrapper( voices.retrieve, ) + self.update = async_to_raw_response_wrapper( + voices.update, + ) self.list = async_to_raw_response_wrapper( voices.list, ) @@ -548,6 +657,9 @@ def __init__(self, voices: VoicesResource) -> None: self.retrieve = to_streamed_response_wrapper( voices.retrieve, ) + self.update = to_streamed_response_wrapper( + voices.update, + ) self.list = to_streamed_response_wrapper( voices.list, ) @@ -569,6 +681,9 @@ def __init__(self, voices: AsyncVoicesResource) -> None: self.retrieve = async_to_streamed_response_wrapper( voices.retrieve, ) + self.update = async_to_streamed_response_wrapper( + voices.update, + ) self.list = async_to_streamed_response_wrapper( voices.list, ) diff --git a/src/runwayml/types/__init__.py b/src/runwayml/types/__init__.py index 411b3fa..dc527e6 100644 --- a/src/runwayml/types/__init__.py +++ b/src/runwayml/types/__init__.py @@ -6,6 +6,7 @@ from .avatar_list_params import AvatarListParams as AvatarListParams from .voice_create_params import VoiceCreateParams as VoiceCreateParams from .voice_list_response import VoiceListResponse as VoiceListResponse +from .voice_update_params import VoiceUpdateParams as VoiceUpdateParams from .workflow_run_params import WorkflowRunParams as WorkflowRunParams from .avatar_create_params import AvatarCreateParams as AvatarCreateParams from .avatar_list_response import AvatarListResponse as AvatarListResponse @@ -13,6 +14,7 @@ from .document_list_params import DocumentListParams as DocumentListParams from .voice_preview_params import VoicePreviewParams as VoicePreviewParams from .voice_create_response import VoiceCreateResponse as VoiceCreateResponse +from .voice_update_response import VoiceUpdateResponse as VoiceUpdateResponse from .workflow_run_response import WorkflowRunResponse as WorkflowRunResponse from .avatar_create_response import AvatarCreateResponse as AvatarCreateResponse from .avatar_update_response import AvatarUpdateResponse as AvatarUpdateResponse @@ -22,9 +24,11 @@ from .task_retrieve_response import TaskRetrieveResponse as TaskRetrieveResponse from .voice_preview_response import VoicePreviewResponse as VoicePreviewResponse from .workflow_list_response import WorkflowListResponse as WorkflowListResponse +from .avatar_get_usage_params import AvatarGetUsageParams as AvatarGetUsageParams from .voice_retrieve_response import VoiceRetrieveResponse as VoiceRetrieveResponse from .avatar_retrieve_response import AvatarRetrieveResponse as AvatarRetrieveResponse from .document_create_response import DocumentCreateResponse as DocumentCreateResponse +from .avatar_get_usage_response import AvatarGetUsageResponse as AvatarGetUsageResponse from .avatar_video_create_params import AvatarVideoCreateParams as AvatarVideoCreateParams from .document_retrieve_response import DocumentRetrieveResponse as DocumentRetrieveResponse from .sound_effect_create_params import SoundEffectCreateParams as SoundEffectCreateParams @@ -49,13 +53,18 @@ from .speech_to_speech_create_params import SpeechToSpeechCreateParams as SpeechToSpeechCreateParams from .text_to_speech_create_response import TextToSpeechCreateResponse as TextToSpeechCreateResponse from .video_to_video_create_response import VideoToVideoCreateResponse as VideoToVideoCreateResponse +from .avatar_conversation_list_params import AvatarConversationListParams as AvatarConversationListParams from .voice_isolation_create_response import VoiceIsolationCreateResponse as VoiceIsolationCreateResponse from .realtime_session_create_response import RealtimeSessionCreateResponse as RealtimeSessionCreateResponse from .speech_to_speech_create_response import SpeechToSpeechCreateResponse as SpeechToSpeechCreateResponse +from .avatar_conversation_list_response import AvatarConversationListResponse as AvatarConversationListResponse from .organization_retrieve_usage_params import OrganizationRetrieveUsageParams as OrganizationRetrieveUsageParams from .realtime_session_retrieve_response import RealtimeSessionRetrieveResponse as RealtimeSessionRetrieveResponse from .character_performance_create_params import CharacterPerformanceCreateParams as CharacterPerformanceCreateParams from .organization_retrieve_usage_response import OrganizationRetrieveUsageResponse as OrganizationRetrieveUsageResponse +from .avatar_conversation_retrieve_response import ( + AvatarConversationRetrieveResponse as AvatarConversationRetrieveResponse, +) from .character_performance_create_response import ( CharacterPerformanceCreateResponse as CharacterPerformanceCreateResponse, ) diff --git a/src/runwayml/types/avatar_conversation_list_params.py b/src/runwayml/types/avatar_conversation_list_params.py new file mode 100644 index 0000000..27f25d2 --- /dev/null +++ b/src/runwayml/types/avatar_conversation_list_params.py @@ -0,0 +1,28 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union +from datetime import datetime +from typing_extensions import Required, Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["AvatarConversationListParams"] + + +class AvatarConversationListParams(TypedDict, total=False): + limit: Required[int] + """The maximum number of items to return per page.""" + + avatar: str + """Filter to conversations that used the given custom avatar.""" + + cursor: str + """Cursor from a previous response for fetching the next page of results.""" + + end_date: Annotated[Union[str, datetime], PropertyInfo(alias="endDate", format="iso8601")] + """Filter conversations created before this timestamp (exclusive).""" + + start_date: Annotated[Union[str, datetime], PropertyInfo(alias="startDate", format="iso8601")] + """Filter conversations created on or after this timestamp (inclusive).""" diff --git a/src/runwayml/types/avatar_conversation_list_response.py b/src/runwayml/types/avatar_conversation_list_response.py new file mode 100644 index 0000000..d4233da --- /dev/null +++ b/src/runwayml/types/avatar_conversation_list_response.py @@ -0,0 +1,71 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Union, Optional +from datetime import datetime +from typing_extensions import Literal, Annotated, TypeAlias + +from pydantic import Field as FieldInfo + +from .._utils import PropertyInfo +from .._models import BaseModel + +__all__ = ["AvatarConversationListResponse", "Avatar", "AvatarRunwayPreset", "AvatarCustom"] + + +class AvatarRunwayPreset(BaseModel): + """A preset avatar.""" + + name: str + """The preset avatar's display name (e.g. "Mina").""" + + preset_id: str = FieldInfo(alias="presetId") + """The preset avatar ID.""" + + type: Literal["runway-preset"] + + +class AvatarCustom(BaseModel): + """A custom avatar created by the user.""" + + id: Optional[str] = None + """The custom avatar ID, or null if deleted.""" + + name: Optional[str] = None + """The avatar's configured name, or null if unavailable.""" + + type: Literal["custom"] + + +Avatar: TypeAlias = Annotated[Union[AvatarRunwayPreset, AvatarCustom, None], PropertyInfo(discriminator="type")] + + +class AvatarConversationListResponse(BaseModel): + """Summary of a conversation for list responses.""" + + id: str + """Unique conversation identifier. + + This is the same value as the realtime session ID for the call. + """ + + avatar: Optional[Avatar] = None + """The avatar used in this conversation.""" + + created_at: datetime = FieldInfo(alias="createdAt") + """When the conversation was created.""" + + duration: Optional[int] = None + """Duration of the conversation in seconds, or null if not started.""" + + has_tools: bool = FieldInfo(alias="hasTools") + """Whether tools were configured for this conversation session.""" + + name: str + """Conversation name (auto-generated or user-provided).""" + + status: Literal["in_progress", "ended", "failed"] + """The status of the conversation. + + `in_progress` means the session is active, `ended` means it completed + successfully, `failed` means it ended due to an error. + """ diff --git a/src/runwayml/types/avatar_conversation_retrieve_response.py b/src/runwayml/types/avatar_conversation_retrieve_response.py new file mode 100644 index 0000000..aa27777 --- /dev/null +++ b/src/runwayml/types/avatar_conversation_retrieve_response.py @@ -0,0 +1,496 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, List, Union, Optional +from datetime import datetime +from typing_extensions import Literal, Annotated, TypeAlias + +from pydantic import Field as FieldInfo + +from .._utils import PropertyInfo +from .._models import BaseModel + +__all__ = [ + "AvatarConversationRetrieveResponse", + "InProgress", + "InProgressAvatar", + "InProgressAvatarRunwayPreset", + "InProgressAvatarCustom", + "InProgressTool", + "InProgressTranscript", + "InProgressTranscriptToolCall", + "InProgressTranscriptToolResult", + "Ended", + "EndedAvatar", + "EndedAvatarRunwayPreset", + "EndedAvatarCustom", + "EndedTool", + "EndedTranscript", + "EndedTranscriptToolCall", + "EndedTranscriptToolResult", + "Failed", + "FailedAvatar", + "FailedAvatarRunwayPreset", + "FailedAvatarCustom", + "FailedTool", + "FailedTranscript", + "FailedTranscriptToolCall", + "FailedTranscriptToolResult", +] + + +class InProgressAvatarRunwayPreset(BaseModel): + """A preset avatar.""" + + preset_id: str = FieldInfo(alias="presetId") + """The preset avatar ID.""" + + type: Literal["runway-preset"] + + +class InProgressAvatarCustom(BaseModel): + """A custom avatar created by the user.""" + + id: Optional[str] = None + """The custom avatar ID, or null if deleted.""" + + image_url: Optional[str] = FieldInfo(alias="imageUrl", default=None) + """URL to the avatar image, or null if unavailable.""" + + name: Optional[str] = None + """The avatar name, or null if unavailable.""" + + type: Literal["custom"] + + +InProgressAvatar: TypeAlias = Annotated[ + Union[InProgressAvatarRunwayPreset, InProgressAvatarCustom, None], PropertyInfo(discriminator="type") +] + + +class InProgressTool(BaseModel): + """Summary of a tool configured for the session.""" + + description: str + """A description of when and how the tool should be used.""" + + name: str + """The tool name.""" + + type: Literal["client_event", "backend_rpc"] + """The tool type.""" + + +class InProgressTranscriptToolCall(BaseModel): + """A tool invocation by the assistant.""" + + arguments: Dict[str, object] + """The arguments passed to the tool.""" + + name: str + """The name of the tool that was called.""" + + id: Optional[str] = None + """Optional identifier linking this call to its result.""" + + +class InProgressTranscriptToolResult(BaseModel): + """The result of a tool invocation.""" + + name: str + """The name of the tool that returned a result.""" + + id: Optional[str] = None + """Optional identifier linking this result to its call.""" + + duration_ms: Optional[float] = FieldInfo(alias="durationMs", default=None) + """How long the tool call took in milliseconds.""" + + error: Optional[str] = None + """Error message if the tool call failed.""" + + result: Union[Dict[str, object], str, None] = None + """The tool result (object, string, or null).""" + + +class InProgressTranscript(BaseModel): + """A single entry in the conversation transcript.""" + + content: Optional[str] = None + """The spoken text, or null for tool-only turns.""" + + role: Literal["user", "assistant"] + """Who produced this transcript entry.""" + + timestamp: Optional[datetime] = None + """When this entry occurred, or null if unavailable.""" + + tool_calls: Optional[List[InProgressTranscriptToolCall]] = FieldInfo(alias="toolCalls", default=None) + """Tool invocations made during this assistant turn. + + Only present on assistant entries. + """ + + tool_results: Optional[List[InProgressTranscriptToolResult]] = FieldInfo(alias="toolResults", default=None) + """Tool results received during this assistant turn. + + Only present on assistant entries. + """ + + +class InProgress(BaseModel): + """A conversation that is currently active.""" + + id: str + """Unique conversation identifier. + + This is the same value as the realtime session ID for the call. + """ + + avatar: Optional[InProgressAvatar] = None + """The avatar used in this conversation.""" + + created_at: datetime = FieldInfo(alias="createdAt") + """When the conversation was created.""" + + duration: Optional[int] = None + """Elapsed duration in seconds, or null if not yet started.""" + + max_duration: Optional[int] = FieldInfo(alias="maxDuration", default=None) + """Maximum allowed duration in seconds, or null if not set.""" + + name: str + """Conversation name.""" + + recording_url: Optional[str] = FieldInfo(alias="recordingUrl", default=None) + """ + A URL to download the conversation recording, or null if no recording is + available. This URL will expire within 24-48 hours, fetch the conversation again + to get a fresh download URL. + """ + + started_at: Optional[datetime] = FieldInfo(alias="startedAt", default=None) + """When the conversation started, or null if not yet started.""" + + status: Literal["in_progress"] + + tools: List[InProgressTool] + """The tools that were configured for this conversation session. + + Empty if no tools were used. + """ + + transcript: List[InProgressTranscript] + """The conversation transcript.""" + + +class EndedAvatarRunwayPreset(BaseModel): + """A preset avatar.""" + + preset_id: str = FieldInfo(alias="presetId") + """The preset avatar ID.""" + + type: Literal["runway-preset"] + + +class EndedAvatarCustom(BaseModel): + """A custom avatar created by the user.""" + + id: Optional[str] = None + """The custom avatar ID, or null if deleted.""" + + image_url: Optional[str] = FieldInfo(alias="imageUrl", default=None) + """URL to the avatar image, or null if unavailable.""" + + name: Optional[str] = None + """The avatar name, or null if unavailable.""" + + type: Literal["custom"] + + +EndedAvatar: TypeAlias = Annotated[ + Union[EndedAvatarRunwayPreset, EndedAvatarCustom, None], PropertyInfo(discriminator="type") +] + + +class EndedTool(BaseModel): + """Summary of a tool configured for the session.""" + + description: str + """A description of when and how the tool should be used.""" + + name: str + """The tool name.""" + + type: Literal["client_event", "backend_rpc"] + """The tool type.""" + + +class EndedTranscriptToolCall(BaseModel): + """A tool invocation by the assistant.""" + + arguments: Dict[str, object] + """The arguments passed to the tool.""" + + name: str + """The name of the tool that was called.""" + + id: Optional[str] = None + """Optional identifier linking this call to its result.""" + + +class EndedTranscriptToolResult(BaseModel): + """The result of a tool invocation.""" + + name: str + """The name of the tool that returned a result.""" + + id: Optional[str] = None + """Optional identifier linking this result to its call.""" + + duration_ms: Optional[float] = FieldInfo(alias="durationMs", default=None) + """How long the tool call took in milliseconds.""" + + error: Optional[str] = None + """Error message if the tool call failed.""" + + result: Union[Dict[str, object], str, None] = None + """The tool result (object, string, or null).""" + + +class EndedTranscript(BaseModel): + """A single entry in the conversation transcript.""" + + content: Optional[str] = None + """The spoken text, or null for tool-only turns.""" + + role: Literal["user", "assistant"] + """Who produced this transcript entry.""" + + timestamp: Optional[datetime] = None + """When this entry occurred, or null if unavailable.""" + + tool_calls: Optional[List[EndedTranscriptToolCall]] = FieldInfo(alias="toolCalls", default=None) + """Tool invocations made during this assistant turn. + + Only present on assistant entries. + """ + + tool_results: Optional[List[EndedTranscriptToolResult]] = FieldInfo(alias="toolResults", default=None) + """Tool results received during this assistant turn. + + Only present on assistant entries. + """ + + +class Ended(BaseModel): + """A conversation that completed successfully.""" + + id: str + """Unique conversation identifier. + + This is the same value as the realtime session ID for the call. + """ + + avatar: Optional[EndedAvatar] = None + """The avatar used in this conversation.""" + + created_at: datetime = FieldInfo(alias="createdAt") + """When the conversation was created.""" + + duration: Optional[int] = None + """Duration of the conversation in seconds.""" + + ended_at: Optional[datetime] = FieldInfo(alias="endedAt", default=None) + """When the conversation ended.""" + + max_duration: Optional[int] = FieldInfo(alias="maxDuration", default=None) + """Maximum allowed duration in seconds, or null if not set.""" + + name: str + """Conversation name.""" + + recording_url: Optional[str] = FieldInfo(alias="recordingUrl", default=None) + """ + A URL to download the conversation recording, or null if no recording is + available. This URL will expire within 24-48 hours, fetch the conversation again + to get a fresh download URL. + """ + + started_at: Optional[datetime] = FieldInfo(alias="startedAt", default=None) + """When the conversation started.""" + + status: Literal["ended"] + + tools: List[EndedTool] + """The tools that were configured for this conversation session. + + Empty if no tools were used. + """ + + transcript: List[EndedTranscript] + """The conversation transcript.""" + + +class FailedAvatarRunwayPreset(BaseModel): + """A preset avatar.""" + + preset_id: str = FieldInfo(alias="presetId") + """The preset avatar ID.""" + + type: Literal["runway-preset"] + + +class FailedAvatarCustom(BaseModel): + """A custom avatar created by the user.""" + + id: Optional[str] = None + """The custom avatar ID, or null if deleted.""" + + image_url: Optional[str] = FieldInfo(alias="imageUrl", default=None) + """URL to the avatar image, or null if unavailable.""" + + name: Optional[str] = None + """The avatar name, or null if unavailable.""" + + type: Literal["custom"] + + +FailedAvatar: TypeAlias = Annotated[ + Union[FailedAvatarRunwayPreset, FailedAvatarCustom, None], PropertyInfo(discriminator="type") +] + + +class FailedTool(BaseModel): + """Summary of a tool configured for the session.""" + + description: str + """A description of when and how the tool should be used.""" + + name: str + """The tool name.""" + + type: Literal["client_event", "backend_rpc"] + """The tool type.""" + + +class FailedTranscriptToolCall(BaseModel): + """A tool invocation by the assistant.""" + + arguments: Dict[str, object] + """The arguments passed to the tool.""" + + name: str + """The name of the tool that was called.""" + + id: Optional[str] = None + """Optional identifier linking this call to its result.""" + + +class FailedTranscriptToolResult(BaseModel): + """The result of a tool invocation.""" + + name: str + """The name of the tool that returned a result.""" + + id: Optional[str] = None + """Optional identifier linking this result to its call.""" + + duration_ms: Optional[float] = FieldInfo(alias="durationMs", default=None) + """How long the tool call took in milliseconds.""" + + error: Optional[str] = None + """Error message if the tool call failed.""" + + result: Union[Dict[str, object], str, None] = None + """The tool result (object, string, or null).""" + + +class FailedTranscript(BaseModel): + """A single entry in the conversation transcript.""" + + content: Optional[str] = None + """The spoken text, or null for tool-only turns.""" + + role: Literal["user", "assistant"] + """Who produced this transcript entry.""" + + timestamp: Optional[datetime] = None + """When this entry occurred, or null if unavailable.""" + + tool_calls: Optional[List[FailedTranscriptToolCall]] = FieldInfo(alias="toolCalls", default=None) + """Tool invocations made during this assistant turn. + + Only present on assistant entries. + """ + + tool_results: Optional[List[FailedTranscriptToolResult]] = FieldInfo(alias="toolResults", default=None) + """Tool results received during this assistant turn. + + Only present on assistant entries. + """ + + +class Failed(BaseModel): + """A conversation that ended due to an error.""" + + id: str + """Unique conversation identifier. + + This is the same value as the realtime session ID for the call. + """ + + avatar: Optional[FailedAvatar] = None + """The avatar used in this conversation.""" + + created_at: datetime = FieldInfo(alias="createdAt") + """When the conversation was created.""" + + duration: Optional[int] = None + """Duration in seconds, or null if the conversation failed before starting.""" + + ended_at: Optional[datetime] = FieldInfo(alias="endedAt", default=None) + """When the conversation ended, or null if it failed before starting.""" + + failure: str + """A human-friendly reason for the failure. + + We do not recommend returning this to users directly without adding context. + """ + + failure_code: str = FieldInfo(alias="failureCode") + """A machine-readable error code for the failure. + + See https://docs.dev.runwayml.com/errors/task-failures/ for more information. + """ + + max_duration: Optional[int] = FieldInfo(alias="maxDuration", default=None) + """Maximum allowed duration in seconds, or null if not set.""" + + name: str + """Conversation name.""" + + recording_url: Optional[str] = FieldInfo(alias="recordingUrl", default=None) + """ + A URL to download the conversation recording, or null if no recording is + available. This URL will expire within 24-48 hours, fetch the conversation again + to get a fresh download URL. + """ + + started_at: Optional[datetime] = FieldInfo(alias="startedAt", default=None) + """When the conversation started, or null if it failed before starting.""" + + status: Literal["failed"] + + tools: List[FailedTool] + """The tools that were configured for this conversation session. + + Empty if no tools were used. + """ + + transcript: List[FailedTranscript] + """The conversation transcript.""" + + +AvatarConversationRetrieveResponse: TypeAlias = Annotated[ + Union[InProgress, Ended, Failed], PropertyInfo(discriminator="status") +] diff --git a/src/runwayml/types/avatar_get_usage_params.py b/src/runwayml/types/avatar_get_usage_params.py new file mode 100644 index 0000000..0bdacd8 --- /dev/null +++ b/src/runwayml/types/avatar_get_usage_params.py @@ -0,0 +1,19 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union +from datetime import datetime +from typing_extensions import Required, Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["AvatarGetUsageParams"] + + +class AvatarGetUsageParams(TypedDict, total=False): + end_date: Required[Annotated[Union[str, datetime], PropertyInfo(alias="endDate", format="iso8601")]] + """End of the date range in UTC (exclusive). Required.""" + + start_date: Required[Annotated[Union[str, datetime], PropertyInfo(alias="startDate", format="iso8601")]] + """Start of the date range in UTC (inclusive). Required.""" diff --git a/src/runwayml/types/avatar_get_usage_response.py b/src/runwayml/types/avatar_get_usage_response.py new file mode 100644 index 0000000..80129fe --- /dev/null +++ b/src/runwayml/types/avatar_get_usage_response.py @@ -0,0 +1,45 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import datetime +from typing import List + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["AvatarGetUsageResponse", "ByDay"] + + +class ByDay(BaseModel): + date: datetime.date + """The UTC calendar date (YYYY-MM-DD).""" + + seconds: int + """Total seconds of measured conversation duration on this date.""" + + sessions: int + """Number of conversations started on this date.""" + + +class AvatarGetUsageResponse(BaseModel): + avg_duration_seconds: int = FieldInfo(alias="avgDurationSeconds") + """ + Average duration in seconds across conversations with a measured duration, or 0 + if none completed. May not equal `totalSeconds / totalSessions` because + unfinished conversations contribute to the session count but not the duration. + """ + + by_day: List[ByDay] = FieldInfo(alias="byDay") + """Per-day usage across the date range. + + Days with no sessions are included with zeroes. + """ + + total_seconds: int = FieldInfo(alias="totalSeconds") + """Total seconds across conversations with a measured duration in the date range.""" + + total_sessions: int = FieldInfo(alias="totalSessions") + """Number of conversations started in the date range. + + Includes unfinished and failed conversations. + """ diff --git a/src/runwayml/types/image_to_video_create_params.py b/src/runwayml/types/image_to_video_create_params.py index 6ec1f88..35e3da8 100644 --- a/src/runwayml/types/image_to_video_create_params.py +++ b/src/runwayml/types/image_to_video_create_params.py @@ -17,9 +17,6 @@ "Gen4TurboContentModeration", "Veo3_1", "Veo3_1PromptImagePromptImage", - "Gen3aTurbo", - "Gen3aTurboPromptImagePromptImage", - "Gen3aTurboContentModeration", "Veo3_1Fast", "Veo3_1FastPromptImagePromptImage", "Happyhorse1_0", @@ -184,60 +181,6 @@ class Veo3_1PromptImagePromptImage(TypedDict, total=False): """A HTTPS URL.""" -class Gen3aTurbo(TypedDict, total=False): - model: Required[Literal["gen3a_turbo"]] - - prompt_image: Required[ - Annotated[Union[str, Iterable[Gen3aTurboPromptImagePromptImage]], PropertyInfo(alias="promptImage")] - ] - """A HTTPS URL.""" - - prompt_text: Required[Annotated[str, PropertyInfo(alias="promptText")]] - """A non-empty string up to 1000 characters (measured in UTF-16 code units). - - This should describe in detail what should appear in the output. - """ - - content_moderation: Annotated[Gen3aTurboContentModeration, PropertyInfo(alias="contentModeration")] - """Settings that affect the behavior of the content moderation system.""" - - duration: Literal[5, 10] - """The duration of the output video in seconds.""" - - ratio: Literal["768:1280", "1280:768"] - """The resolution of the output video.""" - - seed: int - """If unspecified, a random number is chosen. - - Varying the seed integer is a way to get different results for the same other - request parameters. Using the same seed integer for an identical request will - produce similar results. - """ - - -class Gen3aTurboPromptImagePromptImage(TypedDict, total=False): - position: Required[Literal["first", "last"]] - """The position of the image in the output video. - - "first" will use the image as the first frame of the video, "last" will use the - image as the last frame of the video. - """ - - uri: Required[str] - """A HTTPS URL.""" - - -class Gen3aTurboContentModeration(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 Veo3_1Fast(TypedDict, total=False): model: Required[Literal["veo3.1_fast"]] @@ -494,5 +437,5 @@ class Veo3PromptImagePromptImage(TypedDict, total=False): ImageToVideoCreateParams: TypeAlias = Union[ - Gen4_5, Gen4Turbo, Veo3_1, Gen3aTurbo, Veo3_1Fast, Happyhorse1_0, Seedance2, Seedance2Fast, Veo3 + Gen4_5, Gen4Turbo, Veo3_1, Veo3_1Fast, Happyhorse1_0, Seedance2, Seedance2Fast, Veo3 ] diff --git a/src/runwayml/types/organization_retrieve_usage_response.py b/src/runwayml/types/organization_retrieve_usage_response.py index f60e7ae..bea62de 100644 --- a/src/runwayml/types/organization_retrieve_usage_response.py +++ b/src/runwayml/types/organization_retrieve_usage_response.py @@ -56,6 +56,7 @@ class ResultUsedCredit(BaseModel): "klingO3_4k", "happyhorse_1_0", "aleph2", + "product_swap", ] """The model that credits were spent on.""" @@ -111,6 +112,7 @@ class OrganizationRetrieveUsageResponse(BaseModel): "klingO3_4k", "happyhorse_1_0", "aleph2", + "product_swap", ] ] """The list of models with usage during the queried time range.""" diff --git a/src/runwayml/types/video_to_video_create_params.py b/src/runwayml/types/video_to_video_create_params.py index 56d1201..158309d 100644 --- a/src/runwayml/types/video_to_video_create_params.py +++ b/src/runwayml/types/video_to_video_create_params.py @@ -9,18 +9,11 @@ __all__ = [ "VideoToVideoCreateParams", - "Gen4Aleph", - "Gen4AlephContentModeration", - "Gen4AlephReference", - "Aleph2", - "Aleph2ContentModeration", - "Aleph2Keyframe", - "Aleph2KeyframeUnionMember0", - "Aleph2KeyframeUnionMember1", - "Aleph2PromptImage", - "Aleph2PromptImagePosition", - "Aleph2PromptImagePositionTimestampPosition", - "Aleph2PromptImagePositionRelativePosition", + "Variant0", + "Variant0ContentModeration", + "Variant0Keyframe", + "Variant0KeyframeUnionMember0", + "Variant0KeyframeUnionMember1", "Seedance2", "Seedance2ReferenceAudio", "Seedance2Reference", @@ -32,66 +25,7 @@ ] -class Gen4Aleph(TypedDict, total=False): - model: Required[Literal["gen4_aleph"]] - - prompt_text: Required[Annotated[str, PropertyInfo(alias="promptText")]] - """A non-empty string up to 1000 characters (measured in UTF-16 code units). - - This should describe in detail what should appear in the output. - """ - - video_uri: Required[Annotated[str, PropertyInfo(alias="videoUri")]] - """A HTTPS URL.""" - - content_moderation: Annotated[Gen4AlephContentModeration, PropertyInfo(alias="contentModeration")] - """Settings that affect the behavior of the content moderation system.""" - - ratio: Literal["1280:720", "720:1280", "1104:832", "960:960", "832:1104", "1584:672", "848:480", "640:480"] - """Deprecated. - - This field is ignored. The resolution of the output video is determined by the - input video. - """ - - references: Iterable[Gen4AlephReference] - """An array of references. - - Currently up to one reference is supported. See - [our docs](/assets/inputs#images) on image inputs for more information. - """ - - seed: int - """If unspecified, a random number is chosen. - - Varying the seed integer is a way to get different results for the same other - request parameters. Using the same seed integer for an identical request will - produce similar results. - """ - - -class Gen4AlephContentModeration(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 Gen4AlephReference(TypedDict, total=False): - """ - Passing an image reference allows the model to emulate the style or content of the reference in the output. - """ - - type: Required[Literal["image"]] - - uri: Required[str] - """A HTTPS URL.""" - - -class Aleph2(TypedDict, total=False): +class Variant0(TypedDict, total=False): model: Required[Literal["aleph2"]] prompt_text: Required[Annotated[str, PropertyInfo(alias="promptText")]] @@ -103,21 +37,15 @@ class Aleph2(TypedDict, total=False): video_uri: Required[Annotated[str, PropertyInfo(alias="videoUri")]] """A HTTPS URL.""" - content_moderation: Annotated[Aleph2ContentModeration, PropertyInfo(alias="contentModeration")] + content_moderation: Annotated[Variant0ContentModeration, PropertyInfo(alias="contentModeration")] """Settings that affect the behavior of the content moderation system.""" - keyframes: Iterable[Aleph2Keyframe] + keyframes: Iterable[Variant0Keyframe] """Timed guidance images placed at specific points in the input video. Up to 5 keyframes. """ - prompt_image: Annotated[Iterable[Aleph2PromptImage], PropertyInfo(alias="promptImage")] - """ - A list of up to 5 image keyframes for guiding the edit at specific points in the - video. - """ - seed: int """If unspecified, a random number is chosen. @@ -127,7 +55,7 @@ class Aleph2(TypedDict, total=False): """ -class Aleph2ContentModeration(TypedDict, total=False): +class Variant0ContentModeration(TypedDict, total=False): """Settings that affect the behavior of the content moderation system.""" public_figure_threshold: Annotated[Literal["auto", "low"], PropertyInfo(alias="publicFigureThreshold")] @@ -137,7 +65,7 @@ class Aleph2ContentModeration(TypedDict, total=False): """ -class Aleph2KeyframeUnionMember0(TypedDict, total=False): +class Variant0KeyframeUnionMember0(TypedDict, total=False): seconds: Required[float] """ Absolute timestamp in seconds from the start of the input video when this @@ -148,7 +76,7 @@ class Aleph2KeyframeUnionMember0(TypedDict, total=False): """A HTTPS URL.""" -class Aleph2KeyframeUnionMember1(TypedDict, total=False): +class Variant0KeyframeUnionMember1(TypedDict, total=False): at: Required[float] """ Position as a fraction [0.0, 1.0] of the input video duration when this guidance @@ -159,38 +87,7 @@ class Aleph2KeyframeUnionMember1(TypedDict, total=False): """A HTTPS URL.""" -Aleph2Keyframe: TypeAlias = Union[Aleph2KeyframeUnionMember0, Aleph2KeyframeUnionMember1] - - -class Aleph2PromptImagePositionTimestampPosition(TypedDict, total=False): - timestamp_seconds: Required[Annotated[float, PropertyInfo(alias="timestampSeconds")]] - """Absolute timestamp in seconds from the start of the output video.""" - - type: Required[Literal["timestamp"]] - - -class Aleph2PromptImagePositionRelativePosition(TypedDict, total=False): - position_percentage: Required[Annotated[float, PropertyInfo(alias="positionPercentage")]] - """Position as a fraction [0.0, 1.0] of the total video duration.""" - - type: Required[Literal["position"]] - - -Aleph2PromptImagePosition: TypeAlias = Union[ - Literal["first", "last"], Aleph2PromptImagePositionTimestampPosition, Aleph2PromptImagePositionRelativePosition -] - - -class Aleph2PromptImage(TypedDict, total=False): - position: Required[Aleph2PromptImagePosition] - """ - - `first` - Places the image at the start of the output video (timestamp 0). - - `last` - Places the image at the end of the output video (timestamp = - duration). - """ - - uri: Required[str] - """A HTTPS URL.""" +Variant0Keyframe: TypeAlias = Union[Variant0KeyframeUnionMember0, Variant0KeyframeUnionMember1] class Seedance2(TypedDict, total=False): @@ -380,4 +277,4 @@ class Seedance2FastReferenceVideo(TypedDict, total=False): """A HTTPS URL.""" -VideoToVideoCreateParams: TypeAlias = Union[Gen4Aleph, Aleph2, Seedance2, Seedance2Fast] +VideoToVideoCreateParams: TypeAlias = Union[Variant0, Seedance2, Seedance2Fast] diff --git a/src/runwayml/types/voice_update_params.py b/src/runwayml/types/voice_update_params.py new file mode 100644 index 0000000..054d909 --- /dev/null +++ b/src/runwayml/types/voice_update_params.py @@ -0,0 +1,16 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from typing_extensions import TypedDict + +__all__ = ["VoiceUpdateParams"] + + +class VoiceUpdateParams(TypedDict, total=False): + description: Optional[str] + """An optional description of the voice.""" + + name: str + """A name for the voice.""" diff --git a/src/runwayml/types/voice_update_response.py b/src/runwayml/types/voice_update_response.py new file mode 100644 index 0000000..ee4a07c --- /dev/null +++ b/src/runwayml/types/voice_update_response.py @@ -0,0 +1,81 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Union, Optional +from datetime import datetime +from typing_extensions import Literal, Annotated, TypeAlias + +from pydantic import Field as FieldInfo + +from .._utils import PropertyInfo +from .._models import BaseModel + +__all__ = ["VoiceUpdateResponse", "Processing", "Ready", "Failed"] + + +class Processing(BaseModel): + """A voice that is still being processed.""" + + id: str + """The unique identifier of the voice.""" + + created_at: datetime = FieldInfo(alias="createdAt") + """When the voice was created.""" + + description: Optional[str] = None + """A description of the voice, or null if not set.""" + + name: str + """The name of the voice.""" + + status: Literal["PROCESSING"] + + +class Ready(BaseModel): + """A voice that is ready for use.""" + + id: str + """The unique identifier of the voice.""" + + created_at: datetime = FieldInfo(alias="createdAt") + """When the voice was created.""" + + description: Optional[str] = None + """A description of the voice, or null if not set.""" + + name: str + """The name of the voice.""" + + preview_url: Optional[str] = FieldInfo(alias="previewUrl", default=None) + """ + A signed URL to an MP3 audio sample of the voice, or null if no sample is + available. + """ + + status: Literal["READY"] + + +class Failed(BaseModel): + """A voice that failed to finish processing.""" + + id: str + """The unique identifier of the voice.""" + + created_at: datetime = FieldInfo(alias="createdAt") + """When the voice was created.""" + + description: Optional[str] = None + """A description of the voice, or null if not set.""" + + failure_reason: str = FieldInfo(alias="failureReason") + """A human-readable error message. + + This value is not stable and should not be matched against programmatically. + """ + + name: str + """The name of the voice.""" + + status: Literal["FAILED"] + + +VoiceUpdateResponse: TypeAlias = Annotated[Union[Processing, Ready, Failed], PropertyInfo(discriminator="status")] diff --git a/tests/api_resources/test_avatar_conversations.py b/tests/api_resources/test_avatar_conversations.py new file mode 100644 index 0000000..0c34472 --- /dev/null +++ b/tests/api_resources/test_avatar_conversations.py @@ -0,0 +1,265 @@ +# 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 import ( + AvatarConversationListResponse, + AvatarConversationRetrieveResponse, +) +from runwayml._utils import parse_datetime +from runwayml.pagination import SyncCursorPage, AsyncCursorPage + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestAvatarConversations: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_retrieve(self, client: RunwayML) -> None: + avatar_conversation = client.avatar_conversations.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(AvatarConversationRetrieveResponse, avatar_conversation, path=["response"]) + + @parametrize + def test_raw_response_retrieve(self, client: RunwayML) -> None: + response = client.avatar_conversations.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + avatar_conversation = response.parse() + assert_matches_type(AvatarConversationRetrieveResponse, avatar_conversation, path=["response"]) + + @parametrize + def test_streaming_response_retrieve(self, client: RunwayML) -> None: + with client.avatar_conversations.with_streaming_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + avatar_conversation = response.parse() + assert_matches_type(AvatarConversationRetrieveResponse, avatar_conversation, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_retrieve(self, client: RunwayML) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.avatar_conversations.with_raw_response.retrieve( + "", + ) + + @parametrize + def test_method_list(self, client: RunwayML) -> None: + avatar_conversation = client.avatar_conversations.list( + limit=1, + ) + assert_matches_type(SyncCursorPage[AvatarConversationListResponse], avatar_conversation, path=["response"]) + + @parametrize + def test_method_list_with_all_params(self, client: RunwayML) -> None: + avatar_conversation = client.avatar_conversations.list( + limit=1, + avatar="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + cursor="x", + end_date=parse_datetime("2019-12-27T18:11:19.117Z"), + start_date=parse_datetime("2019-12-27T18:11:19.117Z"), + ) + assert_matches_type(SyncCursorPage[AvatarConversationListResponse], avatar_conversation, path=["response"]) + + @parametrize + def test_raw_response_list(self, client: RunwayML) -> None: + response = client.avatar_conversations.with_raw_response.list( + limit=1, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + avatar_conversation = response.parse() + assert_matches_type(SyncCursorPage[AvatarConversationListResponse], avatar_conversation, path=["response"]) + + @parametrize + def test_streaming_response_list(self, client: RunwayML) -> None: + with client.avatar_conversations.with_streaming_response.list( + limit=1, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + avatar_conversation = response.parse() + assert_matches_type(SyncCursorPage[AvatarConversationListResponse], avatar_conversation, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_delete(self, client: RunwayML) -> None: + avatar_conversation = client.avatar_conversations.delete( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert avatar_conversation is None + + @parametrize + def test_raw_response_delete(self, client: RunwayML) -> None: + response = client.avatar_conversations.with_raw_response.delete( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + avatar_conversation = response.parse() + assert avatar_conversation is None + + @parametrize + def test_streaming_response_delete(self, client: RunwayML) -> None: + with client.avatar_conversations.with_streaming_response.delete( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + avatar_conversation = response.parse() + assert avatar_conversation is None + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_delete(self, client: RunwayML) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.avatar_conversations.with_raw_response.delete( + "", + ) + + +class TestAsyncAvatarConversations: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_retrieve(self, async_client: AsyncRunwayML) -> None: + avatar_conversation = await async_client.avatar_conversations.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(AvatarConversationRetrieveResponse, avatar_conversation, path=["response"]) + + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncRunwayML) -> None: + response = await async_client.avatar_conversations.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + avatar_conversation = await response.parse() + assert_matches_type(AvatarConversationRetrieveResponse, avatar_conversation, path=["response"]) + + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncRunwayML) -> None: + async with async_client.avatar_conversations.with_streaming_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + avatar_conversation = await response.parse() + assert_matches_type(AvatarConversationRetrieveResponse, avatar_conversation, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_retrieve(self, async_client: AsyncRunwayML) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.avatar_conversations.with_raw_response.retrieve( + "", + ) + + @parametrize + async def test_method_list(self, async_client: AsyncRunwayML) -> None: + avatar_conversation = await async_client.avatar_conversations.list( + limit=1, + ) + assert_matches_type(AsyncCursorPage[AvatarConversationListResponse], avatar_conversation, path=["response"]) + + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncRunwayML) -> None: + avatar_conversation = await async_client.avatar_conversations.list( + limit=1, + avatar="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + cursor="x", + end_date=parse_datetime("2019-12-27T18:11:19.117Z"), + start_date=parse_datetime("2019-12-27T18:11:19.117Z"), + ) + assert_matches_type(AsyncCursorPage[AvatarConversationListResponse], avatar_conversation, path=["response"]) + + @parametrize + async def test_raw_response_list(self, async_client: AsyncRunwayML) -> None: + response = await async_client.avatar_conversations.with_raw_response.list( + limit=1, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + avatar_conversation = await response.parse() + assert_matches_type(AsyncCursorPage[AvatarConversationListResponse], avatar_conversation, path=["response"]) + + @parametrize + async def test_streaming_response_list(self, async_client: AsyncRunwayML) -> None: + async with async_client.avatar_conversations.with_streaming_response.list( + limit=1, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + avatar_conversation = await response.parse() + assert_matches_type(AsyncCursorPage[AvatarConversationListResponse], avatar_conversation, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_delete(self, async_client: AsyncRunwayML) -> None: + avatar_conversation = await async_client.avatar_conversations.delete( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert avatar_conversation is None + + @parametrize + async def test_raw_response_delete(self, async_client: AsyncRunwayML) -> None: + response = await async_client.avatar_conversations.with_raw_response.delete( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + avatar_conversation = await response.parse() + assert avatar_conversation is None + + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncRunwayML) -> None: + async with async_client.avatar_conversations.with_streaming_response.delete( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + avatar_conversation = await response.parse() + assert avatar_conversation is None + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_delete(self, async_client: AsyncRunwayML) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.avatar_conversations.with_raw_response.delete( + "", + ) diff --git a/tests/api_resources/test_avatars.py b/tests/api_resources/test_avatars.py index 3ba4a33..f145df0 100644 --- a/tests/api_resources/test_avatars.py +++ b/tests/api_resources/test_avatars.py @@ -13,8 +13,10 @@ AvatarListResponse, AvatarCreateResponse, AvatarUpdateResponse, + AvatarGetUsageResponse, AvatarRetrieveResponse, ) +from runwayml._utils import parse_datetime from runwayml.pagination import SyncCursorPage, AsyncCursorPage base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -258,6 +260,40 @@ def test_path_params_delete(self, client: RunwayML) -> None: "", ) + @parametrize + def test_method_get_usage(self, client: RunwayML) -> None: + avatar = client.avatars.get_usage( + end_date=parse_datetime("2019-12-27T18:11:19.117Z"), + start_date=parse_datetime("2019-12-27T18:11:19.117Z"), + ) + assert_matches_type(AvatarGetUsageResponse, avatar, path=["response"]) + + @parametrize + def test_raw_response_get_usage(self, client: RunwayML) -> None: + response = client.avatars.with_raw_response.get_usage( + end_date=parse_datetime("2019-12-27T18:11:19.117Z"), + start_date=parse_datetime("2019-12-27T18:11:19.117Z"), + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + avatar = response.parse() + assert_matches_type(AvatarGetUsageResponse, avatar, path=["response"]) + + @parametrize + def test_streaming_response_get_usage(self, client: RunwayML) -> None: + with client.avatars.with_streaming_response.get_usage( + end_date=parse_datetime("2019-12-27T18:11:19.117Z"), + start_date=parse_datetime("2019-12-27T18:11:19.117Z"), + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + avatar = response.parse() + assert_matches_type(AvatarGetUsageResponse, avatar, path=["response"]) + + assert cast(Any, response.is_closed) is True + class TestAsyncAvatars: parametrize = pytest.mark.parametrize( @@ -498,3 +534,37 @@ async def test_path_params_delete(self, async_client: AsyncRunwayML) -> None: await async_client.avatars.with_raw_response.delete( "", ) + + @parametrize + async def test_method_get_usage(self, async_client: AsyncRunwayML) -> None: + avatar = await async_client.avatars.get_usage( + end_date=parse_datetime("2019-12-27T18:11:19.117Z"), + start_date=parse_datetime("2019-12-27T18:11:19.117Z"), + ) + assert_matches_type(AvatarGetUsageResponse, avatar, path=["response"]) + + @parametrize + async def test_raw_response_get_usage(self, async_client: AsyncRunwayML) -> None: + response = await async_client.avatars.with_raw_response.get_usage( + end_date=parse_datetime("2019-12-27T18:11:19.117Z"), + start_date=parse_datetime("2019-12-27T18:11:19.117Z"), + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + avatar = await response.parse() + assert_matches_type(AvatarGetUsageResponse, avatar, path=["response"]) + + @parametrize + async def test_streaming_response_get_usage(self, async_client: AsyncRunwayML) -> None: + async with async_client.avatars.with_streaming_response.get_usage( + end_date=parse_datetime("2019-12-27T18:11:19.117Z"), + start_date=parse_datetime("2019-12-27T18:11:19.117Z"), + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + avatar = await response.parse() + assert_matches_type(AvatarGetUsageResponse, avatar, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_image_to_video.py b/tests/api_resources/test_image_to_video.py index b51e440..7b32f2c 100644 --- a/tests/api_resources/test_image_to_video.py +++ b/tests/api_resources/test_image_to_video.py @@ -174,56 +174,6 @@ def test_streaming_response_create_overload_3(self, client: RunwayML) -> None: @parametrize def test_method_create_overload_4(self, client: RunwayML) -> None: - image_to_video = client.image_to_video.create( - model="gen3a_turbo", - prompt_image="https://example.com/file", - prompt_text="A beautiful sunset over a calm ocean.", - ) - assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) - - @parametrize - def test_method_create_with_all_params_overload_4(self, client: RunwayML) -> None: - image_to_video = client.image_to_video.create( - model="gen3a_turbo", - prompt_image="https://example.com/file", - prompt_text="A beautiful sunset over a calm ocean.", - content_moderation={"public_figure_threshold": "auto"}, - duration=5, - ratio="1280:768", - seed=0, - ) - assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) - - @parametrize - def test_raw_response_create_overload_4(self, client: RunwayML) -> None: - response = client.image_to_video.with_raw_response.create( - model="gen3a_turbo", - prompt_image="https://example.com/file", - prompt_text="A beautiful sunset over a calm ocean.", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - image_to_video = response.parse() - assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) - - @parametrize - def test_streaming_response_create_overload_4(self, client: RunwayML) -> None: - with client.image_to_video.with_streaming_response.create( - model="gen3a_turbo", - prompt_image="https://example.com/file", - prompt_text="A beautiful sunset over a calm ocean.", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - image_to_video = response.parse() - assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_method_create_overload_5(self, client: RunwayML) -> None: image_to_video = client.image_to_video.create( model="veo3.1_fast", prompt_image="https://example.com/file", @@ -232,7 +182,7 @@ def test_method_create_overload_5(self, client: RunwayML) -> None: assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - def test_method_create_with_all_params_overload_5(self, client: RunwayML) -> None: + def test_method_create_with_all_params_overload_4(self, client: RunwayML) -> None: image_to_video = client.image_to_video.create( model="veo3.1_fast", prompt_image="https://example.com/file", @@ -244,7 +194,7 @@ def test_method_create_with_all_params_overload_5(self, client: RunwayML) -> Non assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - def test_raw_response_create_overload_5(self, client: RunwayML) -> None: + def test_raw_response_create_overload_4(self, client: RunwayML) -> None: response = client.image_to_video.with_raw_response.create( model="veo3.1_fast", prompt_image="https://example.com/file", @@ -257,7 +207,7 @@ def test_raw_response_create_overload_5(self, client: RunwayML) -> None: assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - def test_streaming_response_create_overload_5(self, client: RunwayML) -> None: + def test_streaming_response_create_overload_4(self, client: RunwayML) -> None: with client.image_to_video.with_streaming_response.create( model="veo3.1_fast", prompt_image="https://example.com/file", @@ -272,7 +222,7 @@ def test_streaming_response_create_overload_5(self, client: RunwayML) -> None: assert cast(Any, response.is_closed) is True @parametrize - def test_method_create_overload_6(self, client: RunwayML) -> None: + def test_method_create_overload_5(self, client: RunwayML) -> None: image_to_video = client.image_to_video.create( model="happyhorse_1_0", prompt_image="https://example.com/file", @@ -280,7 +230,7 @@ def test_method_create_overload_6(self, client: RunwayML) -> None: assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - def test_method_create_with_all_params_overload_6(self, client: RunwayML) -> None: + def test_method_create_with_all_params_overload_5(self, client: RunwayML) -> None: image_to_video = client.image_to_video.create( model="happyhorse_1_0", prompt_image="https://example.com/file", @@ -291,7 +241,7 @@ def test_method_create_with_all_params_overload_6(self, client: RunwayML) -> Non assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - def test_raw_response_create_overload_6(self, client: RunwayML) -> None: + def test_raw_response_create_overload_5(self, client: RunwayML) -> None: response = client.image_to_video.with_raw_response.create( model="happyhorse_1_0", prompt_image="https://example.com/file", @@ -303,7 +253,7 @@ def test_raw_response_create_overload_6(self, client: RunwayML) -> None: assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - def test_streaming_response_create_overload_6(self, client: RunwayML) -> None: + def test_streaming_response_create_overload_5(self, client: RunwayML) -> None: with client.image_to_video.with_streaming_response.create( model="happyhorse_1_0", prompt_image="https://example.com/file", @@ -317,7 +267,7 @@ def test_streaming_response_create_overload_6(self, client: RunwayML) -> None: assert cast(Any, response.is_closed) is True @parametrize - def test_method_create_overload_7(self, client: RunwayML) -> None: + def test_method_create_overload_6(self, client: RunwayML) -> None: image_to_video = client.image_to_video.create( model="seedance2", prompt_image="https://example.com/file", @@ -325,7 +275,7 @@ def test_method_create_overload_7(self, client: RunwayML) -> None: assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - def test_method_create_with_all_params_overload_7(self, client: RunwayML) -> None: + def test_method_create_with_all_params_overload_6(self, client: RunwayML) -> None: image_to_video = client.image_to_video.create( model="seedance2", prompt_image="https://example.com/file", @@ -343,7 +293,7 @@ def test_method_create_with_all_params_overload_7(self, client: RunwayML) -> Non assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - def test_raw_response_create_overload_7(self, client: RunwayML) -> None: + def test_raw_response_create_overload_6(self, client: RunwayML) -> None: response = client.image_to_video.with_raw_response.create( model="seedance2", prompt_image="https://example.com/file", @@ -355,7 +305,7 @@ def test_raw_response_create_overload_7(self, client: RunwayML) -> None: assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - def test_streaming_response_create_overload_7(self, client: RunwayML) -> None: + def test_streaming_response_create_overload_6(self, client: RunwayML) -> None: with client.image_to_video.with_streaming_response.create( model="seedance2", prompt_image="https://example.com/file", @@ -369,7 +319,7 @@ def test_streaming_response_create_overload_7(self, client: RunwayML) -> None: assert cast(Any, response.is_closed) is True @parametrize - def test_method_create_overload_8(self, client: RunwayML) -> None: + def test_method_create_overload_7(self, client: RunwayML) -> None: image_to_video = client.image_to_video.create( model="seedance2_fast", prompt_image="https://example.com/file", @@ -377,7 +327,7 @@ def test_method_create_overload_8(self, client: RunwayML) -> None: assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - def test_method_create_with_all_params_overload_8(self, client: RunwayML) -> None: + def test_method_create_with_all_params_overload_7(self, client: RunwayML) -> None: image_to_video = client.image_to_video.create( model="seedance2_fast", prompt_image="https://example.com/file", @@ -395,7 +345,7 @@ def test_method_create_with_all_params_overload_8(self, client: RunwayML) -> Non assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - def test_raw_response_create_overload_8(self, client: RunwayML) -> None: + def test_raw_response_create_overload_7(self, client: RunwayML) -> None: response = client.image_to_video.with_raw_response.create( model="seedance2_fast", prompt_image="https://example.com/file", @@ -407,7 +357,7 @@ def test_raw_response_create_overload_8(self, client: RunwayML) -> None: assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - def test_streaming_response_create_overload_8(self, client: RunwayML) -> None: + def test_streaming_response_create_overload_7(self, client: RunwayML) -> None: with client.image_to_video.with_streaming_response.create( model="seedance2_fast", prompt_image="https://example.com/file", @@ -421,7 +371,7 @@ def test_streaming_response_create_overload_8(self, client: RunwayML) -> None: assert cast(Any, response.is_closed) is True @parametrize - def test_method_create_overload_9(self, client: RunwayML) -> None: + def test_method_create_overload_8(self, client: RunwayML) -> None: image_to_video = client.image_to_video.create( duration=8, model="veo3", @@ -431,7 +381,7 @@ def test_method_create_overload_9(self, client: RunwayML) -> None: assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - def test_method_create_with_all_params_overload_9(self, client: RunwayML) -> None: + def test_method_create_with_all_params_overload_8(self, client: RunwayML) -> None: image_to_video = client.image_to_video.create( duration=8, model="veo3", @@ -442,7 +392,7 @@ def test_method_create_with_all_params_overload_9(self, client: RunwayML) -> Non assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - def test_raw_response_create_overload_9(self, client: RunwayML) -> None: + def test_raw_response_create_overload_8(self, client: RunwayML) -> None: response = client.image_to_video.with_raw_response.create( duration=8, model="veo3", @@ -456,7 +406,7 @@ def test_raw_response_create_overload_9(self, client: RunwayML) -> None: assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - def test_streaming_response_create_overload_9(self, client: RunwayML) -> None: + def test_streaming_response_create_overload_8(self, client: RunwayML) -> None: with client.image_to_video.with_streaming_response.create( duration=8, model="veo3", @@ -634,56 +584,6 @@ async def test_streaming_response_create_overload_3(self, async_client: AsyncRun @parametrize async def test_method_create_overload_4(self, async_client: AsyncRunwayML) -> None: - image_to_video = await async_client.image_to_video.create( - model="gen3a_turbo", - prompt_image="https://example.com/file", - prompt_text="A beautiful sunset over a calm ocean.", - ) - assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) - - @parametrize - async def test_method_create_with_all_params_overload_4(self, async_client: AsyncRunwayML) -> None: - image_to_video = await async_client.image_to_video.create( - model="gen3a_turbo", - prompt_image="https://example.com/file", - prompt_text="A beautiful sunset over a calm ocean.", - content_moderation={"public_figure_threshold": "auto"}, - duration=5, - ratio="1280:768", - seed=0, - ) - assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) - - @parametrize - async def test_raw_response_create_overload_4(self, async_client: AsyncRunwayML) -> None: - response = await async_client.image_to_video.with_raw_response.create( - model="gen3a_turbo", - prompt_image="https://example.com/file", - prompt_text="A beautiful sunset over a calm ocean.", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - image_to_video = await response.parse() - assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) - - @parametrize - async def test_streaming_response_create_overload_4(self, async_client: AsyncRunwayML) -> None: - async with async_client.image_to_video.with_streaming_response.create( - model="gen3a_turbo", - prompt_image="https://example.com/file", - prompt_text="A beautiful sunset over a calm ocean.", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - image_to_video = await response.parse() - assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_method_create_overload_5(self, async_client: AsyncRunwayML) -> None: image_to_video = await async_client.image_to_video.create( model="veo3.1_fast", prompt_image="https://example.com/file", @@ -692,7 +592,7 @@ async def test_method_create_overload_5(self, async_client: AsyncRunwayML) -> No assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - async def test_method_create_with_all_params_overload_5(self, async_client: AsyncRunwayML) -> None: + async def test_method_create_with_all_params_overload_4(self, async_client: AsyncRunwayML) -> None: image_to_video = await async_client.image_to_video.create( model="veo3.1_fast", prompt_image="https://example.com/file", @@ -704,7 +604,7 @@ async def test_method_create_with_all_params_overload_5(self, async_client: Asyn assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - async def test_raw_response_create_overload_5(self, async_client: AsyncRunwayML) -> None: + async def test_raw_response_create_overload_4(self, async_client: AsyncRunwayML) -> None: response = await async_client.image_to_video.with_raw_response.create( model="veo3.1_fast", prompt_image="https://example.com/file", @@ -717,7 +617,7 @@ async def test_raw_response_create_overload_5(self, async_client: AsyncRunwayML) assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - async def test_streaming_response_create_overload_5(self, async_client: AsyncRunwayML) -> None: + async def test_streaming_response_create_overload_4(self, async_client: AsyncRunwayML) -> None: async with async_client.image_to_video.with_streaming_response.create( model="veo3.1_fast", prompt_image="https://example.com/file", @@ -732,7 +632,7 @@ async def test_streaming_response_create_overload_5(self, async_client: AsyncRun assert cast(Any, response.is_closed) is True @parametrize - async def test_method_create_overload_6(self, async_client: AsyncRunwayML) -> None: + async def test_method_create_overload_5(self, async_client: AsyncRunwayML) -> None: image_to_video = await async_client.image_to_video.create( model="happyhorse_1_0", prompt_image="https://example.com/file", @@ -740,7 +640,7 @@ async def test_method_create_overload_6(self, async_client: AsyncRunwayML) -> No assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - async def test_method_create_with_all_params_overload_6(self, async_client: AsyncRunwayML) -> None: + async def test_method_create_with_all_params_overload_5(self, async_client: AsyncRunwayML) -> None: image_to_video = await async_client.image_to_video.create( model="happyhorse_1_0", prompt_image="https://example.com/file", @@ -751,7 +651,7 @@ async def test_method_create_with_all_params_overload_6(self, async_client: Asyn assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - async def test_raw_response_create_overload_6(self, async_client: AsyncRunwayML) -> None: + async def test_raw_response_create_overload_5(self, async_client: AsyncRunwayML) -> None: response = await async_client.image_to_video.with_raw_response.create( model="happyhorse_1_0", prompt_image="https://example.com/file", @@ -763,7 +663,7 @@ async def test_raw_response_create_overload_6(self, async_client: AsyncRunwayML) assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - async def test_streaming_response_create_overload_6(self, async_client: AsyncRunwayML) -> None: + async def test_streaming_response_create_overload_5(self, async_client: AsyncRunwayML) -> None: async with async_client.image_to_video.with_streaming_response.create( model="happyhorse_1_0", prompt_image="https://example.com/file", @@ -777,7 +677,7 @@ async def test_streaming_response_create_overload_6(self, async_client: AsyncRun assert cast(Any, response.is_closed) is True @parametrize - async def test_method_create_overload_7(self, async_client: AsyncRunwayML) -> None: + async def test_method_create_overload_6(self, async_client: AsyncRunwayML) -> None: image_to_video = await async_client.image_to_video.create( model="seedance2", prompt_image="https://example.com/file", @@ -785,7 +685,7 @@ async def test_method_create_overload_7(self, async_client: AsyncRunwayML) -> No assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - async def test_method_create_with_all_params_overload_7(self, async_client: AsyncRunwayML) -> None: + async def test_method_create_with_all_params_overload_6(self, async_client: AsyncRunwayML) -> None: image_to_video = await async_client.image_to_video.create( model="seedance2", prompt_image="https://example.com/file", @@ -803,7 +703,7 @@ async def test_method_create_with_all_params_overload_7(self, async_client: Asyn assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - async def test_raw_response_create_overload_7(self, async_client: AsyncRunwayML) -> None: + async def test_raw_response_create_overload_6(self, async_client: AsyncRunwayML) -> None: response = await async_client.image_to_video.with_raw_response.create( model="seedance2", prompt_image="https://example.com/file", @@ -815,7 +715,7 @@ async def test_raw_response_create_overload_7(self, async_client: AsyncRunwayML) assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - async def test_streaming_response_create_overload_7(self, async_client: AsyncRunwayML) -> None: + async def test_streaming_response_create_overload_6(self, async_client: AsyncRunwayML) -> None: async with async_client.image_to_video.with_streaming_response.create( model="seedance2", prompt_image="https://example.com/file", @@ -829,7 +729,7 @@ async def test_streaming_response_create_overload_7(self, async_client: AsyncRun assert cast(Any, response.is_closed) is True @parametrize - async def test_method_create_overload_8(self, async_client: AsyncRunwayML) -> None: + async def test_method_create_overload_7(self, async_client: AsyncRunwayML) -> None: image_to_video = await async_client.image_to_video.create( model="seedance2_fast", prompt_image="https://example.com/file", @@ -837,7 +737,7 @@ async def test_method_create_overload_8(self, async_client: AsyncRunwayML) -> No assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - async def test_method_create_with_all_params_overload_8(self, async_client: AsyncRunwayML) -> None: + async def test_method_create_with_all_params_overload_7(self, async_client: AsyncRunwayML) -> None: image_to_video = await async_client.image_to_video.create( model="seedance2_fast", prompt_image="https://example.com/file", @@ -855,7 +755,7 @@ async def test_method_create_with_all_params_overload_8(self, async_client: Asyn assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - async def test_raw_response_create_overload_8(self, async_client: AsyncRunwayML) -> None: + async def test_raw_response_create_overload_7(self, async_client: AsyncRunwayML) -> None: response = await async_client.image_to_video.with_raw_response.create( model="seedance2_fast", prompt_image="https://example.com/file", @@ -867,7 +767,7 @@ async def test_raw_response_create_overload_8(self, async_client: AsyncRunwayML) assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - async def test_streaming_response_create_overload_8(self, async_client: AsyncRunwayML) -> None: + async def test_streaming_response_create_overload_7(self, async_client: AsyncRunwayML) -> None: async with async_client.image_to_video.with_streaming_response.create( model="seedance2_fast", prompt_image="https://example.com/file", @@ -881,7 +781,7 @@ async def test_streaming_response_create_overload_8(self, async_client: AsyncRun assert cast(Any, response.is_closed) is True @parametrize - async def test_method_create_overload_9(self, async_client: AsyncRunwayML) -> None: + async def test_method_create_overload_8(self, async_client: AsyncRunwayML) -> None: image_to_video = await async_client.image_to_video.create( duration=8, model="veo3", @@ -891,7 +791,7 @@ async def test_method_create_overload_9(self, async_client: AsyncRunwayML) -> No assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - async def test_method_create_with_all_params_overload_9(self, async_client: AsyncRunwayML) -> None: + async def test_method_create_with_all_params_overload_8(self, async_client: AsyncRunwayML) -> None: image_to_video = await async_client.image_to_video.create( duration=8, model="veo3", @@ -902,7 +802,7 @@ async def test_method_create_with_all_params_overload_9(self, async_client: Asyn assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - async def test_raw_response_create_overload_9(self, async_client: AsyncRunwayML) -> None: + async def test_raw_response_create_overload_8(self, async_client: AsyncRunwayML) -> None: response = await async_client.image_to_video.with_raw_response.create( duration=8, model="veo3", @@ -916,7 +816,7 @@ async def test_raw_response_create_overload_9(self, async_client: AsyncRunwayML) assert_matches_type(ImageToVideoCreateResponse, image_to_video, path=["response"]) @parametrize - async def test_streaming_response_create_overload_9(self, async_client: AsyncRunwayML) -> None: + async def test_streaming_response_create_overload_8(self, async_client: AsyncRunwayML) -> None: async with async_client.image_to_video.with_streaming_response.create( duration=8, model="veo3", diff --git a/tests/api_resources/test_video_to_video.py b/tests/api_resources/test_video_to_video.py index c339001..2c37e33 100644 --- a/tests/api_resources/test_video_to_video.py +++ b/tests/api_resources/test_video_to_video.py @@ -19,61 +19,6 @@ class TestVideoToVideo: @parametrize def test_method_create_overload_1(self, client: RunwayML) -> None: - video_to_video = client.video_to_video.create( - model="gen4_aleph", - prompt_text="x", - video_uri="https://example.com/video.mp4", - ) - assert_matches_type(VideoToVideoCreateResponse, video_to_video, path=["response"]) - - @parametrize - def test_method_create_with_all_params_overload_1(self, client: RunwayML) -> None: - video_to_video = client.video_to_video.create( - model="gen4_aleph", - prompt_text="x", - video_uri="https://example.com/video.mp4", - content_moderation={"public_figure_threshold": "auto"}, - ratio="1280:720", - references=[ - { - "type": "image", - "uri": "https://example.com/file", - } - ], - seed=0, - ) - assert_matches_type(VideoToVideoCreateResponse, video_to_video, path=["response"]) - - @parametrize - def test_raw_response_create_overload_1(self, client: RunwayML) -> None: - response = client.video_to_video.with_raw_response.create( - model="gen4_aleph", - prompt_text="x", - video_uri="https://example.com/video.mp4", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - video_to_video = response.parse() - assert_matches_type(VideoToVideoCreateResponse, video_to_video, path=["response"]) - - @parametrize - def test_streaming_response_create_overload_1(self, client: RunwayML) -> None: - with client.video_to_video.with_streaming_response.create( - model="gen4_aleph", - prompt_text="x", - video_uri="https://example.com/video.mp4", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - video_to_video = response.parse() - assert_matches_type(VideoToVideoCreateResponse, video_to_video, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_method_create_overload_2(self, client: RunwayML) -> None: video_to_video = client.video_to_video.create( model="aleph2", prompt_text="x", @@ -82,7 +27,7 @@ def test_method_create_overload_2(self, client: RunwayML) -> None: assert_matches_type(VideoToVideoCreateResponse, video_to_video, path=["response"]) @parametrize - def test_method_create_with_all_params_overload_2(self, client: RunwayML) -> None: + def test_method_create_with_all_params_overload_1(self, client: RunwayML) -> None: video_to_video = client.video_to_video.create( model="aleph2", prompt_text="x", @@ -94,18 +39,12 @@ def test_method_create_with_all_params_overload_2(self, client: RunwayML) -> Non "uri": "https://example.com/file", } ], - prompt_image=[ - { - "position": "first", - "uri": "https://example.com/file", - } - ], seed=0, ) assert_matches_type(VideoToVideoCreateResponse, video_to_video, path=["response"]) @parametrize - def test_raw_response_create_overload_2(self, client: RunwayML) -> None: + def test_raw_response_create_overload_1(self, client: RunwayML) -> None: response = client.video_to_video.with_raw_response.create( model="aleph2", prompt_text="x", @@ -118,7 +57,7 @@ def test_raw_response_create_overload_2(self, client: RunwayML) -> None: assert_matches_type(VideoToVideoCreateResponse, video_to_video, path=["response"]) @parametrize - def test_streaming_response_create_overload_2(self, client: RunwayML) -> None: + def test_streaming_response_create_overload_1(self, client: RunwayML) -> None: with client.video_to_video.with_streaming_response.create( model="aleph2", prompt_text="x", @@ -133,7 +72,7 @@ def test_streaming_response_create_overload_2(self, client: RunwayML) -> None: assert cast(Any, response.is_closed) is True @parametrize - def test_method_create_overload_3(self, client: RunwayML) -> None: + def test_method_create_overload_2(self, client: RunwayML) -> None: video_to_video = client.video_to_video.create( model="seedance2", prompt_video="https://example.com/video.mp4", @@ -141,7 +80,7 @@ def test_method_create_overload_3(self, client: RunwayML) -> None: assert_matches_type(VideoToVideoCreateResponse, video_to_video, path=["response"]) @parametrize - def test_method_create_with_all_params_overload_3(self, client: RunwayML) -> None: + def test_method_create_with_all_params_overload_2(self, client: RunwayML) -> None: video_to_video = client.video_to_video.create( model="seedance2", prompt_video="https://example.com/video.mp4", @@ -171,7 +110,7 @@ def test_method_create_with_all_params_overload_3(self, client: RunwayML) -> Non assert_matches_type(VideoToVideoCreateResponse, video_to_video, path=["response"]) @parametrize - def test_raw_response_create_overload_3(self, client: RunwayML) -> None: + def test_raw_response_create_overload_2(self, client: RunwayML) -> None: response = client.video_to_video.with_raw_response.create( model="seedance2", prompt_video="https://example.com/video.mp4", @@ -183,7 +122,7 @@ def test_raw_response_create_overload_3(self, client: RunwayML) -> None: assert_matches_type(VideoToVideoCreateResponse, video_to_video, path=["response"]) @parametrize - def test_streaming_response_create_overload_3(self, client: RunwayML) -> None: + def test_streaming_response_create_overload_2(self, client: RunwayML) -> None: with client.video_to_video.with_streaming_response.create( model="seedance2", prompt_video="https://example.com/video.mp4", @@ -197,7 +136,7 @@ def test_streaming_response_create_overload_3(self, client: RunwayML) -> None: assert cast(Any, response.is_closed) is True @parametrize - def test_method_create_overload_4(self, client: RunwayML) -> None: + def test_method_create_overload_3(self, client: RunwayML) -> None: video_to_video = client.video_to_video.create( model="seedance2_fast", prompt_video="https://example.com/video.mp4", @@ -205,7 +144,7 @@ def test_method_create_overload_4(self, client: RunwayML) -> None: assert_matches_type(VideoToVideoCreateResponse, video_to_video, path=["response"]) @parametrize - def test_method_create_with_all_params_overload_4(self, client: RunwayML) -> None: + def test_method_create_with_all_params_overload_3(self, client: RunwayML) -> None: video_to_video = client.video_to_video.create( model="seedance2_fast", prompt_video="https://example.com/video.mp4", @@ -235,7 +174,7 @@ def test_method_create_with_all_params_overload_4(self, client: RunwayML) -> Non assert_matches_type(VideoToVideoCreateResponse, video_to_video, path=["response"]) @parametrize - def test_raw_response_create_overload_4(self, client: RunwayML) -> None: + def test_raw_response_create_overload_3(self, client: RunwayML) -> None: response = client.video_to_video.with_raw_response.create( model="seedance2_fast", prompt_video="https://example.com/video.mp4", @@ -247,7 +186,7 @@ def test_raw_response_create_overload_4(self, client: RunwayML) -> None: assert_matches_type(VideoToVideoCreateResponse, video_to_video, path=["response"]) @parametrize - def test_streaming_response_create_overload_4(self, client: RunwayML) -> None: + def test_streaming_response_create_overload_3(self, client: RunwayML) -> None: with client.video_to_video.with_streaming_response.create( model="seedance2_fast", prompt_video="https://example.com/video.mp4", @@ -268,61 +207,6 @@ class TestAsyncVideoToVideo: @parametrize async def test_method_create_overload_1(self, async_client: AsyncRunwayML) -> None: - video_to_video = await async_client.video_to_video.create( - model="gen4_aleph", - prompt_text="x", - video_uri="https://example.com/video.mp4", - ) - assert_matches_type(VideoToVideoCreateResponse, video_to_video, path=["response"]) - - @parametrize - async def test_method_create_with_all_params_overload_1(self, async_client: AsyncRunwayML) -> None: - video_to_video = await async_client.video_to_video.create( - model="gen4_aleph", - prompt_text="x", - video_uri="https://example.com/video.mp4", - content_moderation={"public_figure_threshold": "auto"}, - ratio="1280:720", - references=[ - { - "type": "image", - "uri": "https://example.com/file", - } - ], - seed=0, - ) - assert_matches_type(VideoToVideoCreateResponse, video_to_video, path=["response"]) - - @parametrize - async def test_raw_response_create_overload_1(self, async_client: AsyncRunwayML) -> None: - response = await async_client.video_to_video.with_raw_response.create( - model="gen4_aleph", - prompt_text="x", - video_uri="https://example.com/video.mp4", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - video_to_video = await response.parse() - assert_matches_type(VideoToVideoCreateResponse, video_to_video, path=["response"]) - - @parametrize - async def test_streaming_response_create_overload_1(self, async_client: AsyncRunwayML) -> None: - async with async_client.video_to_video.with_streaming_response.create( - model="gen4_aleph", - prompt_text="x", - video_uri="https://example.com/video.mp4", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - video_to_video = await response.parse() - assert_matches_type(VideoToVideoCreateResponse, video_to_video, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_method_create_overload_2(self, async_client: AsyncRunwayML) -> None: video_to_video = await async_client.video_to_video.create( model="aleph2", prompt_text="x", @@ -331,7 +215,7 @@ async def test_method_create_overload_2(self, async_client: AsyncRunwayML) -> No assert_matches_type(VideoToVideoCreateResponse, video_to_video, path=["response"]) @parametrize - async def test_method_create_with_all_params_overload_2(self, async_client: AsyncRunwayML) -> None: + async def test_method_create_with_all_params_overload_1(self, async_client: AsyncRunwayML) -> None: video_to_video = await async_client.video_to_video.create( model="aleph2", prompt_text="x", @@ -343,18 +227,12 @@ async def test_method_create_with_all_params_overload_2(self, async_client: Asyn "uri": "https://example.com/file", } ], - prompt_image=[ - { - "position": "first", - "uri": "https://example.com/file", - } - ], seed=0, ) assert_matches_type(VideoToVideoCreateResponse, video_to_video, path=["response"]) @parametrize - async def test_raw_response_create_overload_2(self, async_client: AsyncRunwayML) -> None: + async def test_raw_response_create_overload_1(self, async_client: AsyncRunwayML) -> None: response = await async_client.video_to_video.with_raw_response.create( model="aleph2", prompt_text="x", @@ -367,7 +245,7 @@ async def test_raw_response_create_overload_2(self, async_client: AsyncRunwayML) assert_matches_type(VideoToVideoCreateResponse, video_to_video, path=["response"]) @parametrize - async def test_streaming_response_create_overload_2(self, async_client: AsyncRunwayML) -> None: + async def test_streaming_response_create_overload_1(self, async_client: AsyncRunwayML) -> None: async with async_client.video_to_video.with_streaming_response.create( model="aleph2", prompt_text="x", @@ -382,7 +260,7 @@ async def test_streaming_response_create_overload_2(self, async_client: AsyncRun assert cast(Any, response.is_closed) is True @parametrize - async def test_method_create_overload_3(self, async_client: AsyncRunwayML) -> None: + async def test_method_create_overload_2(self, async_client: AsyncRunwayML) -> None: video_to_video = await async_client.video_to_video.create( model="seedance2", prompt_video="https://example.com/video.mp4", @@ -390,7 +268,7 @@ async def test_method_create_overload_3(self, async_client: AsyncRunwayML) -> No assert_matches_type(VideoToVideoCreateResponse, video_to_video, path=["response"]) @parametrize - async def test_method_create_with_all_params_overload_3(self, async_client: AsyncRunwayML) -> None: + async def test_method_create_with_all_params_overload_2(self, async_client: AsyncRunwayML) -> None: video_to_video = await async_client.video_to_video.create( model="seedance2", prompt_video="https://example.com/video.mp4", @@ -420,7 +298,7 @@ async def test_method_create_with_all_params_overload_3(self, async_client: Asyn assert_matches_type(VideoToVideoCreateResponse, video_to_video, path=["response"]) @parametrize - async def test_raw_response_create_overload_3(self, async_client: AsyncRunwayML) -> None: + async def test_raw_response_create_overload_2(self, async_client: AsyncRunwayML) -> None: response = await async_client.video_to_video.with_raw_response.create( model="seedance2", prompt_video="https://example.com/video.mp4", @@ -432,7 +310,7 @@ async def test_raw_response_create_overload_3(self, async_client: AsyncRunwayML) assert_matches_type(VideoToVideoCreateResponse, video_to_video, path=["response"]) @parametrize - async def test_streaming_response_create_overload_3(self, async_client: AsyncRunwayML) -> None: + async def test_streaming_response_create_overload_2(self, async_client: AsyncRunwayML) -> None: async with async_client.video_to_video.with_streaming_response.create( model="seedance2", prompt_video="https://example.com/video.mp4", @@ -446,7 +324,7 @@ async def test_streaming_response_create_overload_3(self, async_client: AsyncRun assert cast(Any, response.is_closed) is True @parametrize - async def test_method_create_overload_4(self, async_client: AsyncRunwayML) -> None: + async def test_method_create_overload_3(self, async_client: AsyncRunwayML) -> None: video_to_video = await async_client.video_to_video.create( model="seedance2_fast", prompt_video="https://example.com/video.mp4", @@ -454,7 +332,7 @@ async def test_method_create_overload_4(self, async_client: AsyncRunwayML) -> No assert_matches_type(VideoToVideoCreateResponse, video_to_video, path=["response"]) @parametrize - async def test_method_create_with_all_params_overload_4(self, async_client: AsyncRunwayML) -> None: + async def test_method_create_with_all_params_overload_3(self, async_client: AsyncRunwayML) -> None: video_to_video = await async_client.video_to_video.create( model="seedance2_fast", prompt_video="https://example.com/video.mp4", @@ -484,7 +362,7 @@ async def test_method_create_with_all_params_overload_4(self, async_client: Asyn assert_matches_type(VideoToVideoCreateResponse, video_to_video, path=["response"]) @parametrize - async def test_raw_response_create_overload_4(self, async_client: AsyncRunwayML) -> None: + async def test_raw_response_create_overload_3(self, async_client: AsyncRunwayML) -> None: response = await async_client.video_to_video.with_raw_response.create( model="seedance2_fast", prompt_video="https://example.com/video.mp4", @@ -496,7 +374,7 @@ async def test_raw_response_create_overload_4(self, async_client: AsyncRunwayML) assert_matches_type(VideoToVideoCreateResponse, video_to_video, path=["response"]) @parametrize - async def test_streaming_response_create_overload_4(self, async_client: AsyncRunwayML) -> None: + async def test_streaming_response_create_overload_3(self, async_client: AsyncRunwayML) -> None: async with async_client.video_to_video.with_streaming_response.create( model="seedance2_fast", prompt_video="https://example.com/video.mp4", diff --git a/tests/api_resources/test_voices.py b/tests/api_resources/test_voices.py index 3ac744b..1e32196 100644 --- a/tests/api_resources/test_voices.py +++ b/tests/api_resources/test_voices.py @@ -12,6 +12,7 @@ from runwayml.types import ( VoiceListResponse, VoiceCreateResponse, + VoiceUpdateResponse, VoicePreviewResponse, VoiceRetrieveResponse, ) @@ -116,6 +117,53 @@ def test_path_params_retrieve(self, client: RunwayML) -> None: "", ) + @parametrize + def test_method_update(self, client: RunwayML) -> None: + voice = client.voices.update( + id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(VoiceUpdateResponse, voice, path=["response"]) + + @parametrize + def test_method_update_with_all_params(self, client: RunwayML) -> None: + voice = client.voices.update( + id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + description="x", + name="x", + ) + assert_matches_type(VoiceUpdateResponse, voice, path=["response"]) + + @parametrize + def test_raw_response_update(self, client: RunwayML) -> None: + response = client.voices.with_raw_response.update( + id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + voice = response.parse() + assert_matches_type(VoiceUpdateResponse, voice, path=["response"]) + + @parametrize + def test_streaming_response_update(self, client: RunwayML) -> None: + with client.voices.with_streaming_response.update( + id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + voice = response.parse() + assert_matches_type(VoiceUpdateResponse, voice, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_update(self, client: RunwayML) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.voices.with_raw_response.update( + id="", + ) + @parametrize def test_method_list(self, client: RunwayML) -> None: voice = client.voices.list( @@ -326,6 +374,53 @@ async def test_path_params_retrieve(self, async_client: AsyncRunwayML) -> None: "", ) + @parametrize + async def test_method_update(self, async_client: AsyncRunwayML) -> None: + voice = await async_client.voices.update( + id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(VoiceUpdateResponse, voice, path=["response"]) + + @parametrize + async def test_method_update_with_all_params(self, async_client: AsyncRunwayML) -> None: + voice = await async_client.voices.update( + id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + description="x", + name="x", + ) + assert_matches_type(VoiceUpdateResponse, voice, path=["response"]) + + @parametrize + async def test_raw_response_update(self, async_client: AsyncRunwayML) -> None: + response = await async_client.voices.with_raw_response.update( + id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + voice = await response.parse() + assert_matches_type(VoiceUpdateResponse, voice, path=["response"]) + + @parametrize + async def test_streaming_response_update(self, async_client: AsyncRunwayML) -> None: + async with async_client.voices.with_streaming_response.update( + id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + voice = await response.parse() + assert_matches_type(VoiceUpdateResponse, voice, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_update(self, async_client: AsyncRunwayML) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.voices.with_raw_response.update( + id="", + ) + @parametrize async def test_method_list(self, async_client: AsyncRunwayML) -> None: voice = await async_client.voices.list( diff --git a/uv.lock b/uv.lock index ab3a56b..c6c62ac 100644 --- a/uv.lock +++ b/uv.lock @@ -886,7 +886,7 @@ wheels = [ [[package]] name = "runwayml" -version = "4.13.0" +version = "4.18.0" source = { editable = "." } dependencies = [ { name = "anyio", version = "4.12.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" },