diff --git a/google/genai/_gaos/models/__init__.py b/google/genai/_gaos/models/__init__.py index fa2c65963..9f09ae929 100644 --- a/google/genai/_gaos/models/__init__.py +++ b/google/genai/_gaos/models/__init__.py @@ -62,6 +62,12 @@ CreateTriggerRequest, CreateTriggerRequestParam, ) + from .createvoice import ( + CreateVoiceGlobals, + CreateVoiceGlobalsTypedDict, + CreateVoiceRequest, + CreateVoiceRequestParam, + ) from .createwebhook import ( CreateWebhookGlobals, CreateWebhookGlobalsTypedDict, @@ -98,6 +104,12 @@ DeleteTriggerRequest, DeleteTriggerRequestParam, ) + from .deletevoice import ( + DeleteVoiceGlobals, + DeleteVoiceGlobalsTypedDict, + DeleteVoiceRequest, + DeleteVoiceRequestParam, + ) from .deletewebhook import ( DeleteWebhookGlobals, DeleteWebhookGlobalsTypedDict, @@ -142,6 +154,12 @@ GetTriggerRequest, GetTriggerRequestParam, ) + from .getvoice import ( + GetVoiceGlobals, + GetVoiceGlobalsTypedDict, + GetVoiceRequest, + GetVoiceRequestParam, + ) from .getwebhook import ( GetWebhookGlobals, GetWebhookGlobalsTypedDict, @@ -178,6 +196,12 @@ ListTriggersRequest, ListTriggersRequestParam, ) + from .listvoices import ( + ListVoicesGlobals, + ListVoicesGlobalsTypedDict, + ListVoicesRequest, + ListVoicesRequestParam, + ) from .listwebhooks import ( ListWebhooksGlobals, ListWebhooksGlobalsTypedDict, @@ -259,6 +283,10 @@ "CreateTriggerGlobalsTypedDict", "CreateTriggerRequest", "CreateTriggerRequestParam", + "CreateVoiceGlobals", + "CreateVoiceGlobalsTypedDict", + "CreateVoiceRequest", + "CreateVoiceRequestParam", "CreateWebhookGlobals", "CreateWebhookGlobalsTypedDict", "CreateWebhookRequest", @@ -283,6 +311,10 @@ "DeleteTriggerGlobalsTypedDict", "DeleteTriggerRequest", "DeleteTriggerRequestParam", + "DeleteVoiceGlobals", + "DeleteVoiceGlobalsTypedDict", + "DeleteVoiceRequest", + "DeleteVoiceRequestParam", "DeleteWebhookGlobals", "DeleteWebhookGlobalsTypedDict", "DeleteWebhookRequest", @@ -313,6 +345,10 @@ "GetTriggerGlobalsTypedDict", "GetTriggerRequest", "GetTriggerRequestParam", + "GetVoiceGlobals", + "GetVoiceGlobalsTypedDict", + "GetVoiceRequest", + "GetVoiceRequestParam", "GetWebhookGlobals", "GetWebhookGlobalsTypedDict", "GetWebhookRequest", @@ -337,6 +373,10 @@ "ListTriggersGlobalsTypedDict", "ListTriggersRequest", "ListTriggersRequestParam", + "ListVoicesGlobals", + "ListVoicesGlobalsTypedDict", + "ListVoicesRequest", + "ListVoicesRequestParam", "ListWebhooksGlobals", "ListWebhooksGlobalsTypedDict", "ListWebhooksRequest", @@ -402,6 +442,10 @@ "CreateTriggerGlobalsTypedDict": ".createtrigger", "CreateTriggerRequest": ".createtrigger", "CreateTriggerRequestParam": ".createtrigger", + "CreateVoiceGlobals": ".createvoice", + "CreateVoiceGlobalsTypedDict": ".createvoice", + "CreateVoiceRequest": ".createvoice", + "CreateVoiceRequestParam": ".createvoice", "CreateWebhookGlobals": ".createwebhook", "CreateWebhookGlobalsTypedDict": ".createwebhook", "CreateWebhookRequest": ".createwebhook", @@ -426,6 +470,10 @@ "DeleteTriggerGlobalsTypedDict": ".deletetrigger", "DeleteTriggerRequest": ".deletetrigger", "DeleteTriggerRequestParam": ".deletetrigger", + "DeleteVoiceGlobals": ".deletevoice", + "DeleteVoiceGlobalsTypedDict": ".deletevoice", + "DeleteVoiceRequest": ".deletevoice", + "DeleteVoiceRequestParam": ".deletevoice", "DeleteWebhookGlobals": ".deletewebhook", "DeleteWebhookGlobalsTypedDict": ".deletewebhook", "DeleteWebhookRequest": ".deletewebhook", @@ -456,6 +504,10 @@ "GetTriggerGlobalsTypedDict": ".gettrigger", "GetTriggerRequest": ".gettrigger", "GetTriggerRequestParam": ".gettrigger", + "GetVoiceGlobals": ".getvoice", + "GetVoiceGlobalsTypedDict": ".getvoice", + "GetVoiceRequest": ".getvoice", + "GetVoiceRequestParam": ".getvoice", "GetWebhookGlobals": ".getwebhook", "GetWebhookGlobalsTypedDict": ".getwebhook", "GetWebhookRequest": ".getwebhook", @@ -480,6 +532,10 @@ "ListTriggersGlobalsTypedDict": ".listtriggers", "ListTriggersRequest": ".listtriggers", "ListTriggersRequestParam": ".listtriggers", + "ListVoicesGlobals": ".listvoices", + "ListVoicesGlobalsTypedDict": ".listvoices", + "ListVoicesRequest": ".listvoices", + "ListVoicesRequestParam": ".listvoices", "ListWebhooksGlobals": ".listwebhooks", "ListWebhooksGlobalsTypedDict": ".listwebhooks", "ListWebhooksRequest": ".listwebhooks", diff --git a/google/genai/_gaos/models/createvoice.py b/google/genai/_gaos/models/createvoice.py new file mode 100644 index 000000000..9eb620455 --- /dev/null +++ b/google/genai/_gaos/models/createvoice.py @@ -0,0 +1,92 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# pyformat: disable +# pylint: skip-file + +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from ..types import BaseModel, UNSET_SENTINEL +from ..types.voices import createvoicerequest as voices_createvoicerequest +from ..utils import FieldMetadata, PathParamMetadata, RequestMetadata +from pydantic import model_serializer +from typing import Optional +from typing_extensions import Annotated, NotRequired, TypedDict + + +class CreateVoiceGlobalsTypedDict(TypedDict): + api_version: NotRequired[str] + r"""API version for request routing.""" + + +class CreateVoiceGlobals(BaseModel): + api_version: Annotated[ + Optional[str], + FieldMetadata(path=PathParamMetadata(style="simple", explode=False)), + ] = None + r"""API version for request routing.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["api_version"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +class CreateVoiceRequestParam(TypedDict): + body: voices_createvoicerequest.CreateVoiceRequestParam + r"""The request body.""" + api_version: NotRequired[str] + r"""API version for request routing.""" + + +class CreateVoiceRequest(BaseModel): + body: Annotated[ + voices_createvoicerequest.CreateVoiceRequest, + FieldMetadata(request=RequestMetadata(media_type="application/json")), + ] + r"""The request body.""" + + api_version: Annotated[ + Optional[str], + FieldMetadata(path=PathParamMetadata(style="simple", explode=False)), + ] = None + r"""API version for request routing.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["api_version"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m diff --git a/google/genai/_gaos/models/deletevoice.py b/google/genai/_gaos/models/deletevoice.py new file mode 100644 index 000000000..cdbd9b80b --- /dev/null +++ b/google/genai/_gaos/models/deletevoice.py @@ -0,0 +1,97 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# pyformat: disable +# pylint: skip-file + +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from ..types import BaseModel, UNSET_SENTINEL +from ..utils import FieldMetadata, PathParamMetadata +import pydantic +from pydantic import model_serializer +from typing import Optional +from typing_extensions import Annotated, NotRequired, TypedDict + + +class DeleteVoiceGlobalsTypedDict(TypedDict): + api_version: NotRequired[str] + r"""API version for request routing.""" + + +class DeleteVoiceGlobals(BaseModel): + api_version: Annotated[ + Optional[str], + FieldMetadata(path=PathParamMetadata(style="simple", explode=False)), + ] = None + r"""API version for request routing.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["api_version"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +class DeleteVoiceRequestParam(TypedDict): + id: str + r"""Required. The resource name of the custom stored voice to delete + (for example, `voices/voice_abc123def456`). + """ + api_version: NotRequired[str] + r"""API version for request routing.""" + + +class DeleteVoiceRequest(BaseModel): + id: Annotated[ + str, + pydantic.Field(alias="voicesId"), + FieldMetadata(path=PathParamMetadata(style="simple", explode=False)), + ] + r"""Required. The resource name of the custom stored voice to delete + (for example, `voices/voice_abc123def456`). + """ + + api_version: Annotated[ + Optional[str], + FieldMetadata(path=PathParamMetadata(style="simple", explode=False)), + ] = None + r"""API version for request routing.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["api_version"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m diff --git a/google/genai/_gaos/models/getvoice.py b/google/genai/_gaos/models/getvoice.py new file mode 100644 index 000000000..33bfb4602 --- /dev/null +++ b/google/genai/_gaos/models/getvoice.py @@ -0,0 +1,97 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# pyformat: disable +# pylint: skip-file + +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from ..types import BaseModel, UNSET_SENTINEL +from ..utils import FieldMetadata, PathParamMetadata +import pydantic +from pydantic import model_serializer +from typing import Optional +from typing_extensions import Annotated, NotRequired, TypedDict + + +class GetVoiceGlobalsTypedDict(TypedDict): + api_version: NotRequired[str] + r"""API version for request routing.""" + + +class GetVoiceGlobals(BaseModel): + api_version: Annotated[ + Optional[str], + FieldMetadata(path=PathParamMetadata(style="simple", explode=False)), + ] = None + r"""API version for request routing.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["api_version"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +class GetVoiceRequestParam(TypedDict): + id: str + r"""Required. The resource name of the custom stored voice to retrieve + (for example, `voices/voice_abc123def456`). + """ + api_version: NotRequired[str] + r"""API version for request routing.""" + + +class GetVoiceRequest(BaseModel): + id: Annotated[ + str, + pydantic.Field(alias="voicesId"), + FieldMetadata(path=PathParamMetadata(style="simple", explode=False)), + ] + r"""Required. The resource name of the custom stored voice to retrieve + (for example, `voices/voice_abc123def456`). + """ + + api_version: Annotated[ + Optional[str], + FieldMetadata(path=PathParamMetadata(style="simple", explode=False)), + ] = None + r"""API version for request routing.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["api_version"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m diff --git a/google/genai/_gaos/models/listvoices.py b/google/genai/_gaos/models/listvoices.py new file mode 100644 index 000000000..57b2930db --- /dev/null +++ b/google/genai/_gaos/models/listvoices.py @@ -0,0 +1,266 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# pyformat: disable +# pylint: skip-file + +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from ..types import BaseModel, UNSET_SENTINEL +from ..utils import FieldMetadata, PathParamMetadata, QueryParamMetadata +import pydantic +from pydantic import model_serializer +from typing import List, Optional +from typing_extensions import Annotated, NotRequired, TypedDict + + +class ListVoicesGlobalsTypedDict(TypedDict): + api_version: NotRequired[str] + r"""API version for request routing.""" + + +class ListVoicesGlobals(BaseModel): + api_version: Annotated[ + Optional[str], + FieldMetadata(path=PathParamMetadata(style="simple", explode=False)), + ] = None + r"""API version for request routing.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["api_version"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +class ListVoicesRequestParam(TypedDict): + api_version: NotRequired[str] + r"""API version for request routing.""" + accent: NotRequired[List[str]] + r"""Optional. Filter by accent description (e.g. \"American\", \"British\"). + Case-insensitive exact match. If multiple values are specified, matches + voices with any of the specified accents (OR). + """ + contexts: NotRequired[List[str]] + r"""Optional. Filter by intended context or domain (e.g. \"News, Commercial\"). + Case-insensitive exact match. If multiple values are specified, matches + voices with any of the specified contexts (OR). + """ + gender: NotRequired[List[str]] + r"""Optional. Filter by gender presentation (e.g. \"female\", \"male\", \"neutral\"). + Case-insensitive exact match. If multiple values are specified, matches + voices with any of the specified genders (OR). + """ + language_code: NotRequired[List[str]] + r"""Optional. Filter by BCP-47 language code (e.g. \"en-US\"). + Case-insensitive exact match. If multiple values are specified, matches + voices with any of the specified language codes (OR). + """ + page_size: NotRequired[int] + r"""Optional. The maximum number of voices to return per page. The service may + return fewer than this value. If unspecified, at most 50 voices are + returned. The maximum value is 1000; values above 1000 are coerced to + 1000. + """ + page_token: NotRequired[str] + r"""Optional. A page token received from a previous `ListVoices` call. Provide + this to retrieve the subsequent page. + + When paginating, all filter query parameters (`language_code`, + `region_code`, `accent`, `persona`, `context`, `gender`, `pitch`, `type`, + and `search`) must match the call that returned this token; otherwise the + request fails with `INVALID_ARGUMENT`. `page_size` may change between + pages. + """ + persona: NotRequired[List[str]] + r"""Optional. Filter by vocal persona (e.g. \"Warm, Friendly\"). + Case-insensitive exact match. If multiple values are specified, matches + voices with any of the specified personas (OR). + """ + pitch: NotRequired[List[str]] + r"""Optional. Filter by vocal pitch. Accepts `\"low\"`, `\"medium\"`, `\"high\"` + (case-insensitive). If multiple values are specified, matches voices with + any of the specified pitches (OR). + """ + region_code: NotRequired[List[str]] + r"""Optional. Filter by ISO 3166-1 alpha-2 or UN M.49 region code (e.g. \"US\", + \"001\"). + Case-insensitive exact match. If multiple values are specified, matches + voices with any of the specified region codes (OR). + """ + search: NotRequired[str] + r"""Optional. Free-text substring search query matched case-insensitively + against both `display_name` and `description`. Maximum 2048 bytes. + """ + type: NotRequired[List[str]] + r"""Optional. Filter by voice type. Accepts `\"prebuilt\"`, `\"replicated\"`, + `\"prompted\"` (case-insensitive). If multiple values are specified, matches + voices with any of the specified types (OR). + """ + + +class ListVoicesRequest(BaseModel): + api_version: Annotated[ + Optional[str], + FieldMetadata(path=PathParamMetadata(style="simple", explode=False)), + ] = None + r"""API version for request routing.""" + + accent: Annotated[ + Optional[List[str]], + FieldMetadata(query=QueryParamMetadata(style="form", explode=True)), + ] = None + r"""Optional. Filter by accent description (e.g. \"American\", \"British\"). + Case-insensitive exact match. If multiple values are specified, matches + voices with any of the specified accents (OR). + """ + + contexts: Annotated[ + Optional[List[str]], + pydantic.Field(alias="context"), + FieldMetadata(query=QueryParamMetadata(style="form", explode=True)), + ] = None + r"""Optional. Filter by intended context or domain (e.g. \"News, Commercial\"). + Case-insensitive exact match. If multiple values are specified, matches + voices with any of the specified contexts (OR). + """ + + gender: Annotated[ + Optional[List[str]], + FieldMetadata(query=QueryParamMetadata(style="form", explode=True)), + ] = None + r"""Optional. Filter by gender presentation (e.g. \"female\", \"male\", \"neutral\"). + Case-insensitive exact match. If multiple values are specified, matches + voices with any of the specified genders (OR). + """ + + language_code: Annotated[ + Optional[List[str]], + FieldMetadata(query=QueryParamMetadata(style="form", explode=True)), + ] = None + r"""Optional. Filter by BCP-47 language code (e.g. \"en-US\"). + Case-insensitive exact match. If multiple values are specified, matches + voices with any of the specified language codes (OR). + """ + + page_size: Annotated[ + Optional[int], + FieldMetadata(query=QueryParamMetadata(style="form", explode=True)), + ] = None + r"""Optional. The maximum number of voices to return per page. The service may + return fewer than this value. If unspecified, at most 50 voices are + returned. The maximum value is 1000; values above 1000 are coerced to + 1000. + """ + + page_token: Annotated[ + Optional[str], + FieldMetadata(query=QueryParamMetadata(style="form", explode=True)), + ] = None + r"""Optional. A page token received from a previous `ListVoices` call. Provide + this to retrieve the subsequent page. + + When paginating, all filter query parameters (`language_code`, + `region_code`, `accent`, `persona`, `context`, `gender`, `pitch`, `type`, + and `search`) must match the call that returned this token; otherwise the + request fails with `INVALID_ARGUMENT`. `page_size` may change between + pages. + """ + + persona: Annotated[ + Optional[List[str]], + FieldMetadata(query=QueryParamMetadata(style="form", explode=True)), + ] = None + r"""Optional. Filter by vocal persona (e.g. \"Warm, Friendly\"). + Case-insensitive exact match. If multiple values are specified, matches + voices with any of the specified personas (OR). + """ + + pitch: Annotated[ + Optional[List[str]], + FieldMetadata(query=QueryParamMetadata(style="form", explode=True)), + ] = None + r"""Optional. Filter by vocal pitch. Accepts `\"low\"`, `\"medium\"`, `\"high\"` + (case-insensitive). If multiple values are specified, matches voices with + any of the specified pitches (OR). + """ + + region_code: Annotated[ + Optional[List[str]], + FieldMetadata(query=QueryParamMetadata(style="form", explode=True)), + ] = None + r"""Optional. Filter by ISO 3166-1 alpha-2 or UN M.49 region code (e.g. \"US\", + \"001\"). + Case-insensitive exact match. If multiple values are specified, matches + voices with any of the specified region codes (OR). + """ + + search: Annotated[ + Optional[str], + FieldMetadata(query=QueryParamMetadata(style="form", explode=True)), + ] = None + r"""Optional. Free-text substring search query matched case-insensitively + against both `display_name` and `description`. Maximum 2048 bytes. + """ + + type: Annotated[ + Optional[List[str]], + FieldMetadata(query=QueryParamMetadata(style="form", explode=True)), + ] = None + r"""Optional. Filter by voice type. Accepts `\"prebuilt\"`, `\"replicated\"`, + `\"prompted\"` (case-insensitive). If multiple values are specified, matches + voices with any of the specified types (OR). + """ + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set( + [ + "api_version", + "accent", + "contexts", + "gender", + "language_code", + "page_size", + "page_token", + "persona", + "pitch", + "region_code", + "search", + "type", + ] + ) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m diff --git a/google/genai/_gaos/resources/__init__.py b/google/genai/_gaos/resources/__init__.py index 81ed4cc08..bd8a0a221 100644 --- a/google/genai/_gaos/resources/__init__.py +++ b/google/genai/_gaos/resources/__init__.py @@ -22,6 +22,7 @@ from . import environments from . import interactions from . import triggers +from . import voices from . import webhooks __all__ = [ @@ -30,5 +31,6 @@ "environments", "interactions", "triggers", + "voices", "webhooks", ] diff --git a/google/genai/_gaos/resources/voices/__init__.py b/google/genai/_gaos/resources/voices/__init__.py new file mode 100644 index 000000000..e9e1a763e --- /dev/null +++ b/google/genai/_gaos/resources/voices/__init__.py @@ -0,0 +1,52 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# pyformat: disable +# pylint: skip-file + +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from ...models.createvoice import CreateVoiceRequestParam as VoiceCreateParams +from ...models.deletevoice import DeleteVoiceRequestParam as VoiceDeleteParams +from ...models.getvoice import GetVoiceRequestParam as VoiceGetParams +from ...models.listvoices import ListVoicesRequestParam as VoiceListParams +from ...types.voices.audiodata import AudioData +from ...types.voices.createvoicerequest import CreateVoiceRequest +from ...types.voices.deletevoiceresponse import ( + DeleteVoiceResponse as VoiceDeleteResponse, +) +from ...types.voices.listvoicesresponse import ListVoicesResponse as VoiceListResponse +from ...types.voices.pitch import Pitch +from ...types.voices.promptedvoice import PromptedVoice +from ...types.voices.replicatedvoice import ReplicatedVoice +from ...types.voices.voicetype import VoiceType +from . import createvoicerequest +from . import voicelistresponse + +__all__ = [ + "AudioData", + "CreateVoiceRequest", + "Pitch", + "PromptedVoice", + "ReplicatedVoice", + "VoiceCreateParams", + "VoiceDeleteParams", + "VoiceDeleteResponse", + "VoiceGetParams", + "VoiceListParams", + "VoiceListResponse", + "VoiceType", + "createvoicerequest", + "voicelistresponse", +] diff --git a/google/genai/_gaos/resources/voices/createvoicerequest/__init__.py b/google/genai/_gaos/resources/voices/createvoicerequest/__init__.py new file mode 100644 index 000000000..d012b1650 --- /dev/null +++ b/google/genai/_gaos/resources/voices/createvoicerequest/__init__.py @@ -0,0 +1,22 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# pyformat: disable +# pylint: skip-file + +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from ....types.voices.voice_input import VoiceInput as Voice + +__all__ = ["Voice"] diff --git a/google/genai/_gaos/resources/voices/voicelistresponse/__init__.py b/google/genai/_gaos/resources/voices/voicelistresponse/__init__.py new file mode 100644 index 000000000..2e70befc3 --- /dev/null +++ b/google/genai/_gaos/resources/voices/voicelistresponse/__init__.py @@ -0,0 +1,22 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# pyformat: disable +# pylint: skip-file + +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from ....types.voices.voice_output import VoiceOutput as Voice + +__all__ = ["Voice"] diff --git a/google/genai/_gaos/sdk.py b/google/genai/_gaos/sdk.py index ecc566eae..6abfec12b 100644 --- a/google/genai/_gaos/sdk.py +++ b/google/genai/_gaos/sdk.py @@ -44,6 +44,7 @@ from .environments import AsyncEnvironments, Environments from .interactions import AsyncInteractions, Interactions from .triggers import AsyncTriggers, Triggers + from .voices import AsyncVoices, Voices from .webhooks import AsyncWebhooks, Webhooks @@ -63,6 +64,7 @@ def with_streaming_response(self): credentials: "Credentials" interactions: "Interactions" triggers: "Triggers" + voices: "Voices" webhooks: "Webhooks" _sub_sdk_map = { "environments": (".environments", "Environments"), @@ -70,6 +72,7 @@ def with_streaming_response(self): "credentials": (".credentials", "Credentials"), "interactions": (".interactions", "Interactions"), "triggers": (".triggers", "Triggers"), + "voices": (".voices", "Voices"), "webhooks": (".webhooks", "Webhooks"), } @@ -234,6 +237,10 @@ def interactions(self): def triggers(self): return self._sdk.triggers.with_raw_response + @property + def voices(self): + return self._sdk.voices.with_raw_response + @property def webhooks(self): return self._sdk.webhooks.with_raw_response @@ -263,6 +270,10 @@ def interactions(self): def triggers(self): return self._sdk.triggers.with_streaming_response + @property + def voices(self): + return self._sdk.voices.with_streaming_response + @property def webhooks(self): return self._sdk.webhooks.with_streaming_response @@ -284,6 +295,7 @@ def with_streaming_response(self): credentials: "AsyncCredentials" interactions: "AsyncInteractions" triggers: "AsyncTriggers" + voices: "AsyncVoices" webhooks: "AsyncWebhooks" _sub_sdk_map = { "environments": (".environments", "AsyncEnvironments"), @@ -291,6 +303,7 @@ def with_streaming_response(self): "credentials": (".credentials", "AsyncCredentials"), "interactions": (".interactions", "AsyncInteractions"), "triggers": (".triggers", "AsyncTriggers"), + "voices": (".voices", "AsyncVoices"), "webhooks": (".webhooks", "AsyncWebhooks"), } @@ -453,6 +466,10 @@ def interactions(self): def triggers(self): return self._sdk.triggers.with_raw_response + @property + def voices(self): + return self._sdk.voices.with_raw_response + @property def webhooks(self): return self._sdk.webhooks.with_raw_response @@ -482,6 +499,10 @@ def interactions(self): def triggers(self): return self._sdk.triggers.with_streaming_response + @property + def voices(self): + return self._sdk.voices.with_streaming_response + @property def webhooks(self): return self._sdk.webhooks.with_streaming_response diff --git a/google/genai/_gaos/types/__init__.py b/google/genai/_gaos/types/__init__.py index 767369fe4..9e7116f83 100644 --- a/google/genai/_gaos/types/__init__.py +++ b/google/genai/_gaos/types/__init__.py @@ -33,7 +33,15 @@ if TYPE_CHECKING: from .security import Security, SecurityTypedDict - from . import agents, credentials, environments, interactions, triggers, webhooks + from . import ( + agents, + credentials, + environments, + interactions, + triggers, + voices, + webhooks, + ) __all__ = [ "Base64EncodedString", @@ -60,6 +68,7 @@ "environments", "interactions", "triggers", + "voices", "webhooks", ] diff --git a/google/genai/_gaos/types/voices/__init__.py b/google/genai/_gaos/types/voices/__init__.py new file mode 100644 index 000000000..390e9547d --- /dev/null +++ b/google/genai/_gaos/types/voices/__init__.py @@ -0,0 +1,86 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# pyformat: disable +# pylint: skip-file + +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from typing import Any, TYPE_CHECKING + +from ...utils.dynamic_imports import lazy_getattr, lazy_dir + +if TYPE_CHECKING: + from .audiodata import AudioData, AudioDataParam + from .createvoicerequest import CreateVoiceRequest, CreateVoiceRequestParam + from .deletevoiceresponse import DeleteVoiceResponse, DeleteVoiceResponseTypedDict + from .listvoicesresponse import ListVoicesResponse, ListVoicesResponseTypedDict + from .pitch import Pitch + from .promptedvoice import PromptedVoice, PromptedVoiceParam + from .replicatedvoice import ReplicatedVoice, ReplicatedVoiceParam + from .voice_input import VoiceInput, VoiceInputParam + from .voice_output import VoiceOutput, VoiceOutputTypedDict + from .voicetype import VoiceType + +__all__ = [ + "AudioData", + "AudioDataParam", + "CreateVoiceRequest", + "CreateVoiceRequestParam", + "DeleteVoiceResponse", + "DeleteVoiceResponseTypedDict", + "ListVoicesResponse", + "ListVoicesResponseTypedDict", + "Pitch", + "PromptedVoice", + "PromptedVoiceParam", + "ReplicatedVoice", + "ReplicatedVoiceParam", + "VoiceInput", + "VoiceInputParam", + "VoiceOutput", + "VoiceOutputTypedDict", + "VoiceType", +] + +_dynamic_imports: dict[str, str] = { + "AudioData": ".audiodata", + "AudioDataParam": ".audiodata", + "CreateVoiceRequest": ".createvoicerequest", + "CreateVoiceRequestParam": ".createvoicerequest", + "DeleteVoiceResponse": ".deletevoiceresponse", + "DeleteVoiceResponseTypedDict": ".deletevoiceresponse", + "ListVoicesResponse": ".listvoicesresponse", + "ListVoicesResponseTypedDict": ".listvoicesresponse", + "Pitch": ".pitch", + "PromptedVoice": ".promptedvoice", + "PromptedVoiceParam": ".promptedvoice", + "ReplicatedVoice": ".replicatedvoice", + "ReplicatedVoiceParam": ".replicatedvoice", + "VoiceInput": ".voice_input", + "VoiceInputParam": ".voice_input", + "VoiceOutput": ".voice_output", + "VoiceOutputTypedDict": ".voice_output", + "VoiceType": ".voicetype", +} + + +def __getattr__(attr_name: str) -> Any: + return lazy_getattr( + attr_name, package=__package__, dynamic_imports=_dynamic_imports + ) + + +def __dir__(): + return lazy_dir(dynamic_imports=_dynamic_imports) diff --git a/google/genai/_gaos/types/voices/audiodata.py b/google/genai/_gaos/types/voices/audiodata.py new file mode 100644 index 000000000..51f786621 --- /dev/null +++ b/google/genai/_gaos/types/voices/audiodata.py @@ -0,0 +1,46 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# pyformat: disable +# pylint: skip-file + +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .. import Base64EncodedString, Base64FileInput, BaseModel +from typing import Union +from typing_extensions import TypedDict + + +class AudioDataParam(TypedDict): + r"""Audio payload used for voice creation.""" + + data: Union[str, Base64FileInput] + r"""Required. The raw audio bytes.""" + mime_type: str + r"""Required. The IANA MIME type of the audio data (for example, `audio/wav` or + `audio/mpeg`). + """ + + +class AudioData(BaseModel): + r"""Audio payload used for voice creation.""" + + data: Base64EncodedString + r"""Required. The raw audio bytes.""" + + mime_type: str + r"""Required. The IANA MIME type of the audio data (for example, `audio/wav` or + `audio/mpeg`). + """ diff --git a/google/genai/_gaos/types/voices/createvoicerequest.py b/google/genai/_gaos/types/voices/createvoicerequest.py new file mode 100644 index 000000000..4adadb312 --- /dev/null +++ b/google/genai/_gaos/types/voices/createvoicerequest.py @@ -0,0 +1,90 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# pyformat: disable +# pylint: skip-file + +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .voice_input import VoiceInput, VoiceInputParam +from .. import BaseModel, UNSET_SENTINEL +from pydantic import model_serializer +from typing import Optional +from typing_extensions import NotRequired, TypedDict + + +class CreateVoiceRequestParam(TypedDict): + r"""Request message for `VoicesService.CreateVoice`.""" + + voice: VoiceInputParam + r"""A voice resource representing either a custom voice (created via + `CreateVoice`) or a prebuilt system voice (returned by `ListVoices`). + """ + store: NotRequired[bool] + r"""Optional. Whether the created voice is persisted and managed by Google. + + * When `true`, Google stores the voice and returns `Voice.id` (for example, + `voice_abc123def456`), which can be managed via `GetVoice`, `ListVoices`, + and `DeleteVoice` and referenced by ID in synthesis requests. Projects + are subject to a maximum active stored voice quota; exceeding the quota + returns `RESOURCE_EXHAUSTED`. + * When `false` (default), the voice is not stored by Google and `Voice.key` + (for example, `voicekey_...`) is returned for client-side storage and + synthesis. Optional discovery metadata fields on `voice` are not + persisted or returned when `store` is `false`. + * Required to be `true` when `voice.type` is `\"prompted\"` + (otherwise fails with `INVALID_ARGUMENT`). + """ + + +class CreateVoiceRequest(BaseModel): + r"""Request message for `VoicesService.CreateVoice`.""" + + voice: VoiceInput + r"""A voice resource representing either a custom voice (created via + `CreateVoice`) or a prebuilt system voice (returned by `ListVoices`). + """ + + store: Optional[bool] = None + r"""Optional. Whether the created voice is persisted and managed by Google. + + * When `true`, Google stores the voice and returns `Voice.id` (for example, + `voice_abc123def456`), which can be managed via `GetVoice`, `ListVoices`, + and `DeleteVoice` and referenced by ID in synthesis requests. Projects + are subject to a maximum active stored voice quota; exceeding the quota + returns `RESOURCE_EXHAUSTED`. + * When `false` (default), the voice is not stored by Google and `Voice.key` + (for example, `voicekey_...`) is returned for client-side storage and + synthesis. Optional discovery metadata fields on `voice` are not + persisted or returned when `store` is `false`. + * Required to be `true` when `voice.type` is `\"prompted\"` + (otherwise fails with `INVALID_ARGUMENT`). + """ + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["store"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m diff --git a/google/genai/_gaos/types/voices/deletevoiceresponse.py b/google/genai/_gaos/types/voices/deletevoiceresponse.py new file mode 100644 index 000000000..b72eb9f09 --- /dev/null +++ b/google/genai/_gaos/types/voices/deletevoiceresponse.py @@ -0,0 +1,30 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# pyformat: disable +# pylint: skip-file + +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .. import BaseModel +from typing_extensions import TypedDict + + +class DeleteVoiceResponseTypedDict(TypedDict): + r"""Response message for `VoicesService.DeleteVoice`.""" + + +class DeleteVoiceResponse(BaseModel): + r"""Response message for `VoicesService.DeleteVoice`.""" diff --git a/google/genai/_gaos/types/voices/listvoicesresponse.py b/google/genai/_gaos/types/voices/listvoicesresponse.py new file mode 100644 index 000000000..da41afbf0 --- /dev/null +++ b/google/genai/_gaos/types/voices/listvoicesresponse.py @@ -0,0 +1,64 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# pyformat: disable +# pylint: skip-file + +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .voice_output import VoiceOutput, VoiceOutputTypedDict +from .. import BaseModel, UNSET_SENTINEL +from pydantic import model_serializer +from typing import List, Optional +from typing_extensions import NotRequired, TypedDict + + +class ListVoicesResponseTypedDict(TypedDict): + r"""Response message for `VoicesService.ListVoices`.""" + + next_page_token: NotRequired[str] + r"""A token that can be sent as `page_token` to retrieve the next page. + If empty, there are no subsequent pages. + """ + voices: NotRequired[List[VoiceOutputTypedDict]] + r"""The voices from the specified collection.""" + + +class ListVoicesResponse(BaseModel): + r"""Response message for `VoicesService.ListVoices`.""" + + next_page_token: Optional[str] = None + r"""A token that can be sent as `page_token` to retrieve the next page. + If empty, there are no subsequent pages. + """ + + voices: Optional[List[VoiceOutput]] = None + r"""The voices from the specified collection.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["next_page_token", "voices"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m diff --git a/google/genai/_gaos/types/voices/pitch.py b/google/genai/_gaos/types/voices/pitch.py new file mode 100644 index 000000000..0bd581f6e --- /dev/null +++ b/google/genai/_gaos/types/voices/pitch.py @@ -0,0 +1,32 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# pyformat: disable +# pylint: skip-file + +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .. import UnrecognizedStr +from typing import Literal, Union + + +Pitch = Union[ + Literal[ + "low", + "medium", + "high", + ], + UnrecognizedStr, +] diff --git a/google/genai/_gaos/types/voices/promptedvoice.py b/google/genai/_gaos/types/voices/promptedvoice.py new file mode 100644 index 000000000..060d8887d --- /dev/null +++ b/google/genai/_gaos/types/voices/promptedvoice.py @@ -0,0 +1,46 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# pyformat: disable +# pylint: skip-file + +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .. import BaseModel +from typing_extensions import TypedDict + + +class PromptedVoiceParam(TypedDict): + r"""Parameters for prompted voice generation. + Required in `CreateVoice` when `type` is `\"prompted\"`. Returned in + `CreateVoice`, `GetVoice`, and `ListVoices` responses for prompted voices. + """ + + input: str + r"""Required. The natural-language prompt describing the desired voice, e.g. + \"A deep, booming male voice of a massive evil ogre in his middle years.\" + """ + + +class PromptedVoice(BaseModel): + r"""Parameters for prompted voice generation. + Required in `CreateVoice` when `type` is `\"prompted\"`. Returned in + `CreateVoice`, `GetVoice`, and `ListVoices` responses for prompted voices. + """ + + input: str + r"""Required. The natural-language prompt describing the desired voice, e.g. + \"A deep, booming male voice of a massive evil ogre in his middle years.\" + """ diff --git a/google/genai/_gaos/types/voices/replicatedvoice.py b/google/genai/_gaos/types/voices/replicatedvoice.py new file mode 100644 index 000000000..29a1db847 --- /dev/null +++ b/google/genai/_gaos/types/voices/replicatedvoice.py @@ -0,0 +1,48 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# pyformat: disable +# pylint: skip-file + +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .audiodata import AudioData, AudioDataParam +from .. import BaseModel +from typing_extensions import TypedDict + + +class ReplicatedVoiceParam(TypedDict): + r"""Input only. Parameters for replicated voice generation. + Required on input when `type` is `\"replicated\"`. Not returned in + responses. + """ + + consent_audio: AudioDataParam + r"""Audio payload used for voice creation.""" + source_audio: AudioDataParam + r"""Audio payload used for voice creation.""" + + +class ReplicatedVoice(BaseModel): + r"""Input only. Parameters for replicated voice generation. + Required on input when `type` is `\"replicated\"`. Not returned in + responses. + """ + + consent_audio: AudioData + r"""Audio payload used for voice creation.""" + + source_audio: AudioData + r"""Audio payload used for voice creation.""" diff --git a/google/genai/_gaos/types/voices/voice_input.py b/google/genai/_gaos/types/voices/voice_input.py new file mode 100644 index 000000000..452baf0a2 --- /dev/null +++ b/google/genai/_gaos/types/voices/voice_input.py @@ -0,0 +1,177 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# pyformat: disable +# pylint: skip-file + +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .pitch import Pitch +from .promptedvoice import PromptedVoice, PromptedVoiceParam +from .replicatedvoice import ReplicatedVoice, ReplicatedVoiceParam +from .voicetype import VoiceType +from .. import BaseModel, UNSET_SENTINEL +from pydantic import model_serializer +from typing import Optional +from typing_extensions import NotRequired, TypedDict + + +class VoiceInputParam(TypedDict): + r"""A voice resource representing either a custom voice (created via + `CreateVoice`) or a prebuilt system voice (returned by `ListVoices`). + """ + + type: VoiceType + accent: NotRequired[str] + r"""Optional. Regional accent descriptor (e.g. \"American\", \"British\").""" + context: NotRequired[str] + r"""Optional. Optimal usage context or domain (e.g. \"Conversational\", + \"Audiobook\", \"News\"). + """ + description: NotRequired[str] + r"""Optional. Descriptive summary of vocal timbre, personality, and tone.""" + display_name: NotRequired[str] + r"""Optional. User-provided display name for a stored voice (`store = true`), + or the catalog name for a prebuilt voice. + """ + gender: NotRequired[str] + r"""Optional. Perceived voice gender presentation (e.g. \"female\", \"male\", + \"neutral\"). + """ + language_code: NotRequired[str] + r"""Optional. Primary BCP-47 language tag (e.g. \"en-US\", \"fr-FR\").""" + model: NotRequired[str] + r"""Optional. The model used to design or replicate the voice. + If omitted in `CreateVoice`, defaults to the latest supported voice design + model. Returned in `CreateVoice`, `GetVoice`, and `ListVoices` responses + for custom voices (`\"prompted\"` and `\"replicated\"`); unset for `\"prebuilt\"` + voices. Created voices can be synthesized across any supported TTS + synthesis model. + """ + persona: NotRequired[str] + r"""Optional. Intended persona or character archetype (e.g. \"Warm, Friendly\", + \"Narrator\"). + """ + pitch: NotRequired[Pitch] + prompted: NotRequired[PromptedVoiceParam] + r"""Parameters for prompted voice generation. + Required in `CreateVoice` when `type` is `\"prompted\"`. Returned in + `CreateVoice`, `GetVoice`, and `ListVoices` responses for prompted voices. + """ + region_code: NotRequired[str] + r"""Optional. ISO 3166-1 alpha-2 or UN M.49 geographic region code (e.g. \"US\", + \"GB\", \"001\"). + """ + replicated: NotRequired[ReplicatedVoiceParam] + r"""Input only. Parameters for replicated voice generation. + Required on input when `type` is `\"replicated\"`. Not returned in + responses. + """ + + +class VoiceInput(BaseModel): + r"""A voice resource representing either a custom voice (created via + `CreateVoice`) or a prebuilt system voice (returned by `ListVoices`). + """ + + type: VoiceType + + accent: Optional[str] = None + r"""Optional. Regional accent descriptor (e.g. \"American\", \"British\").""" + + context: Optional[str] = None + r"""Optional. Optimal usage context or domain (e.g. \"Conversational\", + \"Audiobook\", \"News\"). + """ + + description: Optional[str] = None + r"""Optional. Descriptive summary of vocal timbre, personality, and tone.""" + + display_name: Optional[str] = None + r"""Optional. User-provided display name for a stored voice (`store = true`), + or the catalog name for a prebuilt voice. + """ + + gender: Optional[str] = None + r"""Optional. Perceived voice gender presentation (e.g. \"female\", \"male\", + \"neutral\"). + """ + + language_code: Optional[str] = None + r"""Optional. Primary BCP-47 language tag (e.g. \"en-US\", \"fr-FR\").""" + + model: Optional[str] = None + r"""Optional. The model used to design or replicate the voice. + If omitted in `CreateVoice`, defaults to the latest supported voice design + model. Returned in `CreateVoice`, `GetVoice`, and `ListVoices` responses + for custom voices (`\"prompted\"` and `\"replicated\"`); unset for `\"prebuilt\"` + voices. Created voices can be synthesized across any supported TTS + synthesis model. + """ + + persona: Optional[str] = None + r"""Optional. Intended persona or character archetype (e.g. \"Warm, Friendly\", + \"Narrator\"). + """ + + pitch: Optional[Pitch] = None + + prompted: Optional[PromptedVoice] = None + r"""Parameters for prompted voice generation. + Required in `CreateVoice` when `type` is `\"prompted\"`. Returned in + `CreateVoice`, `GetVoice`, and `ListVoices` responses for prompted voices. + """ + + region_code: Optional[str] = None + r"""Optional. ISO 3166-1 alpha-2 or UN M.49 geographic region code (e.g. \"US\", + \"GB\", \"001\"). + """ + + replicated: Optional[ReplicatedVoice] = None + r"""Input only. Parameters for replicated voice generation. + Required on input when `type` is `\"replicated\"`. Not returned in + responses. + """ + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set( + [ + "accent", + "context", + "description", + "display_name", + "gender", + "language_code", + "model", + "persona", + "pitch", + "prompted", + "region_code", + "replicated", + ] + ) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m diff --git a/google/genai/_gaos/types/voices/voice_output.py b/google/genai/_gaos/types/voices/voice_output.py new file mode 100644 index 000000000..13494290d --- /dev/null +++ b/google/genai/_gaos/types/voices/voice_output.py @@ -0,0 +1,224 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# pyformat: disable +# pylint: skip-file + +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .pitch import Pitch +from .promptedvoice import PromptedVoice, PromptedVoiceParam +from .voicetype import VoiceType +from datetime import datetime +from .. import BaseModel, UNSET_SENTINEL +from ..interactions import usage as interactions_usage +from pydantic import model_serializer +from typing import Optional +from typing_extensions import NotRequired, TypedDict + + +class VoiceOutputTypedDict(TypedDict): + r"""A voice resource representing either a custom voice (created via + `CreateVoice`) or a prebuilt system voice (returned by `ListVoices`). + """ + + type: VoiceType + accent: NotRequired[str] + r"""Optional. Regional accent descriptor (e.g. \"American\", \"British\").""" + context: NotRequired[str] + r"""Optional. Optimal usage context or domain (e.g. \"Conversational\", + \"Audiobook\", \"News\"). + """ + description: NotRequired[str] + r"""Optional. Descriptive summary of vocal timbre, personality, and tone.""" + display_name: NotRequired[str] + r"""Optional. User-provided display name for a stored voice (`store = true`), + or the catalog name for a prebuilt voice. + """ + expire_time: NotRequired[datetime] + r"""Output only. The timestamp at which a custom stored voice (`store = true`) + or replicated voice key (`store = false`) expires. Unset for prebuilt + catalog voices (`\"prebuilt\"`), which do not expire. + """ + gender: NotRequired[str] + r"""Optional. Perceived voice gender presentation (e.g. \"female\", \"male\", + \"neutral\"). + """ + id: NotRequired[str] + r"""Output only. The unique identifier of the voice. + + * For Google-managed custom voices (`store = true`), this is a generated ID + with prefix `voice_` (for example, `voice_abc123def456`). Pass + `voices/{id}` as the `name` in `GetVoice` and `DeleteVoice`, and pass + `{id}` directly to `SpeechConfig.voice_config.voice` (or + `SpeechConfig.voice`) during speech synthesis. + * For prebuilt catalog voices (`\"prebuilt\"` returned by `ListVoices`), this + is the speaker name (for example, `Puck` or `Charon`). + * Unset when `CreateVoice` is called with `store = false`. + """ + key: NotRequired[str] + r"""Output only. The client-managed voice replication key (with prefix + `voicekey_`). Returned only by `CreateVoice` when `type` is `\"replicated\"` + and `store` is `false`. Pass this key to `SpeechConfig.voice_config.voice` + (or `SpeechConfig.voice`) during speech synthesis. + """ + language_code: NotRequired[str] + r"""Optional. Primary BCP-47 language tag (e.g. \"en-US\", \"fr-FR\").""" + model: NotRequired[str] + r"""Optional. The model used to design or replicate the voice. + If omitted in `CreateVoice`, defaults to the latest supported voice design + model. Returned in `CreateVoice`, `GetVoice`, and `ListVoices` responses + for custom voices (`\"prompted\"` and `\"replicated\"`); unset for `\"prebuilt\"` + voices. Created voices can be synthesized across any supported TTS + synthesis model. + """ + persona: NotRequired[str] + r"""Optional. Intended persona or character archetype (e.g. \"Warm, Friendly\", + \"Narrator\"). + """ + pitch: NotRequired[Pitch] + prompted: NotRequired[PromptedVoiceParam] + r"""Parameters for prompted voice generation. + Required in `CreateVoice` when `type` is `\"prompted\"`. Returned in + `CreateVoice`, `GetVoice`, and `ListVoices` responses for prompted voices. + """ + region_code: NotRequired[str] + r"""Optional. ISO 3166-1 alpha-2 or UN M.49 geographic region code (e.g. \"US\", + \"GB\", \"001\"). + """ + usage: NotRequired[interactions_usage.UsageTypedDict] + r"""Statistics on the interaction request's token usage.""" + + +class VoiceOutput(BaseModel): + r"""A voice resource representing either a custom voice (created via + `CreateVoice`) or a prebuilt system voice (returned by `ListVoices`). + """ + + type: VoiceType + + accent: Optional[str] = None + r"""Optional. Regional accent descriptor (e.g. \"American\", \"British\").""" + + context: Optional[str] = None + r"""Optional. Optimal usage context or domain (e.g. \"Conversational\", + \"Audiobook\", \"News\"). + """ + + description: Optional[str] = None + r"""Optional. Descriptive summary of vocal timbre, personality, and tone.""" + + display_name: Optional[str] = None + r"""Optional. User-provided display name for a stored voice (`store = true`), + or the catalog name for a prebuilt voice. + """ + + expire_time: Optional[datetime] = None + r"""Output only. The timestamp at which a custom stored voice (`store = true`) + or replicated voice key (`store = false`) expires. Unset for prebuilt + catalog voices (`\"prebuilt\"`), which do not expire. + """ + + gender: Optional[str] = None + r"""Optional. Perceived voice gender presentation (e.g. \"female\", \"male\", + \"neutral\"). + """ + + id: Optional[str] = None + r"""Output only. The unique identifier of the voice. + + * For Google-managed custom voices (`store = true`), this is a generated ID + with prefix `voice_` (for example, `voice_abc123def456`). Pass + `voices/{id}` as the `name` in `GetVoice` and `DeleteVoice`, and pass + `{id}` directly to `SpeechConfig.voice_config.voice` (or + `SpeechConfig.voice`) during speech synthesis. + * For prebuilt catalog voices (`\"prebuilt\"` returned by `ListVoices`), this + is the speaker name (for example, `Puck` or `Charon`). + * Unset when `CreateVoice` is called with `store = false`. + """ + + key: Optional[str] = None + r"""Output only. The client-managed voice replication key (with prefix + `voicekey_`). Returned only by `CreateVoice` when `type` is `\"replicated\"` + and `store` is `false`. Pass this key to `SpeechConfig.voice_config.voice` + (or `SpeechConfig.voice`) during speech synthesis. + """ + + language_code: Optional[str] = None + r"""Optional. Primary BCP-47 language tag (e.g. \"en-US\", \"fr-FR\").""" + + model: Optional[str] = None + r"""Optional. The model used to design or replicate the voice. + If omitted in `CreateVoice`, defaults to the latest supported voice design + model. Returned in `CreateVoice`, `GetVoice`, and `ListVoices` responses + for custom voices (`\"prompted\"` and `\"replicated\"`); unset for `\"prebuilt\"` + voices. Created voices can be synthesized across any supported TTS + synthesis model. + """ + + persona: Optional[str] = None + r"""Optional. Intended persona or character archetype (e.g. \"Warm, Friendly\", + \"Narrator\"). + """ + + pitch: Optional[Pitch] = None + + prompted: Optional[PromptedVoice] = None + r"""Parameters for prompted voice generation. + Required in `CreateVoice` when `type` is `\"prompted\"`. Returned in + `CreateVoice`, `GetVoice`, and `ListVoices` responses for prompted voices. + """ + + region_code: Optional[str] = None + r"""Optional. ISO 3166-1 alpha-2 or UN M.49 geographic region code (e.g. \"US\", + \"GB\", \"001\"). + """ + + usage: Optional[interactions_usage.Usage] = None + r"""Statistics on the interaction request's token usage.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set( + [ + "accent", + "context", + "description", + "display_name", + "expire_time", + "gender", + "id", + "key", + "language_code", + "model", + "persona", + "pitch", + "prompted", + "region_code", + "usage", + ] + ) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m diff --git a/google/genai/_gaos/types/voices/voicetype.py b/google/genai/_gaos/types/voices/voicetype.py new file mode 100644 index 000000000..4bce9fbf1 --- /dev/null +++ b/google/genai/_gaos/types/voices/voicetype.py @@ -0,0 +1,32 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# pyformat: disable +# pylint: skip-file + +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .. import UnrecognizedStr +from typing import Literal, Union + + +VoiceType = Union[ + Literal[ + "replicated", + "prompted", + "prebuilt", + ], + UnrecognizedStr, +] diff --git a/google/genai/_gaos/voices.py b/google/genai/_gaos/voices.py new file mode 100644 index 000000000..9a27ae090 --- /dev/null +++ b/google/genai/_gaos/voices.py @@ -0,0 +1,1512 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# pyformat: disable +# pylint: skip-file + +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from .basesdk import AsyncBaseSDK, BaseSDK +from . import errors, models, types, utils +from ._hooks import AfterParseErrorContext, HookContext, ResponseContext +from .types import OptionalNullable, UNSET, voices +from .types.voices import voice_input as voices_voice_input +from .utils import get_security_from_env, response_helpers +from .utils.unmarshal_json_response import unmarshal_json_response +import httpx +from typing import Any, Iterable, List, Mapping, Optional, Union, cast + + +class Voices(BaseSDK): + @property + def with_raw_response(self): + return VoicesWithRawResponse(self) + + @property + def with_streaming_response(self): + return VoicesWithStreamingResponse(self) + + def list( + self, + *, + api_version: Optional[str] = None, + accent: Optional[Iterable[str]] = None, + contexts: Optional[Iterable[str]] = None, + gender: Optional[Iterable[str]] = None, + language_code: Optional[Iterable[str]] = None, + page_size: Optional[int] = None, + page_token: Optional[str] = None, + persona: Optional[Iterable[str]] = None, + pitch: Optional[Iterable[str]] = None, + region_code: Optional[Iterable[str]] = None, + search: Optional[str] = None, + type_: Optional[Iterable[str]] = None, + extra_headers: Optional[Mapping[str, str]] = None, + extra_query: Optional[Mapping[str, Any]] = None, + timeout: Optional[Union[float, httpx.Timeout]] = None, + ) -> voices.ListVoicesResponse: + r"""Lists custom stored voices owned by the caller (ordered newest first) + followed by prebuilt system voices from Google's voice catalog. + + :param api_version: API version for request routing. + :param accent: Optional. Filter by accent description (e.g. \"American\", \"British\"). + Case-insensitive exact match. If multiple values are specified, matches + voices with any of the specified accents (OR). + :param contexts: Optional. Filter by intended context or domain (e.g. \"News, Commercial\"). + Case-insensitive exact match. If multiple values are specified, matches + voices with any of the specified contexts (OR). + :param gender: Optional. Filter by gender presentation (e.g. \"female\", \"male\", \"neutral\"). + Case-insensitive exact match. If multiple values are specified, matches + voices with any of the specified genders (OR). + :param language_code: Optional. Filter by BCP-47 language code (e.g. \"en-US\"). + Case-insensitive exact match. If multiple values are specified, matches + voices with any of the specified language codes (OR). + :param page_size: Optional. The maximum number of voices to return per page. The service may + return fewer than this value. If unspecified, at most 50 voices are + returned. The maximum value is 1000; values above 1000 are coerced to + 1000. + :param page_token: Optional. A page token received from a previous `ListVoices` call. Provide + this to retrieve the subsequent page. + + When paginating, all filter query parameters (`language_code`, + `region_code`, `accent`, `persona`, `context`, `gender`, `pitch`, `type`, + and `search`) must match the call that returned this token; otherwise the + request fails with `INVALID_ARGUMENT`. `page_size` may change between + pages. + :param persona: Optional. Filter by vocal persona (e.g. \"Warm, Friendly\"). + Case-insensitive exact match. If multiple values are specified, matches + voices with any of the specified personas (OR). + :param pitch: Optional. Filter by vocal pitch. Accepts `\"low\"`, `\"medium\"`, `\"high\"` + (case-insensitive). If multiple values are specified, matches voices with + any of the specified pitches (OR). + :param region_code: Optional. Filter by ISO 3166-1 alpha-2 or UN M.49 region code (e.g. \"US\", + \"001\"). + Case-insensitive exact match. If multiple values are specified, matches + voices with any of the specified region codes (OR). + :param search: Optional. Free-text substring search query matched case-insensitively + against both `display_name` and `description`. Maximum 2048 bytes. + :param type: Optional. Filter by voice type. Accepts `\"prebuilt\"`, `\"replicated\"`, + `\"prompted\"` (case-insensitive). If multiple values are specified, matches + voices with any of the specified types (OR). + :param extra_headers: Additional headers to set or replace on requests. + :param extra_query: Additional query parameters to append to requests. + :param timeout: Override the default request timeout configuration for this method in seconds + """ + base_url = None + url_variables = None + retries: OptionalNullable[utils.RetryConfig] = UNSET + server_url = None + http_headers = extra_headers + timeout_ms = self._coerce_timeout_ms(timeout) + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + else: + base_url = self._get_url(base_url, url_variables) + + request = models.ListVoicesRequest( + api_version=api_version, + accent=utils.unmarshal(accent, Optional[List[str]]), + contexts=utils.unmarshal(contexts, Optional[List[str]]), + gender=utils.unmarshal(gender, Optional[List[str]]), + language_code=utils.unmarshal(language_code, Optional[List[str]]), + page_size=page_size, + page_token=page_token, + persona=utils.unmarshal(persona, Optional[List[str]]), + pitch=utils.unmarshal(pitch, Optional[List[str]]), + region_code=utils.unmarshal(region_code, Optional[List[str]]), + search=search, + type=utils.unmarshal(type_, Optional[List[str]]), + ) + + _speakeasy_response_mode, http_headers = response_helpers.consume_response_mode( + http_headers + ) + req = self._build_request( + method="GET", + path="/{api_version}/voices", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + http_headers=http_headers, + extra_query_params=extra_query, + _globals=models.ListVoicesGlobals( + api_version=self.sdk_configuration.globals.api_version, + ), + security=self.sdk_configuration.security, + allow_empty_value=None, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + else: + retries = utils.RetryConfig( + "attempt-count-backoff", + utils.BackoffStrategy(500, 8000, 2, 30000), + True, + max_retries=4, + ) + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, ["408", "409", "429", "5XX"]) + + def _speakeasy_parse_response(http_res): + if utils.match_response(http_res, "4XX", "*"): + http_res_text = utils.stream_to_text(http_res) + raise errors.GenAiDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "5XX", "*"): + http_res_text = utils.stream_to_text(http_res) + raise errors.GenAiDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "default", "application/json"): + return unmarshal_json_response( + voices.ListVoicesResponse, http_res, validate=False + ) + + raise errors.GenAiDefaultError("Unexpected response received", http_res) + + _speakeasy_hook_ctx = HookContext( + config=self.sdk_configuration, + base_url=base_url or "", + operation_id="ListVoices", + oauth2_scopes=None, + security_source=get_security_from_env( + self.sdk_configuration.security, types.Security + ), + tags=["voices"], + extensions=None, + response=ResponseContext(mode=_speakeasy_response_mode, execution="sync"), + ) + http_res = self.do_request( + hook_ctx=_speakeasy_hook_ctx, + request=req, + is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c), + stream=_speakeasy_response_mode == "streaming", + retry_config=retry_config, + ) + if _speakeasy_response_mode != "parsed": + if utils.match_status_codes(["4XX", "5XX"], http_res.status_code): + http_res.read() + try: + _speakeasy_parse_response(http_res) + except Exception as parse_exc_: + response_helpers.raise_parse_error( + self.sdk_configuration.__dict__["_hooks"], + AfterParseErrorContext(_speakeasy_hook_ctx), + http_res, + parse_exc_, + ) + _speakeasy_response_cls = ( + response_helpers.StreamedAPIResponse + if _speakeasy_response_mode == "streaming" + else response_helpers.APIResponse + ) + return cast( + Any, + _speakeasy_response_cls( + raw=http_res, + parser=_speakeasy_parse_response, + mode="buffered", + client_ref=self, + hook_ctx=AfterParseErrorContext(_speakeasy_hook_ctx), + hooks=self.sdk_configuration.__dict__.get("_hooks"), + ), + ) + try: + return _speakeasy_parse_response(http_res) + except Exception as parse_exc_: + response_helpers.raise_parse_error( + self.sdk_configuration.__dict__["_hooks"], + AfterParseErrorContext(_speakeasy_hook_ctx), + http_res, + parse_exc_, + ) + + def create( + self, + *, + voice: Union[voices_voice_input.VoiceInput, voices_voice_input.VoiceInputParam], + api_version: Optional[str] = None, + store: Optional[bool] = None, + extra_headers: Optional[Mapping[str, str]] = None, + extra_query: Optional[Mapping[str, Any]] = None, + extra_body: Optional[Mapping[str, Any]] = None, + timeout: Optional[Union[float, httpx.Timeout]] = None, + ) -> voices.VoiceOutput: + r"""Creates a custom voice from a natural-language prompt + (`VOICE_TYPE_PROMPTED`) or from reference and consent audio recordings + (`VOICE_TYPE_REPLICATED`). + + :param voice: A voice resource representing either a custom voice (created via + `CreateVoice`) or a prebuilt system voice (returned by `ListVoices`). + :param api_version: API version for request routing. + :param store: Optional. Whether the created voice is persisted and managed by Google. + + * When `true`, Google stores the voice and returns `Voice.id` (for example, + `voice_abc123def456`), which can be managed via `GetVoice`, `ListVoices`, + and `DeleteVoice` and referenced by ID in synthesis requests. Projects + are subject to a maximum active stored voice quota; exceeding the quota + returns `RESOURCE_EXHAUSTED`. + * When `false` (default), the voice is not stored by Google and `Voice.key` + (for example, `voicekey_...`) is returned for client-side storage and + synthesis. Optional discovery metadata fields on `voice` are not + persisted or returned when `store` is `false`. + * Required to be `true` when `voice.type` is `\"prompted\"` + (otherwise fails with `INVALID_ARGUMENT`). + :param extra_headers: Additional headers to set or replace on requests. + :param extra_query: Additional query parameters to append to requests. + :param extra_body: Additional JSON object fields to merge into request bodies. + :param timeout: Override the default request timeout configuration for this method in seconds + """ + base_url = None + url_variables = None + retries: OptionalNullable[utils.RetryConfig] = UNSET + server_url = None + http_headers = extra_headers + timeout_ms = self._coerce_timeout_ms(timeout) + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + else: + base_url = self._get_url(base_url, url_variables) + + request = models.CreateVoiceRequest( + api_version=api_version, + body=voices.CreateVoiceRequest( + store=store, + voice=utils.get_pydantic_model(voice, voices.VoiceInput), + ), + ) + + _speakeasy_response_mode, http_headers = response_helpers.consume_response_mode( + http_headers + ) + req = self._build_request( + method="POST", + path="/{api_version}/voices", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=True, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + http_headers=http_headers, + extra_query_params=extra_query, + _globals=models.CreateVoiceGlobals( + api_version=self.sdk_configuration.globals.api_version, + ), + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body( + request.body, + False, + False, + "json", + voices.CreateVoiceRequest, + extra_body=extra_body, + ), + allow_empty_value=None, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + else: + retries = utils.RetryConfig( + "attempt-count-backoff", + utils.BackoffStrategy(500, 8000, 2, 30000), + True, + max_retries=4, + ) + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, ["408", "409", "429", "5XX"]) + + def _speakeasy_parse_response(http_res): + if utils.match_response(http_res, "4XX", "*"): + http_res_text = utils.stream_to_text(http_res) + raise errors.GenAiDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "5XX", "*"): + http_res_text = utils.stream_to_text(http_res) + raise errors.GenAiDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "default", "application/json"): + return unmarshal_json_response( + voices.VoiceOutput, http_res, validate=False + ) + + raise errors.GenAiDefaultError("Unexpected response received", http_res) + + _speakeasy_hook_ctx = HookContext( + config=self.sdk_configuration, + base_url=base_url or "", + operation_id="CreateVoice", + oauth2_scopes=None, + security_source=get_security_from_env( + self.sdk_configuration.security, types.Security + ), + tags=["voices"], + extensions=None, + response=ResponseContext(mode=_speakeasy_response_mode, execution="sync"), + ) + http_res = self.do_request( + hook_ctx=_speakeasy_hook_ctx, + request=req, + is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c), + stream=_speakeasy_response_mode == "streaming", + retry_config=retry_config, + ) + if _speakeasy_response_mode != "parsed": + if utils.match_status_codes(["4XX", "5XX"], http_res.status_code): + http_res.read() + try: + _speakeasy_parse_response(http_res) + except Exception as parse_exc_: + response_helpers.raise_parse_error( + self.sdk_configuration.__dict__["_hooks"], + AfterParseErrorContext(_speakeasy_hook_ctx), + http_res, + parse_exc_, + ) + _speakeasy_response_cls = ( + response_helpers.StreamedAPIResponse + if _speakeasy_response_mode == "streaming" + else response_helpers.APIResponse + ) + return cast( + Any, + _speakeasy_response_cls( + raw=http_res, + parser=_speakeasy_parse_response, + mode="buffered", + client_ref=self, + hook_ctx=AfterParseErrorContext(_speakeasy_hook_ctx), + hooks=self.sdk_configuration.__dict__.get("_hooks"), + ), + ) + try: + return _speakeasy_parse_response(http_res) + except Exception as parse_exc_: + response_helpers.raise_parse_error( + self.sdk_configuration.__dict__["_hooks"], + AfterParseErrorContext(_speakeasy_hook_ctx), + http_res, + parse_exc_, + ) + + def delete( + self, + id: str, + *, + api_version: Optional[str] = None, + extra_headers: Optional[Mapping[str, str]] = None, + extra_query: Optional[Mapping[str, Any]] = None, + timeout: Optional[Union[float, httpx.Timeout]] = None, + ) -> voices.DeleteVoiceResponse: + r"""Deletes a custom stored voice (`store = true`) by resource name. + Prebuilt catalog voices (`VOICE_TYPE_PREBUILT`) cannot be deleted. + + :param id: Required. The resource name of the custom stored voice to delete + (for example, `voices/voice_abc123def456`). + :param api_version: API version for request routing. + :param extra_headers: Additional headers to set or replace on requests. + :param extra_query: Additional query parameters to append to requests. + :param timeout: Override the default request timeout configuration for this method in seconds + """ + base_url = None + url_variables = None + retries: OptionalNullable[utils.RetryConfig] = UNSET + server_url = None + http_headers = extra_headers + timeout_ms = self._coerce_timeout_ms(timeout) + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + else: + base_url = self._get_url(base_url, url_variables) + + request = models.DeleteVoiceRequest( + api_version=api_version, + id=id, + ) + + _speakeasy_response_mode, http_headers = response_helpers.consume_response_mode( + http_headers + ) + req = self._build_request( + method="DELETE", + path="/{api_version}/voices/{voicesId}", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + http_headers=http_headers, + extra_query_params=extra_query, + _globals=models.DeleteVoiceGlobals( + api_version=self.sdk_configuration.globals.api_version, + ), + security=self.sdk_configuration.security, + allow_empty_value=None, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + else: + retries = utils.RetryConfig( + "attempt-count-backoff", + utils.BackoffStrategy(500, 8000, 2, 30000), + True, + max_retries=4, + ) + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, ["408", "409", "429", "5XX"]) + + def _speakeasy_parse_response(http_res): + if utils.match_response(http_res, "4XX", "*"): + http_res_text = utils.stream_to_text(http_res) + raise errors.GenAiDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "5XX", "*"): + http_res_text = utils.stream_to_text(http_res) + raise errors.GenAiDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "default", "application/json"): + return unmarshal_json_response( + voices.DeleteVoiceResponse, http_res, validate=False + ) + + raise errors.GenAiDefaultError("Unexpected response received", http_res) + + _speakeasy_hook_ctx = HookContext( + config=self.sdk_configuration, + base_url=base_url or "", + operation_id="DeleteVoice", + oauth2_scopes=None, + security_source=get_security_from_env( + self.sdk_configuration.security, types.Security + ), + tags=["voices"], + extensions=None, + response=ResponseContext(mode=_speakeasy_response_mode, execution="sync"), + ) + http_res = self.do_request( + hook_ctx=_speakeasy_hook_ctx, + request=req, + is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c), + stream=_speakeasy_response_mode == "streaming", + retry_config=retry_config, + ) + if _speakeasy_response_mode != "parsed": + if utils.match_status_codes(["4XX", "5XX"], http_res.status_code): + http_res.read() + try: + _speakeasy_parse_response(http_res) + except Exception as parse_exc_: + response_helpers.raise_parse_error( + self.sdk_configuration.__dict__["_hooks"], + AfterParseErrorContext(_speakeasy_hook_ctx), + http_res, + parse_exc_, + ) + _speakeasy_response_cls = ( + response_helpers.StreamedAPIResponse + if _speakeasy_response_mode == "streaming" + else response_helpers.APIResponse + ) + return cast( + Any, + _speakeasy_response_cls( + raw=http_res, + parser=_speakeasy_parse_response, + mode="buffered", + client_ref=self, + hook_ctx=AfterParseErrorContext(_speakeasy_hook_ctx), + hooks=self.sdk_configuration.__dict__.get("_hooks"), + ), + ) + try: + return _speakeasy_parse_response(http_res) + except Exception as parse_exc_: + response_helpers.raise_parse_error( + self.sdk_configuration.__dict__["_hooks"], + AfterParseErrorContext(_speakeasy_hook_ctx), + http_res, + parse_exc_, + ) + + def get( + self, + id: str, + *, + api_version: Optional[str] = None, + extra_headers: Optional[Mapping[str, str]] = None, + extra_query: Optional[Mapping[str, Any]] = None, + timeout: Optional[Union[float, httpx.Timeout]] = None, + ) -> voices.VoiceOutput: + r"""Gets a custom stored voice (`store = true`) by resource name. + Prebuilt catalog voices (`VOICE_TYPE_PREBUILT`) cannot be retrieved via + `GetVoice`; use `ListVoices` instead. + + :param id: Required. The resource name of the custom stored voice to retrieve + (for example, `voices/voice_abc123def456`). + :param api_version: API version for request routing. + :param extra_headers: Additional headers to set or replace on requests. + :param extra_query: Additional query parameters to append to requests. + :param timeout: Override the default request timeout configuration for this method in seconds + """ + base_url = None + url_variables = None + retries: OptionalNullable[utils.RetryConfig] = UNSET + server_url = None + http_headers = extra_headers + timeout_ms = self._coerce_timeout_ms(timeout) + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + else: + base_url = self._get_url(base_url, url_variables) + + request = models.GetVoiceRequest( + api_version=api_version, + id=id, + ) + + _speakeasy_response_mode, http_headers = response_helpers.consume_response_mode( + http_headers + ) + req = self._build_request( + method="GET", + path="/{api_version}/voices/{voicesId}", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + http_headers=http_headers, + extra_query_params=extra_query, + _globals=models.GetVoiceGlobals( + api_version=self.sdk_configuration.globals.api_version, + ), + security=self.sdk_configuration.security, + allow_empty_value=None, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + else: + retries = utils.RetryConfig( + "attempt-count-backoff", + utils.BackoffStrategy(500, 8000, 2, 30000), + True, + max_retries=4, + ) + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, ["408", "409", "429", "5XX"]) + + def _speakeasy_parse_response(http_res): + if utils.match_response(http_res, "4XX", "*"): + http_res_text = utils.stream_to_text(http_res) + raise errors.GenAiDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "5XX", "*"): + http_res_text = utils.stream_to_text(http_res) + raise errors.GenAiDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "default", "application/json"): + return unmarshal_json_response( + voices.VoiceOutput, http_res, validate=False + ) + + raise errors.GenAiDefaultError("Unexpected response received", http_res) + + _speakeasy_hook_ctx = HookContext( + config=self.sdk_configuration, + base_url=base_url or "", + operation_id="GetVoice", + oauth2_scopes=None, + security_source=get_security_from_env( + self.sdk_configuration.security, types.Security + ), + tags=["voices"], + extensions=None, + response=ResponseContext(mode=_speakeasy_response_mode, execution="sync"), + ) + http_res = self.do_request( + hook_ctx=_speakeasy_hook_ctx, + request=req, + is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c), + stream=_speakeasy_response_mode == "streaming", + retry_config=retry_config, + ) + if _speakeasy_response_mode != "parsed": + if utils.match_status_codes(["4XX", "5XX"], http_res.status_code): + http_res.read() + try: + _speakeasy_parse_response(http_res) + except Exception as parse_exc_: + response_helpers.raise_parse_error( + self.sdk_configuration.__dict__["_hooks"], + AfterParseErrorContext(_speakeasy_hook_ctx), + http_res, + parse_exc_, + ) + _speakeasy_response_cls = ( + response_helpers.StreamedAPIResponse + if _speakeasy_response_mode == "streaming" + else response_helpers.APIResponse + ) + return cast( + Any, + _speakeasy_response_cls( + raw=http_res, + parser=_speakeasy_parse_response, + mode="buffered", + client_ref=self, + hook_ctx=AfterParseErrorContext(_speakeasy_hook_ctx), + hooks=self.sdk_configuration.__dict__.get("_hooks"), + ), + ) + try: + return _speakeasy_parse_response(http_res) + except Exception as parse_exc_: + response_helpers.raise_parse_error( + self.sdk_configuration.__dict__["_hooks"], + AfterParseErrorContext(_speakeasy_hook_ctx), + http_res, + parse_exc_, + ) + + +class VoicesWithRawResponse: + def __init__(self, sdk: Voices) -> None: + self._sdk = sdk + self.list = response_helpers.to_raw_response_wrapper(sdk.list, "extra_headers") + self.create = response_helpers.to_raw_response_wrapper( + sdk.create, "extra_headers" + ) + self.delete = response_helpers.to_raw_response_wrapper( + sdk.delete, "extra_headers" + ) + self.get = response_helpers.to_raw_response_wrapper(sdk.get, "extra_headers") + + +class VoicesWithStreamingResponse: + def __init__(self, sdk: Voices) -> None: + self._sdk = sdk + self.list = response_helpers.to_streamed_response_wrapper( + sdk.list, "extra_headers" + ) + self.create = response_helpers.to_streamed_response_wrapper( + sdk.create, "extra_headers" + ) + self.delete = response_helpers.to_streamed_response_wrapper( + sdk.delete, "extra_headers" + ) + self.get = response_helpers.to_streamed_response_wrapper( + sdk.get, "extra_headers" + ) + + +class AsyncVoices(AsyncBaseSDK): + @property + def with_raw_response(self): + return AsyncVoicesWithRawResponse(self) + + @property + def with_streaming_response(self): + return AsyncVoicesWithStreamingResponse(self) + + async def list( + self, + *, + api_version: Optional[str] = None, + accent: Optional[Iterable[str]] = None, + contexts: Optional[Iterable[str]] = None, + gender: Optional[Iterable[str]] = None, + language_code: Optional[Iterable[str]] = None, + page_size: Optional[int] = None, + page_token: Optional[str] = None, + persona: Optional[Iterable[str]] = None, + pitch: Optional[Iterable[str]] = None, + region_code: Optional[Iterable[str]] = None, + search: Optional[str] = None, + type_: Optional[Iterable[str]] = None, + extra_headers: Optional[Mapping[str, str]] = None, + extra_query: Optional[Mapping[str, Any]] = None, + timeout: Optional[Union[float, httpx.Timeout]] = None, + ) -> voices.ListVoicesResponse: + r"""Lists custom stored voices owned by the caller (ordered newest first) + followed by prebuilt system voices from Google's voice catalog. + + :param api_version: API version for request routing. + :param accent: Optional. Filter by accent description (e.g. \"American\", \"British\"). + Case-insensitive exact match. If multiple values are specified, matches + voices with any of the specified accents (OR). + :param contexts: Optional. Filter by intended context or domain (e.g. \"News, Commercial\"). + Case-insensitive exact match. If multiple values are specified, matches + voices with any of the specified contexts (OR). + :param gender: Optional. Filter by gender presentation (e.g. \"female\", \"male\", \"neutral\"). + Case-insensitive exact match. If multiple values are specified, matches + voices with any of the specified genders (OR). + :param language_code: Optional. Filter by BCP-47 language code (e.g. \"en-US\"). + Case-insensitive exact match. If multiple values are specified, matches + voices with any of the specified language codes (OR). + :param page_size: Optional. The maximum number of voices to return per page. The service may + return fewer than this value. If unspecified, at most 50 voices are + returned. The maximum value is 1000; values above 1000 are coerced to + 1000. + :param page_token: Optional. A page token received from a previous `ListVoices` call. Provide + this to retrieve the subsequent page. + + When paginating, all filter query parameters (`language_code`, + `region_code`, `accent`, `persona`, `context`, `gender`, `pitch`, `type`, + and `search`) must match the call that returned this token; otherwise the + request fails with `INVALID_ARGUMENT`. `page_size` may change between + pages. + :param persona: Optional. Filter by vocal persona (e.g. \"Warm, Friendly\"). + Case-insensitive exact match. If multiple values are specified, matches + voices with any of the specified personas (OR). + :param pitch: Optional. Filter by vocal pitch. Accepts `\"low\"`, `\"medium\"`, `\"high\"` + (case-insensitive). If multiple values are specified, matches voices with + any of the specified pitches (OR). + :param region_code: Optional. Filter by ISO 3166-1 alpha-2 or UN M.49 region code (e.g. \"US\", + \"001\"). + Case-insensitive exact match. If multiple values are specified, matches + voices with any of the specified region codes (OR). + :param search: Optional. Free-text substring search query matched case-insensitively + against both `display_name` and `description`. Maximum 2048 bytes. + :param type: Optional. Filter by voice type. Accepts `\"prebuilt\"`, `\"replicated\"`, + `\"prompted\"` (case-insensitive). If multiple values are specified, matches + voices with any of the specified types (OR). + :param extra_headers: Additional headers to set or replace on requests. + :param extra_query: Additional query parameters to append to requests. + :param timeout: Override the default request timeout configuration for this method in seconds + """ + base_url = None + url_variables = None + retries: OptionalNullable[utils.RetryConfig] = UNSET + server_url = None + http_headers = extra_headers + timeout_ms = self._coerce_timeout_ms(timeout) + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + else: + base_url = self._get_url(base_url, url_variables) + + request = models.ListVoicesRequest( + api_version=api_version, + accent=utils.unmarshal(accent, Optional[List[str]]), + contexts=utils.unmarshal(contexts, Optional[List[str]]), + gender=utils.unmarshal(gender, Optional[List[str]]), + language_code=utils.unmarshal(language_code, Optional[List[str]]), + page_size=page_size, + page_token=page_token, + persona=utils.unmarshal(persona, Optional[List[str]]), + pitch=utils.unmarshal(pitch, Optional[List[str]]), + region_code=utils.unmarshal(region_code, Optional[List[str]]), + search=search, + type=utils.unmarshal(type_, Optional[List[str]]), + ) + + _speakeasy_response_mode, http_headers = response_helpers.consume_response_mode( + http_headers + ) + req = self._build_request_async( + method="GET", + path="/{api_version}/voices", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + http_headers=http_headers, + extra_query_params=extra_query, + _globals=models.ListVoicesGlobals( + api_version=self.sdk_configuration.globals.api_version, + ), + security=self.sdk_configuration.security, + allow_empty_value=None, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + else: + retries = utils.RetryConfig( + "attempt-count-backoff", + utils.BackoffStrategy(500, 8000, 2, 30000), + True, + max_retries=4, + ) + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, ["408", "409", "429", "5XX"]) + + async def _speakeasy_parse_response(http_res): + if utils.match_response(http_res, "4XX", "*"): + http_res_text = await utils.stream_to_text_async(http_res) + raise errors.GenAiDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "5XX", "*"): + http_res_text = await utils.stream_to_text_async(http_res) + raise errors.GenAiDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "default", "application/json"): + return unmarshal_json_response( + voices.ListVoicesResponse, http_res, validate=False + ) + + raise errors.GenAiDefaultError("Unexpected response received", http_res) + + _speakeasy_hook_ctx = HookContext( + config=self.sdk_configuration, + base_url=base_url or "", + operation_id="ListVoices", + oauth2_scopes=None, + security_source=get_security_from_env( + self.sdk_configuration.security, types.Security + ), + tags=["voices"], + extensions=None, + response=ResponseContext(mode=_speakeasy_response_mode, execution="async"), + ) + http_res = await self.do_request_async( + hook_ctx=_speakeasy_hook_ctx, + request=req, + is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c), + stream=_speakeasy_response_mode == "streaming", + retry_config=retry_config, + ) + if _speakeasy_response_mode != "parsed": + if utils.match_status_codes(["4XX", "5XX"], http_res.status_code): + await http_res.aread() + try: + await _speakeasy_parse_response(http_res) + except Exception as parse_exc_: + await response_helpers.raise_parse_error_async( + self.sdk_configuration.__dict__.get("_async_hooks"), + self.sdk_configuration.__dict__.get("_hooks"), + AfterParseErrorContext(_speakeasy_hook_ctx), + http_res, + parse_exc_, + ) + _speakeasy_response_cls = ( + response_helpers.AsyncStreamedAPIResponse + if _speakeasy_response_mode == "streaming" + else response_helpers.AsyncAPIResponse + ) + return cast( + Any, + _speakeasy_response_cls( + raw=http_res, + parser=_speakeasy_parse_response, + mode="buffered", + client_ref=self, + hook_ctx=AfterParseErrorContext(_speakeasy_hook_ctx), + hooks=self.sdk_configuration.__dict__.get("_hooks"), + async_hooks=self.sdk_configuration.__dict__.get("_async_hooks"), + ), + ) + try: + return await _speakeasy_parse_response(http_res) + except Exception as parse_exc_: + await response_helpers.raise_parse_error_async( + self.sdk_configuration.__dict__.get("_async_hooks"), + self.sdk_configuration.__dict__.get("_hooks"), + AfterParseErrorContext(_speakeasy_hook_ctx), + http_res, + parse_exc_, + ) + + async def create( + self, + *, + voice: Union[voices_voice_input.VoiceInput, voices_voice_input.VoiceInputParam], + api_version: Optional[str] = None, + store: Optional[bool] = None, + extra_headers: Optional[Mapping[str, str]] = None, + extra_query: Optional[Mapping[str, Any]] = None, + extra_body: Optional[Mapping[str, Any]] = None, + timeout: Optional[Union[float, httpx.Timeout]] = None, + ) -> voices.VoiceOutput: + r"""Creates a custom voice from a natural-language prompt + (`VOICE_TYPE_PROMPTED`) or from reference and consent audio recordings + (`VOICE_TYPE_REPLICATED`). + + :param voice: A voice resource representing either a custom voice (created via + `CreateVoice`) or a prebuilt system voice (returned by `ListVoices`). + :param api_version: API version for request routing. + :param store: Optional. Whether the created voice is persisted and managed by Google. + + * When `true`, Google stores the voice and returns `Voice.id` (for example, + `voice_abc123def456`), which can be managed via `GetVoice`, `ListVoices`, + and `DeleteVoice` and referenced by ID in synthesis requests. Projects + are subject to a maximum active stored voice quota; exceeding the quota + returns `RESOURCE_EXHAUSTED`. + * When `false` (default), the voice is not stored by Google and `Voice.key` + (for example, `voicekey_...`) is returned for client-side storage and + synthesis. Optional discovery metadata fields on `voice` are not + persisted or returned when `store` is `false`. + * Required to be `true` when `voice.type` is `\"prompted\"` + (otherwise fails with `INVALID_ARGUMENT`). + :param extra_headers: Additional headers to set or replace on requests. + :param extra_query: Additional query parameters to append to requests. + :param extra_body: Additional JSON object fields to merge into request bodies. + :param timeout: Override the default request timeout configuration for this method in seconds + """ + base_url = None + url_variables = None + retries: OptionalNullable[utils.RetryConfig] = UNSET + server_url = None + http_headers = extra_headers + timeout_ms = self._coerce_timeout_ms(timeout) + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + else: + base_url = self._get_url(base_url, url_variables) + + request = models.CreateVoiceRequest( + api_version=api_version, + body=voices.CreateVoiceRequest( + store=store, + voice=utils.get_pydantic_model(voice, voices.VoiceInput), + ), + ) + + _speakeasy_response_mode, http_headers = response_helpers.consume_response_mode( + http_headers + ) + req = self._build_request_async( + method="POST", + path="/{api_version}/voices", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=True, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + http_headers=http_headers, + extra_query_params=extra_query, + _globals=models.CreateVoiceGlobals( + api_version=self.sdk_configuration.globals.api_version, + ), + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body( + request.body, + False, + False, + "json", + voices.CreateVoiceRequest, + extra_body=extra_body, + ), + allow_empty_value=None, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + else: + retries = utils.RetryConfig( + "attempt-count-backoff", + utils.BackoffStrategy(500, 8000, 2, 30000), + True, + max_retries=4, + ) + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, ["408", "409", "429", "5XX"]) + + async def _speakeasy_parse_response(http_res): + if utils.match_response(http_res, "4XX", "*"): + http_res_text = await utils.stream_to_text_async(http_res) + raise errors.GenAiDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "5XX", "*"): + http_res_text = await utils.stream_to_text_async(http_res) + raise errors.GenAiDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "default", "application/json"): + return unmarshal_json_response( + voices.VoiceOutput, http_res, validate=False + ) + + raise errors.GenAiDefaultError("Unexpected response received", http_res) + + _speakeasy_hook_ctx = HookContext( + config=self.sdk_configuration, + base_url=base_url or "", + operation_id="CreateVoice", + oauth2_scopes=None, + security_source=get_security_from_env( + self.sdk_configuration.security, types.Security + ), + tags=["voices"], + extensions=None, + response=ResponseContext(mode=_speakeasy_response_mode, execution="async"), + ) + http_res = await self.do_request_async( + hook_ctx=_speakeasy_hook_ctx, + request=req, + is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c), + stream=_speakeasy_response_mode == "streaming", + retry_config=retry_config, + ) + if _speakeasy_response_mode != "parsed": + if utils.match_status_codes(["4XX", "5XX"], http_res.status_code): + await http_res.aread() + try: + await _speakeasy_parse_response(http_res) + except Exception as parse_exc_: + await response_helpers.raise_parse_error_async( + self.sdk_configuration.__dict__.get("_async_hooks"), + self.sdk_configuration.__dict__.get("_hooks"), + AfterParseErrorContext(_speakeasy_hook_ctx), + http_res, + parse_exc_, + ) + _speakeasy_response_cls = ( + response_helpers.AsyncStreamedAPIResponse + if _speakeasy_response_mode == "streaming" + else response_helpers.AsyncAPIResponse + ) + return cast( + Any, + _speakeasy_response_cls( + raw=http_res, + parser=_speakeasy_parse_response, + mode="buffered", + client_ref=self, + hook_ctx=AfterParseErrorContext(_speakeasy_hook_ctx), + hooks=self.sdk_configuration.__dict__.get("_hooks"), + async_hooks=self.sdk_configuration.__dict__.get("_async_hooks"), + ), + ) + try: + return await _speakeasy_parse_response(http_res) + except Exception as parse_exc_: + await response_helpers.raise_parse_error_async( + self.sdk_configuration.__dict__.get("_async_hooks"), + self.sdk_configuration.__dict__.get("_hooks"), + AfterParseErrorContext(_speakeasy_hook_ctx), + http_res, + parse_exc_, + ) + + async def delete( + self, + id: str, + *, + api_version: Optional[str] = None, + extra_headers: Optional[Mapping[str, str]] = None, + extra_query: Optional[Mapping[str, Any]] = None, + timeout: Optional[Union[float, httpx.Timeout]] = None, + ) -> voices.DeleteVoiceResponse: + r"""Deletes a custom stored voice (`store = true`) by resource name. + Prebuilt catalog voices (`VOICE_TYPE_PREBUILT`) cannot be deleted. + + :param id: Required. The resource name of the custom stored voice to delete + (for example, `voices/voice_abc123def456`). + :param api_version: API version for request routing. + :param extra_headers: Additional headers to set or replace on requests. + :param extra_query: Additional query parameters to append to requests. + :param timeout: Override the default request timeout configuration for this method in seconds + """ + base_url = None + url_variables = None + retries: OptionalNullable[utils.RetryConfig] = UNSET + server_url = None + http_headers = extra_headers + timeout_ms = self._coerce_timeout_ms(timeout) + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + else: + base_url = self._get_url(base_url, url_variables) + + request = models.DeleteVoiceRequest( + api_version=api_version, + id=id, + ) + + _speakeasy_response_mode, http_headers = response_helpers.consume_response_mode( + http_headers + ) + req = self._build_request_async( + method="DELETE", + path="/{api_version}/voices/{voicesId}", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + http_headers=http_headers, + extra_query_params=extra_query, + _globals=models.DeleteVoiceGlobals( + api_version=self.sdk_configuration.globals.api_version, + ), + security=self.sdk_configuration.security, + allow_empty_value=None, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + else: + retries = utils.RetryConfig( + "attempt-count-backoff", + utils.BackoffStrategy(500, 8000, 2, 30000), + True, + max_retries=4, + ) + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, ["408", "409", "429", "5XX"]) + + async def _speakeasy_parse_response(http_res): + if utils.match_response(http_res, "4XX", "*"): + http_res_text = await utils.stream_to_text_async(http_res) + raise errors.GenAiDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "5XX", "*"): + http_res_text = await utils.stream_to_text_async(http_res) + raise errors.GenAiDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "default", "application/json"): + return unmarshal_json_response( + voices.DeleteVoiceResponse, http_res, validate=False + ) + + raise errors.GenAiDefaultError("Unexpected response received", http_res) + + _speakeasy_hook_ctx = HookContext( + config=self.sdk_configuration, + base_url=base_url or "", + operation_id="DeleteVoice", + oauth2_scopes=None, + security_source=get_security_from_env( + self.sdk_configuration.security, types.Security + ), + tags=["voices"], + extensions=None, + response=ResponseContext(mode=_speakeasy_response_mode, execution="async"), + ) + http_res = await self.do_request_async( + hook_ctx=_speakeasy_hook_ctx, + request=req, + is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c), + stream=_speakeasy_response_mode == "streaming", + retry_config=retry_config, + ) + if _speakeasy_response_mode != "parsed": + if utils.match_status_codes(["4XX", "5XX"], http_res.status_code): + await http_res.aread() + try: + await _speakeasy_parse_response(http_res) + except Exception as parse_exc_: + await response_helpers.raise_parse_error_async( + self.sdk_configuration.__dict__.get("_async_hooks"), + self.sdk_configuration.__dict__.get("_hooks"), + AfterParseErrorContext(_speakeasy_hook_ctx), + http_res, + parse_exc_, + ) + _speakeasy_response_cls = ( + response_helpers.AsyncStreamedAPIResponse + if _speakeasy_response_mode == "streaming" + else response_helpers.AsyncAPIResponse + ) + return cast( + Any, + _speakeasy_response_cls( + raw=http_res, + parser=_speakeasy_parse_response, + mode="buffered", + client_ref=self, + hook_ctx=AfterParseErrorContext(_speakeasy_hook_ctx), + hooks=self.sdk_configuration.__dict__.get("_hooks"), + async_hooks=self.sdk_configuration.__dict__.get("_async_hooks"), + ), + ) + try: + return await _speakeasy_parse_response(http_res) + except Exception as parse_exc_: + await response_helpers.raise_parse_error_async( + self.sdk_configuration.__dict__.get("_async_hooks"), + self.sdk_configuration.__dict__.get("_hooks"), + AfterParseErrorContext(_speakeasy_hook_ctx), + http_res, + parse_exc_, + ) + + async def get( + self, + id: str, + *, + api_version: Optional[str] = None, + extra_headers: Optional[Mapping[str, str]] = None, + extra_query: Optional[Mapping[str, Any]] = None, + timeout: Optional[Union[float, httpx.Timeout]] = None, + ) -> voices.VoiceOutput: + r"""Gets a custom stored voice (`store = true`) by resource name. + Prebuilt catalog voices (`VOICE_TYPE_PREBUILT`) cannot be retrieved via + `GetVoice`; use `ListVoices` instead. + + :param id: Required. The resource name of the custom stored voice to retrieve + (for example, `voices/voice_abc123def456`). + :param api_version: API version for request routing. + :param extra_headers: Additional headers to set or replace on requests. + :param extra_query: Additional query parameters to append to requests. + :param timeout: Override the default request timeout configuration for this method in seconds + """ + base_url = None + url_variables = None + retries: OptionalNullable[utils.RetryConfig] = UNSET + server_url = None + http_headers = extra_headers + timeout_ms = self._coerce_timeout_ms(timeout) + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + else: + base_url = self._get_url(base_url, url_variables) + + request = models.GetVoiceRequest( + api_version=api_version, + id=id, + ) + + _speakeasy_response_mode, http_headers = response_helpers.consume_response_mode( + http_headers + ) + req = self._build_request_async( + method="GET", + path="/{api_version}/voices/{voicesId}", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + http_headers=http_headers, + extra_query_params=extra_query, + _globals=models.GetVoiceGlobals( + api_version=self.sdk_configuration.globals.api_version, + ), + security=self.sdk_configuration.security, + allow_empty_value=None, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + else: + retries = utils.RetryConfig( + "attempt-count-backoff", + utils.BackoffStrategy(500, 8000, 2, 30000), + True, + max_retries=4, + ) + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, ["408", "409", "429", "5XX"]) + + async def _speakeasy_parse_response(http_res): + if utils.match_response(http_res, "4XX", "*"): + http_res_text = await utils.stream_to_text_async(http_res) + raise errors.GenAiDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "5XX", "*"): + http_res_text = await utils.stream_to_text_async(http_res) + raise errors.GenAiDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "default", "application/json"): + return unmarshal_json_response( + voices.VoiceOutput, http_res, validate=False + ) + + raise errors.GenAiDefaultError("Unexpected response received", http_res) + + _speakeasy_hook_ctx = HookContext( + config=self.sdk_configuration, + base_url=base_url or "", + operation_id="GetVoice", + oauth2_scopes=None, + security_source=get_security_from_env( + self.sdk_configuration.security, types.Security + ), + tags=["voices"], + extensions=None, + response=ResponseContext(mode=_speakeasy_response_mode, execution="async"), + ) + http_res = await self.do_request_async( + hook_ctx=_speakeasy_hook_ctx, + request=req, + is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c), + stream=_speakeasy_response_mode == "streaming", + retry_config=retry_config, + ) + if _speakeasy_response_mode != "parsed": + if utils.match_status_codes(["4XX", "5XX"], http_res.status_code): + await http_res.aread() + try: + await _speakeasy_parse_response(http_res) + except Exception as parse_exc_: + await response_helpers.raise_parse_error_async( + self.sdk_configuration.__dict__.get("_async_hooks"), + self.sdk_configuration.__dict__.get("_hooks"), + AfterParseErrorContext(_speakeasy_hook_ctx), + http_res, + parse_exc_, + ) + _speakeasy_response_cls = ( + response_helpers.AsyncStreamedAPIResponse + if _speakeasy_response_mode == "streaming" + else response_helpers.AsyncAPIResponse + ) + return cast( + Any, + _speakeasy_response_cls( + raw=http_res, + parser=_speakeasy_parse_response, + mode="buffered", + client_ref=self, + hook_ctx=AfterParseErrorContext(_speakeasy_hook_ctx), + hooks=self.sdk_configuration.__dict__.get("_hooks"), + async_hooks=self.sdk_configuration.__dict__.get("_async_hooks"), + ), + ) + try: + return await _speakeasy_parse_response(http_res) + except Exception as parse_exc_: + await response_helpers.raise_parse_error_async( + self.sdk_configuration.__dict__.get("_async_hooks"), + self.sdk_configuration.__dict__.get("_hooks"), + AfterParseErrorContext(_speakeasy_hook_ctx), + http_res, + parse_exc_, + ) + + +class AsyncVoicesWithRawResponse: + def __init__(self, sdk: AsyncVoices) -> None: + self._sdk = sdk + self.list = response_helpers.async_to_raw_response_wrapper( + sdk.list, "extra_headers" + ) + self.create = response_helpers.async_to_raw_response_wrapper( + sdk.create, "extra_headers" + ) + self.delete = response_helpers.async_to_raw_response_wrapper( + sdk.delete, "extra_headers" + ) + self.get = response_helpers.async_to_raw_response_wrapper( + sdk.get, "extra_headers" + ) + + +class AsyncVoicesWithStreamingResponse: + def __init__(self, sdk: AsyncVoices) -> None: + self._sdk = sdk + self.list = response_helpers.async_to_streamed_response_wrapper( + sdk.list, "extra_headers" + ) + self.create = response_helpers.async_to_streamed_response_wrapper( + sdk.create, "extra_headers" + ) + self.delete = response_helpers.async_to_streamed_response_wrapper( + sdk.delete, "extra_headers" + ) + self.get = response_helpers.async_to_streamed_response_wrapper( + sdk.get, "extra_headers" + )