diff --git a/README.md b/README.md index 7291477..b6c5d9f 100644 --- a/README.md +++ b/README.md @@ -44,8 +44,10 @@ client = Speechify( token="YOUR_TOKEN", ) client.tts.audio.speech( - input="input", - voice_id="voice_id", + audio_format="mp3", + input="Hello! This is the Speechify text-to-speech API.", + model="simba-english", + voice_id="george", ) ``` @@ -65,8 +67,10 @@ client = AsyncSpeechify( async def main() -> None: await client.tts.audio.speech( - input="input", - voice_id="voice_id", + audio_format="mp3", + input="Hello! This is the Speechify text-to-speech API.", + model="simba-english", + voice_id="george", ) diff --git a/poetry.lock b/poetry.lock index 1a4242d..0474c73 100644 --- a/poetry.lock +++ b/poetry.lock @@ -38,13 +38,13 @@ trio = ["trio (>=0.26.1)"] [[package]] name = "certifi" -version = "2026.4.22" +version = "2026.6.17" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.7" files = [ - {file = "certifi-2026.4.22-py3-none-any.whl", hash = "sha256:3cb2210c8f88ba2318d29b0388d1023c8492ff72ecdde4ebdaddbb13a31b1c4a"}, - {file = "certifi-2026.4.22.tar.gz", hash = "sha256:8d455352a37b71bf76a79caa83a3d6c25afee4a385d632127b6afb3963f1c580"}, + {file = "certifi-2026.6.17-py3-none-any.whl", hash = "sha256:2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db"}, + {file = "certifi-2026.6.17.tar.gz", hash = "sha256:024c88eeec92ca068db80f02b8b07c9cef7b9fe261d1d535abfd5abd6f6af432"}, ] [[package]] @@ -133,13 +133,13 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "idna" -version = "3.13" +version = "3.15" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.8" files = [ - {file = "idna-3.13-py3-none-any.whl", hash = "sha256:892ea0cde124a99ce773decba204c5552b69c3c67ffd5f232eb7696135bc8bb3"}, - {file = "idna-3.13.tar.gz", hash = "sha256:585ea8fe5d69b9181ec1afba340451fba6ba764af97026f92a91d4eef164a242"}, + {file = "idna-3.15-py3-none-any.whl", hash = "sha256:048adeaf8c2d788c40fee287673ccaa74c24ffd8dcf09ffa555a2fbb59f10ac8"}, + {file = "idna-3.15.tar.gz", hash = "sha256:ca962446ea538f7092a95e057da437618e886f4d349216d2b1e294abfdb65fdc"}, ] [package.extras] diff --git a/pyproject.toml b/pyproject.toml index d29a471..2615901 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,9 @@ +[project] +name = "speechify-api" + [tool.poetry] name = "speechify-api" -version = "1.2.3" +version = "1.2.4" description = "Official Speechify API SDK" readme = "README.md" authors = [ @@ -36,7 +39,7 @@ packages = [ { include = "speechify", from = "src"} ] -[tool.poetry.urls] +[project.urls] Documentation = 'https://docs.speechify.ai/api-reference' Homepage = 'https://docs.speechify.ai' Repository = 'https://github.com/speechifyinc/speechify-api-sdk-python' diff --git a/reference.md b/reference.md index 14e9f47..fb5f4ee 100644 --- a/reference.md +++ b/reference.md @@ -12,7 +12,9 @@
-Gets the speech data for the given input +Synthesize speech audio from text or SSML. Returns the complete audio +file plus billing and speech-mark metadata in a single response. For +low-latency playback or long-form text, use POST /v1/audio/stream.
@@ -33,8 +35,10 @@ client = Speechify( token="YOUR_TOKEN", ) client.tts.audio.speech( - input="input", - voice_id="voice_id", + audio_format="mp3", + input="Hello! This is the Speechify text-to-speech API.", + model="simba-english", + voice_id="george", ) ``` @@ -90,10 +94,7 @@ Please refer to the list of the supported languages and recommendations regardin
-**model:** `typing.Optional[GetSpeechRequestModel]` - -Model used for audio synthesis. `simba-base` and `simba-turbo` are deprecated. -`simba-3.0` is the new streaming-native model with lower TTFB and richer expressivity. Currently English only; multilingual coming soon. Non-English voices return 400 until multilingual support ships. +**model:** `typing.Optional[GetSpeechRequestModel]` — Model used for audio synthesis. `simba-english` is optimized for English, `simba-multilingual` for non-English or mixed input. `simba-3.0` is the streaming-native model with lower TTFB and richer expressivity. Currently English only; multilingual coming soon. Non-English voices return 400 until multilingual support ships.
@@ -133,7 +134,10 @@ Model used for audio synthesis. `simba-base` and `simba-turbo` are deprecated.
-Gets the stream speech for the given input +Synthesize speech and stream the audio back as it is generated, for +low-latency playback. The Accept header selects the audio container. +For short text where receiving the whole file at once is fine, use +POST /v1/audio/speech.
@@ -212,10 +216,7 @@ Please refer to the list of the supported languages and recommendations regardin
-**model:** `typing.Optional[GetStreamRequestModel]` - -Model used for audio synthesis. `simba-base` and `simba-turbo` are deprecated. -`simba-3.0` is the new streaming-native model with lower TTFB and richer expressivity. Currently English only; multilingual coming soon. Non-English voices return 400 until multilingual support ships. +**model:** `typing.Optional[GetStreamRequestModel]` — Model used for audio synthesis. `simba-english` is optimized for English, `simba-multilingual` for non-English or mixed input. `simba-3.0` is the streaming-native model with lower TTFB and richer expressivity. Currently English only; multilingual coming soon. Non-English voices return 400 until multilingual support ships.
@@ -239,88 +240,6 @@ Model used for audio synthesis. `simba-base` and `simba-turbo` are deprecated. - - - - -## Tts Auth -
client.tts.auth.create_access_token(...) -
-
- -#### 📝 Description - -
-
- -
-
- -WARNING: This endpoint is deprecated. Create a new API token for the logged in user. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.auth.create_access_token( - grant_type="client_credentials", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**grant_type:** `CreateAccessTokenRequestGrantType` — in: body - -
-
- -
-
- -**scope:** `typing.Optional[CreateAccessTokenRequestScope]` - -The scope, or a space-delimited list of scopes the token is requested for -in: body - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- -
@@ -651,6758 +570,3 @@ client.tts.voices.download_sample( -## Tts Agents -
client.tts.agents.list() -
-
- -#### 📝 Description - -
-
- -
-
- -List voice agents owned by the caller. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.list() - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.create(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Create a voice agent. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.create( - name="name", - voice_id="voice_id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**name:** `str` - -
-
- -
-
- -**voice_id:** `str` — Voice slug from the VMS catalog (see GET /v1/voices). Required — the server rejects writes with an unknown or empty slug. - -
-
- -
-
- -**slug:** `typing.Optional[str]` — Optional. Server derives slug from name with a random suffix when omitted; if you supply your own, a collision returns 400 'slug already taken'. - -
-
- -
-
- -**prompt:** `typing.Optional[str]` - -
-
- -
-
- -**first_message:** `typing.Optional[str]` — Spoken verbatim at session start — no LLM round trip. - -
-
- -
-
- -**language:** `typing.Optional[str]` - -
-
- -
-
- -**llm_model:** `typing.Optional[str]` — Optional chat model slug. Leave empty to use the Speechify default. - -
-
- -
-
- -**temperature:** `typing.Optional[float]` - -
-
- -
-
- -**config:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]` - -
-
- -
-
- -**is_public:** `typing.Optional[bool]` - -
-
- -
-
- -**allowed_origins:** `typing.Optional[typing.Sequence[str]]` - -
-
- -
-
- -**hostname_allowlist:** `typing.Optional[typing.Sequence[str]]` — Optional per-agent hostname allowlist (see Agent schema). - -
-
- -
-
- -**memory_enabled:** `typing.Optional[bool]` - -
-
- -
-
- -**memory_retention_days:** `typing.Optional[int]` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.get(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Retrieve a voice agent by ID. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.get( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.delete(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Delete a voice agent. Conversations and attached tools remain. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.delete( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.update(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Update a voice agent. Only fields present on the request body are changed. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.update( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**name:** `typing.Optional[str]` - -
-
- -
-
- -**prompt:** `typing.Optional[str]` - -
-
- -
-
- -**first_message:** `typing.Optional[str]` - -
-
- -
-
- -**language:** `typing.Optional[str]` - -
-
- -
-
- -**llm_model:** `typing.Optional[str]` - -
-
- -
-
- -**voice_id:** `typing.Optional[str]` - -
-
- -
-
- -**temperature:** `typing.Optional[float]` - -
-
- -
-
- -**config:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]` - -
-
- -
-
- -**is_public:** `typing.Optional[bool]` - -
-
- -
-
- -**allowed_origins:** `typing.Optional[typing.Sequence[str]]` - -
-
- -
-
- -**hostname_allowlist:** `typing.Optional[typing.Sequence[str]]` - -When supplied, replaces the stored list. Pass an empty -array to clear enforcement (public agent is open again). -Omit the field to leave the existing value unchanged. - -
-
- -
-
- -**memory_enabled:** `typing.Optional[bool]` - -
-
- -
-
- -**memory_retention_days:** `typing.Optional[int]` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.list_tools(...) -
-
- -#### 📝 Description - -
-
- -
-
- -List tools currently attached to the agent. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.list_tools( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.attach_tool(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Attach an existing tool to the agent so the LLM can call it. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.attach_tool( - id="id", - tool_id="toolId", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**tool_id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.detach_tool(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Detach a tool from the agent. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.detach_tool( - id="id", - tool_id="toolId", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**tool_id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.get_evaluation_config(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Retrieve the agent's post-call evaluation criteria + data-collection config. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.get_evaluation_config( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.update_evaluation_config(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Replace the agent's evaluation criteria + data-collection fields. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify -from speechify.tts import DataCollectionField, EvaluationCriterion - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.update_evaluation_config( - id="id", - criteria=[ - EvaluationCriterion( - id="id", - name="name", - description="description", - ) - ], - data_collection=[ - DataCollectionField( - key="key", - description="description", - type="string", - ) - ], -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**criteria:** `typing.Sequence[EvaluationCriterion]` - -
-
- -
-
- -**data_collection:** `typing.Sequence[DataCollectionField]` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.get_dynamic_variables(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Retrieve the agent's customer-scope dynamic variables and the read-only -catalogue of reserved `system__*` keys. The system variables list is -provided so editor UIs can render the reference list without maintaining -a client-side copy of the catalogue. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.get_dynamic_variables( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.update_dynamic_variables(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Replace the agent's customer-scope dynamic variable definitions. -The supplied list overwrites the stored list wholesale (same -semantics as `updateEvaluationConfig`). Pass an empty array to -clear all variables. Up to 20 variables per agent. Keys must -match `[a-zA-Z0-9_]+` and must not start with the reserved -`system__` prefix. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify -from speechify.tts import DynamicVariable - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.update_dynamic_variables( - id="id", - variables=[ - DynamicVariable( - key="product_name", - type="string", - default="Speechify", - description="Product the agent is supporting.", - ), - DynamicVariable( - key="support_tier", - type="number", - default=1, - ), - DynamicVariable( - key="account_metadata", - type="json", - description="Arbitrary account context injected into tool bodies.", - ), - ], -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**variables:** `typing.Sequence[DynamicVariable]` — The new variable list. Replaces the existing list entirely. - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.create_conversation(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Start a new voice conversation with the agent. Returns a realtime -voice session + short-lived client token so the caller can -connect the audio pipeline directly. The agent is dispatched -server-side; no additional client action required. - -Pass `dynamic_variables` to supply per-session values that override -the agent's stored variable defaults for this one conversation. -Keys in the `system__` namespace are rejected at this boundary. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.create_conversation( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**transport:** `typing.Optional[str]` — Transport hint. Omit to use the agent's default. - -
-
- -
-
- -**dynamic_variables:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]` - -Per-session variable overrides that merge on top of the agent's -stored variable defaults for this one conversation. Keys in the -reserved `system__` namespace are rejected. Values must match the -declared type of the corresponding variable definition on the agent. - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.create_session(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Mint a realtime voice session for the given agent. Widget-friendly -counterpart to `createConversation` — same response shape, dual -authentication: - -* **Authenticated (Bearer)**: works for any agent the caller - owns. Typical server-to-server flow where the embedding - site's backend mints a token and hands it to the browser so - the API key never reaches the client. -* **Unauthenticated**: works only when `agent.is_public = true` - AND the request's `Origin` header matches `agent.allowed_origins` - (or that list is empty). When `agent.hostname_allowlist` is - non-empty, the `Origin` hostname must additionally be a - member of that list. Used directly by the - `` web component. - -Responds with the same `CreateConversationResponse` as -`createConversation`. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.create_session( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**user_identity:** `typing.Optional[str]` — Opaque identifier for the end-user (e.g. your app's user ID). Stamped onto the conversation. Optional - defaults to an anonymous per-session ID. - -
-
- -
-
- -**dynamic_variables:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]` - -Per-session variable overrides that merge on top of the agent's -stored variable defaults for this one session. Keys in the -reserved `system__` namespace are rejected at this boundary. -Values must match the declared type of the corresponding variable -definition on the agent (a `string` type expects a JSON string, -`number` expects a JSON number, etc.). - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.list_agent_knowledge_bases(...) -
-
- -#### 📝 Description - -
-
- -
-
- -List knowledge bases attached to an agent. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.list_agent_knowledge_bases( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.attach_knowledge_base(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Attach a knowledge base to an agent. The `search_knowledge` tool -is auto-registered on the next conversation and can only query the -attached knowledge bases. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.attach_knowledge_base( - id="id", - kb_id="kbId", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**kb_id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.detach_knowledge_base(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Detach a knowledge base from an agent. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.detach_knowledge_base( - id="id", - kb_id="kbId", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**kb_id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.list_memories(...) -
-
- -#### 📝 Description - -
-
- -
-
- -List per-caller memories extracted for an agent. Memories are -written post-call by the built-in extractor when `memory_enabled` -is true on the agent; the list is sorted newest-first. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.list_memories( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**limit:** `typing.Optional[int]` — Maximum rows to return. Defaults to 100, capped at 200. - -
-
- -
-
- -**offset:** `typing.Optional[int]` — Number of rows to skip. Combine with `limit` to page through older memories. - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.delete_memories_by_caller(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Delete every memory ever extracted for a specific caller on -this agent. Privacy / GDPR surface. Returns the count of rows -soft-deleted; rows become permanently unreachable immediately -and are hard-deleted by the retention job after the tenant's -configured retention window. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.delete_memories_by_caller( - id="id", - agent_id="agent_id", - caller_identity="caller_identity", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**agent_id:** `str` - -
-
- -
-
- -**caller_identity:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.list_tests(...) -
-
- -#### 📝 Description - -
-
- -
-
- -List all tests configured for the agent. Each entry includes the -most recent run so the console can render pass/fail badges without -an extra round-trip. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.list_tests( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` — Agent ID. - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.create_test(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Create a new test for the agent. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify -from speechify.tts import ScenarioConfig - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.create_test( - id="id", - name="Greet the caller by name", - description="Agent should greet the caller using their name when provided.", - type="scenario", - config=ScenarioConfig( - context="The caller says: Hi, I'm Alice.", - success_criteria="The agent greets Alice by name.", - success_examples=["Hi Alice! How can I help you today?"], - failure_examples=["Hello! How can I help you?"], - ), -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` — Agent ID. - -
-
- -
-
- -**name:** `str` — Short human-readable label for the test. - -
-
- -
-
- -**type:** `TestType` - -
-
- -
-
- -**config:** `CreateAgentTestRequestConfig` — Type-specific configuration. Must match the shape for the given `type`. - -
-
- -
-
- -**description:** `typing.Optional[str]` — Optional longer description of what this test verifies. - -
-
- -
-
- -**tool_mock_config:** `typing.Optional[ToolMockConfig]` — Optional tool-mocking config applied during every run of this test. - -
-
- -
-
- -**variables:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]` - -Per-test variable values substituted into string fields of the -config at run-start. Keys use the same rules as agent-level -`DynamicVariable` keys. - -
-
- -
-
- -**folder_id:** `typing.Optional[str]` — Folder to place the test in. Omit for root. - -
-
- -
-
- -**attached_agent_ids:** `typing.Optional[typing.Sequence[str]]` - -Optional list of additional agents this test should also run -against. The owner agent (path param) is always attached -implicitly. - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.run_all_tests(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Enqueue runs for every test on the agent concurrently. Up to 50 -tests are dispatched in one call. Each returned run starts in -`queued` status; poll `GET /v1/test-runs/{id}` for the terminal -result. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.run_all_tests( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` — Agent ID. - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.get_test(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Retrieve a test by ID. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.get_test( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` — Test ID. - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.delete_test(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Delete a test and all its run history. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.delete_test( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` — Test ID. - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.update_test(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Update a test. Only fields present on the request body are changed. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.update_test( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` — Test ID. - -
-
- -
-
- -**name:** `typing.Optional[str]` - -
-
- -
-
- -**description:** `typing.Optional[str]` - -
-
- -
-
- -**config:** `typing.Optional[UpdateAgentTestRequestConfig]` — Replaces the test config when present. - -
-
- -
-
- -**tool_mock_config:** `typing.Optional[ToolMockConfig]` — Replaces the tool-mock config when present. - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.list_test_runs(...) -
-
- -#### 📝 Description - -
-
- -
-
- -List the run history for a test, newest first. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.list_test_runs( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` — Test ID. - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.run_test(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Enqueue a single run of the test. The returned run starts in -`queued` status. Poll `GET /v1/test-runs/{id}` until the status -reaches a terminal state (`passed`, `failed`, or `error`). -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.run_test( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` — Test ID. - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.get_test_run(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Retrieve a single test run by ID. Poll this endpoint until -`status` reaches a terminal state (`passed`, `failed`, or `error`). -The `result` field is populated on terminal states. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.get_test_run( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` — Test run ID. - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.list_all_tests(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Workspace-wide list of tests across every agent the caller owns. -Supports filters (agent, type, last-run status, folder), full-text -search on name/description, and cursor pagination. Each row carries -its newest run and attached agent IDs so the list renders without -N+1 round-trips. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.list_all_tests() - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**agent_id:** `typing.Optional[str]` — Comma-separated agent IDs to filter on. - -
-
- -
-
- -**type:** `typing.Optional[str]` — Comma-separated test types (scenario|tool|simulation). - -
-
- -
-
- -**status:** `typing.Optional[str]` — Comma-separated last-run statuses. - -
-
- -
-
- -**folder_id:** `typing.Optional[str]` — Folder ID to filter on, or "root" for unfiled tests. - -
-
- -
-
- -**updated_after:** `typing.Optional[str]` — Only return tests updated after this RFC3339 timestamp. - -
-
- -
-
- -**q:** `typing.Optional[str]` — Substring match on name or description. - -
-
- -
-
- -**limit:** `typing.Optional[int]` — Max tests per page (default 50, max 200). - -
-
- -
-
- -**cursor:** `typing.Optional[str]` — Opaque pagination cursor from a previous response. - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.get_test_stats(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Aggregate pass-rate metrics over the last N days. Returns dense -daily buckets (one entry per day, zero-filled) plus totals and a -per-type breakdown. Powers the header chart on the global tests -page. Default window is 30 days, max 90. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.get_test_stats() - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**window_days:** `typing.Optional[int]` — Trailing window in days (default 30, max 90). - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.run_tests_batch(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Queue runs for every (test, agent) pair in the body. Entries -without an `agent_id` fan out to every agent the test is -attached to. Total expanded runs are capped at 100 per call. -Each entry in the response is a queued run; poll -`GET /v1/test-runs/{id}` for each. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify -from speechify.tts import BatchRunEntry - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.run_tests_batch( - entries=[ - BatchRunEntry( - test_id="test_id", - ) - ], -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**entries:** `typing.Sequence[BatchRunEntry]` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.list_test_attachments(...) -
-
- -#### 📝 Description - -
-
- -
-
- -List every agent a test is attached to. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.list_test_attachments( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.attach_test(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Attach a test to an additional agent. After this call, the test -will also run as part of that agent's regression suite (and -against its prompt + tool config when invoked with -`agent_id = {agentId}`). Idempotent. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.attach_test( - id="id", - agent_id="agentId", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**agent_id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.detach_test(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Detach a test from an agent. The owner agent (the agent the test -was authored against) cannot be detached; delete the test -instead. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.detach_test( - id="id", - agent_id="agentId", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**agent_id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.move_test(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Move a test into a folder. Pass `folder_id: null` for root. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.move_test( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**folder_id:** `typing.Optional[str]` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.list_test_folders() -
-
- -#### 📝 Description - -
-
- -
-
- -List every test folder the caller owns. Flat list; build the tree client-side. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.list_test_folders() - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.create_test_folder(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Create a test folder. Max depth is 3. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.create_test_folder( - name="name", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**name:** `str` - -
-
- -
-
- -**parent_folder_id:** `typing.Optional[str]` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.delete_test_folder(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Soft-delete a folder. Child tests drop back to root. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.delete_test_folder( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.agents.update_test_folder(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Rename or reparent a test folder. Cycles are rejected. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.agents.update_test_folder( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**name:** `typing.Optional[str]` - -
-
- -
-
- -**parent_folder_id:** `typing.Optional[str]` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -## Tts Tools -
client.tts.tools.list() -
-
- -#### 📝 Description - -
-
- -
-
- -List tools owned by the caller. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.tools.list() - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.tools.create(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Create a tool. For webhook tools, the response includes the HMAC -`webhook_secret` exactly once — store it immediately; subsequent -reads return a masked placeholder. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify -from speechify.tts import SystemToolConfig - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.tools.create( - name="name", - description="description", - kind="system", - config=SystemToolConfig( - builtin="end_call", - ), -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**name:** `str` - -
-
- -
-
- -**description:** `str` - -
-
- -
-
- -**kind:** `ToolKind` - -
-
- -
-
- -**config:** `CreateToolRequestConfig` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.tools.get(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Retrieve a tool by ID. Webhook secrets are always masked here. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.tools.get( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.tools.delete(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Delete a tool. Agents that had it attached get a soft-detach. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.tools.delete( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.tools.update(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Update a tool. Tool kind is immutable — create a new tool to change it. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.tools.update( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**name:** `typing.Optional[str]` - -
-
- -
-
- -**description:** `typing.Optional[str]` - -
-
- -
-
- -**config:** `typing.Optional[UpdateToolRequestConfig]` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -## Tts Conversations -
client.tts.conversations.list() -
-
- -#### 📝 Description - -
-
- -
-
- -List conversations owned by the caller, ordered by most recent. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.conversations.list() - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.conversations.stats() -
-
- -#### 📝 Description - -
-
- -
-
- -Aggregated counts and averages over the caller's conversations, scoped by the same filters as the list endpoint. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.conversations.stats() - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.conversations.get(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Retrieve a conversation by ID. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.conversations.get( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.conversations.list_messages(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Retrieve the full transcript for a conversation, in order. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.conversations.list_messages( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.conversations.list_evaluations(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Retrieve post-call evaluation results for a conversation. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.conversations.list_evaluations( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.conversations.list_memories(...) -
-
- -#### 📝 Description - -
-
- -
-
- -List memories extracted from a specific conversation. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.conversations.list_memories( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -## Tts KnowledgeBases -
client.tts.knowledge_bases.list() -
-
- -#### 📝 Description - -
-
- -
-
- -List knowledge bases owned by the caller. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.knowledge_bases.list() - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.knowledge_bases.create(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Create a new knowledge base. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.knowledge_bases.create( - name="name", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**name:** `str` — Human-readable label. - -
-
- -
-
- -**description:** `typing.Optional[str]` — Optional description. - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.knowledge_bases.get(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Retrieve a knowledge base by ID. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.knowledge_bases.get( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.knowledge_bases.delete(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Soft-delete a knowledge base. Documents and chunks are cascaded. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.knowledge_bases.delete( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.knowledge_bases.update(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Update a knowledge base. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.knowledge_bases.update( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**name:** `typing.Optional[str]` - -
-
- -
-
- -**description:** `typing.Optional[str]` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.knowledge_bases.list_documents(...) -
-
- -#### 📝 Description - -
-
- -
-
- -List documents ingested into a knowledge base. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.knowledge_bases.list_documents( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.knowledge_bases.upload_document(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Upload a document (PDF, plain text, markdown, or HTML) to a -knowledge base. The document is extracted, chunked, embedded, and -indexed synchronously; expect a few seconds per MB of input. -Maximum 10 MB per upload. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.knowledge_bases.upload_document( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**file:** `from __future__ import annotations - -core.File` — See core.File for more documentation - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.knowledge_bases.get_document(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Retrieve a document by ID. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.knowledge_bases.get_document( - doc_id="docId", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**doc_id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.knowledge_bases.delete_document(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Delete a document and all its chunks. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.knowledge_bases.delete_document( - doc_id="docId", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**doc_id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.knowledge_bases.list_chunks(...) -
-
- -#### 📝 Description - -
-
- -
-
- -List the chunks for a document. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.knowledge_bases.list_chunks( - doc_id="docId", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**doc_id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.knowledge_bases.search(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Semantic search across a caller-owned list of knowledge bases. -Returns ranked chunks with source filename and a cosine-similarity -score. Limited to 50 results per request. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.knowledge_bases.search( - query="query", - kb_ids=["kb_ids"], -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**query:** `str` — Natural-language search query. - -
-
- -
-
- -**kb_ids:** `typing.Sequence[str]` — Knowledge bases to search across. Results scoped to caller-owned entries; unknown IDs are silently ignored. - -
-
- -
-
- -**top_k:** `typing.Optional[int]` — Max hits to return (default 5, capped at 50). - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -## Tts Memories -
client.tts.memories.delete(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Soft-delete one memory row. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.memories.delete( - memory_id="memoryId", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**memory_id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -## Tts PhoneNumbers -
client.tts.phone_numbers.list() -
-
- -#### 📝 Description - -
-
- -
-
- -List all phone numbers in the caller's workspace. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.phone_numbers.list() - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.phone_numbers.import_(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Import a phone number into the workspace. The `source` field -determines the provisioning path: - -- `livekit` - LiveKit purchases the number on your behalf. US - inbound only. Quickest path for local testing. -- `twilio` - Provide your Twilio Account SID, Auth Token, and - the E.164 number you already own. We provision an Elastic SIP - Trunk on your Twilio account automatically. -- `byoc` - Provide an existing SIP trunk ID. The number is - registered against that trunk. - -Returns 402 when the workspace has reached the 100-number cap. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.phone_numbers.import_( - request={"key": "value"}, -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**request:** `typing.Optional[typing.Any]` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.phone_numbers.get(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Retrieve a phone number by ID. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.phone_numbers.get( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.phone_numbers.delete(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Delete a phone number from the workspace. For Twilio and LiveKit -numbers this also deprovisions the backing SIP trunk and dispatch -rule on LiveKit Cloud. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.phone_numbers.delete( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.phone_numbers.update(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Update a phone number. Only `label` and `agent_id` are mutable; -`source` and `e164` are immutable after import. Pass `null` for -`agent_id` to unbind the number from its current agent. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.phone_numbers.update( - id="id", - request={"key": "value"}, -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**request:** `typing.Optional[typing.Any]` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -## Tts SipTrunks -
client.tts.sip_trunks.list() -
-
- -#### 📝 Description - -
-
- -
-
- -List all SIP trunks in the caller's workspace. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.sip_trunks.list() - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.sip_trunks.create(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Create a SIP trunk. For `kind=byoc` supply `sip_address` plus -optional digest credentials and IP allowlist. For `kind=twilio` -use `ImportPhoneNumber` with a `twilio` spec instead - trunk -creation is handled automatically. Returns 402 when the workspace -has reached the 20-trunk cap. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.sip_trunks.create( - request={"key": "value"}, -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**request:** `typing.Optional[typing.Any]` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.sip_trunks.get(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Retrieve a SIP trunk by ID. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.sip_trunks.get( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.sip_trunks.delete(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Delete a SIP trunk. This also removes the backing LiveKit inbound -trunk, outbound trunk, and dispatch rule if they were provisioned -by us. Phone numbers attached to this trunk are left in place but -become non-functional until rebound to a new trunk. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.sip_trunks.delete( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -## Tts OutboundCalls -
client.tts.outbound_calls.create(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Place an outbound call from an agent to a phone number. LiveKit -originates the SIP INVITE through the outbound trunk bound to the -agent's workspace; the agent worker is dispatched into the room -automatically. - -The response is returned as soon as LiveKit accepts the INVITE. -Poll `GET /v1/conversations/{conversation_id}` for status -transitions: `pending` → `active` (answered) → `completed`. - -Requires a Twilio or BYOC trunk. LiveKit-native numbers are -inbound-only. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.outbound_calls.create( - request={"key": "value"}, -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**request:** `typing.Optional[typing.Any]` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -## Tts Workspaces -
client.tts.workspaces.list() -
-
- -#### 📝 Description - -
-
- -
-
- -List every workspace the authenticated user belongs to. Powers the workspace switcher. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.workspaces.list() - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.workspaces.create(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Create a new workspace with the authenticated user as owner. -The caller must switch their active workspace client-side via -the `X-Tenant-ID` header to act on the new tenant. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.workspaces.create() - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**name:** `typing.Optional[str]` — Display name for the new workspace. Trimmed; must be 120 characters or fewer. - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.workspaces.get_current() -
-
- -#### 📝 Description - -
-
- -
-
- -Retrieve the workspace currently selected by the caller (via `X-Tenant-ID` or auto-resolved). -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.workspaces.get_current() - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.workspaces.update_current(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Rename the current workspace. Owner or admin only. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.workspaces.update_current( - name="name", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**name:** `str` — New display name. Required; must be 120 characters or fewer. - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.workspaces.list_members() -
-
- -#### 📝 Description - -
-
- -
-
- -List every member of the current workspace. Any member may call this. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.workspaces.list_members() - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.workspaces.leave() -
-
- -#### 📝 Description - -
-
- -
-
- -Remove the authenticated caller from the current workspace. -Refused with 409 when the caller is the last owner — promote -another member to owner first. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.workspaces.leave() - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.workspaces.remove_member(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Remove a member from the current workspace. Owner or admin -only. The caller cannot remove themselves — use -`POST /v1/tenants/current/members/leave` instead. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.workspaces.remove_member( - user_uid="user_uid", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**user_uid:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.workspaces.update_member_role(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Change a member's role. Owner only — admins may add or remove -members but may not change roles. Refused with 409 when -demoting the last remaining owner. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.workspaces.update_member_role( - user_uid="user_uid", - role="owner", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**user_uid:** `str` - -
-
- -
-
- -**role:** `MemberRole` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.workspaces.list_invites() -
-
- -#### 📝 Description - -
-
- -
-
- -List outstanding invites for the current workspace. Invite tokens are redacted. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.workspaces.list_invites() - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.workspaces.create_invite(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Create an invite to the current workspace. Owner or admin only. -The response contains the invite token ONCE — subsequent list -calls redact it. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.workspaces.create_invite( - email="email", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**email:** `str` — Email of the person to invite. Validated as an RFC 5322 address. - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.workspaces.revoke_invite(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Revoke an outstanding invite. Owner or admin only. Idempotent. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.workspaces.revoke_invite( - id="id", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.workspaces.accept_invite(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Accept a workspace invite. The authenticated caller is joined -to the invite's workspace as a member. Expired, revoked, or -already-accepted tokens return 404 to avoid token enumeration. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.workspaces.accept_invite( - token="token", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**token:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.workspaces.preview_invite(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Preview a workspace invite without authenticating. Returns the -workspace name, inviter details, and expiry so the `/join/{token}` -page can render before the recipient signs in. Anyone with the -token can already accept, so this endpoint deliberately surfaces -the same information a caller would see after accepting. Invalid -tokens (unknown, expired, revoked, already-accepted, or pointing -at a soft-deleted workspace) collapse to a single 404 to prevent -enumeration. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.workspaces.preview_invite( - token="token", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**token:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- -
client.tts.workspaces.transfer_workspace_owner(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Transfer ownership of the current workspace atomically. Promotes -the target member to owner and demotes the caller to admin in a -single transaction. Owner-only; admins cannot hand off a role -they were never granted. Prefer this over two PATCH calls to -`/v1/tenants/current/members/{user_uid}`: a sole-owner caller -cannot demote themselves first without tripping the last-owner -guard, which this endpoint sidesteps by promoting before -demoting. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from speechify import Speechify - -client = Speechify( - token="YOUR_TOKEN", -) -client.tts.workspaces.transfer_workspace_owner( - user_uid="user_uid", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**user_uid:** `str` — Firebase UID of the member who will become the new owner. - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
- diff --git a/src/speechify/__init__.py b/src/speechify/__init__.py index c35fd6b..4c530dd 100644 --- a/src/speechify/__init__.py +++ b/src/speechify/__init__.py @@ -1,8 +1,80 @@ # This file was auto-generated by Fern from our API Definition. +from .types import ( + CreateVoiceLanguage, + CreateVoiceModel, + CreateVoiceModelName, + CreatedVoice, + CreatedVoiceGender, + CreatedVoiceType, + Error, + ErrorCode, + ErrorDetail, + GetSpeechOptionsRequest, + GetSpeechResponse, + GetSpeechResponseAudioFormat, + GetStreamOptionsRequest, + GetVoice, + GetVoiceGender, + GetVoiceLanguage, + GetVoiceType, + GetVoicesModel, + GetVoicesModelName, + NestedChunk, + SpeechMarks, +) +from .errors import ( + BadGatewayError, + BadRequestError, + ForbiddenError, + InternalServerError, + NotFoundError, + PaymentRequiredError, + ServiceUnavailableError, + TooManyRequestsError, + UnauthorizedError, + UnprocessableEntityError, +) from . import tts from .client import AsyncSpeechify, Speechify from .environment import SpeechifyEnvironment from .version import __version__ -__all__ = ["AsyncSpeechify", "Speechify", "SpeechifyEnvironment", "__version__", "tts"] +__all__ = [ + "AsyncSpeechify", + "BadGatewayError", + "BadRequestError", + "CreateVoiceLanguage", + "CreateVoiceModel", + "CreateVoiceModelName", + "CreatedVoice", + "CreatedVoiceGender", + "CreatedVoiceType", + "Error", + "ErrorCode", + "ErrorDetail", + "ForbiddenError", + "GetSpeechOptionsRequest", + "GetSpeechResponse", + "GetSpeechResponseAudioFormat", + "GetStreamOptionsRequest", + "GetVoice", + "GetVoiceGender", + "GetVoiceLanguage", + "GetVoiceType", + "GetVoicesModel", + "GetVoicesModelName", + "InternalServerError", + "NestedChunk", + "NotFoundError", + "PaymentRequiredError", + "ServiceUnavailableError", + "SpeechMarks", + "Speechify", + "SpeechifyEnvironment", + "TooManyRequestsError", + "UnauthorizedError", + "UnprocessableEntityError", + "__version__", + "tts", +] diff --git a/src/speechify/client.py b/src/speechify/client.py index 909afb0..e356bae 100644 --- a/src/speechify/client.py +++ b/src/speechify/client.py @@ -4,6 +4,7 @@ from .environment import SpeechifyEnvironment import os import httpx +from .core.api_error import ApiError from .core.client_wrapper import SyncClientWrapper from .tts.client import TtsClient from .core.client_wrapper import AsyncClientWrapper @@ -58,6 +59,10 @@ def __init__( httpx_client: typing.Optional[httpx.Client] = None, ): _defaulted_timeout = timeout if timeout is not None else 60 if httpx_client is None else None + if token is None: + raise ApiError( + body="The client must be instantiated be either passing in token or setting SPEECHIFY_API_KEY" + ) self._client_wrapper = SyncClientWrapper( base_url=_get_base_url(base_url=base_url, environment=environment), token=token, @@ -119,6 +124,10 @@ def __init__( httpx_client: typing.Optional[httpx.AsyncClient] = None, ): _defaulted_timeout = timeout if timeout is not None else 60 if httpx_client is None else None + if token is None: + raise ApiError( + body="The client must be instantiated be either passing in token or setting SPEECHIFY_API_KEY" + ) self._client_wrapper = AsyncClientWrapper( base_url=_get_base_url(base_url=base_url, environment=environment), token=token, diff --git a/src/speechify/tts/errors/__init__.py b/src/speechify/errors/__init__.py similarity index 60% rename from src/speechify/tts/errors/__init__.py rename to src/speechify/errors/__init__.py index 4bf158a..7b4bd00 100644 --- a/src/speechify/tts/errors/__init__.py +++ b/src/speechify/errors/__init__.py @@ -1,21 +1,25 @@ # This file was auto-generated by Fern from our API Definition. +from .bad_gateway_error import BadGatewayError from .bad_request_error import BadRequestError -from .conflict_error import ConflictError -from .content_too_large_error import ContentTooLargeError from .forbidden_error import ForbiddenError from .internal_server_error import InternalServerError from .not_found_error import NotFoundError from .payment_required_error import PaymentRequiredError +from .service_unavailable_error import ServiceUnavailableError +from .too_many_requests_error import TooManyRequestsError from .unauthorized_error import UnauthorizedError +from .unprocessable_entity_error import UnprocessableEntityError __all__ = [ + "BadGatewayError", "BadRequestError", - "ConflictError", - "ContentTooLargeError", "ForbiddenError", "InternalServerError", "NotFoundError", "PaymentRequiredError", + "ServiceUnavailableError", + "TooManyRequestsError", "UnauthorizedError", + "UnprocessableEntityError", ] diff --git a/src/speechify/errors/bad_gateway_error.py b/src/speechify/errors/bad_gateway_error.py new file mode 100644 index 0000000..a75235c --- /dev/null +++ b/src/speechify/errors/bad_gateway_error.py @@ -0,0 +1,9 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.api_error import ApiError +from ..types.error import Error + + +class BadGatewayError(ApiError): + def __init__(self, body: Error): + super().__init__(status_code=502, body=body) diff --git a/src/speechify/tts/errors/bad_request_error.py b/src/speechify/errors/bad_request_error.py similarity index 85% rename from src/speechify/tts/errors/bad_request_error.py rename to src/speechify/errors/bad_request_error.py index 66ac1e3..9c13c61 100644 --- a/src/speechify/tts/errors/bad_request_error.py +++ b/src/speechify/errors/bad_request_error.py @@ -1,6 +1,6 @@ # This file was auto-generated by Fern from our API Definition. -from ...core.api_error import ApiError +from ..core.api_error import ApiError import typing diff --git a/src/speechify/tts/errors/forbidden_error.py b/src/speechify/errors/forbidden_error.py similarity index 57% rename from src/speechify/tts/errors/forbidden_error.py rename to src/speechify/errors/forbidden_error.py index cc295c8..6f2a04a 100644 --- a/src/speechify/tts/errors/forbidden_error.py +++ b/src/speechify/errors/forbidden_error.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ...core.api_error import ApiError -import typing +from ..core.api_error import ApiError +from ..types.error import Error class ForbiddenError(ApiError): - def __init__(self, body: typing.Optional[typing.Any]): + def __init__(self, body: Error): super().__init__(status_code=403, body=body) diff --git a/src/speechify/tts/errors/internal_server_error.py b/src/speechify/errors/internal_server_error.py similarity index 58% rename from src/speechify/tts/errors/internal_server_error.py rename to src/speechify/errors/internal_server_error.py index 2bd9889..c5dcb4a 100644 --- a/src/speechify/tts/errors/internal_server_error.py +++ b/src/speechify/errors/internal_server_error.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ...core.api_error import ApiError -import typing +from ..core.api_error import ApiError +from ..types.error import Error class InternalServerError(ApiError): - def __init__(self, body: typing.Optional[typing.Any]): + def __init__(self, body: Error): super().__init__(status_code=500, body=body) diff --git a/src/speechify/tts/errors/not_found_error.py b/src/speechify/errors/not_found_error.py similarity index 85% rename from src/speechify/tts/errors/not_found_error.py rename to src/speechify/errors/not_found_error.py index f5fb993..a1235b8 100644 --- a/src/speechify/tts/errors/not_found_error.py +++ b/src/speechify/errors/not_found_error.py @@ -1,6 +1,6 @@ # This file was auto-generated by Fern from our API Definition. -from ...core.api_error import ApiError +from ..core.api_error import ApiError import typing diff --git a/src/speechify/tts/errors/payment_required_error.py b/src/speechify/errors/payment_required_error.py similarity index 58% rename from src/speechify/tts/errors/payment_required_error.py rename to src/speechify/errors/payment_required_error.py index 3a82ecc..4159359 100644 --- a/src/speechify/tts/errors/payment_required_error.py +++ b/src/speechify/errors/payment_required_error.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ...core.api_error import ApiError -import typing +from ..core.api_error import ApiError +from ..types.error import Error class PaymentRequiredError(ApiError): - def __init__(self, body: typing.Optional[typing.Any]): + def __init__(self, body: Error): super().__init__(status_code=402, body=body) diff --git a/src/speechify/errors/service_unavailable_error.py b/src/speechify/errors/service_unavailable_error.py new file mode 100644 index 0000000..81c32e6 --- /dev/null +++ b/src/speechify/errors/service_unavailable_error.py @@ -0,0 +1,9 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.api_error import ApiError +from ..types.error import Error + + +class ServiceUnavailableError(ApiError): + def __init__(self, body: Error): + super().__init__(status_code=503, body=body) diff --git a/src/speechify/errors/too_many_requests_error.py b/src/speechify/errors/too_many_requests_error.py new file mode 100644 index 0000000..c2b3b10 --- /dev/null +++ b/src/speechify/errors/too_many_requests_error.py @@ -0,0 +1,9 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.api_error import ApiError +from ..types.error import Error + + +class TooManyRequestsError(ApiError): + def __init__(self, body: Error): + super().__init__(status_code=429, body=body) diff --git a/src/speechify/tts/errors/unauthorized_error.py b/src/speechify/errors/unauthorized_error.py similarity index 85% rename from src/speechify/tts/errors/unauthorized_error.py rename to src/speechify/errors/unauthorized_error.py index b8bb12b..1c00f98 100644 --- a/src/speechify/tts/errors/unauthorized_error.py +++ b/src/speechify/errors/unauthorized_error.py @@ -1,6 +1,6 @@ # This file was auto-generated by Fern from our API Definition. -from ...core.api_error import ApiError +from ..core.api_error import ApiError import typing diff --git a/src/speechify/errors/unprocessable_entity_error.py b/src/speechify/errors/unprocessable_entity_error.py new file mode 100644 index 0000000..f9752ba --- /dev/null +++ b/src/speechify/errors/unprocessable_entity_error.py @@ -0,0 +1,9 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.api_error import ApiError +from ..types.error import Error + + +class UnprocessableEntityError(ApiError): + def __init__(self, body: Error): + super().__init__(status_code=422, body=body) diff --git a/src/speechify/tts/__init__.py b/src/speechify/tts/__init__.py index 878b91d..2bdc653 100644 --- a/src/speechify/tts/__init__.py +++ b/src/speechify/tts/__init__.py @@ -1,297 +1,15 @@ # This file was auto-generated by Fern from our API Definition. -from .types import ( - AccessToken, - AccessTokenScope, - AccessTokenTokenType, - Agent, - AgentTest, - AgentTestAttachment, - AgentTestConfig, - AgentTestFolder, - AgentTestRun, - AgentTestWithLastRun, - ApiKey, - BatchRunEntry, - ClientToolConfig, - Conversation, - ConversationStats, - ConversationStatus, - ConversationTransport, - CreateConversationResponse, - CreateVoiceLanguage, - CreateVoiceModel, - CreateVoiceModelName, - CreatedVoice, - CreatedVoiceGender, - CreatedVoiceType, - DataCollectionField, - DataCollectionFieldType, - DeleteMemoriesByCallerResponse, - DynamicVariable, - DynamicVariableType, - Evaluation, - EvaluationConfig, - EvaluationCriterion, - EvaluationKind, - EvaluationStatus, - GetSpeechOptionsRequest, - GetSpeechResponse, - GetSpeechResponseAudioFormat, - GetStreamOptionsRequest, - GetVoice, - GetVoiceGender, - GetVoiceLanguage, - GetVoiceType, - GetVoicesModel, - GetVoicesModelName, - Invite, - InvitePreview, - InvitesListResponse, - KnowledgeBase, - KnowledgeBaseChunk, - KnowledgeBaseDocument, - KnowledgeBaseDocumentStatus, - KnowledgeBaseSearchHit, - ListAgentTestAttachmentsResponse, - ListAgentTestFoldersResponse, - ListAgentTestRunsResponse, - ListAgentTestsResponse, - ListAgentsResponse, - ListConversationsResponse, - ListDynamicVariablesResponse, - ListEvaluationsResponse, - ListKnowledgeBaseChunksResponse, - ListKnowledgeBaseDocumentsResponse, - ListKnowledgeBasesResponse, - ListMemoriesResponse, - ListMessagesResponse, - ListTestsResponse, - ListToolsResponse, - Member, - MemberRole, - MembersListResponse, - Memory, - Message, - MessageRole, - MockingStrategy, - NestedChunk, - NoMatchBehavior, - OAuthError, - OAuthErrorError, - ParameterCheck, - ParameterCheckMode, - ParameterCheckResult, - RunAgentTestsResponse, - RunBatchResponse, - ScenarioConfig, - ScenarioResult, - SearchKnowledgeBasesResponse, - SimulationConfig, - SimulationMessage, - SimulationMessageRole, - SimulationResult, - SimulationToolCall, - SpeechMarks, - SystemToolConfig, - SystemToolConfigBuiltin, - SystemVariableDoc, - Tenant, - TenantDataRegion, - TenantPlan, - TenantsListResponse, - TestRunResult, - TestRunStatus, - TestStats, - TestStatsBucket, - TestType, - Tool, - ToolCallConfig, - ToolCallResult, - ToolConfig, - ToolKind, - ToolMock, - ToolMockConfig, - ToolParam, - ToolParamType, - WebhookToolConfig, - WebhookToolConfigMethod, -) -from .errors import ( - BadRequestError, - ConflictError, - ContentTooLargeError, - ForbiddenError, - InternalServerError, - NotFoundError, - PaymentRequiredError, - UnauthorizedError, -) -from . import ( - agents, - audio, - auth, - conversations, - knowledge_bases, - memories, - outbound_calls, - phone_numbers, - sip_trunks, - tools, - voices, - workspaces, -) -from .agents import CreateAgentTestRequestConfig, UpdateAgentTestRequestConfig +from . import audio, voices from .audio import GetSpeechRequestAudioFormat, GetSpeechRequestModel, GetStreamRequestModel, StreamAudioRequestAccept -from .auth import CreateAccessTokenRequestGrantType, CreateAccessTokenRequestScope -from .tools import CreateToolRequestConfig, UpdateToolRequestConfig from .voices import CreateVoicesRequestGender __all__ = [ - "AccessToken", - "AccessTokenScope", - "AccessTokenTokenType", - "Agent", - "AgentTest", - "AgentTestAttachment", - "AgentTestConfig", - "AgentTestFolder", - "AgentTestRun", - "AgentTestWithLastRun", - "ApiKey", - "BadRequestError", - "BatchRunEntry", - "ClientToolConfig", - "ConflictError", - "ContentTooLargeError", - "Conversation", - "ConversationStats", - "ConversationStatus", - "ConversationTransport", - "CreateAccessTokenRequestGrantType", - "CreateAccessTokenRequestScope", - "CreateAgentTestRequestConfig", - "CreateConversationResponse", - "CreateToolRequestConfig", - "CreateVoiceLanguage", - "CreateVoiceModel", - "CreateVoiceModelName", "CreateVoicesRequestGender", - "CreatedVoice", - "CreatedVoiceGender", - "CreatedVoiceType", - "DataCollectionField", - "DataCollectionFieldType", - "DeleteMemoriesByCallerResponse", - "DynamicVariable", - "DynamicVariableType", - "Evaluation", - "EvaluationConfig", - "EvaluationCriterion", - "EvaluationKind", - "EvaluationStatus", - "ForbiddenError", - "GetSpeechOptionsRequest", "GetSpeechRequestAudioFormat", "GetSpeechRequestModel", - "GetSpeechResponse", - "GetSpeechResponseAudioFormat", - "GetStreamOptionsRequest", "GetStreamRequestModel", - "GetVoice", - "GetVoiceGender", - "GetVoiceLanguage", - "GetVoiceType", - "GetVoicesModel", - "GetVoicesModelName", - "InternalServerError", - "Invite", - "InvitePreview", - "InvitesListResponse", - "KnowledgeBase", - "KnowledgeBaseChunk", - "KnowledgeBaseDocument", - "KnowledgeBaseDocumentStatus", - "KnowledgeBaseSearchHit", - "ListAgentTestAttachmentsResponse", - "ListAgentTestFoldersResponse", - "ListAgentTestRunsResponse", - "ListAgentTestsResponse", - "ListAgentsResponse", - "ListConversationsResponse", - "ListDynamicVariablesResponse", - "ListEvaluationsResponse", - "ListKnowledgeBaseChunksResponse", - "ListKnowledgeBaseDocumentsResponse", - "ListKnowledgeBasesResponse", - "ListMemoriesResponse", - "ListMessagesResponse", - "ListTestsResponse", - "ListToolsResponse", - "Member", - "MemberRole", - "MembersListResponse", - "Memory", - "Message", - "MessageRole", - "MockingStrategy", - "NestedChunk", - "NoMatchBehavior", - "NotFoundError", - "OAuthError", - "OAuthErrorError", - "ParameterCheck", - "ParameterCheckMode", - "ParameterCheckResult", - "PaymentRequiredError", - "RunAgentTestsResponse", - "RunBatchResponse", - "ScenarioConfig", - "ScenarioResult", - "SearchKnowledgeBasesResponse", - "SimulationConfig", - "SimulationMessage", - "SimulationMessageRole", - "SimulationResult", - "SimulationToolCall", - "SpeechMarks", "StreamAudioRequestAccept", - "SystemToolConfig", - "SystemToolConfigBuiltin", - "SystemVariableDoc", - "Tenant", - "TenantDataRegion", - "TenantPlan", - "TenantsListResponse", - "TestRunResult", - "TestRunStatus", - "TestStats", - "TestStatsBucket", - "TestType", - "Tool", - "ToolCallConfig", - "ToolCallResult", - "ToolConfig", - "ToolKind", - "ToolMock", - "ToolMockConfig", - "ToolParam", - "ToolParamType", - "UnauthorizedError", - "UpdateAgentTestRequestConfig", - "UpdateToolRequestConfig", - "WebhookToolConfig", - "WebhookToolConfigMethod", - "agents", "audio", - "auth", - "conversations", - "knowledge_bases", - "memories", - "outbound_calls", - "phone_numbers", - "sip_trunks", - "tools", "voices", - "workspaces", ] diff --git a/src/speechify/tts/agents/__init__.py b/src/speechify/tts/agents/__init__.py deleted file mode 100644 index 1e56e81..0000000 --- a/src/speechify/tts/agents/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from .types import CreateAgentTestRequestConfig, UpdateAgentTestRequestConfig - -__all__ = ["CreateAgentTestRequestConfig", "UpdateAgentTestRequestConfig"] diff --git a/src/speechify/tts/agents/client.py b/src/speechify/tts/agents/client.py deleted file mode 100644 index 17433d1..0000000 --- a/src/speechify/tts/agents/client.py +++ /dev/null @@ -1,6604 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing -from ...core.client_wrapper import SyncClientWrapper -from ...core.request_options import RequestOptions -from ..types.list_agents_response import ListAgentsResponse -from ...core.pydantic_utilities import parse_obj_as -from ..errors.unauthorized_error import UnauthorizedError -from json.decoder import JSONDecodeError -from ...core.api_error import ApiError -from ..types.agent import Agent -from ..errors.bad_request_error import BadRequestError -from ...core.jsonable_encoder import jsonable_encoder -from ..errors.not_found_error import NotFoundError -from ..types.list_tools_response import ListToolsResponse -from ..types.evaluation_config import EvaluationConfig -from ..types.evaluation_criterion import EvaluationCriterion -from ..types.data_collection_field import DataCollectionField -from ...core.serialization import convert_and_respect_annotation_metadata -from ..types.list_dynamic_variables_response import ListDynamicVariablesResponse -from ..types.dynamic_variable import DynamicVariable -from ..types.create_conversation_response import CreateConversationResponse -from ..errors.forbidden_error import ForbiddenError -from ..types.list_knowledge_bases_response import ListKnowledgeBasesResponse -from ..types.list_memories_response import ListMemoriesResponse -from ..types.delete_memories_by_caller_response import DeleteMemoriesByCallerResponse -from ..types.list_agent_tests_response import ListAgentTestsResponse -from ..types.test_type import TestType -from .types.create_agent_test_request_config import CreateAgentTestRequestConfig -from ..types.tool_mock_config import ToolMockConfig -from ..types.agent_test import AgentTest -from ..types.run_agent_tests_response import RunAgentTestsResponse -from .types.update_agent_test_request_config import UpdateAgentTestRequestConfig -from ..types.list_agent_test_runs_response import ListAgentTestRunsResponse -from ..types.agent_test_run import AgentTestRun -from ..types.list_tests_response import ListTestsResponse -from ..types.test_stats import TestStats -from ..types.batch_run_entry import BatchRunEntry -from ..types.run_batch_response import RunBatchResponse -from ..types.list_agent_test_attachments_response import ListAgentTestAttachmentsResponse -from ..types.list_agent_test_folders_response import ListAgentTestFoldersResponse -from ..types.agent_test_folder import AgentTestFolder -from ...core.client_wrapper import AsyncClientWrapper - -# this is used as the default value for optional parameters -OMIT = typing.cast(typing.Any, ...) - - -class AgentsClient: - def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper - - def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> ListAgentsResponse: - """ - List voice agents owned by the caller. - - Parameters - ---------- - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListAgentsResponse - A list of voice agents. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.list() - """ - _response = self._client_wrapper.httpx_client.request( - "v1/agents", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListAgentsResponse, - parse_obj_as( - type_=ListAgentsResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def create( - self, - *, - name: str, - voice_id: str, - slug: typing.Optional[str] = OMIT, - prompt: typing.Optional[str] = OMIT, - first_message: typing.Optional[str] = OMIT, - language: typing.Optional[str] = OMIT, - llm_model: typing.Optional[str] = OMIT, - temperature: typing.Optional[float] = OMIT, - config: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, - is_public: typing.Optional[bool] = OMIT, - allowed_origins: typing.Optional[typing.Sequence[str]] = OMIT, - hostname_allowlist: typing.Optional[typing.Sequence[str]] = OMIT, - memory_enabled: typing.Optional[bool] = OMIT, - memory_retention_days: typing.Optional[int] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> Agent: - """ - Create a voice agent. - - Parameters - ---------- - name : str - - voice_id : str - Voice slug from the VMS catalog (see GET /v1/voices). Required — the server rejects writes with an unknown or empty slug. - - slug : typing.Optional[str] - Optional. Server derives slug from name with a random suffix when omitted; if you supply your own, a collision returns 400 'slug already taken'. - - prompt : typing.Optional[str] - - first_message : typing.Optional[str] - Spoken verbatim at session start — no LLM round trip. - - language : typing.Optional[str] - - llm_model : typing.Optional[str] - Optional chat model slug. Leave empty to use the Speechify default. - - temperature : typing.Optional[float] - - config : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] - - is_public : typing.Optional[bool] - - allowed_origins : typing.Optional[typing.Sequence[str]] - - hostname_allowlist : typing.Optional[typing.Sequence[str]] - Optional per-agent hostname allowlist (see Agent schema). - - memory_enabled : typing.Optional[bool] - - memory_retention_days : typing.Optional[int] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Agent - The created agent. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.create( - name="name", - voice_id="voice_id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - "v1/agents", - method="POST", - json={ - "name": name, - "slug": slug, - "prompt": prompt, - "first_message": first_message, - "language": language, - "llm_model": llm_model, - "voice_id": voice_id, - "temperature": temperature, - "config": config, - "is_public": is_public, - "allowed_origins": allowed_origins, - "hostname_allowlist": hostname_allowlist, - "memory_enabled": memory_enabled, - "memory_retention_days": memory_retention_days, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Agent, - parse_obj_as( - type_=Agent, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Agent: - """ - Retrieve a voice agent by ID. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Agent - The requested agent. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.get( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Agent, - parse_obj_as( - type_=Agent, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Delete a voice agent. Conversations and attached tools remain. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.delete( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}", - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def update( - self, - id: str, - *, - name: typing.Optional[str] = OMIT, - prompt: typing.Optional[str] = OMIT, - first_message: typing.Optional[str] = OMIT, - language: typing.Optional[str] = OMIT, - llm_model: typing.Optional[str] = OMIT, - voice_id: typing.Optional[str] = OMIT, - temperature: typing.Optional[float] = OMIT, - config: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, - is_public: typing.Optional[bool] = OMIT, - allowed_origins: typing.Optional[typing.Sequence[str]] = OMIT, - hostname_allowlist: typing.Optional[typing.Sequence[str]] = OMIT, - memory_enabled: typing.Optional[bool] = OMIT, - memory_retention_days: typing.Optional[int] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> Agent: - """ - Update a voice agent. Only fields present on the request body are changed. - - Parameters - ---------- - id : str - - name : typing.Optional[str] - - prompt : typing.Optional[str] - - first_message : typing.Optional[str] - - language : typing.Optional[str] - - llm_model : typing.Optional[str] - - voice_id : typing.Optional[str] - - temperature : typing.Optional[float] - - config : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] - - is_public : typing.Optional[bool] - - allowed_origins : typing.Optional[typing.Sequence[str]] - - hostname_allowlist : typing.Optional[typing.Sequence[str]] - When supplied, replaces the stored list. Pass an empty - array to clear enforcement (public agent is open again). - Omit the field to leave the existing value unchanged. - - memory_enabled : typing.Optional[bool] - - memory_retention_days : typing.Optional[int] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Agent - The updated agent. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.update( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}", - method="PATCH", - json={ - "name": name, - "prompt": prompt, - "first_message": first_message, - "language": language, - "llm_model": llm_model, - "voice_id": voice_id, - "temperature": temperature, - "config": config, - "is_public": is_public, - "allowed_origins": allowed_origins, - "hostname_allowlist": hostname_allowlist, - "memory_enabled": memory_enabled, - "memory_retention_days": memory_retention_days, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Agent, - parse_obj_as( - type_=Agent, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def list_tools(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> ListToolsResponse: - """ - List tools currently attached to the agent. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListToolsResponse - Attached tools for the agent. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.list_tools( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/tools", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListToolsResponse, - parse_obj_as( - type_=ListToolsResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def attach_tool(self, id: str, tool_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Attach an existing tool to the agent so the LLM can call it. - - Parameters - ---------- - id : str - - tool_id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.attach_tool( - id="id", - tool_id="toolId", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/tools/{jsonable_encoder(tool_id)}", - method="POST", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def detach_tool(self, id: str, tool_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Detach a tool from the agent. - - Parameters - ---------- - id : str - - tool_id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.detach_tool( - id="id", - tool_id="toolId", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/tools/{jsonable_encoder(tool_id)}", - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def get_evaluation_config( - self, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> EvaluationConfig: - """ - Retrieve the agent's post-call evaluation criteria + data-collection config. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - EvaluationConfig - The evaluation config for the agent. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.get_evaluation_config( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/evaluation-config", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - EvaluationConfig, - parse_obj_as( - type_=EvaluationConfig, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def update_evaluation_config( - self, - id: str, - *, - criteria: typing.Sequence[EvaluationCriterion], - data_collection: typing.Sequence[DataCollectionField], - request_options: typing.Optional[RequestOptions] = None, - ) -> EvaluationConfig: - """ - Replace the agent's evaluation criteria + data-collection fields. - - Parameters - ---------- - id : str - - criteria : typing.Sequence[EvaluationCriterion] - - data_collection : typing.Sequence[DataCollectionField] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - EvaluationConfig - The updated evaluation config. - - Examples - -------- - from speechify import Speechify - from speechify.tts import DataCollectionField, EvaluationCriterion - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.update_evaluation_config( - id="id", - criteria=[ - EvaluationCriterion( - id="id", - name="name", - description="description", - ) - ], - data_collection=[ - DataCollectionField( - key="key", - description="description", - type="string", - ) - ], - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/evaluation-config", - method="PATCH", - json={ - "criteria": convert_and_respect_annotation_metadata( - object_=criteria, annotation=typing.Sequence[EvaluationCriterion], direction="write" - ), - "data_collection": convert_and_respect_annotation_metadata( - object_=data_collection, annotation=typing.Sequence[DataCollectionField], direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - EvaluationConfig, - parse_obj_as( - type_=EvaluationConfig, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def get_dynamic_variables( - self, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> ListDynamicVariablesResponse: - """ - Retrieve the agent's customer-scope dynamic variables and the read-only - catalogue of reserved `system__*` keys. The system variables list is - provided so editor UIs can render the reference list without maintaining - a client-side copy of the catalogue. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListDynamicVariablesResponse - The agent's variable catalogue. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.get_dynamic_variables( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/variables", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListDynamicVariablesResponse, - parse_obj_as( - type_=ListDynamicVariablesResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def update_dynamic_variables( - self, - id: str, - *, - variables: typing.Sequence[DynamicVariable], - request_options: typing.Optional[RequestOptions] = None, - ) -> ListDynamicVariablesResponse: - """ - Replace the agent's customer-scope dynamic variable definitions. - The supplied list overwrites the stored list wholesale (same - semantics as `updateEvaluationConfig`). Pass an empty array to - clear all variables. Up to 20 variables per agent. Keys must - match `[a-zA-Z0-9_]+` and must not start with the reserved - `system__` prefix. - - Parameters - ---------- - id : str - - variables : typing.Sequence[DynamicVariable] - The new variable list. Replaces the existing list entirely. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListDynamicVariablesResponse - The updated variable catalogue. - - Examples - -------- - from speechify import Speechify - from speechify.tts import DynamicVariable - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.update_dynamic_variables( - id="id", - variables=[ - DynamicVariable( - key="product_name", - type="string", - default="Speechify", - description="Product the agent is supporting.", - ), - DynamicVariable( - key="support_tier", - type="number", - default=1, - ), - DynamicVariable( - key="account_metadata", - type="json", - description="Arbitrary account context injected into tool bodies.", - ), - ], - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/variables", - method="PATCH", - json={ - "variables": convert_and_respect_annotation_metadata( - object_=variables, annotation=typing.Sequence[DynamicVariable], direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListDynamicVariablesResponse, - parse_obj_as( - type_=ListDynamicVariablesResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def create_conversation( - self, - id: str, - *, - transport: typing.Optional[str] = OMIT, - dynamic_variables: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> CreateConversationResponse: - """ - Start a new voice conversation with the agent. Returns a realtime - voice session + short-lived client token so the caller can - connect the audio pipeline directly. The agent is dispatched - server-side; no additional client action required. - - Pass `dynamic_variables` to supply per-session values that override - the agent's stored variable defaults for this one conversation. - Keys in the `system__` namespace are rejected at this boundary. - - Parameters - ---------- - id : str - - transport : typing.Optional[str] - Transport hint. Omit to use the agent's default. - - dynamic_variables : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] - Per-session variable overrides that merge on top of the agent's - stored variable defaults for this one conversation. Keys in the - reserved `system__` namespace are rejected. Values must match the - declared type of the corresponding variable definition on the agent. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - CreateConversationResponse - The created conversation with its realtime session token. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.create_conversation( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/conversations", - method="POST", - json={ - "transport": transport, - "dynamic_variables": dynamic_variables, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CreateConversationResponse, - parse_obj_as( - type_=CreateConversationResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def create_session( - self, - id: str, - *, - user_identity: typing.Optional[str] = OMIT, - dynamic_variables: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> CreateConversationResponse: - """ - Mint a realtime voice session for the given agent. Widget-friendly - counterpart to `createConversation` — same response shape, dual - authentication: - - * **Authenticated (Bearer)**: works for any agent the caller - owns. Typical server-to-server flow where the embedding - site's backend mints a token and hands it to the browser so - the API key never reaches the client. - * **Unauthenticated**: works only when `agent.is_public = true` - AND the request's `Origin` header matches `agent.allowed_origins` - (or that list is empty). When `agent.hostname_allowlist` is - non-empty, the `Origin` hostname must additionally be a - member of that list. Used directly by the - `` web component. - - Responds with the same `CreateConversationResponse` as - `createConversation`. - - Parameters - ---------- - id : str - - user_identity : typing.Optional[str] - Opaque identifier for the end-user (e.g. your app's user ID). Stamped onto the conversation. Optional - defaults to an anonymous per-session ID. - - dynamic_variables : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] - Per-session variable overrides that merge on top of the agent's - stored variable defaults for this one session. Keys in the - reserved `system__` namespace are rejected at this boundary. - Values must match the declared type of the corresponding variable - definition on the agent (a `string` type expects a JSON string, - `number` expects a JSON number, etc.). - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - CreateConversationResponse - The created session with its realtime token + URL. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.create_session( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/sessions", - method="POST", - json={ - "user_identity": user_identity, - "dynamic_variables": dynamic_variables, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CreateConversationResponse, - parse_obj_as( - type_=CreateConversationResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def list_agent_knowledge_bases( - self, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> ListKnowledgeBasesResponse: - """ - List knowledge bases attached to an agent. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListKnowledgeBasesResponse - The knowledge bases attached to the agent. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.list_agent_knowledge_bases( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/knowledge-bases", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListKnowledgeBasesResponse, - parse_obj_as( - type_=ListKnowledgeBasesResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def attach_knowledge_base( - self, id: str, kb_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> None: - """ - Attach a knowledge base to an agent. The `search_knowledge` tool - is auto-registered on the next conversation and can only query the - attached knowledge bases. - - Parameters - ---------- - id : str - - kb_id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.attach_knowledge_base( - id="id", - kb_id="kbId", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/knowledge-bases/{jsonable_encoder(kb_id)}", - method="POST", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def detach_knowledge_base( - self, id: str, kb_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> None: - """ - Detach a knowledge base from an agent. - - Parameters - ---------- - id : str - - kb_id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.detach_knowledge_base( - id="id", - kb_id="kbId", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/knowledge-bases/{jsonable_encoder(kb_id)}", - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def list_memories( - self, - id: str, - *, - limit: typing.Optional[int] = None, - offset: typing.Optional[int] = None, - request_options: typing.Optional[RequestOptions] = None, - ) -> ListMemoriesResponse: - """ - List per-caller memories extracted for an agent. Memories are - written post-call by the built-in extractor when `memory_enabled` - is true on the agent; the list is sorted newest-first. - - Parameters - ---------- - id : str - - limit : typing.Optional[int] - Maximum rows to return. Defaults to 100, capped at 200. - - offset : typing.Optional[int] - Number of rows to skip. Combine with `limit` to page through older memories. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListMemoriesResponse - Memories for the agent. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.list_memories( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/memories", - method="GET", - params={ - "limit": limit, - "offset": offset, - }, - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListMemoriesResponse, - parse_obj_as( - type_=ListMemoriesResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def delete_memories_by_caller( - self, id: str, *, agent_id: str, caller_identity: str, request_options: typing.Optional[RequestOptions] = None - ) -> DeleteMemoriesByCallerResponse: - """ - Delete every memory ever extracted for a specific caller on - this agent. Privacy / GDPR surface. Returns the count of rows - soft-deleted; rows become permanently unreachable immediately - and are hard-deleted by the retention job after the tenant's - configured retention window. - - Parameters - ---------- - id : str - - agent_id : str - - caller_identity : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - DeleteMemoriesByCallerResponse - Deletion summary. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.delete_memories_by_caller( - id="id", - agent_id="agent_id", - caller_identity="caller_identity", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/memories/delete-by-caller", - method="POST", - json={ - "agent_id": agent_id, - "caller_identity": caller_identity, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - DeleteMemoriesByCallerResponse, - parse_obj_as( - type_=DeleteMemoriesByCallerResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def list_tests(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> ListAgentTestsResponse: - """ - List all tests configured for the agent. Each entry includes the - most recent run so the console can render pass/fail badges without - an extra round-trip. - - Parameters - ---------- - id : str - Agent ID. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListAgentTestsResponse - Tests for the agent with last-run summaries. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.list_tests( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/tests", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListAgentTestsResponse, - parse_obj_as( - type_=ListAgentTestsResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def create_test( - self, - id: str, - *, - name: str, - type: TestType, - config: CreateAgentTestRequestConfig, - description: typing.Optional[str] = OMIT, - tool_mock_config: typing.Optional[ToolMockConfig] = OMIT, - variables: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, - folder_id: typing.Optional[str] = OMIT, - attached_agent_ids: typing.Optional[typing.Sequence[str]] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> AgentTest: - """ - Create a new test for the agent. - - Parameters - ---------- - id : str - Agent ID. - - name : str - Short human-readable label for the test. - - type : TestType - - config : CreateAgentTestRequestConfig - Type-specific configuration. Must match the shape for the given `type`. - - description : typing.Optional[str] - Optional longer description of what this test verifies. - - tool_mock_config : typing.Optional[ToolMockConfig] - Optional tool-mocking config applied during every run of this test. - - variables : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] - Per-test variable values substituted into string fields of the - config at run-start. Keys use the same rules as agent-level - `DynamicVariable` keys. - - folder_id : typing.Optional[str] - Folder to place the test in. Omit for root. - - attached_agent_ids : typing.Optional[typing.Sequence[str]] - Optional list of additional agents this test should also run - against. The owner agent (path param) is always attached - implicitly. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - AgentTest - The created test. - - Examples - -------- - from speechify import Speechify - from speechify.tts import ScenarioConfig - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.create_test( - id="id", - name="Greet the caller by name", - description="Agent should greet the caller using their name when provided.", - type="scenario", - config=ScenarioConfig( - context="The caller says: Hi, I'm Alice.", - success_criteria="The agent greets Alice by name.", - success_examples=["Hi Alice! How can I help you today?"], - failure_examples=["Hello! How can I help you?"], - ), - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/tests", - method="POST", - json={ - "name": name, - "description": description, - "type": type, - "config": convert_and_respect_annotation_metadata( - object_=config, annotation=CreateAgentTestRequestConfig, direction="write" - ), - "tool_mock_config": convert_and_respect_annotation_metadata( - object_=tool_mock_config, annotation=ToolMockConfig, direction="write" - ), - "variables": variables, - "folder_id": folder_id, - "attached_agent_ids": attached_agent_ids, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AgentTest, - parse_obj_as( - type_=AgentTest, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def run_all_tests( - self, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> RunAgentTestsResponse: - """ - Enqueue runs for every test on the agent concurrently. Up to 50 - tests are dispatched in one call. Each returned run starts in - `queued` status; poll `GET /v1/test-runs/{id}` for the terminal - result. - - Parameters - ---------- - id : str - Agent ID. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - RunAgentTestsResponse - Queued runs for all tests on the agent. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.run_all_tests( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/tests/runs", - method="POST", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - RunAgentTestsResponse, - parse_obj_as( - type_=RunAgentTestsResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def get_test(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> AgentTest: - """ - Retrieve a test by ID. - - Parameters - ---------- - id : str - Test ID. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - AgentTest - The requested test. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.get_test( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/tests/{jsonable_encoder(id)}", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AgentTest, - parse_obj_as( - type_=AgentTest, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def delete_test(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Delete a test and all its run history. - - Parameters - ---------- - id : str - Test ID. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.delete_test( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/tests/{jsonable_encoder(id)}", - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def update_test( - self, - id: str, - *, - name: typing.Optional[str] = OMIT, - description: typing.Optional[str] = OMIT, - config: typing.Optional[UpdateAgentTestRequestConfig] = OMIT, - tool_mock_config: typing.Optional[ToolMockConfig] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> AgentTest: - """ - Update a test. Only fields present on the request body are changed. - - Parameters - ---------- - id : str - Test ID. - - name : typing.Optional[str] - - description : typing.Optional[str] - - config : typing.Optional[UpdateAgentTestRequestConfig] - Replaces the test config when present. - - tool_mock_config : typing.Optional[ToolMockConfig] - Replaces the tool-mock config when present. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - AgentTest - The updated test. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.update_test( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/tests/{jsonable_encoder(id)}", - method="PATCH", - json={ - "name": name, - "description": description, - "config": convert_and_respect_annotation_metadata( - object_=config, annotation=UpdateAgentTestRequestConfig, direction="write" - ), - "tool_mock_config": convert_and_respect_annotation_metadata( - object_=tool_mock_config, annotation=ToolMockConfig, direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AgentTest, - parse_obj_as( - type_=AgentTest, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def list_test_runs( - self, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> ListAgentTestRunsResponse: - """ - List the run history for a test, newest first. - - Parameters - ---------- - id : str - Test ID. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListAgentTestRunsResponse - Run history for the test. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.list_test_runs( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/tests/{jsonable_encoder(id)}/runs", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListAgentTestRunsResponse, - parse_obj_as( - type_=ListAgentTestRunsResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def run_test(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> AgentTestRun: - """ - Enqueue a single run of the test. The returned run starts in - `queued` status. Poll `GET /v1/test-runs/{id}` until the status - reaches a terminal state (`passed`, `failed`, or `error`). - - Parameters - ---------- - id : str - Test ID. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - AgentTestRun - The queued run. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.run_test( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/tests/{jsonable_encoder(id)}/runs", - method="POST", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AgentTestRun, - parse_obj_as( - type_=AgentTestRun, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def get_test_run(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> AgentTestRun: - """ - Retrieve a single test run by ID. Poll this endpoint until - `status` reaches a terminal state (`passed`, `failed`, or `error`). - The `result` field is populated on terminal states. - - Parameters - ---------- - id : str - Test run ID. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - AgentTestRun - The test run. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.get_test_run( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/test-runs/{jsonable_encoder(id)}", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AgentTestRun, - parse_obj_as( - type_=AgentTestRun, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def list_all_tests( - self, - *, - agent_id: typing.Optional[str] = None, - type: typing.Optional[str] = None, - status: typing.Optional[str] = None, - folder_id: typing.Optional[str] = None, - updated_after: typing.Optional[str] = None, - q: typing.Optional[str] = None, - limit: typing.Optional[int] = None, - cursor: typing.Optional[str] = None, - request_options: typing.Optional[RequestOptions] = None, - ) -> ListTestsResponse: - """ - Workspace-wide list of tests across every agent the caller owns. - Supports filters (agent, type, last-run status, folder), full-text - search on name/description, and cursor pagination. Each row carries - its newest run and attached agent IDs so the list renders without - N+1 round-trips. - - Parameters - ---------- - agent_id : typing.Optional[str] - Comma-separated agent IDs to filter on. - - type : typing.Optional[str] - Comma-separated test types (scenario|tool|simulation). - - status : typing.Optional[str] - Comma-separated last-run statuses. - - folder_id : typing.Optional[str] - Folder ID to filter on, or "root" for unfiled tests. - - updated_after : typing.Optional[str] - Only return tests updated after this RFC3339 timestamp. - - q : typing.Optional[str] - Substring match on name or description. - - limit : typing.Optional[int] - Max tests per page (default 50, max 200). - - cursor : typing.Optional[str] - Opaque pagination cursor from a previous response. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListTestsResponse - Paginated list. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.list_all_tests() - """ - _response = self._client_wrapper.httpx_client.request( - "v1/tests", - method="GET", - params={ - "agent_id": agent_id, - "type": type, - "status": status, - "folder_id": folder_id, - "updated_after": updated_after, - "q": q, - "limit": limit, - "cursor": cursor, - }, - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListTestsResponse, - parse_obj_as( - type_=ListTestsResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def get_test_stats( - self, *, window_days: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None - ) -> TestStats: - """ - Aggregate pass-rate metrics over the last N days. Returns dense - daily buckets (one entry per day, zero-filled) plus totals and a - per-type breakdown. Powers the header chart on the global tests - page. Default window is 30 days, max 90. - - Parameters - ---------- - window_days : typing.Optional[int] - Trailing window in days (default 30, max 90). - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - TestStats - Stats payload. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.get_test_stats() - """ - _response = self._client_wrapper.httpx_client.request( - "v1/tests/stats", - method="GET", - params={ - "window_days": window_days, - }, - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - TestStats, - parse_obj_as( - type_=TestStats, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def run_tests_batch( - self, *, entries: typing.Sequence[BatchRunEntry], request_options: typing.Optional[RequestOptions] = None - ) -> RunBatchResponse: - """ - Queue runs for every (test, agent) pair in the body. Entries - without an `agent_id` fan out to every agent the test is - attached to. Total expanded runs are capped at 100 per call. - Each entry in the response is a queued run; poll - `GET /v1/test-runs/{id}` for each. - - Parameters - ---------- - entries : typing.Sequence[BatchRunEntry] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - RunBatchResponse - Runs queued. - - Examples - -------- - from speechify import Speechify - from speechify.tts import BatchRunEntry - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.run_tests_batch( - entries=[ - BatchRunEntry( - test_id="test_id", - ) - ], - ) - """ - _response = self._client_wrapper.httpx_client.request( - "v1/tests/runs:batch", - method="POST", - json={ - "entries": convert_and_respect_annotation_metadata( - object_=entries, annotation=typing.Sequence[BatchRunEntry], direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - RunBatchResponse, - parse_obj_as( - type_=RunBatchResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def list_test_attachments( - self, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> ListAgentTestAttachmentsResponse: - """ - List every agent a test is attached to. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListAgentTestAttachmentsResponse - Attachment list. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.list_test_attachments( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/tests/{jsonable_encoder(id)}/attachments", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListAgentTestAttachmentsResponse, - parse_obj_as( - type_=ListAgentTestAttachmentsResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def attach_test(self, id: str, agent_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Attach a test to an additional agent. After this call, the test - will also run as part of that agent's regression suite (and - against its prompt + tool config when invoked with - `agent_id = {agentId}`). Idempotent. - - Parameters - ---------- - id : str - - agent_id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.attach_test( - id="id", - agent_id="agentId", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/tests/{jsonable_encoder(id)}/attachments/{jsonable_encoder(agent_id)}", - method="POST", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def detach_test(self, id: str, agent_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Detach a test from an agent. The owner agent (the agent the test - was authored against) cannot be detached; delete the test - instead. - - Parameters - ---------- - id : str - - agent_id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.detach_test( - id="id", - agent_id="agentId", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/tests/{jsonable_encoder(id)}/attachments/{jsonable_encoder(agent_id)}", - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def move_test( - self, - id: str, - *, - folder_id: typing.Optional[str] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> None: - """ - Move a test into a folder. Pass `folder_id: null` for root. - - Parameters - ---------- - id : str - - folder_id : typing.Optional[str] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.move_test( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/tests/{jsonable_encoder(id)}/move", - method="POST", - json={ - "folder_id": folder_id, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def list_test_folders( - self, *, request_options: typing.Optional[RequestOptions] = None - ) -> ListAgentTestFoldersResponse: - """ - List every test folder the caller owns. Flat list; build the tree client-side. - - Parameters - ---------- - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListAgentTestFoldersResponse - Folder list. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.list_test_folders() - """ - _response = self._client_wrapper.httpx_client.request( - "v1/test-folders", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListAgentTestFoldersResponse, - parse_obj_as( - type_=ListAgentTestFoldersResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def create_test_folder( - self, - *, - name: str, - parent_folder_id: typing.Optional[str] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> AgentTestFolder: - """ - Create a test folder. Max depth is 3. - - Parameters - ---------- - name : str - - parent_folder_id : typing.Optional[str] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - AgentTestFolder - Created folder. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.create_test_folder( - name="name", - ) - """ - _response = self._client_wrapper.httpx_client.request( - "v1/test-folders", - method="POST", - json={ - "name": name, - "parent_folder_id": parent_folder_id, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AgentTestFolder, - parse_obj_as( - type_=AgentTestFolder, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def delete_test_folder(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Soft-delete a folder. Child tests drop back to root. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.delete_test_folder( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/test-folders/{jsonable_encoder(id)}", - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def update_test_folder( - self, - id: str, - *, - name: typing.Optional[str] = OMIT, - parent_folder_id: typing.Optional[str] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> AgentTestFolder: - """ - Rename or reparent a test folder. Cycles are rejected. - - Parameters - ---------- - id : str - - name : typing.Optional[str] - - parent_folder_id : typing.Optional[str] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - AgentTestFolder - Updated folder. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.agents.update_test_folder( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/test-folders/{jsonable_encoder(id)}", - method="PATCH", - json={ - "name": name, - "parent_folder_id": parent_folder_id, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AgentTestFolder, - parse_obj_as( - type_=AgentTestFolder, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - -class AsyncAgentsClient: - def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper - - async def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> ListAgentsResponse: - """ - List voice agents owned by the caller. - - Parameters - ---------- - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListAgentsResponse - A list of voice agents. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.list() - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/agents", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListAgentsResponse, - parse_obj_as( - type_=ListAgentsResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def create( - self, - *, - name: str, - voice_id: str, - slug: typing.Optional[str] = OMIT, - prompt: typing.Optional[str] = OMIT, - first_message: typing.Optional[str] = OMIT, - language: typing.Optional[str] = OMIT, - llm_model: typing.Optional[str] = OMIT, - temperature: typing.Optional[float] = OMIT, - config: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, - is_public: typing.Optional[bool] = OMIT, - allowed_origins: typing.Optional[typing.Sequence[str]] = OMIT, - hostname_allowlist: typing.Optional[typing.Sequence[str]] = OMIT, - memory_enabled: typing.Optional[bool] = OMIT, - memory_retention_days: typing.Optional[int] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> Agent: - """ - Create a voice agent. - - Parameters - ---------- - name : str - - voice_id : str - Voice slug from the VMS catalog (see GET /v1/voices). Required — the server rejects writes with an unknown or empty slug. - - slug : typing.Optional[str] - Optional. Server derives slug from name with a random suffix when omitted; if you supply your own, a collision returns 400 'slug already taken'. - - prompt : typing.Optional[str] - - first_message : typing.Optional[str] - Spoken verbatim at session start — no LLM round trip. - - language : typing.Optional[str] - - llm_model : typing.Optional[str] - Optional chat model slug. Leave empty to use the Speechify default. - - temperature : typing.Optional[float] - - config : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] - - is_public : typing.Optional[bool] - - allowed_origins : typing.Optional[typing.Sequence[str]] - - hostname_allowlist : typing.Optional[typing.Sequence[str]] - Optional per-agent hostname allowlist (see Agent schema). - - memory_enabled : typing.Optional[bool] - - memory_retention_days : typing.Optional[int] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Agent - The created agent. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.create( - name="name", - voice_id="voice_id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/agents", - method="POST", - json={ - "name": name, - "slug": slug, - "prompt": prompt, - "first_message": first_message, - "language": language, - "llm_model": llm_model, - "voice_id": voice_id, - "temperature": temperature, - "config": config, - "is_public": is_public, - "allowed_origins": allowed_origins, - "hostname_allowlist": hostname_allowlist, - "memory_enabled": memory_enabled, - "memory_retention_days": memory_retention_days, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Agent, - parse_obj_as( - type_=Agent, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Agent: - """ - Retrieve a voice agent by ID. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Agent - The requested agent. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.get( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Agent, - parse_obj_as( - type_=Agent, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Delete a voice agent. Conversations and attached tools remain. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.delete( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}", - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def update( - self, - id: str, - *, - name: typing.Optional[str] = OMIT, - prompt: typing.Optional[str] = OMIT, - first_message: typing.Optional[str] = OMIT, - language: typing.Optional[str] = OMIT, - llm_model: typing.Optional[str] = OMIT, - voice_id: typing.Optional[str] = OMIT, - temperature: typing.Optional[float] = OMIT, - config: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, - is_public: typing.Optional[bool] = OMIT, - allowed_origins: typing.Optional[typing.Sequence[str]] = OMIT, - hostname_allowlist: typing.Optional[typing.Sequence[str]] = OMIT, - memory_enabled: typing.Optional[bool] = OMIT, - memory_retention_days: typing.Optional[int] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> Agent: - """ - Update a voice agent. Only fields present on the request body are changed. - - Parameters - ---------- - id : str - - name : typing.Optional[str] - - prompt : typing.Optional[str] - - first_message : typing.Optional[str] - - language : typing.Optional[str] - - llm_model : typing.Optional[str] - - voice_id : typing.Optional[str] - - temperature : typing.Optional[float] - - config : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] - - is_public : typing.Optional[bool] - - allowed_origins : typing.Optional[typing.Sequence[str]] - - hostname_allowlist : typing.Optional[typing.Sequence[str]] - When supplied, replaces the stored list. Pass an empty - array to clear enforcement (public agent is open again). - Omit the field to leave the existing value unchanged. - - memory_enabled : typing.Optional[bool] - - memory_retention_days : typing.Optional[int] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Agent - The updated agent. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.update( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}", - method="PATCH", - json={ - "name": name, - "prompt": prompt, - "first_message": first_message, - "language": language, - "llm_model": llm_model, - "voice_id": voice_id, - "temperature": temperature, - "config": config, - "is_public": is_public, - "allowed_origins": allowed_origins, - "hostname_allowlist": hostname_allowlist, - "memory_enabled": memory_enabled, - "memory_retention_days": memory_retention_days, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Agent, - parse_obj_as( - type_=Agent, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def list_tools( - self, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> ListToolsResponse: - """ - List tools currently attached to the agent. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListToolsResponse - Attached tools for the agent. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.list_tools( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/tools", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListToolsResponse, - parse_obj_as( - type_=ListToolsResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def attach_tool( - self, id: str, tool_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> None: - """ - Attach an existing tool to the agent so the LLM can call it. - - Parameters - ---------- - id : str - - tool_id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.attach_tool( - id="id", - tool_id="toolId", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/tools/{jsonable_encoder(tool_id)}", - method="POST", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def detach_tool( - self, id: str, tool_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> None: - """ - Detach a tool from the agent. - - Parameters - ---------- - id : str - - tool_id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.detach_tool( - id="id", - tool_id="toolId", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/tools/{jsonable_encoder(tool_id)}", - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def get_evaluation_config( - self, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> EvaluationConfig: - """ - Retrieve the agent's post-call evaluation criteria + data-collection config. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - EvaluationConfig - The evaluation config for the agent. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.get_evaluation_config( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/evaluation-config", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - EvaluationConfig, - parse_obj_as( - type_=EvaluationConfig, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def update_evaluation_config( - self, - id: str, - *, - criteria: typing.Sequence[EvaluationCriterion], - data_collection: typing.Sequence[DataCollectionField], - request_options: typing.Optional[RequestOptions] = None, - ) -> EvaluationConfig: - """ - Replace the agent's evaluation criteria + data-collection fields. - - Parameters - ---------- - id : str - - criteria : typing.Sequence[EvaluationCriterion] - - data_collection : typing.Sequence[DataCollectionField] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - EvaluationConfig - The updated evaluation config. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - from speechify.tts import DataCollectionField, EvaluationCriterion - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.update_evaluation_config( - id="id", - criteria=[ - EvaluationCriterion( - id="id", - name="name", - description="description", - ) - ], - data_collection=[ - DataCollectionField( - key="key", - description="description", - type="string", - ) - ], - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/evaluation-config", - method="PATCH", - json={ - "criteria": convert_and_respect_annotation_metadata( - object_=criteria, annotation=typing.Sequence[EvaluationCriterion], direction="write" - ), - "data_collection": convert_and_respect_annotation_metadata( - object_=data_collection, annotation=typing.Sequence[DataCollectionField], direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - EvaluationConfig, - parse_obj_as( - type_=EvaluationConfig, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def get_dynamic_variables( - self, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> ListDynamicVariablesResponse: - """ - Retrieve the agent's customer-scope dynamic variables and the read-only - catalogue of reserved `system__*` keys. The system variables list is - provided so editor UIs can render the reference list without maintaining - a client-side copy of the catalogue. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListDynamicVariablesResponse - The agent's variable catalogue. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.get_dynamic_variables( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/variables", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListDynamicVariablesResponse, - parse_obj_as( - type_=ListDynamicVariablesResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def update_dynamic_variables( - self, - id: str, - *, - variables: typing.Sequence[DynamicVariable], - request_options: typing.Optional[RequestOptions] = None, - ) -> ListDynamicVariablesResponse: - """ - Replace the agent's customer-scope dynamic variable definitions. - The supplied list overwrites the stored list wholesale (same - semantics as `updateEvaluationConfig`). Pass an empty array to - clear all variables. Up to 20 variables per agent. Keys must - match `[a-zA-Z0-9_]+` and must not start with the reserved - `system__` prefix. - - Parameters - ---------- - id : str - - variables : typing.Sequence[DynamicVariable] - The new variable list. Replaces the existing list entirely. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListDynamicVariablesResponse - The updated variable catalogue. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - from speechify.tts import DynamicVariable - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.update_dynamic_variables( - id="id", - variables=[ - DynamicVariable( - key="product_name", - type="string", - default="Speechify", - description="Product the agent is supporting.", - ), - DynamicVariable( - key="support_tier", - type="number", - default=1, - ), - DynamicVariable( - key="account_metadata", - type="json", - description="Arbitrary account context injected into tool bodies.", - ), - ], - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/variables", - method="PATCH", - json={ - "variables": convert_and_respect_annotation_metadata( - object_=variables, annotation=typing.Sequence[DynamicVariable], direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListDynamicVariablesResponse, - parse_obj_as( - type_=ListDynamicVariablesResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def create_conversation( - self, - id: str, - *, - transport: typing.Optional[str] = OMIT, - dynamic_variables: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> CreateConversationResponse: - """ - Start a new voice conversation with the agent. Returns a realtime - voice session + short-lived client token so the caller can - connect the audio pipeline directly. The agent is dispatched - server-side; no additional client action required. - - Pass `dynamic_variables` to supply per-session values that override - the agent's stored variable defaults for this one conversation. - Keys in the `system__` namespace are rejected at this boundary. - - Parameters - ---------- - id : str - - transport : typing.Optional[str] - Transport hint. Omit to use the agent's default. - - dynamic_variables : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] - Per-session variable overrides that merge on top of the agent's - stored variable defaults for this one conversation. Keys in the - reserved `system__` namespace are rejected. Values must match the - declared type of the corresponding variable definition on the agent. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - CreateConversationResponse - The created conversation with its realtime session token. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.create_conversation( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/conversations", - method="POST", - json={ - "transport": transport, - "dynamic_variables": dynamic_variables, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CreateConversationResponse, - parse_obj_as( - type_=CreateConversationResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def create_session( - self, - id: str, - *, - user_identity: typing.Optional[str] = OMIT, - dynamic_variables: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> CreateConversationResponse: - """ - Mint a realtime voice session for the given agent. Widget-friendly - counterpart to `createConversation` — same response shape, dual - authentication: - - * **Authenticated (Bearer)**: works for any agent the caller - owns. Typical server-to-server flow where the embedding - site's backend mints a token and hands it to the browser so - the API key never reaches the client. - * **Unauthenticated**: works only when `agent.is_public = true` - AND the request's `Origin` header matches `agent.allowed_origins` - (or that list is empty). When `agent.hostname_allowlist` is - non-empty, the `Origin` hostname must additionally be a - member of that list. Used directly by the - `` web component. - - Responds with the same `CreateConversationResponse` as - `createConversation`. - - Parameters - ---------- - id : str - - user_identity : typing.Optional[str] - Opaque identifier for the end-user (e.g. your app's user ID). Stamped onto the conversation. Optional - defaults to an anonymous per-session ID. - - dynamic_variables : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] - Per-session variable overrides that merge on top of the agent's - stored variable defaults for this one session. Keys in the - reserved `system__` namespace are rejected at this boundary. - Values must match the declared type of the corresponding variable - definition on the agent (a `string` type expects a JSON string, - `number` expects a JSON number, etc.). - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - CreateConversationResponse - The created session with its realtime token + URL. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.create_session( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/sessions", - method="POST", - json={ - "user_identity": user_identity, - "dynamic_variables": dynamic_variables, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CreateConversationResponse, - parse_obj_as( - type_=CreateConversationResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def list_agent_knowledge_bases( - self, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> ListKnowledgeBasesResponse: - """ - List knowledge bases attached to an agent. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListKnowledgeBasesResponse - The knowledge bases attached to the agent. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.list_agent_knowledge_bases( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/knowledge-bases", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListKnowledgeBasesResponse, - parse_obj_as( - type_=ListKnowledgeBasesResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def attach_knowledge_base( - self, id: str, kb_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> None: - """ - Attach a knowledge base to an agent. The `search_knowledge` tool - is auto-registered on the next conversation and can only query the - attached knowledge bases. - - Parameters - ---------- - id : str - - kb_id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.attach_knowledge_base( - id="id", - kb_id="kbId", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/knowledge-bases/{jsonable_encoder(kb_id)}", - method="POST", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def detach_knowledge_base( - self, id: str, kb_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> None: - """ - Detach a knowledge base from an agent. - - Parameters - ---------- - id : str - - kb_id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.detach_knowledge_base( - id="id", - kb_id="kbId", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/knowledge-bases/{jsonable_encoder(kb_id)}", - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def list_memories( - self, - id: str, - *, - limit: typing.Optional[int] = None, - offset: typing.Optional[int] = None, - request_options: typing.Optional[RequestOptions] = None, - ) -> ListMemoriesResponse: - """ - List per-caller memories extracted for an agent. Memories are - written post-call by the built-in extractor when `memory_enabled` - is true on the agent; the list is sorted newest-first. - - Parameters - ---------- - id : str - - limit : typing.Optional[int] - Maximum rows to return. Defaults to 100, capped at 200. - - offset : typing.Optional[int] - Number of rows to skip. Combine with `limit` to page through older memories. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListMemoriesResponse - Memories for the agent. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.list_memories( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/memories", - method="GET", - params={ - "limit": limit, - "offset": offset, - }, - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListMemoriesResponse, - parse_obj_as( - type_=ListMemoriesResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def delete_memories_by_caller( - self, id: str, *, agent_id: str, caller_identity: str, request_options: typing.Optional[RequestOptions] = None - ) -> DeleteMemoriesByCallerResponse: - """ - Delete every memory ever extracted for a specific caller on - this agent. Privacy / GDPR surface. Returns the count of rows - soft-deleted; rows become permanently unreachable immediately - and are hard-deleted by the retention job after the tenant's - configured retention window. - - Parameters - ---------- - id : str - - agent_id : str - - caller_identity : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - DeleteMemoriesByCallerResponse - Deletion summary. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.delete_memories_by_caller( - id="id", - agent_id="agent_id", - caller_identity="caller_identity", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/memories/delete-by-caller", - method="POST", - json={ - "agent_id": agent_id, - "caller_identity": caller_identity, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - DeleteMemoriesByCallerResponse, - parse_obj_as( - type_=DeleteMemoriesByCallerResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def list_tests( - self, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> ListAgentTestsResponse: - """ - List all tests configured for the agent. Each entry includes the - most recent run so the console can render pass/fail badges without - an extra round-trip. - - Parameters - ---------- - id : str - Agent ID. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListAgentTestsResponse - Tests for the agent with last-run summaries. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.list_tests( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/tests", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListAgentTestsResponse, - parse_obj_as( - type_=ListAgentTestsResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def create_test( - self, - id: str, - *, - name: str, - type: TestType, - config: CreateAgentTestRequestConfig, - description: typing.Optional[str] = OMIT, - tool_mock_config: typing.Optional[ToolMockConfig] = OMIT, - variables: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, - folder_id: typing.Optional[str] = OMIT, - attached_agent_ids: typing.Optional[typing.Sequence[str]] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> AgentTest: - """ - Create a new test for the agent. - - Parameters - ---------- - id : str - Agent ID. - - name : str - Short human-readable label for the test. - - type : TestType - - config : CreateAgentTestRequestConfig - Type-specific configuration. Must match the shape for the given `type`. - - description : typing.Optional[str] - Optional longer description of what this test verifies. - - tool_mock_config : typing.Optional[ToolMockConfig] - Optional tool-mocking config applied during every run of this test. - - variables : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] - Per-test variable values substituted into string fields of the - config at run-start. Keys use the same rules as agent-level - `DynamicVariable` keys. - - folder_id : typing.Optional[str] - Folder to place the test in. Omit for root. - - attached_agent_ids : typing.Optional[typing.Sequence[str]] - Optional list of additional agents this test should also run - against. The owner agent (path param) is always attached - implicitly. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - AgentTest - The created test. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - from speechify.tts import ScenarioConfig - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.create_test( - id="id", - name="Greet the caller by name", - description="Agent should greet the caller using their name when provided.", - type="scenario", - config=ScenarioConfig( - context="The caller says: Hi, I'm Alice.", - success_criteria="The agent greets Alice by name.", - success_examples=["Hi Alice! How can I help you today?"], - failure_examples=["Hello! How can I help you?"], - ), - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/tests", - method="POST", - json={ - "name": name, - "description": description, - "type": type, - "config": convert_and_respect_annotation_metadata( - object_=config, annotation=CreateAgentTestRequestConfig, direction="write" - ), - "tool_mock_config": convert_and_respect_annotation_metadata( - object_=tool_mock_config, annotation=ToolMockConfig, direction="write" - ), - "variables": variables, - "folder_id": folder_id, - "attached_agent_ids": attached_agent_ids, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AgentTest, - parse_obj_as( - type_=AgentTest, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def run_all_tests( - self, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> RunAgentTestsResponse: - """ - Enqueue runs for every test on the agent concurrently. Up to 50 - tests are dispatched in one call. Each returned run starts in - `queued` status; poll `GET /v1/test-runs/{id}` for the terminal - result. - - Parameters - ---------- - id : str - Agent ID. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - RunAgentTestsResponse - Queued runs for all tests on the agent. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.run_all_tests( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/agents/{jsonable_encoder(id)}/tests/runs", - method="POST", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - RunAgentTestsResponse, - parse_obj_as( - type_=RunAgentTestsResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def get_test(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> AgentTest: - """ - Retrieve a test by ID. - - Parameters - ---------- - id : str - Test ID. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - AgentTest - The requested test. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.get_test( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/tests/{jsonable_encoder(id)}", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AgentTest, - parse_obj_as( - type_=AgentTest, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def delete_test(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Delete a test and all its run history. - - Parameters - ---------- - id : str - Test ID. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.delete_test( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/tests/{jsonable_encoder(id)}", - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def update_test( - self, - id: str, - *, - name: typing.Optional[str] = OMIT, - description: typing.Optional[str] = OMIT, - config: typing.Optional[UpdateAgentTestRequestConfig] = OMIT, - tool_mock_config: typing.Optional[ToolMockConfig] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> AgentTest: - """ - Update a test. Only fields present on the request body are changed. - - Parameters - ---------- - id : str - Test ID. - - name : typing.Optional[str] - - description : typing.Optional[str] - - config : typing.Optional[UpdateAgentTestRequestConfig] - Replaces the test config when present. - - tool_mock_config : typing.Optional[ToolMockConfig] - Replaces the tool-mock config when present. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - AgentTest - The updated test. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.update_test( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/tests/{jsonable_encoder(id)}", - method="PATCH", - json={ - "name": name, - "description": description, - "config": convert_and_respect_annotation_metadata( - object_=config, annotation=UpdateAgentTestRequestConfig, direction="write" - ), - "tool_mock_config": convert_and_respect_annotation_metadata( - object_=tool_mock_config, annotation=ToolMockConfig, direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AgentTest, - parse_obj_as( - type_=AgentTest, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def list_test_runs( - self, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> ListAgentTestRunsResponse: - """ - List the run history for a test, newest first. - - Parameters - ---------- - id : str - Test ID. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListAgentTestRunsResponse - Run history for the test. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.list_test_runs( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/tests/{jsonable_encoder(id)}/runs", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListAgentTestRunsResponse, - parse_obj_as( - type_=ListAgentTestRunsResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def run_test(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> AgentTestRun: - """ - Enqueue a single run of the test. The returned run starts in - `queued` status. Poll `GET /v1/test-runs/{id}` until the status - reaches a terminal state (`passed`, `failed`, or `error`). - - Parameters - ---------- - id : str - Test ID. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - AgentTestRun - The queued run. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.run_test( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/tests/{jsonable_encoder(id)}/runs", - method="POST", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AgentTestRun, - parse_obj_as( - type_=AgentTestRun, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def get_test_run(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> AgentTestRun: - """ - Retrieve a single test run by ID. Poll this endpoint until - `status` reaches a terminal state (`passed`, `failed`, or `error`). - The `result` field is populated on terminal states. - - Parameters - ---------- - id : str - Test run ID. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - AgentTestRun - The test run. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.get_test_run( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/test-runs/{jsonable_encoder(id)}", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AgentTestRun, - parse_obj_as( - type_=AgentTestRun, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def list_all_tests( - self, - *, - agent_id: typing.Optional[str] = None, - type: typing.Optional[str] = None, - status: typing.Optional[str] = None, - folder_id: typing.Optional[str] = None, - updated_after: typing.Optional[str] = None, - q: typing.Optional[str] = None, - limit: typing.Optional[int] = None, - cursor: typing.Optional[str] = None, - request_options: typing.Optional[RequestOptions] = None, - ) -> ListTestsResponse: - """ - Workspace-wide list of tests across every agent the caller owns. - Supports filters (agent, type, last-run status, folder), full-text - search on name/description, and cursor pagination. Each row carries - its newest run and attached agent IDs so the list renders without - N+1 round-trips. - - Parameters - ---------- - agent_id : typing.Optional[str] - Comma-separated agent IDs to filter on. - - type : typing.Optional[str] - Comma-separated test types (scenario|tool|simulation). - - status : typing.Optional[str] - Comma-separated last-run statuses. - - folder_id : typing.Optional[str] - Folder ID to filter on, or "root" for unfiled tests. - - updated_after : typing.Optional[str] - Only return tests updated after this RFC3339 timestamp. - - q : typing.Optional[str] - Substring match on name or description. - - limit : typing.Optional[int] - Max tests per page (default 50, max 200). - - cursor : typing.Optional[str] - Opaque pagination cursor from a previous response. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListTestsResponse - Paginated list. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.list_all_tests() - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/tests", - method="GET", - params={ - "agent_id": agent_id, - "type": type, - "status": status, - "folder_id": folder_id, - "updated_after": updated_after, - "q": q, - "limit": limit, - "cursor": cursor, - }, - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListTestsResponse, - parse_obj_as( - type_=ListTestsResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def get_test_stats( - self, *, window_days: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None - ) -> TestStats: - """ - Aggregate pass-rate metrics over the last N days. Returns dense - daily buckets (one entry per day, zero-filled) plus totals and a - per-type breakdown. Powers the header chart on the global tests - page. Default window is 30 days, max 90. - - Parameters - ---------- - window_days : typing.Optional[int] - Trailing window in days (default 30, max 90). - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - TestStats - Stats payload. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.get_test_stats() - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/tests/stats", - method="GET", - params={ - "window_days": window_days, - }, - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - TestStats, - parse_obj_as( - type_=TestStats, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def run_tests_batch( - self, *, entries: typing.Sequence[BatchRunEntry], request_options: typing.Optional[RequestOptions] = None - ) -> RunBatchResponse: - """ - Queue runs for every (test, agent) pair in the body. Entries - without an `agent_id` fan out to every agent the test is - attached to. Total expanded runs are capped at 100 per call. - Each entry in the response is a queued run; poll - `GET /v1/test-runs/{id}` for each. - - Parameters - ---------- - entries : typing.Sequence[BatchRunEntry] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - RunBatchResponse - Runs queued. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - from speechify.tts import BatchRunEntry - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.run_tests_batch( - entries=[ - BatchRunEntry( - test_id="test_id", - ) - ], - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/tests/runs:batch", - method="POST", - json={ - "entries": convert_and_respect_annotation_metadata( - object_=entries, annotation=typing.Sequence[BatchRunEntry], direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - RunBatchResponse, - parse_obj_as( - type_=RunBatchResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def list_test_attachments( - self, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> ListAgentTestAttachmentsResponse: - """ - List every agent a test is attached to. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListAgentTestAttachmentsResponse - Attachment list. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.list_test_attachments( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/tests/{jsonable_encoder(id)}/attachments", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListAgentTestAttachmentsResponse, - parse_obj_as( - type_=ListAgentTestAttachmentsResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def attach_test( - self, id: str, agent_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> None: - """ - Attach a test to an additional agent. After this call, the test - will also run as part of that agent's regression suite (and - against its prompt + tool config when invoked with - `agent_id = {agentId}`). Idempotent. - - Parameters - ---------- - id : str - - agent_id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.attach_test( - id="id", - agent_id="agentId", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/tests/{jsonable_encoder(id)}/attachments/{jsonable_encoder(agent_id)}", - method="POST", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def detach_test( - self, id: str, agent_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> None: - """ - Detach a test from an agent. The owner agent (the agent the test - was authored against) cannot be detached; delete the test - instead. - - Parameters - ---------- - id : str - - agent_id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.detach_test( - id="id", - agent_id="agentId", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/tests/{jsonable_encoder(id)}/attachments/{jsonable_encoder(agent_id)}", - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def move_test( - self, - id: str, - *, - folder_id: typing.Optional[str] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> None: - """ - Move a test into a folder. Pass `folder_id: null` for root. - - Parameters - ---------- - id : str - - folder_id : typing.Optional[str] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.move_test( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/tests/{jsonable_encoder(id)}/move", - method="POST", - json={ - "folder_id": folder_id, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def list_test_folders( - self, *, request_options: typing.Optional[RequestOptions] = None - ) -> ListAgentTestFoldersResponse: - """ - List every test folder the caller owns. Flat list; build the tree client-side. - - Parameters - ---------- - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListAgentTestFoldersResponse - Folder list. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.list_test_folders() - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/test-folders", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListAgentTestFoldersResponse, - parse_obj_as( - type_=ListAgentTestFoldersResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def create_test_folder( - self, - *, - name: str, - parent_folder_id: typing.Optional[str] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> AgentTestFolder: - """ - Create a test folder. Max depth is 3. - - Parameters - ---------- - name : str - - parent_folder_id : typing.Optional[str] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - AgentTestFolder - Created folder. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.create_test_folder( - name="name", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/test-folders", - method="POST", - json={ - "name": name, - "parent_folder_id": parent_folder_id, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AgentTestFolder, - parse_obj_as( - type_=AgentTestFolder, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def delete_test_folder(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Soft-delete a folder. Child tests drop back to root. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.delete_test_folder( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/test-folders/{jsonable_encoder(id)}", - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def update_test_folder( - self, - id: str, - *, - name: typing.Optional[str] = OMIT, - parent_folder_id: typing.Optional[str] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> AgentTestFolder: - """ - Rename or reparent a test folder. Cycles are rejected. - - Parameters - ---------- - id : str - - name : typing.Optional[str] - - parent_folder_id : typing.Optional[str] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - AgentTestFolder - Updated folder. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.agents.update_test_folder( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/test-folders/{jsonable_encoder(id)}", - method="PATCH", - json={ - "name": name, - "parent_folder_id": parent_folder_id, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AgentTestFolder, - parse_obj_as( - type_=AgentTestFolder, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/speechify/tts/agents/types/__init__.py b/src/speechify/tts/agents/types/__init__.py deleted file mode 100644 index 6b02c60..0000000 --- a/src/speechify/tts/agents/types/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from .create_agent_test_request_config import CreateAgentTestRequestConfig -from .update_agent_test_request_config import UpdateAgentTestRequestConfig - -__all__ = ["CreateAgentTestRequestConfig", "UpdateAgentTestRequestConfig"] diff --git a/src/speechify/tts/agents/types/create_agent_test_request_config.py b/src/speechify/tts/agents/types/create_agent_test_request_config.py deleted file mode 100644 index b2d407d..0000000 --- a/src/speechify/tts/agents/types/create_agent_test_request_config.py +++ /dev/null @@ -1,8 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing -from ...types.scenario_config import ScenarioConfig -from ...types.tool_call_config import ToolCallConfig -from ...types.simulation_config import SimulationConfig - -CreateAgentTestRequestConfig = typing.Union[ScenarioConfig, ToolCallConfig, SimulationConfig] diff --git a/src/speechify/tts/agents/types/update_agent_test_request_config.py b/src/speechify/tts/agents/types/update_agent_test_request_config.py deleted file mode 100644 index 67638a8..0000000 --- a/src/speechify/tts/agents/types/update_agent_test_request_config.py +++ /dev/null @@ -1,8 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing -from ...types.scenario_config import ScenarioConfig -from ...types.tool_call_config import ToolCallConfig -from ...types.simulation_config import SimulationConfig - -UpdateAgentTestRequestConfig = typing.Union[ScenarioConfig, ToolCallConfig, SimulationConfig] diff --git a/src/speechify/tts/audio/client.py b/src/speechify/tts/audio/client.py index 055a5d8..786549d 100644 --- a/src/speechify/tts/audio/client.py +++ b/src/speechify/tts/audio/client.py @@ -4,21 +4,26 @@ from ...core.client_wrapper import SyncClientWrapper from .types.get_speech_request_audio_format import GetSpeechRequestAudioFormat from .types.get_speech_request_model import GetSpeechRequestModel -from ..types.get_speech_options_request import GetSpeechOptionsRequest +from ...types.get_speech_options_request import GetSpeechOptionsRequest from ...core.request_options import RequestOptions -from ..types.get_speech_response import GetSpeechResponse +from ...types.get_speech_response import GetSpeechResponse from ...core.serialization import convert_and_respect_annotation_metadata from ...core.pydantic_utilities import parse_obj_as -from ..errors.bad_request_error import BadRequestError -from ..errors.unauthorized_error import UnauthorizedError -from ..errors.payment_required_error import PaymentRequiredError -from ..errors.forbidden_error import ForbiddenError -from ..errors.internal_server_error import InternalServerError +from ...errors.bad_request_error import BadRequestError +from ...errors.unauthorized_error import UnauthorizedError +from ...errors.payment_required_error import PaymentRequiredError +from ...types.error import Error +from ...errors.forbidden_error import ForbiddenError +from ...errors.not_found_error import NotFoundError +from ...errors.too_many_requests_error import TooManyRequestsError +from ...errors.internal_server_error import InternalServerError +from ...errors.bad_gateway_error import BadGatewayError +from ...errors.service_unavailable_error import ServiceUnavailableError from json.decoder import JSONDecodeError from ...core.api_error import ApiError from .types.stream_audio_request_accept import StreamAudioRequestAccept from .types.get_stream_request_model import GetStreamRequestModel -from ..types.get_stream_options_request import GetStreamOptionsRequest +from ...types.get_stream_options_request import GetStreamOptionsRequest from ...core.client_wrapper import AsyncClientWrapper # this is used as the default value for optional parameters @@ -41,7 +46,9 @@ def speech( request_options: typing.Optional[RequestOptions] = None, ) -> GetSpeechResponse: """ - Gets the speech data for the given input + Synthesize speech audio from text or SSML. Returns the complete audio + file plus billing and speech-mark metadata in a single response. For + low-latency playback or long-form text, use POST /v1/audio/stream. Parameters ---------- @@ -61,8 +68,7 @@ def speech( Please refer to the list of the supported languages and recommendations regarding this parameter: https://docs.speechify.ai/docs/language-support. model : typing.Optional[GetSpeechRequestModel] - Model used for audio synthesis. `simba-base` and `simba-turbo` are deprecated. - `simba-3.0` is the new streaming-native model with lower TTFB and richer expressivity. Currently English only; multilingual coming soon. Non-English voices return 400 until multilingual support ships. + Model used for audio synthesis. `simba-english` is optimized for English, `simba-multilingual` for non-English or mixed input. `simba-3.0` is the streaming-native model with lower TTFB and richer expressivity. Currently English only; multilingual coming soon. Non-English voices return 400 until multilingual support ships. options : typing.Optional[GetSpeechOptionsRequest] @@ -72,7 +78,7 @@ def speech( Returns ------- GetSpeechResponse - + Synthesized speech audio for the requested input. Examples -------- @@ -82,8 +88,10 @@ def speech( token="YOUR_TOKEN", ) client.tts.audio.speech( - input="input", - voice_id="voice_id", + audio_format="mp3", + input="Hello! This is the Speechify text-to-speech API.", + model="simba-english", + voice_id="george", ) """ _response = self._client_wrapper.httpx_client.request( @@ -137,15 +145,25 @@ def speech( if _response.status_code == 402: raise PaymentRequiredError( typing.cast( - typing.Optional[typing.Any], + Error, parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore + type_=Error, # type: ignore object_=_response.json(), ), ) ) if _response.status_code == 403: raise ForbiddenError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( typing.cast( typing.Optional[typing.Any], parse_obj_as( @@ -154,12 +172,42 @@ def speech( ), ) ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: raise InternalServerError( typing.cast( - typing.Optional[typing.Any], + Error, parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 502: + raise BadGatewayError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 503: + raise ServiceUnavailableError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore object_=_response.json(), ), ) @@ -181,7 +229,10 @@ def stream( request_options: typing.Optional[RequestOptions] = None, ) -> typing.Iterator[bytes]: """ - Gets the stream speech for the given input + Synthesize speech and stream the audio back as it is generated, for + low-latency playback. The Accept header selects the audio container. + For short text where receiving the whole file at once is fine, use + POST /v1/audio/speech. Parameters ---------- @@ -200,8 +251,7 @@ def stream( Please refer to the list of the supported languages and recommendations regarding this parameter: https://docs.speechify.ai/docs/language-support. model : typing.Optional[GetStreamRequestModel] - Model used for audio synthesis. `simba-base` and `simba-turbo` are deprecated. - `simba-3.0` is the new streaming-native model with lower TTFB and richer expressivity. Currently English only; multilingual coming soon. Non-English voices return 400 until multilingual support ships. + Model used for audio synthesis. `simba-english` is optimized for English, `simba-multilingual` for non-English or mixed input. `simba-3.0` is the streaming-native model with lower TTFB and richer expressivity. Currently English only; multilingual coming soon. Non-English voices return 400 until multilingual support ships. options : typing.Optional[GetStreamOptionsRequest] @@ -211,7 +261,7 @@ def stream( Yields ------ typing.Iterator[bytes] - + Chunked audio stream for the requested input. Examples -------- @@ -275,15 +325,25 @@ def stream( if _response.status_code == 402: raise PaymentRequiredError( typing.cast( - typing.Optional[typing.Any], + Error, parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore + type_=Error, # type: ignore object_=_response.json(), ), ) ) if _response.status_code == 403: raise ForbiddenError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( typing.cast( typing.Optional[typing.Any], parse_obj_as( @@ -292,12 +352,42 @@ def stream( ), ) ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: raise InternalServerError( typing.cast( - typing.Optional[typing.Any], + Error, parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 502: + raise BadGatewayError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 503: + raise ServiceUnavailableError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore object_=_response.json(), ), ) @@ -324,7 +414,9 @@ async def speech( request_options: typing.Optional[RequestOptions] = None, ) -> GetSpeechResponse: """ - Gets the speech data for the given input + Synthesize speech audio from text or SSML. Returns the complete audio + file plus billing and speech-mark metadata in a single response. For + low-latency playback or long-form text, use POST /v1/audio/stream. Parameters ---------- @@ -344,8 +436,7 @@ async def speech( Please refer to the list of the supported languages and recommendations regarding this parameter: https://docs.speechify.ai/docs/language-support. model : typing.Optional[GetSpeechRequestModel] - Model used for audio synthesis. `simba-base` and `simba-turbo` are deprecated. - `simba-3.0` is the new streaming-native model with lower TTFB and richer expressivity. Currently English only; multilingual coming soon. Non-English voices return 400 until multilingual support ships. + Model used for audio synthesis. `simba-english` is optimized for English, `simba-multilingual` for non-English or mixed input. `simba-3.0` is the streaming-native model with lower TTFB and richer expressivity. Currently English only; multilingual coming soon. Non-English voices return 400 until multilingual support ships. options : typing.Optional[GetSpeechOptionsRequest] @@ -355,7 +446,7 @@ async def speech( Returns ------- GetSpeechResponse - + Synthesized speech audio for the requested input. Examples -------- @@ -370,8 +461,10 @@ async def speech( async def main() -> None: await client.tts.audio.speech( - input="input", - voice_id="voice_id", + audio_format="mp3", + input="Hello! This is the Speechify text-to-speech API.", + model="simba-english", + voice_id="george", ) @@ -428,15 +521,25 @@ async def main() -> None: if _response.status_code == 402: raise PaymentRequiredError( typing.cast( - typing.Optional[typing.Any], + Error, parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore + type_=Error, # type: ignore object_=_response.json(), ), ) ) if _response.status_code == 403: raise ForbiddenError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( typing.cast( typing.Optional[typing.Any], parse_obj_as( @@ -445,12 +548,42 @@ async def main() -> None: ), ) ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: raise InternalServerError( typing.cast( - typing.Optional[typing.Any], + Error, parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 502: + raise BadGatewayError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 503: + raise ServiceUnavailableError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore object_=_response.json(), ), ) @@ -472,7 +605,10 @@ async def stream( request_options: typing.Optional[RequestOptions] = None, ) -> typing.AsyncIterator[bytes]: """ - Gets the stream speech for the given input + Synthesize speech and stream the audio back as it is generated, for + low-latency playback. The Accept header selects the audio container. + For short text where receiving the whole file at once is fine, use + POST /v1/audio/speech. Parameters ---------- @@ -491,8 +627,7 @@ async def stream( Please refer to the list of the supported languages and recommendations regarding this parameter: https://docs.speechify.ai/docs/language-support. model : typing.Optional[GetStreamRequestModel] - Model used for audio synthesis. `simba-base` and `simba-turbo` are deprecated. - `simba-3.0` is the new streaming-native model with lower TTFB and richer expressivity. Currently English only; multilingual coming soon. Non-English voices return 400 until multilingual support ships. + Model used for audio synthesis. `simba-english` is optimized for English, `simba-multilingual` for non-English or mixed input. `simba-3.0` is the streaming-native model with lower TTFB and richer expressivity. Currently English only; multilingual coming soon. Non-English voices return 400 until multilingual support ships. options : typing.Optional[GetStreamOptionsRequest] @@ -502,7 +637,7 @@ async def stream( Yields ------ typing.AsyncIterator[bytes] - + Chunked audio stream for the requested input. Examples -------- @@ -574,15 +709,25 @@ async def main() -> None: if _response.status_code == 402: raise PaymentRequiredError( typing.cast( - typing.Optional[typing.Any], + Error, parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore + type_=Error, # type: ignore object_=_response.json(), ), ) ) if _response.status_code == 403: raise ForbiddenError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( typing.cast( typing.Optional[typing.Any], parse_obj_as( @@ -591,12 +736,42 @@ async def main() -> None: ), ) ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: raise InternalServerError( typing.cast( - typing.Optional[typing.Any], + Error, parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 502: + raise BadGatewayError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 503: + raise ServiceUnavailableError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore object_=_response.json(), ), ) diff --git a/src/speechify/tts/audio/types/get_speech_request_model.py b/src/speechify/tts/audio/types/get_speech_request_model.py index 6ff3461..da407de 100644 --- a/src/speechify/tts/audio/types/get_speech_request_model.py +++ b/src/speechify/tts/audio/types/get_speech_request_model.py @@ -2,6 +2,4 @@ import typing -GetSpeechRequestModel = typing.Union[ - typing.Literal["simba-base", "simba-english", "simba-multilingual", "simba-turbo", "simba-3.0"], typing.Any -] +GetSpeechRequestModel = typing.Union[typing.Literal["simba-english", "simba-multilingual", "simba-3.0"], typing.Any] diff --git a/src/speechify/tts/audio/types/get_stream_request_model.py b/src/speechify/tts/audio/types/get_stream_request_model.py index af9c4b3..76d1582 100644 --- a/src/speechify/tts/audio/types/get_stream_request_model.py +++ b/src/speechify/tts/audio/types/get_stream_request_model.py @@ -2,6 +2,4 @@ import typing -GetStreamRequestModel = typing.Union[ - typing.Literal["simba-base", "simba-english", "simba-multilingual", "simba-turbo", "simba-3.0"], typing.Any -] +GetStreamRequestModel = typing.Union[typing.Literal["simba-english", "simba-multilingual", "simba-3.0"], typing.Any] diff --git a/src/speechify/tts/auth/__init__.py b/src/speechify/tts/auth/__init__.py deleted file mode 100644 index b1b7579..0000000 --- a/src/speechify/tts/auth/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from .types import CreateAccessTokenRequestGrantType, CreateAccessTokenRequestScope - -__all__ = ["CreateAccessTokenRequestGrantType", "CreateAccessTokenRequestScope"] diff --git a/src/speechify/tts/auth/client.py b/src/speechify/tts/auth/client.py deleted file mode 100644 index d43c9c2..0000000 --- a/src/speechify/tts/auth/client.py +++ /dev/null @@ -1,205 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing -from ...core.client_wrapper import SyncClientWrapper -from .types.create_access_token_request_grant_type import CreateAccessTokenRequestGrantType -from .types.create_access_token_request_scope import CreateAccessTokenRequestScope -from ...core.request_options import RequestOptions -from ..types.access_token import AccessToken -from ...core.pydantic_utilities import parse_obj_as -from ..errors.bad_request_error import BadRequestError -from ..errors.unauthorized_error import UnauthorizedError -from json.decoder import JSONDecodeError -from ...core.api_error import ApiError -from ...core.client_wrapper import AsyncClientWrapper - -# this is used as the default value for optional parameters -OMIT = typing.cast(typing.Any, ...) - - -class AuthClient: - def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper - - def create_access_token( - self, - *, - grant_type: CreateAccessTokenRequestGrantType, - scope: typing.Optional[CreateAccessTokenRequestScope] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> AccessToken: - """ - WARNING: This endpoint is deprecated. Create a new API token for the logged in user. - - Parameters - ---------- - grant_type : CreateAccessTokenRequestGrantType - in: body - - scope : typing.Optional[CreateAccessTokenRequestScope] - The scope, or a space-delimited list of scopes the token is requested for - in: body - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - AccessToken - Contains the details of the token which can be used by the user to access the API - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.auth.create_access_token( - grant_type="client_credentials", - ) - """ - _response = self._client_wrapper.httpx_client.request( - "v1/auth/token", - method="POST", - json={ - "grant_type": grant_type, - "scope": scope, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AccessToken, - parse_obj_as( - type_=AccessToken, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - -class AsyncAuthClient: - def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper - - async def create_access_token( - self, - *, - grant_type: CreateAccessTokenRequestGrantType, - scope: typing.Optional[CreateAccessTokenRequestScope] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> AccessToken: - """ - WARNING: This endpoint is deprecated. Create a new API token for the logged in user. - - Parameters - ---------- - grant_type : CreateAccessTokenRequestGrantType - in: body - - scope : typing.Optional[CreateAccessTokenRequestScope] - The scope, or a space-delimited list of scopes the token is requested for - in: body - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - AccessToken - Contains the details of the token which can be used by the user to access the API - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.auth.create_access_token( - grant_type="client_credentials", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/auth/token", - method="POST", - json={ - "grant_type": grant_type, - "scope": scope, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AccessToken, - parse_obj_as( - type_=AccessToken, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/speechify/tts/auth/types/__init__.py b/src/speechify/tts/auth/types/__init__.py deleted file mode 100644 index d4ee5b2..0000000 --- a/src/speechify/tts/auth/types/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from .create_access_token_request_grant_type import CreateAccessTokenRequestGrantType -from .create_access_token_request_scope import CreateAccessTokenRequestScope - -__all__ = ["CreateAccessTokenRequestGrantType", "CreateAccessTokenRequestScope"] diff --git a/src/speechify/tts/auth/types/create_access_token_request_grant_type.py b/src/speechify/tts/auth/types/create_access_token_request_grant_type.py deleted file mode 100644 index 9d7c254..0000000 --- a/src/speechify/tts/auth/types/create_access_token_request_grant_type.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -CreateAccessTokenRequestGrantType = typing.Union[typing.Literal["client_credentials"], typing.Any] diff --git a/src/speechify/tts/auth/types/create_access_token_request_scope.py b/src/speechify/tts/auth/types/create_access_token_request_scope.py deleted file mode 100644 index 6c7c11c..0000000 --- a/src/speechify/tts/auth/types/create_access_token_request_scope.py +++ /dev/null @@ -1,10 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -CreateAccessTokenRequestScope = typing.Union[ - typing.Literal[ - "audio:speech", "audio:stream", "audio:all", "voices:read", "voices:create", "voices:delete", "voices:all" - ], - typing.Any, -] diff --git a/src/speechify/tts/client.py b/src/speechify/tts/client.py index 34a8e3c..36c3574 100644 --- a/src/speechify/tts/client.py +++ b/src/speechify/tts/client.py @@ -2,61 +2,21 @@ from ..core.client_wrapper import SyncClientWrapper from .audio.client import AudioClient -from .auth.client import AuthClient from .voices.client import VoicesClient -from .agents.client import AgentsClient -from .tools.client import ToolsClient -from .conversations.client import ConversationsClient -from .knowledge_bases.client import KnowledgeBasesClient -from .memories.client import MemoriesClient -from .phone_numbers.client import PhoneNumbersClient -from .sip_trunks.client import SipTrunksClient -from .outbound_calls.client import OutboundCallsClient -from .workspaces.client import WorkspacesClient from ..core.client_wrapper import AsyncClientWrapper from .audio.client import AsyncAudioClient -from .auth.client import AsyncAuthClient from .voices.client import AsyncVoicesClient -from .agents.client import AsyncAgentsClient -from .tools.client import AsyncToolsClient -from .conversations.client import AsyncConversationsClient -from .knowledge_bases.client import AsyncKnowledgeBasesClient -from .memories.client import AsyncMemoriesClient -from .phone_numbers.client import AsyncPhoneNumbersClient -from .sip_trunks.client import AsyncSipTrunksClient -from .outbound_calls.client import AsyncOutboundCallsClient -from .workspaces.client import AsyncWorkspacesClient class TtsClient: def __init__(self, *, client_wrapper: SyncClientWrapper): self._client_wrapper = client_wrapper self.audio = AudioClient(client_wrapper=self._client_wrapper) - self.auth = AuthClient(client_wrapper=self._client_wrapper) self.voices = VoicesClient(client_wrapper=self._client_wrapper) - self.agents = AgentsClient(client_wrapper=self._client_wrapper) - self.tools = ToolsClient(client_wrapper=self._client_wrapper) - self.conversations = ConversationsClient(client_wrapper=self._client_wrapper) - self.knowledge_bases = KnowledgeBasesClient(client_wrapper=self._client_wrapper) - self.memories = MemoriesClient(client_wrapper=self._client_wrapper) - self.phone_numbers = PhoneNumbersClient(client_wrapper=self._client_wrapper) - self.sip_trunks = SipTrunksClient(client_wrapper=self._client_wrapper) - self.outbound_calls = OutboundCallsClient(client_wrapper=self._client_wrapper) - self.workspaces = WorkspacesClient(client_wrapper=self._client_wrapper) class AsyncTtsClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): self._client_wrapper = client_wrapper self.audio = AsyncAudioClient(client_wrapper=self._client_wrapper) - self.auth = AsyncAuthClient(client_wrapper=self._client_wrapper) self.voices = AsyncVoicesClient(client_wrapper=self._client_wrapper) - self.agents = AsyncAgentsClient(client_wrapper=self._client_wrapper) - self.tools = AsyncToolsClient(client_wrapper=self._client_wrapper) - self.conversations = AsyncConversationsClient(client_wrapper=self._client_wrapper) - self.knowledge_bases = AsyncKnowledgeBasesClient(client_wrapper=self._client_wrapper) - self.memories = AsyncMemoriesClient(client_wrapper=self._client_wrapper) - self.phone_numbers = AsyncPhoneNumbersClient(client_wrapper=self._client_wrapper) - self.sip_trunks = AsyncSipTrunksClient(client_wrapper=self._client_wrapper) - self.outbound_calls = AsyncOutboundCallsClient(client_wrapper=self._client_wrapper) - self.workspaces = AsyncWorkspacesClient(client_wrapper=self._client_wrapper) diff --git a/src/speechify/tts/conversations/__init__.py b/src/speechify/tts/conversations/__init__.py deleted file mode 100644 index f3ea265..0000000 --- a/src/speechify/tts/conversations/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - diff --git a/src/speechify/tts/conversations/client.py b/src/speechify/tts/conversations/client.py deleted file mode 100644 index 9fe6ab8..0000000 --- a/src/speechify/tts/conversations/client.py +++ /dev/null @@ -1,824 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.client_wrapper import SyncClientWrapper -import typing -from ...core.request_options import RequestOptions -from ..types.list_conversations_response import ListConversationsResponse -from ...core.pydantic_utilities import parse_obj_as -from ..errors.unauthorized_error import UnauthorizedError -from json.decoder import JSONDecodeError -from ...core.api_error import ApiError -from ..types.conversation_stats import ConversationStats -from ..types.conversation import Conversation -from ...core.jsonable_encoder import jsonable_encoder -from ..errors.not_found_error import NotFoundError -from ..types.list_messages_response import ListMessagesResponse -from ..types.list_evaluations_response import ListEvaluationsResponse -from ..types.list_memories_response import ListMemoriesResponse -from ...core.client_wrapper import AsyncClientWrapper - - -class ConversationsClient: - def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper - - def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> ListConversationsResponse: - """ - List conversations owned by the caller, ordered by most recent. - - Parameters - ---------- - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListConversationsResponse - A list of conversations. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.conversations.list() - """ - _response = self._client_wrapper.httpx_client.request( - "v1/conversations", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListConversationsResponse, - parse_obj_as( - type_=ListConversationsResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def stats(self, *, request_options: typing.Optional[RequestOptions] = None) -> ConversationStats: - """ - Aggregated counts and averages over the caller's conversations, scoped by the same filters as the list endpoint. - - Parameters - ---------- - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ConversationStats - Stats for the matched conversations. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.conversations.stats() - """ - _response = self._client_wrapper.httpx_client.request( - "v1/conversations/stats", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ConversationStats, - parse_obj_as( - type_=ConversationStats, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Conversation: - """ - Retrieve a conversation by ID. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Conversation - The requested conversation. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.conversations.get( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/conversations/{jsonable_encoder(id)}", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Conversation, - parse_obj_as( - type_=Conversation, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def list_messages( - self, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> ListMessagesResponse: - """ - Retrieve the full transcript for a conversation, in order. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListMessagesResponse - The messages for the conversation. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.conversations.list_messages( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/conversations/{jsonable_encoder(id)}/messages", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListMessagesResponse, - parse_obj_as( - type_=ListMessagesResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def list_evaluations( - self, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> ListEvaluationsResponse: - """ - Retrieve post-call evaluation results for a conversation. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListEvaluationsResponse - The evaluations for the conversation. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.conversations.list_evaluations( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/conversations/{jsonable_encoder(id)}/evaluations", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListEvaluationsResponse, - parse_obj_as( - type_=ListEvaluationsResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def list_memories( - self, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> ListMemoriesResponse: - """ - List memories extracted from a specific conversation. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListMemoriesResponse - Memories written during this conversation. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.conversations.list_memories( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/conversations/{jsonable_encoder(id)}/memories", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListMemoriesResponse, - parse_obj_as( - type_=ListMemoriesResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - -class AsyncConversationsClient: - def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper - - async def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> ListConversationsResponse: - """ - List conversations owned by the caller, ordered by most recent. - - Parameters - ---------- - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListConversationsResponse - A list of conversations. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.conversations.list() - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/conversations", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListConversationsResponse, - parse_obj_as( - type_=ListConversationsResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def stats(self, *, request_options: typing.Optional[RequestOptions] = None) -> ConversationStats: - """ - Aggregated counts and averages over the caller's conversations, scoped by the same filters as the list endpoint. - - Parameters - ---------- - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ConversationStats - Stats for the matched conversations. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.conversations.stats() - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/conversations/stats", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ConversationStats, - parse_obj_as( - type_=ConversationStats, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Conversation: - """ - Retrieve a conversation by ID. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Conversation - The requested conversation. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.conversations.get( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/conversations/{jsonable_encoder(id)}", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Conversation, - parse_obj_as( - type_=Conversation, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def list_messages( - self, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> ListMessagesResponse: - """ - Retrieve the full transcript for a conversation, in order. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListMessagesResponse - The messages for the conversation. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.conversations.list_messages( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/conversations/{jsonable_encoder(id)}/messages", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListMessagesResponse, - parse_obj_as( - type_=ListMessagesResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def list_evaluations( - self, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> ListEvaluationsResponse: - """ - Retrieve post-call evaluation results for a conversation. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListEvaluationsResponse - The evaluations for the conversation. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.conversations.list_evaluations( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/conversations/{jsonable_encoder(id)}/evaluations", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListEvaluationsResponse, - parse_obj_as( - type_=ListEvaluationsResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def list_memories( - self, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> ListMemoriesResponse: - """ - List memories extracted from a specific conversation. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListMemoriesResponse - Memories written during this conversation. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.conversations.list_memories( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/conversations/{jsonable_encoder(id)}/memories", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListMemoriesResponse, - parse_obj_as( - type_=ListMemoriesResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/speechify/tts/errors/conflict_error.py b/src/speechify/tts/errors/conflict_error.py deleted file mode 100644 index d7a46cb..0000000 --- a/src/speechify/tts/errors/conflict_error.py +++ /dev/null @@ -1,9 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.api_error import ApiError -import typing - - -class ConflictError(ApiError): - def __init__(self, body: typing.Optional[typing.Any]): - super().__init__(status_code=409, body=body) diff --git a/src/speechify/tts/errors/content_too_large_error.py b/src/speechify/tts/errors/content_too_large_error.py deleted file mode 100644 index d418735..0000000 --- a/src/speechify/tts/errors/content_too_large_error.py +++ /dev/null @@ -1,9 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.api_error import ApiError -import typing - - -class ContentTooLargeError(ApiError): - def __init__(self, body: typing.Optional[typing.Any]): - super().__init__(status_code=413, body=body) diff --git a/src/speechify/tts/knowledge_bases/__init__.py b/src/speechify/tts/knowledge_bases/__init__.py deleted file mode 100644 index f3ea265..0000000 --- a/src/speechify/tts/knowledge_bases/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - diff --git a/src/speechify/tts/knowledge_bases/client.py b/src/speechify/tts/knowledge_bases/client.py deleted file mode 100644 index 534ae91..0000000 --- a/src/speechify/tts/knowledge_bases/client.py +++ /dev/null @@ -1,1722 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing -from ...core.client_wrapper import SyncClientWrapper -from ...core.request_options import RequestOptions -from ..types.list_knowledge_bases_response import ListKnowledgeBasesResponse -from ...core.pydantic_utilities import parse_obj_as -from ..errors.unauthorized_error import UnauthorizedError -from json.decoder import JSONDecodeError -from ...core.api_error import ApiError -from ..types.knowledge_base import KnowledgeBase -from ..errors.bad_request_error import BadRequestError -from ...core.jsonable_encoder import jsonable_encoder -from ..errors.not_found_error import NotFoundError -from ..types.list_knowledge_base_documents_response import ListKnowledgeBaseDocumentsResponse -from ... import core -from ..types.knowledge_base_document import KnowledgeBaseDocument -from ..errors.content_too_large_error import ContentTooLargeError -from ..types.list_knowledge_base_chunks_response import ListKnowledgeBaseChunksResponse -from ..types.search_knowledge_bases_response import SearchKnowledgeBasesResponse -from ...core.client_wrapper import AsyncClientWrapper - -# this is used as the default value for optional parameters -OMIT = typing.cast(typing.Any, ...) - - -class KnowledgeBasesClient: - def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper - - def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> ListKnowledgeBasesResponse: - """ - List knowledge bases owned by the caller. - - Parameters - ---------- - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListKnowledgeBasesResponse - The knowledge bases for the caller. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.knowledge_bases.list() - """ - _response = self._client_wrapper.httpx_client.request( - "v1/knowledge-bases", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListKnowledgeBasesResponse, - parse_obj_as( - type_=ListKnowledgeBasesResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def create( - self, - *, - name: str, - description: typing.Optional[str] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> KnowledgeBase: - """ - Create a new knowledge base. - - Parameters - ---------- - name : str - Human-readable label. - - description : typing.Optional[str] - Optional description. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - KnowledgeBase - The created knowledge base. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.knowledge_bases.create( - name="name", - ) - """ - _response = self._client_wrapper.httpx_client.request( - "v1/knowledge-bases", - method="POST", - json={ - "name": name, - "description": description, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - KnowledgeBase, - parse_obj_as( - type_=KnowledgeBase, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> KnowledgeBase: - """ - Retrieve a knowledge base by ID. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - KnowledgeBase - The requested knowledge base. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.knowledge_bases.get( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/knowledge-bases/{jsonable_encoder(id)}", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - KnowledgeBase, - parse_obj_as( - type_=KnowledgeBase, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Soft-delete a knowledge base. Documents and chunks are cascaded. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.knowledge_bases.delete( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/knowledge-bases/{jsonable_encoder(id)}", - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def update( - self, - id: str, - *, - name: typing.Optional[str] = OMIT, - description: typing.Optional[str] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> KnowledgeBase: - """ - Update a knowledge base. - - Parameters - ---------- - id : str - - name : typing.Optional[str] - - description : typing.Optional[str] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - KnowledgeBase - The updated knowledge base. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.knowledge_bases.update( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/knowledge-bases/{jsonable_encoder(id)}", - method="PATCH", - json={ - "name": name, - "description": description, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - KnowledgeBase, - parse_obj_as( - type_=KnowledgeBase, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def list_documents( - self, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> ListKnowledgeBaseDocumentsResponse: - """ - List documents ingested into a knowledge base. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListKnowledgeBaseDocumentsResponse - The documents in the knowledge base. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.knowledge_bases.list_documents( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/knowledge-bases/{jsonable_encoder(id)}/documents", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListKnowledgeBaseDocumentsResponse, - parse_obj_as( - type_=ListKnowledgeBaseDocumentsResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def upload_document( - self, id: str, *, file: core.File, request_options: typing.Optional[RequestOptions] = None - ) -> KnowledgeBaseDocument: - """ - Upload a document (PDF, plain text, markdown, or HTML) to a - knowledge base. The document is extracted, chunked, embedded, and - indexed synchronously; expect a few seconds per MB of input. - Maximum 10 MB per upload. - - Parameters - ---------- - id : str - - file : core.File - See core.File for more documentation - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - KnowledgeBaseDocument - The ingested document record. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.knowledge_bases.upload_document( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/knowledge-bases/{jsonable_encoder(id)}/documents", - method="POST", - data={}, - files={ - "file": file, - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - KnowledgeBaseDocument, - parse_obj_as( - type_=KnowledgeBaseDocument, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 413: - raise ContentTooLargeError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def get_document( - self, doc_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> KnowledgeBaseDocument: - """ - Retrieve a document by ID. - - Parameters - ---------- - doc_id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - KnowledgeBaseDocument - The document record. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.knowledge_bases.get_document( - doc_id="docId", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/knowledge-bases/documents/{jsonable_encoder(doc_id)}", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - KnowledgeBaseDocument, - parse_obj_as( - type_=KnowledgeBaseDocument, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def delete_document(self, doc_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Delete a document and all its chunks. - - Parameters - ---------- - doc_id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.knowledge_bases.delete_document( - doc_id="docId", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/knowledge-bases/documents/{jsonable_encoder(doc_id)}", - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def list_chunks( - self, doc_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> ListKnowledgeBaseChunksResponse: - """ - List the chunks for a document. - - Parameters - ---------- - doc_id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListKnowledgeBaseChunksResponse - The chunks for the document. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.knowledge_bases.list_chunks( - doc_id="docId", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/knowledge-bases/documents/{jsonable_encoder(doc_id)}/chunks", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListKnowledgeBaseChunksResponse, - parse_obj_as( - type_=ListKnowledgeBaseChunksResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def search( - self, - *, - query: str, - kb_ids: typing.Sequence[str], - top_k: typing.Optional[int] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> SearchKnowledgeBasesResponse: - """ - Semantic search across a caller-owned list of knowledge bases. - Returns ranked chunks with source filename and a cosine-similarity - score. Limited to 50 results per request. - - Parameters - ---------- - query : str - Natural-language search query. - - kb_ids : typing.Sequence[str] - Knowledge bases to search across. Results scoped to caller-owned entries; unknown IDs are silently ignored. - - top_k : typing.Optional[int] - Max hits to return (default 5, capped at 50). - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - SearchKnowledgeBasesResponse - Ranked search hits across the selected knowledge bases. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.knowledge_bases.search( - query="query", - kb_ids=["kb_ids"], - ) - """ - _response = self._client_wrapper.httpx_client.request( - "v1/knowledge-bases/search", - method="POST", - json={ - "query": query, - "kb_ids": kb_ids, - "top_k": top_k, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - SearchKnowledgeBasesResponse, - parse_obj_as( - type_=SearchKnowledgeBasesResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - -class AsyncKnowledgeBasesClient: - def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper - - async def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> ListKnowledgeBasesResponse: - """ - List knowledge bases owned by the caller. - - Parameters - ---------- - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListKnowledgeBasesResponse - The knowledge bases for the caller. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.knowledge_bases.list() - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/knowledge-bases", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListKnowledgeBasesResponse, - parse_obj_as( - type_=ListKnowledgeBasesResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def create( - self, - *, - name: str, - description: typing.Optional[str] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> KnowledgeBase: - """ - Create a new knowledge base. - - Parameters - ---------- - name : str - Human-readable label. - - description : typing.Optional[str] - Optional description. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - KnowledgeBase - The created knowledge base. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.knowledge_bases.create( - name="name", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/knowledge-bases", - method="POST", - json={ - "name": name, - "description": description, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - KnowledgeBase, - parse_obj_as( - type_=KnowledgeBase, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> KnowledgeBase: - """ - Retrieve a knowledge base by ID. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - KnowledgeBase - The requested knowledge base. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.knowledge_bases.get( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/knowledge-bases/{jsonable_encoder(id)}", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - KnowledgeBase, - parse_obj_as( - type_=KnowledgeBase, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Soft-delete a knowledge base. Documents and chunks are cascaded. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.knowledge_bases.delete( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/knowledge-bases/{jsonable_encoder(id)}", - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def update( - self, - id: str, - *, - name: typing.Optional[str] = OMIT, - description: typing.Optional[str] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> KnowledgeBase: - """ - Update a knowledge base. - - Parameters - ---------- - id : str - - name : typing.Optional[str] - - description : typing.Optional[str] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - KnowledgeBase - The updated knowledge base. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.knowledge_bases.update( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/knowledge-bases/{jsonable_encoder(id)}", - method="PATCH", - json={ - "name": name, - "description": description, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - KnowledgeBase, - parse_obj_as( - type_=KnowledgeBase, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def list_documents( - self, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> ListKnowledgeBaseDocumentsResponse: - """ - List documents ingested into a knowledge base. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListKnowledgeBaseDocumentsResponse - The documents in the knowledge base. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.knowledge_bases.list_documents( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/knowledge-bases/{jsonable_encoder(id)}/documents", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListKnowledgeBaseDocumentsResponse, - parse_obj_as( - type_=ListKnowledgeBaseDocumentsResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def upload_document( - self, id: str, *, file: core.File, request_options: typing.Optional[RequestOptions] = None - ) -> KnowledgeBaseDocument: - """ - Upload a document (PDF, plain text, markdown, or HTML) to a - knowledge base. The document is extracted, chunked, embedded, and - indexed synchronously; expect a few seconds per MB of input. - Maximum 10 MB per upload. - - Parameters - ---------- - id : str - - file : core.File - See core.File for more documentation - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - KnowledgeBaseDocument - The ingested document record. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.knowledge_bases.upload_document( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/knowledge-bases/{jsonable_encoder(id)}/documents", - method="POST", - data={}, - files={ - "file": file, - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - KnowledgeBaseDocument, - parse_obj_as( - type_=KnowledgeBaseDocument, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 413: - raise ContentTooLargeError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def get_document( - self, doc_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> KnowledgeBaseDocument: - """ - Retrieve a document by ID. - - Parameters - ---------- - doc_id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - KnowledgeBaseDocument - The document record. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.knowledge_bases.get_document( - doc_id="docId", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/knowledge-bases/documents/{jsonable_encoder(doc_id)}", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - KnowledgeBaseDocument, - parse_obj_as( - type_=KnowledgeBaseDocument, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def delete_document(self, doc_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Delete a document and all its chunks. - - Parameters - ---------- - doc_id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.knowledge_bases.delete_document( - doc_id="docId", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/knowledge-bases/documents/{jsonable_encoder(doc_id)}", - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def list_chunks( - self, doc_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> ListKnowledgeBaseChunksResponse: - """ - List the chunks for a document. - - Parameters - ---------- - doc_id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListKnowledgeBaseChunksResponse - The chunks for the document. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.knowledge_bases.list_chunks( - doc_id="docId", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/knowledge-bases/documents/{jsonable_encoder(doc_id)}/chunks", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListKnowledgeBaseChunksResponse, - parse_obj_as( - type_=ListKnowledgeBaseChunksResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def search( - self, - *, - query: str, - kb_ids: typing.Sequence[str], - top_k: typing.Optional[int] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> SearchKnowledgeBasesResponse: - """ - Semantic search across a caller-owned list of knowledge bases. - Returns ranked chunks with source filename and a cosine-similarity - score. Limited to 50 results per request. - - Parameters - ---------- - query : str - Natural-language search query. - - kb_ids : typing.Sequence[str] - Knowledge bases to search across. Results scoped to caller-owned entries; unknown IDs are silently ignored. - - top_k : typing.Optional[int] - Max hits to return (default 5, capped at 50). - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - SearchKnowledgeBasesResponse - Ranked search hits across the selected knowledge bases. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.knowledge_bases.search( - query="query", - kb_ids=["kb_ids"], - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/knowledge-bases/search", - method="POST", - json={ - "query": query, - "kb_ids": kb_ids, - "top_k": top_k, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - SearchKnowledgeBasesResponse, - parse_obj_as( - type_=SearchKnowledgeBasesResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/speechify/tts/memories/__init__.py b/src/speechify/tts/memories/__init__.py deleted file mode 100644 index f3ea265..0000000 --- a/src/speechify/tts/memories/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - diff --git a/src/speechify/tts/memories/client.py b/src/speechify/tts/memories/client.py deleted file mode 100644 index afb9f84..0000000 --- a/src/speechify/tts/memories/client.py +++ /dev/null @@ -1,148 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.client_wrapper import SyncClientWrapper -import typing -from ...core.request_options import RequestOptions -from ...core.jsonable_encoder import jsonable_encoder -from ..errors.unauthorized_error import UnauthorizedError -from ...core.pydantic_utilities import parse_obj_as -from ..errors.not_found_error import NotFoundError -from json.decoder import JSONDecodeError -from ...core.api_error import ApiError -from ...core.client_wrapper import AsyncClientWrapper - - -class MemoriesClient: - def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper - - def delete(self, memory_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Soft-delete one memory row. - - Parameters - ---------- - memory_id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.memories.delete( - memory_id="memoryId", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/memories/{jsonable_encoder(memory_id)}", - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - -class AsyncMemoriesClient: - def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper - - async def delete(self, memory_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Soft-delete one memory row. - - Parameters - ---------- - memory_id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.memories.delete( - memory_id="memoryId", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/memories/{jsonable_encoder(memory_id)}", - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/speechify/tts/outbound_calls/__init__.py b/src/speechify/tts/outbound_calls/__init__.py deleted file mode 100644 index f3ea265..0000000 --- a/src/speechify/tts/outbound_calls/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - diff --git a/src/speechify/tts/outbound_calls/client.py b/src/speechify/tts/outbound_calls/client.py deleted file mode 100644 index d8f9e3b..0000000 --- a/src/speechify/tts/outbound_calls/client.py +++ /dev/null @@ -1,213 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing -from ...core.client_wrapper import SyncClientWrapper -from ...core.request_options import RequestOptions -from ...core.pydantic_utilities import parse_obj_as -from ..errors.bad_request_error import BadRequestError -from ..errors.unauthorized_error import UnauthorizedError -from ..errors.not_found_error import NotFoundError -from json.decoder import JSONDecodeError -from ...core.api_error import ApiError -from ...core.client_wrapper import AsyncClientWrapper - -# this is used as the default value for optional parameters -OMIT = typing.cast(typing.Any, ...) - - -class OutboundCallsClient: - def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper - - def create( - self, *, request: typing.Optional[typing.Any] = None, request_options: typing.Optional[RequestOptions] = None - ) -> typing.Optional[typing.Any]: - """ - Place an outbound call from an agent to a phone number. LiveKit - originates the SIP INVITE through the outbound trunk bound to the - agent's workspace; the agent worker is dispatched into the room - automatically. - - The response is returned as soon as LiveKit accepts the INVITE. - Poll `GET /v1/conversations/{conversation_id}` for status - transitions: `pending` → `active` (answered) → `completed`. - - Requires a Twilio or BYOC trunk. LiveKit-native numbers are - inbound-only. - - Parameters - ---------- - request : typing.Optional[typing.Any] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.Optional[typing.Any] - The outbound call was accepted by LiveKit. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.outbound_calls.create( - request={"key": "value"}, - ) - """ - _response = self._client_wrapper.httpx_client.request( - "v1/outbound-calls", - method="POST", - json=request, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - -class AsyncOutboundCallsClient: - def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper - - async def create( - self, *, request: typing.Optional[typing.Any] = None, request_options: typing.Optional[RequestOptions] = None - ) -> typing.Optional[typing.Any]: - """ - Place an outbound call from an agent to a phone number. LiveKit - originates the SIP INVITE through the outbound trunk bound to the - agent's workspace; the agent worker is dispatched into the room - automatically. - - The response is returned as soon as LiveKit accepts the INVITE. - Poll `GET /v1/conversations/{conversation_id}` for status - transitions: `pending` → `active` (answered) → `completed`. - - Requires a Twilio or BYOC trunk. LiveKit-native numbers are - inbound-only. - - Parameters - ---------- - request : typing.Optional[typing.Any] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.Optional[typing.Any] - The outbound call was accepted by LiveKit. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.outbound_calls.create( - request={"key": "value"}, - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/outbound-calls", - method="POST", - json=request, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/speechify/tts/phone_numbers/__init__.py b/src/speechify/tts/phone_numbers/__init__.py deleted file mode 100644 index f3ea265..0000000 --- a/src/speechify/tts/phone_numbers/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - diff --git a/src/speechify/tts/phone_numbers/client.py b/src/speechify/tts/phone_numbers/client.py deleted file mode 100644 index 956091a..0000000 --- a/src/speechify/tts/phone_numbers/client.py +++ /dev/null @@ -1,787 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing -from ...core.client_wrapper import SyncClientWrapper -from ...core.request_options import RequestOptions -from ...core.pydantic_utilities import parse_obj_as -from ..errors.unauthorized_error import UnauthorizedError -from json.decoder import JSONDecodeError -from ...core.api_error import ApiError -from ..errors.bad_request_error import BadRequestError -from ..errors.payment_required_error import PaymentRequiredError -from ...core.jsonable_encoder import jsonable_encoder -from ..errors.not_found_error import NotFoundError -from ...core.client_wrapper import AsyncClientWrapper - -# this is used as the default value for optional parameters -OMIT = typing.cast(typing.Any, ...) - - -class PhoneNumbersClient: - def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper - - def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> typing.Optional[typing.Any]: - """ - List all phone numbers in the caller's workspace. - - Parameters - ---------- - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.Optional[typing.Any] - The phone numbers for the workspace. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.phone_numbers.list() - """ - _response = self._client_wrapper.httpx_client.request( - "v1/phone-numbers", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def import_( - self, *, request: typing.Optional[typing.Any] = None, request_options: typing.Optional[RequestOptions] = None - ) -> typing.Optional[typing.Any]: - """ - Import a phone number into the workspace. The `source` field - determines the provisioning path: - - - `livekit` - LiveKit purchases the number on your behalf. US - inbound only. Quickest path for local testing. - - `twilio` - Provide your Twilio Account SID, Auth Token, and - the E.164 number you already own. We provision an Elastic SIP - Trunk on your Twilio account automatically. - - `byoc` - Provide an existing SIP trunk ID. The number is - registered against that trunk. - - Returns 402 when the workspace has reached the 100-number cap. - - Parameters - ---------- - request : typing.Optional[typing.Any] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.Optional[typing.Any] - The imported phone number. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.phone_numbers.import_( - request={"key": "value"}, - ) - """ - _response = self._client_wrapper.httpx_client.request( - "v1/phone-numbers", - method="POST", - json=request, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 402: - raise PaymentRequiredError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> typing.Optional[typing.Any]: - """ - Retrieve a phone number by ID. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.Optional[typing.Any] - The requested phone number. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.phone_numbers.get( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/phone-numbers/{jsonable_encoder(id)}", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Delete a phone number from the workspace. For Twilio and LiveKit - numbers this also deprovisions the backing SIP trunk and dispatch - rule on LiveKit Cloud. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.phone_numbers.delete( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/phone-numbers/{jsonable_encoder(id)}", - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def update( - self, - id: str, - *, - request: typing.Optional[typing.Any] = None, - request_options: typing.Optional[RequestOptions] = None, - ) -> typing.Optional[typing.Any]: - """ - Update a phone number. Only `label` and `agent_id` are mutable; - `source` and `e164` are immutable after import. Pass `null` for - `agent_id` to unbind the number from its current agent. - - Parameters - ---------- - id : str - - request : typing.Optional[typing.Any] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.Optional[typing.Any] - The updated phone number. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.phone_numbers.update( - id="id", - request={"key": "value"}, - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/phone-numbers/{jsonable_encoder(id)}", - method="PATCH", - json=request, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - -class AsyncPhoneNumbersClient: - def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper - - async def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> typing.Optional[typing.Any]: - """ - List all phone numbers in the caller's workspace. - - Parameters - ---------- - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.Optional[typing.Any] - The phone numbers for the workspace. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.phone_numbers.list() - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/phone-numbers", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def import_( - self, *, request: typing.Optional[typing.Any] = None, request_options: typing.Optional[RequestOptions] = None - ) -> typing.Optional[typing.Any]: - """ - Import a phone number into the workspace. The `source` field - determines the provisioning path: - - - `livekit` - LiveKit purchases the number on your behalf. US - inbound only. Quickest path for local testing. - - `twilio` - Provide your Twilio Account SID, Auth Token, and - the E.164 number you already own. We provision an Elastic SIP - Trunk on your Twilio account automatically. - - `byoc` - Provide an existing SIP trunk ID. The number is - registered against that trunk. - - Returns 402 when the workspace has reached the 100-number cap. - - Parameters - ---------- - request : typing.Optional[typing.Any] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.Optional[typing.Any] - The imported phone number. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.phone_numbers.import_( - request={"key": "value"}, - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/phone-numbers", - method="POST", - json=request, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 402: - raise PaymentRequiredError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def get( - self, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> typing.Optional[typing.Any]: - """ - Retrieve a phone number by ID. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.Optional[typing.Any] - The requested phone number. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.phone_numbers.get( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/phone-numbers/{jsonable_encoder(id)}", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Delete a phone number from the workspace. For Twilio and LiveKit - numbers this also deprovisions the backing SIP trunk and dispatch - rule on LiveKit Cloud. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.phone_numbers.delete( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/phone-numbers/{jsonable_encoder(id)}", - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def update( - self, - id: str, - *, - request: typing.Optional[typing.Any] = None, - request_options: typing.Optional[RequestOptions] = None, - ) -> typing.Optional[typing.Any]: - """ - Update a phone number. Only `label` and `agent_id` are mutable; - `source` and `e164` are immutable after import. Pass `null` for - `agent_id` to unbind the number from its current agent. - - Parameters - ---------- - id : str - - request : typing.Optional[typing.Any] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.Optional[typing.Any] - The updated phone number. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.phone_numbers.update( - id="id", - request={"key": "value"}, - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/phone-numbers/{jsonable_encoder(id)}", - method="PATCH", - json=request, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/speechify/tts/sip_trunks/__init__.py b/src/speechify/tts/sip_trunks/__init__.py deleted file mode 100644 index f3ea265..0000000 --- a/src/speechify/tts/sip_trunks/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - diff --git a/src/speechify/tts/sip_trunks/client.py b/src/speechify/tts/sip_trunks/client.py deleted file mode 100644 index 2d837a8..0000000 --- a/src/speechify/tts/sip_trunks/client.py +++ /dev/null @@ -1,589 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing -from ...core.client_wrapper import SyncClientWrapper -from ...core.request_options import RequestOptions -from ...core.pydantic_utilities import parse_obj_as -from ..errors.unauthorized_error import UnauthorizedError -from json.decoder import JSONDecodeError -from ...core.api_error import ApiError -from ..errors.bad_request_error import BadRequestError -from ..errors.payment_required_error import PaymentRequiredError -from ...core.jsonable_encoder import jsonable_encoder -from ..errors.not_found_error import NotFoundError -from ...core.client_wrapper import AsyncClientWrapper - -# this is used as the default value for optional parameters -OMIT = typing.cast(typing.Any, ...) - - -class SipTrunksClient: - def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper - - def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> typing.Optional[typing.Any]: - """ - List all SIP trunks in the caller's workspace. - - Parameters - ---------- - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.Optional[typing.Any] - The SIP trunks for the workspace. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.sip_trunks.list() - """ - _response = self._client_wrapper.httpx_client.request( - "v1/sip-trunks", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def create( - self, *, request: typing.Optional[typing.Any] = None, request_options: typing.Optional[RequestOptions] = None - ) -> typing.Optional[typing.Any]: - """ - Create a SIP trunk. For `kind=byoc` supply `sip_address` plus - optional digest credentials and IP allowlist. For `kind=twilio` - use `ImportPhoneNumber` with a `twilio` spec instead - trunk - creation is handled automatically. Returns 402 when the workspace - has reached the 20-trunk cap. - - Parameters - ---------- - request : typing.Optional[typing.Any] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.Optional[typing.Any] - The created SIP trunk. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.sip_trunks.create( - request={"key": "value"}, - ) - """ - _response = self._client_wrapper.httpx_client.request( - "v1/sip-trunks", - method="POST", - json=request, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 402: - raise PaymentRequiredError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> typing.Optional[typing.Any]: - """ - Retrieve a SIP trunk by ID. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.Optional[typing.Any] - The requested SIP trunk. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.sip_trunks.get( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/sip-trunks/{jsonable_encoder(id)}", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Delete a SIP trunk. This also removes the backing LiveKit inbound - trunk, outbound trunk, and dispatch rule if they were provisioned - by us. Phone numbers attached to this trunk are left in place but - become non-functional until rebound to a new trunk. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.sip_trunks.delete( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/sip-trunks/{jsonable_encoder(id)}", - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - -class AsyncSipTrunksClient: - def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper - - async def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> typing.Optional[typing.Any]: - """ - List all SIP trunks in the caller's workspace. - - Parameters - ---------- - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.Optional[typing.Any] - The SIP trunks for the workspace. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.sip_trunks.list() - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/sip-trunks", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def create( - self, *, request: typing.Optional[typing.Any] = None, request_options: typing.Optional[RequestOptions] = None - ) -> typing.Optional[typing.Any]: - """ - Create a SIP trunk. For `kind=byoc` supply `sip_address` plus - optional digest credentials and IP allowlist. For `kind=twilio` - use `ImportPhoneNumber` with a `twilio` spec instead - trunk - creation is handled automatically. Returns 402 when the workspace - has reached the 20-trunk cap. - - Parameters - ---------- - request : typing.Optional[typing.Any] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.Optional[typing.Any] - The created SIP trunk. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.sip_trunks.create( - request={"key": "value"}, - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/sip-trunks", - method="POST", - json=request, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 402: - raise PaymentRequiredError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def get( - self, id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> typing.Optional[typing.Any]: - """ - Retrieve a SIP trunk by ID. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.Optional[typing.Any] - The requested SIP trunk. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.sip_trunks.get( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/sip-trunks/{jsonable_encoder(id)}", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Delete a SIP trunk. This also removes the backing LiveKit inbound - trunk, outbound trunk, and dispatch rule if they were provisioned - by us. Phone numbers attached to this trunk are left in place but - become non-functional until rebound to a new trunk. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.sip_trunks.delete( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/sip-trunks/{jsonable_encoder(id)}", - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/speechify/tts/tools/__init__.py b/src/speechify/tts/tools/__init__.py deleted file mode 100644 index 3d29f5d..0000000 --- a/src/speechify/tts/tools/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from .types import CreateToolRequestConfig, UpdateToolRequestConfig - -__all__ = ["CreateToolRequestConfig", "UpdateToolRequestConfig"] diff --git a/src/speechify/tts/tools/client.py b/src/speechify/tts/tools/client.py deleted file mode 100644 index 56cbb77..0000000 --- a/src/speechify/tts/tools/client.py +++ /dev/null @@ -1,828 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing -from ...core.client_wrapper import SyncClientWrapper -from ...core.request_options import RequestOptions -from ..types.list_tools_response import ListToolsResponse -from ...core.pydantic_utilities import parse_obj_as -from ..errors.unauthorized_error import UnauthorizedError -from json.decoder import JSONDecodeError -from ...core.api_error import ApiError -from ..types.tool_kind import ToolKind -from .types.create_tool_request_config import CreateToolRequestConfig -from ..types.tool import Tool -from ...core.serialization import convert_and_respect_annotation_metadata -from ..errors.bad_request_error import BadRequestError -from ...core.jsonable_encoder import jsonable_encoder -from ..errors.not_found_error import NotFoundError -from .types.update_tool_request_config import UpdateToolRequestConfig -from ...core.client_wrapper import AsyncClientWrapper - -# this is used as the default value for optional parameters -OMIT = typing.cast(typing.Any, ...) - - -class ToolsClient: - def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper - - def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> ListToolsResponse: - """ - List tools owned by the caller. - - Parameters - ---------- - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListToolsResponse - A list of tools. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.tools.list() - """ - _response = self._client_wrapper.httpx_client.request( - "v1/tools", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListToolsResponse, - parse_obj_as( - type_=ListToolsResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def create( - self, - *, - name: str, - description: str, - kind: ToolKind, - config: CreateToolRequestConfig, - request_options: typing.Optional[RequestOptions] = None, - ) -> Tool: - """ - Create a tool. For webhook tools, the response includes the HMAC - `webhook_secret` exactly once — store it immediately; subsequent - reads return a masked placeholder. - - Parameters - ---------- - name : str - - description : str - - kind : ToolKind - - config : CreateToolRequestConfig - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Tool - The created tool. - - Examples - -------- - from speechify import Speechify - from speechify.tts import SystemToolConfig - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.tools.create( - name="name", - description="description", - kind="system", - config=SystemToolConfig( - builtin="end_call", - ), - ) - """ - _response = self._client_wrapper.httpx_client.request( - "v1/tools", - method="POST", - json={ - "name": name, - "description": description, - "kind": kind, - "config": convert_and_respect_annotation_metadata( - object_=config, annotation=CreateToolRequestConfig, direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Tool, - parse_obj_as( - type_=Tool, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Tool: - """ - Retrieve a tool by ID. Webhook secrets are always masked here. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Tool - The requested tool. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.tools.get( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/tools/{jsonable_encoder(id)}", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Tool, - parse_obj_as( - type_=Tool, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Delete a tool. Agents that had it attached get a soft-detach. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.tools.delete( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/tools/{jsonable_encoder(id)}", - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def update( - self, - id: str, - *, - name: typing.Optional[str] = OMIT, - description: typing.Optional[str] = OMIT, - config: typing.Optional[UpdateToolRequestConfig] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> Tool: - """ - Update a tool. Tool kind is immutable — create a new tool to change it. - - Parameters - ---------- - id : str - - name : typing.Optional[str] - - description : typing.Optional[str] - - config : typing.Optional[UpdateToolRequestConfig] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Tool - The updated tool. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.tools.update( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/tools/{jsonable_encoder(id)}", - method="PATCH", - json={ - "name": name, - "description": description, - "config": convert_and_respect_annotation_metadata( - object_=config, annotation=UpdateToolRequestConfig, direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Tool, - parse_obj_as( - type_=Tool, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - -class AsyncToolsClient: - def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper - - async def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> ListToolsResponse: - """ - List tools owned by the caller. - - Parameters - ---------- - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ListToolsResponse - A list of tools. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.tools.list() - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/tools", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListToolsResponse, - parse_obj_as( - type_=ListToolsResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def create( - self, - *, - name: str, - description: str, - kind: ToolKind, - config: CreateToolRequestConfig, - request_options: typing.Optional[RequestOptions] = None, - ) -> Tool: - """ - Create a tool. For webhook tools, the response includes the HMAC - `webhook_secret` exactly once — store it immediately; subsequent - reads return a masked placeholder. - - Parameters - ---------- - name : str - - description : str - - kind : ToolKind - - config : CreateToolRequestConfig - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Tool - The created tool. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - from speechify.tts import SystemToolConfig - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.tools.create( - name="name", - description="description", - kind="system", - config=SystemToolConfig( - builtin="end_call", - ), - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/tools", - method="POST", - json={ - "name": name, - "description": description, - "kind": kind, - "config": convert_and_respect_annotation_metadata( - object_=config, annotation=CreateToolRequestConfig, direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Tool, - parse_obj_as( - type_=Tool, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Tool: - """ - Retrieve a tool by ID. Webhook secrets are always masked here. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Tool - The requested tool. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.tools.get( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/tools/{jsonable_encoder(id)}", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Tool, - parse_obj_as( - type_=Tool, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Delete a tool. Agents that had it attached get a soft-detach. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.tools.delete( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/tools/{jsonable_encoder(id)}", - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def update( - self, - id: str, - *, - name: typing.Optional[str] = OMIT, - description: typing.Optional[str] = OMIT, - config: typing.Optional[UpdateToolRequestConfig] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> Tool: - """ - Update a tool. Tool kind is immutable — create a new tool to change it. - - Parameters - ---------- - id : str - - name : typing.Optional[str] - - description : typing.Optional[str] - - config : typing.Optional[UpdateToolRequestConfig] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Tool - The updated tool. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.tools.update( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/tools/{jsonable_encoder(id)}", - method="PATCH", - json={ - "name": name, - "description": description, - "config": convert_and_respect_annotation_metadata( - object_=config, annotation=UpdateToolRequestConfig, direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Tool, - parse_obj_as( - type_=Tool, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/speechify/tts/tools/types/__init__.py b/src/speechify/tts/tools/types/__init__.py deleted file mode 100644 index 5bc7f9e..0000000 --- a/src/speechify/tts/tools/types/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from .create_tool_request_config import CreateToolRequestConfig -from .update_tool_request_config import UpdateToolRequestConfig - -__all__ = ["CreateToolRequestConfig", "UpdateToolRequestConfig"] diff --git a/src/speechify/tts/tools/types/create_tool_request_config.py b/src/speechify/tts/tools/types/create_tool_request_config.py deleted file mode 100644 index d1a85f1..0000000 --- a/src/speechify/tts/tools/types/create_tool_request_config.py +++ /dev/null @@ -1,8 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing -from ...types.system_tool_config import SystemToolConfig -from ...types.webhook_tool_config import WebhookToolConfig -from ...types.client_tool_config import ClientToolConfig - -CreateToolRequestConfig = typing.Union[SystemToolConfig, WebhookToolConfig, ClientToolConfig] diff --git a/src/speechify/tts/tools/types/update_tool_request_config.py b/src/speechify/tts/tools/types/update_tool_request_config.py deleted file mode 100644 index b20f9b7..0000000 --- a/src/speechify/tts/tools/types/update_tool_request_config.py +++ /dev/null @@ -1,8 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing -from ...types.system_tool_config import SystemToolConfig -from ...types.webhook_tool_config import WebhookToolConfig -from ...types.client_tool_config import ClientToolConfig - -UpdateToolRequestConfig = typing.Union[SystemToolConfig, WebhookToolConfig, ClientToolConfig] diff --git a/src/speechify/tts/types/__init__.py b/src/speechify/tts/types/__init__.py deleted file mode 100644 index accbecf..0000000 --- a/src/speechify/tts/types/__init__.py +++ /dev/null @@ -1,235 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from .access_token import AccessToken -from .access_token_scope import AccessTokenScope -from .access_token_token_type import AccessTokenTokenType -from .agent import Agent -from .agent_test import AgentTest -from .agent_test_attachment import AgentTestAttachment -from .agent_test_config import AgentTestConfig -from .agent_test_folder import AgentTestFolder -from .agent_test_run import AgentTestRun -from .agent_test_with_last_run import AgentTestWithLastRun -from .api_key import ApiKey -from .batch_run_entry import BatchRunEntry -from .client_tool_config import ClientToolConfig -from .conversation import Conversation -from .conversation_stats import ConversationStats -from .conversation_status import ConversationStatus -from .conversation_transport import ConversationTransport -from .create_conversation_response import CreateConversationResponse -from .create_voice_language import CreateVoiceLanguage -from .create_voice_model import CreateVoiceModel -from .create_voice_model_name import CreateVoiceModelName -from .created_voice import CreatedVoice -from .created_voice_gender import CreatedVoiceGender -from .created_voice_type import CreatedVoiceType -from .data_collection_field import DataCollectionField -from .data_collection_field_type import DataCollectionFieldType -from .delete_memories_by_caller_response import DeleteMemoriesByCallerResponse -from .dynamic_variable import DynamicVariable -from .dynamic_variable_type import DynamicVariableType -from .evaluation import Evaluation -from .evaluation_config import EvaluationConfig -from .evaluation_criterion import EvaluationCriterion -from .evaluation_kind import EvaluationKind -from .evaluation_status import EvaluationStatus -from .get_speech_options_request import GetSpeechOptionsRequest -from .get_speech_response import GetSpeechResponse -from .get_speech_response_audio_format import GetSpeechResponseAudioFormat -from .get_stream_options_request import GetStreamOptionsRequest -from .get_voice import GetVoice -from .get_voice_gender import GetVoiceGender -from .get_voice_language import GetVoiceLanguage -from .get_voice_type import GetVoiceType -from .get_voices_model import GetVoicesModel -from .get_voices_model_name import GetVoicesModelName -from .invite import Invite -from .invite_preview import InvitePreview -from .invites_list_response import InvitesListResponse -from .knowledge_base import KnowledgeBase -from .knowledge_base_chunk import KnowledgeBaseChunk -from .knowledge_base_document import KnowledgeBaseDocument -from .knowledge_base_document_status import KnowledgeBaseDocumentStatus -from .knowledge_base_search_hit import KnowledgeBaseSearchHit -from .list_agent_test_attachments_response import ListAgentTestAttachmentsResponse -from .list_agent_test_folders_response import ListAgentTestFoldersResponse -from .list_agent_test_runs_response import ListAgentTestRunsResponse -from .list_agent_tests_response import ListAgentTestsResponse -from .list_agents_response import ListAgentsResponse -from .list_conversations_response import ListConversationsResponse -from .list_dynamic_variables_response import ListDynamicVariablesResponse -from .list_evaluations_response import ListEvaluationsResponse -from .list_knowledge_base_chunks_response import ListKnowledgeBaseChunksResponse -from .list_knowledge_base_documents_response import ListKnowledgeBaseDocumentsResponse -from .list_knowledge_bases_response import ListKnowledgeBasesResponse -from .list_memories_response import ListMemoriesResponse -from .list_messages_response import ListMessagesResponse -from .list_tests_response import ListTestsResponse -from .list_tools_response import ListToolsResponse -from .member import Member -from .member_role import MemberRole -from .members_list_response import MembersListResponse -from .memory import Memory -from .message import Message -from .message_role import MessageRole -from .mocking_strategy import MockingStrategy -from .nested_chunk import NestedChunk -from .no_match_behavior import NoMatchBehavior -from .o_auth_error import OAuthError -from .o_auth_error_error import OAuthErrorError -from .parameter_check import ParameterCheck -from .parameter_check_mode import ParameterCheckMode -from .parameter_check_result import ParameterCheckResult -from .run_agent_tests_response import RunAgentTestsResponse -from .run_batch_response import RunBatchResponse -from .scenario_config import ScenarioConfig -from .scenario_result import ScenarioResult -from .search_knowledge_bases_response import SearchKnowledgeBasesResponse -from .simulation_config import SimulationConfig -from .simulation_message import SimulationMessage -from .simulation_message_role import SimulationMessageRole -from .simulation_result import SimulationResult -from .simulation_tool_call import SimulationToolCall -from .speech_marks import SpeechMarks -from .system_tool_config import SystemToolConfig -from .system_tool_config_builtin import SystemToolConfigBuiltin -from .system_variable_doc import SystemVariableDoc -from .tenant import Tenant -from .tenant_data_region import TenantDataRegion -from .tenant_plan import TenantPlan -from .tenants_list_response import TenantsListResponse -from .test_run_result import TestRunResult -from .test_run_status import TestRunStatus -from .test_stats import TestStats -from .test_stats_bucket import TestStatsBucket -from .test_type import TestType -from .tool import Tool -from .tool_call_config import ToolCallConfig -from .tool_call_result import ToolCallResult -from .tool_config import ToolConfig -from .tool_kind import ToolKind -from .tool_mock import ToolMock -from .tool_mock_config import ToolMockConfig -from .tool_param import ToolParam -from .tool_param_type import ToolParamType -from .webhook_tool_config import WebhookToolConfig -from .webhook_tool_config_method import WebhookToolConfigMethod - -__all__ = [ - "AccessToken", - "AccessTokenScope", - "AccessTokenTokenType", - "Agent", - "AgentTest", - "AgentTestAttachment", - "AgentTestConfig", - "AgentTestFolder", - "AgentTestRun", - "AgentTestWithLastRun", - "ApiKey", - "BatchRunEntry", - "ClientToolConfig", - "Conversation", - "ConversationStats", - "ConversationStatus", - "ConversationTransport", - "CreateConversationResponse", - "CreateVoiceLanguage", - "CreateVoiceModel", - "CreateVoiceModelName", - "CreatedVoice", - "CreatedVoiceGender", - "CreatedVoiceType", - "DataCollectionField", - "DataCollectionFieldType", - "DeleteMemoriesByCallerResponse", - "DynamicVariable", - "DynamicVariableType", - "Evaluation", - "EvaluationConfig", - "EvaluationCriterion", - "EvaluationKind", - "EvaluationStatus", - "GetSpeechOptionsRequest", - "GetSpeechResponse", - "GetSpeechResponseAudioFormat", - "GetStreamOptionsRequest", - "GetVoice", - "GetVoiceGender", - "GetVoiceLanguage", - "GetVoiceType", - "GetVoicesModel", - "GetVoicesModelName", - "Invite", - "InvitePreview", - "InvitesListResponse", - "KnowledgeBase", - "KnowledgeBaseChunk", - "KnowledgeBaseDocument", - "KnowledgeBaseDocumentStatus", - "KnowledgeBaseSearchHit", - "ListAgentTestAttachmentsResponse", - "ListAgentTestFoldersResponse", - "ListAgentTestRunsResponse", - "ListAgentTestsResponse", - "ListAgentsResponse", - "ListConversationsResponse", - "ListDynamicVariablesResponse", - "ListEvaluationsResponse", - "ListKnowledgeBaseChunksResponse", - "ListKnowledgeBaseDocumentsResponse", - "ListKnowledgeBasesResponse", - "ListMemoriesResponse", - "ListMessagesResponse", - "ListTestsResponse", - "ListToolsResponse", - "Member", - "MemberRole", - "MembersListResponse", - "Memory", - "Message", - "MessageRole", - "MockingStrategy", - "NestedChunk", - "NoMatchBehavior", - "OAuthError", - "OAuthErrorError", - "ParameterCheck", - "ParameterCheckMode", - "ParameterCheckResult", - "RunAgentTestsResponse", - "RunBatchResponse", - "ScenarioConfig", - "ScenarioResult", - "SearchKnowledgeBasesResponse", - "SimulationConfig", - "SimulationMessage", - "SimulationMessageRole", - "SimulationResult", - "SimulationToolCall", - "SpeechMarks", - "SystemToolConfig", - "SystemToolConfigBuiltin", - "SystemVariableDoc", - "Tenant", - "TenantDataRegion", - "TenantPlan", - "TenantsListResponse", - "TestRunResult", - "TestRunStatus", - "TestStats", - "TestStatsBucket", - "TestType", - "Tool", - "ToolCallConfig", - "ToolCallResult", - "ToolConfig", - "ToolKind", - "ToolMock", - "ToolMockConfig", - "ToolParam", - "ToolParamType", - "WebhookToolConfig", - "WebhookToolConfigMethod", -] diff --git a/src/speechify/tts/types/access_token.py b/src/speechify/tts/types/access_token.py deleted file mode 100644 index 52dbb9d..0000000 --- a/src/speechify/tts/types/access_token.py +++ /dev/null @@ -1,35 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -import pydantic -from .access_token_scope import AccessTokenScope -from .access_token_token_type import AccessTokenTokenType -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class AccessToken(UniversalBaseModel): - access_token: typing.Optional[str] = None - expires_in: typing.Optional[int] = pydantic.Field(default=None) - """ - Expiration time, in seconds from the issue time - """ - - scope: typing.Optional[AccessTokenScope] = pydantic.Field(default=None) - """ - The scope, or a space-delimited list of scopes the token is issued for - """ - - token_type: typing.Optional[AccessTokenTokenType] = pydantic.Field(default=None) - """ - Token type - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/access_token_scope.py b/src/speechify/tts/types/access_token_scope.py deleted file mode 100644 index 73cae3b..0000000 --- a/src/speechify/tts/types/access_token_scope.py +++ /dev/null @@ -1,10 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -AccessTokenScope = typing.Union[ - typing.Literal[ - "audio:speech", "audio:stream", "audio:all", "voices:read", "voices:create", "voices:delete", "voices:all" - ], - typing.Any, -] diff --git a/src/speechify/tts/types/access_token_token_type.py b/src/speechify/tts/types/access_token_token_type.py deleted file mode 100644 index 065f512..0000000 --- a/src/speechify/tts/types/access_token_token_type.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -AccessTokenTokenType = typing.Union[typing.Literal["bearer"], typing.Any] diff --git a/src/speechify/tts/types/agent.py b/src/speechify/tts/types/agent.py deleted file mode 100644 index 13a28c4..0000000 --- a/src/speechify/tts/types/agent.py +++ /dev/null @@ -1,87 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -import pydantic -import datetime as dt -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class Agent(UniversalBaseModel): - id: str - name: str - slug: str - prompt: typing.Optional[str] = None - first_message: typing.Optional[str] = None - language: str = pydantic.Field() - """ - ISO 639-1 code, e.g. 'en'. - """ - - llm_model: str = pydantic.Field() - """ - Chat model slug. Leave empty to use the Speechify default. - """ - - voice_id: str = pydantic.Field() - """ - Speechify voice slug. - """ - - temperature: float - config: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None) - """ - Free-form agent config JSON (evaluation_config is read via its own endpoint). - """ - - is_public: bool = pydantic.Field() - """ - When true, the `` web component can start a - session against this agent without an API key, subject to - the `allowed_origins` allowlist. When false (default), only - authenticated callers can start sessions. - """ - - allowed_origins: typing.List[str] = pydantic.Field() - """ - Exact `Origin` header values (e.g. `https://example.com`) - that are allowed to start public sessions. Empty array - with `is_public = true` means any origin is accepted — - intended for open demos. No subdomain wildcards. - """ - - hostname_allowlist: typing.Optional[typing.List[str]] = pydantic.Field(default=None) - """ - Optional per-agent hostname allowlist enforced at - session-creation time. When set and non-empty, the - `Origin` header's hostname must be an exact member. - Bare hostnames only — no scheme, port, or path. Up to - 10 entries. Omit (null) or leave empty for no - enforcement (public agents accept any hostname). - """ - - memory_enabled: bool = pydantic.Field() - """ - When true, the post-call extractor writes durable facts about - each caller; at conversation-start the retriever injects the - top matches into the system prompt via the `{{memory}}` - template variable. Defaults to false. - """ - - memory_retention_days: int = pydantic.Field() - """ - Maximum age (in days) of memories kept and surfaced to the - retriever. 0 disables the cap. Defaults to 90. - """ - - created_at: dt.datetime - updated_at: dt.datetime - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/agent_test.py b/src/speechify/tts/types/agent_test.py deleted file mode 100644 index 9b7cf6c..0000000 --- a/src/speechify/tts/types/agent_test.py +++ /dev/null @@ -1,57 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -from .test_type import TestType -from .agent_test_config import AgentTestConfig -import pydantic -import typing -from .tool_mock_config import ToolMockConfig -import datetime as dt -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class AgentTest(UniversalBaseModel): - """ - A configured test against a voice agent. `config` is a - type-specific document - see `ScenarioConfig`, `ToolCallConfig`, - and `SimulationConfig` for the per-type shapes (discriminated by `type`). - """ - - id: str - agent_id: str - name: str - description: str - type: TestType - config: AgentTestConfig = pydantic.Field() - """ - Type-specific configuration document. - """ - - tool_mock_config: typing.Optional[ToolMockConfig] = pydantic.Field(default=None) - """ - Optional tool-mocking config applied during runs of this test. - """ - - variables: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None) - """ - Per-test dynamic-variable overrides. Keys substitute `{{key}}` - placeholders inside the test config at run-start. Unknown keys - render as empty string, matching session dispatch behaviour. - """ - - folder_id: typing.Optional[str] = pydantic.Field(default=None) - """ - Folder the test belongs to; null = root (unfiled). - """ - - created_at: dt.datetime - updated_at: dt.datetime - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/agent_test_attachment.py b/src/speechify/tts/types/agent_test_attachment.py deleted file mode 100644 index 3a1f30f..0000000 --- a/src/speechify/tts/types/agent_test_attachment.py +++ /dev/null @@ -1,26 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import datetime as dt -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import typing -import pydantic - - -class AgentTestAttachment(UniversalBaseModel): - """ - One (test, agent) pair. Poll the `attached_agent_ids` field on `AgentTestWithLastRun` or hit `/v1/tests/{id}/attachments` for the authoritative set. - """ - - test_id: str - agent_id: str - created_at: dt.datetime - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/agent_test_config.py b/src/speechify/tts/types/agent_test_config.py deleted file mode 100644 index d0ce190..0000000 --- a/src/speechify/tts/types/agent_test_config.py +++ /dev/null @@ -1,8 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing -from .scenario_config import ScenarioConfig -from .tool_call_config import ToolCallConfig -from .simulation_config import SimulationConfig - -AgentTestConfig = typing.Union[ScenarioConfig, ToolCallConfig, SimulationConfig] diff --git a/src/speechify/tts/types/agent_test_folder.py b/src/speechify/tts/types/agent_test_folder.py deleted file mode 100644 index 88cc31d..0000000 --- a/src/speechify/tts/types/agent_test_folder.py +++ /dev/null @@ -1,28 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -import datetime as dt -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic - - -class AgentTestFolder(UniversalBaseModel): - """ - One organisational node in the per-owner tests tree. - """ - - id: str - parent_folder_id: typing.Optional[str] = None - name: str - created_at: dt.datetime - updated_at: dt.datetime - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/agent_test_run.py b/src/speechify/tts/types/agent_test_run.py deleted file mode 100644 index 3f51754..0000000 --- a/src/speechify/tts/types/agent_test_run.py +++ /dev/null @@ -1,44 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -from .test_run_status import TestRunStatus -import typing -import datetime as dt -from .test_run_result import TestRunResult -import pydantic -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class AgentTestRun(UniversalBaseModel): - """ - One execution of a test. `result` is populated when `status` - reaches a terminal state (`passed`, `failed`, or `error`). - See `TestRunResult` for the shape. - """ - - id: str - test_id: str - agent_id: str - status: TestRunStatus - started_at: typing.Optional[dt.datetime] = None - completed_at: typing.Optional[dt.datetime] = None - result: typing.Optional[TestRunResult] = pydantic.Field(default=None) - """ - Populated on terminal status only. - """ - - error: typing.Optional[str] = pydantic.Field(default=None) - """ - Human-readable error message when status is `error`. - """ - - created_at: dt.datetime - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/agent_test_with_last_run.py b/src/speechify/tts/types/agent_test_with_last_run.py deleted file mode 100644 index cb22c0b..0000000 --- a/src/speechify/tts/types/agent_test_with_last_run.py +++ /dev/null @@ -1,36 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from .agent_test import AgentTest -import typing -from .agent_test_run import AgentTestRun -import pydantic -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class AgentTestWithLastRun(AgentTest): - """ - List-view projection of a test that includes the most recent run - so the console can display pass/fail badges without an extra - round-trip. On the global `/v1/tests` surface, also carries - `attached_agent_ids` so the row can render agent chips without a - follow-up request. - """ - - last_run: typing.Optional[AgentTestRun] = pydantic.Field(default=None) - """ - The most recent run, or null if the test has never been run. - """ - - attached_agent_ids: typing.Optional[typing.List[str]] = pydantic.Field(default=None) - """ - Every agent this test runs against. Always includes the owner agent. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/api_key.py b/src/speechify/tts/types/api_key.py deleted file mode 100644 index ce1b612..0000000 --- a/src/speechify/tts/types/api_key.py +++ /dev/null @@ -1,47 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -import pydantic -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class ApiKey(UniversalBaseModel): - api_key: typing.Optional[str] = pydantic.Field(default=None) - """ - API key - """ - - created_at: typing.Optional[int] = pydantic.Field(default=None) - """ - Creation time of the key - """ - - id: typing.Optional[int] = pydantic.Field(default=None) - """ - ID of the key - """ - - name: typing.Optional[str] = pydantic.Field(default=None) - """ - Name of the key - """ - - updated_at: typing.Optional[int] = pydantic.Field(default=None) - """ - Last updated time of the key - """ - - user_id: typing.Optional[str] = pydantic.Field(default=None) - """ - User ID to whom the key belongs - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/batch_run_entry.py b/src/speechify/tts/types/batch_run_entry.py deleted file mode 100644 index 7ba49b3..0000000 --- a/src/speechify/tts/types/batch_run_entry.py +++ /dev/null @@ -1,25 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic - - -class BatchRunEntry(UniversalBaseModel): - """ - One entry in a batch-run request. Omit `agent_id` to fan out to - every agent the test is attached to. - """ - - test_id: str - agent_id: typing.Optional[str] = None - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/client_tool_config.py b/src/speechify/tts/types/client_tool_config.py deleted file mode 100644 index 5966aaa..0000000 --- a/src/speechify/tts/types/client_tool_config.py +++ /dev/null @@ -1,25 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from .tool_param import ToolParam -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic - - -class ClientToolConfig(UniversalBaseModel): - """ - Config shape for `kind=client`. Execution happens in the caller's browser / SDK. - """ - - params: typing.Optional[typing.List[ToolParam]] = None - timeout_ms: typing.Optional[int] = None - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/conversation.py b/src/speechify/tts/types/conversation.py deleted file mode 100644 index e198694..0000000 --- a/src/speechify/tts/types/conversation.py +++ /dev/null @@ -1,40 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from .conversation_status import ConversationStatus -from .conversation_transport import ConversationTransport -import datetime as dt -import pydantic -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class Conversation(UniversalBaseModel): - id: str - agent_id: str - room_name: str - room_sid: typing.Optional[str] = None - status: ConversationStatus - transport: ConversationTransport - started_at: typing.Optional[dt.datetime] = pydantic.Field(default=None) - """ - Set when the first user participant joins the realtime - voice session. Null between CreateConversation and the - participant-joined event, and stays null if no user ever - joins. - """ - - ended_at: typing.Optional[dt.datetime] = None - duration_ms: typing.Optional[int] = None - cost_cents: typing.Optional[int] = None - recording_url: typing.Optional[str] = None - metadata: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/conversation_stats.py b/src/speechify/tts/types/conversation_stats.py deleted file mode 100644 index 011243f..0000000 --- a/src/speechify/tts/types/conversation_stats.py +++ /dev/null @@ -1,29 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic - - -class ConversationStats(UniversalBaseModel): - """ - Counts + averages over the caller's conversations matching the supplied filters. AVG fields are null when no rows match the FILTER predicate. - """ - - total: int - completed: int - failed: int - active: int - pending: int - avg_duration_ms: typing.Optional[float] = None - avg_cost_cents: typing.Optional[float] = None - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/conversation_status.py b/src/speechify/tts/types/conversation_status.py deleted file mode 100644 index 7b121bf..0000000 --- a/src/speechify/tts/types/conversation_status.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -ConversationStatus = typing.Union[typing.Literal["pending", "active", "completed", "failed"], typing.Any] diff --git a/src/speechify/tts/types/conversation_transport.py b/src/speechify/tts/types/conversation_transport.py deleted file mode 100644 index 4451eb9..0000000 --- a/src/speechify/tts/types/conversation_transport.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -ConversationTransport = typing.Union[typing.Literal["web", "sip"], typing.Any] diff --git a/src/speechify/tts/types/create_conversation_response.py b/src/speechify/tts/types/create_conversation_response.py deleted file mode 100644 index cc53806..0000000 --- a/src/speechify/tts/types/create_conversation_response.py +++ /dev/null @@ -1,37 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -from .conversation import Conversation -import pydantic -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import typing - - -class CreateConversationResponse(UniversalBaseModel): - """ - Returned when a conversation is created. The `token` + `url` - let the caller connect its browser/SDK directly to the - realtime voice session — the agent that answers is dispatched - server-side. - """ - - conversation: Conversation - room: str - token: str = pydantic.Field() - """ - Short-lived realtime session access token (JWT). - """ - - url: str = pydantic.Field() - """ - Realtime session wss:// URL to connect to. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/create_voice_model_name.py b/src/speechify/tts/types/create_voice_model_name.py deleted file mode 100644 index 34c21b3..0000000 --- a/src/speechify/tts/types/create_voice_model_name.py +++ /dev/null @@ -1,7 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -CreateVoiceModelName = typing.Union[ - typing.Literal["simba-base", "simba-english", "simba-multilingual", "simba-turbo", "simba-3.0"], typing.Any -] diff --git a/src/speechify/tts/types/data_collection_field.py b/src/speechify/tts/types/data_collection_field.py deleted file mode 100644 index 1f55f6b..0000000 --- a/src/speechify/tts/types/data_collection_field.py +++ /dev/null @@ -1,28 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -from .data_collection_field_type import DataCollectionFieldType -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import typing -import pydantic - - -class DataCollectionField(UniversalBaseModel): - """ - A structured value the post-call evaluator should extract from the - transcript. `int` is distinct from `number` so downstream consumers - receive whole integers without a synthetic decimal. - """ - - key: str - description: str - type: DataCollectionFieldType - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/data_collection_field_type.py b/src/speechify/tts/types/data_collection_field_type.py deleted file mode 100644 index b9a1a96..0000000 --- a/src/speechify/tts/types/data_collection_field_type.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -DataCollectionFieldType = typing.Union[typing.Literal["string", "int", "number", "boolean"], typing.Any] diff --git a/src/speechify/tts/types/delete_memories_by_caller_response.py b/src/speechify/tts/types/delete_memories_by_caller_response.py deleted file mode 100644 index f7fdf5b..0000000 --- a/src/speechify/tts/types/delete_memories_by_caller_response.py +++ /dev/null @@ -1,22 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import pydantic -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import typing - - -class DeleteMemoriesByCallerResponse(UniversalBaseModel): - deleted: int = pydantic.Field() - """ - Number of memories soft-deleted. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/dynamic_variable.py b/src/speechify/tts/types/dynamic_variable.py deleted file mode 100644 index aab728b..0000000 --- a/src/speechify/tts/types/dynamic_variable.py +++ /dev/null @@ -1,43 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import pydantic -from .dynamic_variable_type import DynamicVariableType -import typing -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class DynamicVariable(UniversalBaseModel): - """ - One customer-scope variable definition on an agent. Referenced in - prompts, first messages, and webhook tool configs via `{{key}}` or - `{{key|json}}`. Missing variables render as empty string at dispatch - time - a typo never breaks a session. - """ - - key: str = pydantic.Field() - """ - Variable name. Must match `[a-zA-Z0-9_]+`. The `system__` prefix - is reserved for platform-populated variables and will be rejected. - """ - - type: DynamicVariableType - default: typing.Optional[typing.Optional[typing.Any]] = pydantic.Field(default=None) - """ - Optional default value used when no per-session override is - supplied. Must conform to the declared `type`. - """ - - description: typing.Optional[str] = pydantic.Field(default=None) - """ - Human-readable note shown in the console variable editor. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/dynamic_variable_type.py b/src/speechify/tts/types/dynamic_variable_type.py deleted file mode 100644 index d12f3f8..0000000 --- a/src/speechify/tts/types/dynamic_variable_type.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -DynamicVariableType = typing.Union[typing.Literal["string", "number", "boolean", "json"], typing.Any] diff --git a/src/speechify/tts/types/evaluation.py b/src/speechify/tts/types/evaluation.py deleted file mode 100644 index 06414f1..0000000 --- a/src/speechify/tts/types/evaluation.py +++ /dev/null @@ -1,51 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -from .evaluation_kind import EvaluationKind -import typing -from .evaluation_status import EvaluationStatus -import pydantic -import datetime as dt -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class Evaluation(UniversalBaseModel): - """ - Three flavours coexist, discriminated by `kind`: - - `criterion` rows carry `status` + `passed` + `score` + `rationale` for one criterion - - `summary` row carries overall sentiment + rationale in `rationale` - - `data` row carries the structured data-collection payload in `data` - - `status` is the canonical three-state result. `passed` is a - derived boolean kept for backwards compatibility with earlier - webhook consumers: success→true, failure→false, unknown→null. - """ - - id: str - conversation_id: str - kind: EvaluationKind - criterion_id: typing.Optional[str] = None - name: str - status: typing.Optional[EvaluationStatus] = pydantic.Field(default=None) - """ - Three-state criterion result. `unknown` means the criterion did not apply to this call. - """ - - passed: typing.Optional[bool] = None - score: typing.Optional[float] = None - rationale: str - data: typing.Optional[typing.Optional[typing.Any]] = pydantic.Field(default=None) - """ - Structured data-collection payload (present only on `kind=data` rows). - """ - - created_at: dt.datetime - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/evaluation_config.py b/src/speechify/tts/types/evaluation_config.py deleted file mode 100644 index cc757ed..0000000 --- a/src/speechify/tts/types/evaluation_config.py +++ /dev/null @@ -1,22 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from .evaluation_criterion import EvaluationCriterion -from .data_collection_field import DataCollectionField -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic - - -class EvaluationConfig(UniversalBaseModel): - criteria: typing.List[EvaluationCriterion] - data_collection: typing.List[DataCollectionField] - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/evaluation_criterion.py b/src/speechify/tts/types/evaluation_criterion.py deleted file mode 100644 index 235443b..0000000 --- a/src/speechify/tts/types/evaluation_criterion.py +++ /dev/null @@ -1,25 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import typing -import pydantic - - -class EvaluationCriterion(UniversalBaseModel): - """ - One LLM-scored assertion about the call ("Did the agent confirm the customer's name?"). - """ - - id: str - name: str - description: str - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/evaluation_kind.py b/src/speechify/tts/types/evaluation_kind.py deleted file mode 100644 index 8c1feac..0000000 --- a/src/speechify/tts/types/evaluation_kind.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -EvaluationKind = typing.Union[typing.Literal["criterion", "summary", "data"], typing.Any] diff --git a/src/speechify/tts/types/evaluation_status.py b/src/speechify/tts/types/evaluation_status.py deleted file mode 100644 index 9af14a4..0000000 --- a/src/speechify/tts/types/evaluation_status.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -EvaluationStatus = typing.Union[typing.Literal["success", "failure", "unknown"], typing.Any] diff --git a/src/speechify/tts/types/get_voices_model_name.py b/src/speechify/tts/types/get_voices_model_name.py deleted file mode 100644 index 121de6e..0000000 --- a/src/speechify/tts/types/get_voices_model_name.py +++ /dev/null @@ -1,7 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -GetVoicesModelName = typing.Union[ - typing.Literal["simba-base", "simba-english", "simba-multilingual", "simba-turbo"], typing.Any -] diff --git a/src/speechify/tts/types/invite.py b/src/speechify/tts/types/invite.py deleted file mode 100644 index 3314199..0000000 --- a/src/speechify/tts/types/invite.py +++ /dev/null @@ -1,56 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import pydantic -import datetime as dt -import typing -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class Invite(UniversalBaseModel): - """ - A pending or historical workspace invite. - """ - - id: str = pydantic.Field() - """ - Opaque invite ID. - """ - - email: str = pydantic.Field() - """ - Invitee email. - """ - - invited_by: str = pydantic.Field() - """ - Firebase UID of the member who created the invite. - """ - - created_at: dt.datetime - expires_at: dt.datetime - accepted_at: typing.Optional[dt.datetime] = pydantic.Field(default=None) - """ - Populated once the invite has been accepted. - """ - - revoked_at: typing.Optional[dt.datetime] = pydantic.Field(default=None) - """ - Populated once the invite has been revoked. - """ - - token: typing.Optional[str] = pydantic.Field(default=None) - """ - Invite token. Returned ONLY on the create-invite response; - subsequent list calls redact it. Use the token to build the - `/join/{token}` join URL. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/invite_preview.py b/src/speechify/tts/types/invite_preview.py deleted file mode 100644 index 0a9d2ca..0000000 --- a/src/speechify/tts/types/invite_preview.py +++ /dev/null @@ -1,54 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import pydantic -import typing -import datetime as dt -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class InvitePreview(UniversalBaseModel): - """ - Unauthenticated preview of a workspace invite. Surfaces only what - the recipient needs to decide whether to accept (workspace name, - invited address, inviter, expiry). Billing, plan, data region, - and invite token are deliberately omitted. - """ - - tenant_id: str = pydantic.Field() - """ - Opaque workspace id. Safe to echo back on the accept call. - """ - - tenant_name: str = pydantic.Field() - """ - Workspace display name. - """ - - invited_email: str = pydantic.Field() - """ - The email address the inviter typed when creating the invite. - """ - - invited_by_email: typing.Optional[str] = pydantic.Field(default=None) - """ - Firebase email of the member who created the invite. May be - absent if the Firebase profile lookup failed transiently — - clients should still render the preview in that case. - """ - - invited_by_display_name: typing.Optional[str] = pydantic.Field(default=None) - """ - Firebase display name of the member who created the invite. - """ - - expires_at: dt.datetime - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/invites_list_response.py b/src/speechify/tts/types/invites_list_response.py deleted file mode 100644 index 640fcc9..0000000 --- a/src/speechify/tts/types/invites_list_response.py +++ /dev/null @@ -1,20 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from .invite import Invite -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic - - -class InvitesListResponse(UniversalBaseModel): - invites: typing.List[Invite] - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/knowledge_base.py b/src/speechify/tts/types/knowledge_base.py deleted file mode 100644 index 55add05..0000000 --- a/src/speechify/tts/types/knowledge_base.py +++ /dev/null @@ -1,43 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import pydantic -import datetime as dt -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import typing - - -class KnowledgeBase(UniversalBaseModel): - """ - A bundle of documents that can be attached to one or more voice - agents. Chunks across every document in the knowledge base are - embedded and searched together. - """ - - id: str - name: str = pydantic.Field() - """ - Human-readable label, shown in the console. - """ - - description: str = pydantic.Field() - """ - Optional description. - """ - - document_count: int = pydantic.Field() - """ - Number of ingested documents. - """ - - created_at: dt.datetime - updated_at: dt.datetime - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/knowledge_base_chunk.py b/src/speechify/tts/types/knowledge_base_chunk.py deleted file mode 100644 index c0e2081..0000000 --- a/src/speechify/tts/types/knowledge_base_chunk.py +++ /dev/null @@ -1,23 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import typing -import pydantic - - -class KnowledgeBaseChunk(UniversalBaseModel): - id: str - document_id: str - kb_id: str - chunk_index: int - content: str - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/knowledge_base_document.py b/src/speechify/tts/types/knowledge_base_document.py deleted file mode 100644 index bcf1ae3..0000000 --- a/src/speechify/tts/types/knowledge_base_document.py +++ /dev/null @@ -1,35 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -from .knowledge_base_document_status import KnowledgeBaseDocumentStatus -import typing -import pydantic -import datetime as dt -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class KnowledgeBaseDocument(UniversalBaseModel): - id: str - kb_id: str - filename: str - content_type: str - byte_size: int - char_count: int - chunk_count: int - status: KnowledgeBaseDocumentStatus - error: typing.Optional[str] = pydantic.Field(default=None) - """ - Populated when status is failed. - """ - - created_at: dt.datetime - updated_at: dt.datetime - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/knowledge_base_document_status.py b/src/speechify/tts/types/knowledge_base_document_status.py deleted file mode 100644 index 35fb962..0000000 --- a/src/speechify/tts/types/knowledge_base_document_status.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -KnowledgeBaseDocumentStatus = typing.Union[typing.Literal["embedding", "ready", "failed"], typing.Any] diff --git a/src/speechify/tts/types/knowledge_base_search_hit.py b/src/speechify/tts/types/knowledge_base_search_hit.py deleted file mode 100644 index 4422827..0000000 --- a/src/speechify/tts/types/knowledge_base_search_hit.py +++ /dev/null @@ -1,28 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import pydantic -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import typing - - -class KnowledgeBaseSearchHit(UniversalBaseModel): - chunk_id: str - document_id: str - kb_id: str - filename: str - chunk_index: int - content: str - score: float = pydantic.Field() - """ - Cosine similarity (higher = more relevant). - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/list_agent_test_attachments_response.py b/src/speechify/tts/types/list_agent_test_attachments_response.py deleted file mode 100644 index 0f4287a..0000000 --- a/src/speechify/tts/types/list_agent_test_attachments_response.py +++ /dev/null @@ -1,20 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from .agent_test_attachment import AgentTestAttachment -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic - - -class ListAgentTestAttachmentsResponse(UniversalBaseModel): - attachments: typing.List[AgentTestAttachment] - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/list_agent_test_folders_response.py b/src/speechify/tts/types/list_agent_test_folders_response.py deleted file mode 100644 index 553d728..0000000 --- a/src/speechify/tts/types/list_agent_test_folders_response.py +++ /dev/null @@ -1,20 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from .agent_test_folder import AgentTestFolder -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic - - -class ListAgentTestFoldersResponse(UniversalBaseModel): - folders: typing.List[AgentTestFolder] - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/list_agent_test_runs_response.py b/src/speechify/tts/types/list_agent_test_runs_response.py deleted file mode 100644 index 27c484b..0000000 --- a/src/speechify/tts/types/list_agent_test_runs_response.py +++ /dev/null @@ -1,20 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from .agent_test_run import AgentTestRun -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic - - -class ListAgentTestRunsResponse(UniversalBaseModel): - runs: typing.List[AgentTestRun] - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/list_agent_tests_response.py b/src/speechify/tts/types/list_agent_tests_response.py deleted file mode 100644 index 41e6bdd..0000000 --- a/src/speechify/tts/types/list_agent_tests_response.py +++ /dev/null @@ -1,20 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from .agent_test_with_last_run import AgentTestWithLastRun -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic - - -class ListAgentTestsResponse(UniversalBaseModel): - tests: typing.List[AgentTestWithLastRun] - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/list_agents_response.py b/src/speechify/tts/types/list_agents_response.py deleted file mode 100644 index 757f14d..0000000 --- a/src/speechify/tts/types/list_agents_response.py +++ /dev/null @@ -1,20 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from .agent import Agent -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic - - -class ListAgentsResponse(UniversalBaseModel): - agents: typing.List[Agent] - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/list_conversations_response.py b/src/speechify/tts/types/list_conversations_response.py deleted file mode 100644 index 79c0d2a..0000000 --- a/src/speechify/tts/types/list_conversations_response.py +++ /dev/null @@ -1,20 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from .conversation import Conversation -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic - - -class ListConversationsResponse(UniversalBaseModel): - conversations: typing.List[Conversation] - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/list_dynamic_variables_response.py b/src/speechify/tts/types/list_dynamic_variables_response.py deleted file mode 100644 index 2cf72f8..0000000 --- a/src/speechify/tts/types/list_dynamic_variables_response.py +++ /dev/null @@ -1,36 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from .dynamic_variable import DynamicVariable -import pydantic -from .system_variable_doc import SystemVariableDoc -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class ListDynamicVariablesResponse(UniversalBaseModel): - """ - Response for `GET /v1/agents/{id}/variables`. Returns both the - customer-scope variable catalogue and the read-only `system__*` - catalogue so the editor UI has a single source of truth. - """ - - variables: typing.List[DynamicVariable] = pydantic.Field() - """ - Customer-defined variables for this agent. - """ - - system_variables: typing.List[SystemVariableDoc] = pydantic.Field() - """ - Platform-populated `system__*` variables, provided for - reference. This list is the same for every agent. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/list_evaluations_response.py b/src/speechify/tts/types/list_evaluations_response.py deleted file mode 100644 index 79d9b91..0000000 --- a/src/speechify/tts/types/list_evaluations_response.py +++ /dev/null @@ -1,20 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from .evaluation import Evaluation -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic - - -class ListEvaluationsResponse(UniversalBaseModel): - evaluations: typing.List[Evaluation] - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/list_knowledge_base_chunks_response.py b/src/speechify/tts/types/list_knowledge_base_chunks_response.py deleted file mode 100644 index 9324636..0000000 --- a/src/speechify/tts/types/list_knowledge_base_chunks_response.py +++ /dev/null @@ -1,20 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from .knowledge_base_chunk import KnowledgeBaseChunk -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic - - -class ListKnowledgeBaseChunksResponse(UniversalBaseModel): - chunks: typing.List[KnowledgeBaseChunk] - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/list_knowledge_base_documents_response.py b/src/speechify/tts/types/list_knowledge_base_documents_response.py deleted file mode 100644 index 15d69ed..0000000 --- a/src/speechify/tts/types/list_knowledge_base_documents_response.py +++ /dev/null @@ -1,20 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from .knowledge_base_document import KnowledgeBaseDocument -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic - - -class ListKnowledgeBaseDocumentsResponse(UniversalBaseModel): - documents: typing.List[KnowledgeBaseDocument] - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/list_knowledge_bases_response.py b/src/speechify/tts/types/list_knowledge_bases_response.py deleted file mode 100644 index acb38d7..0000000 --- a/src/speechify/tts/types/list_knowledge_bases_response.py +++ /dev/null @@ -1,20 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from .knowledge_base import KnowledgeBase -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic - - -class ListKnowledgeBasesResponse(UniversalBaseModel): - knowledge_bases: typing.List[KnowledgeBase] - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/list_memories_response.py b/src/speechify/tts/types/list_memories_response.py deleted file mode 100644 index 79b426b..0000000 --- a/src/speechify/tts/types/list_memories_response.py +++ /dev/null @@ -1,20 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from .memory import Memory -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic - - -class ListMemoriesResponse(UniversalBaseModel): - memories: typing.List[Memory] - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/list_messages_response.py b/src/speechify/tts/types/list_messages_response.py deleted file mode 100644 index 1a71747..0000000 --- a/src/speechify/tts/types/list_messages_response.py +++ /dev/null @@ -1,20 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from .message import Message -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic - - -class ListMessagesResponse(UniversalBaseModel): - messages: typing.List[Message] - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/list_tests_response.py b/src/speechify/tts/types/list_tests_response.py deleted file mode 100644 index 144048b..0000000 --- a/src/speechify/tts/types/list_tests_response.py +++ /dev/null @@ -1,27 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from .agent_test_with_last_run import AgentTestWithLastRun -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic - - -class ListTestsResponse(UniversalBaseModel): - """ - Workspace-wide paginated list of tests. `next_cursor` is the opaque - page cursor; omit on the first call, then pass through to get the - next page until the field is absent. - """ - - tests: typing.List[AgentTestWithLastRun] - next_cursor: typing.Optional[str] = None - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/list_tools_response.py b/src/speechify/tts/types/list_tools_response.py deleted file mode 100644 index bb7bb05..0000000 --- a/src/speechify/tts/types/list_tools_response.py +++ /dev/null @@ -1,20 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from .tool import Tool -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic - - -class ListToolsResponse(UniversalBaseModel): - tools: typing.List[Tool] - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/member.py b/src/speechify/tts/types/member.py deleted file mode 100644 index 158f541..0000000 --- a/src/speechify/tts/types/member.py +++ /dev/null @@ -1,49 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import pydantic -import typing -from .member_role import MemberRole -import datetime as dt -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class Member(UniversalBaseModel): - """ - A member of a workspace (joined from `tenant_users` + Firebase profile). - """ - - user_uid: str = pydantic.Field() - """ - Firebase user ID. - """ - - email: typing.Optional[str] = pydantic.Field(default=None) - """ - Member's email from Firebase. Empty when the account has been deleted. - """ - - display_name: typing.Optional[str] = pydantic.Field(default=None) - """ - Member's display name from Firebase. - """ - - role: MemberRole - created_at: dt.datetime = pydantic.Field() - """ - When the user joined the workspace. - """ - - is_self: bool = pydantic.Field() - """ - True when this row is the authenticated caller. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/member_role.py b/src/speechify/tts/types/member_role.py deleted file mode 100644 index 13def0f..0000000 --- a/src/speechify/tts/types/member_role.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -MemberRole = typing.Union[typing.Literal["owner", "admin", "member"], typing.Any] diff --git a/src/speechify/tts/types/members_list_response.py b/src/speechify/tts/types/members_list_response.py deleted file mode 100644 index 819d86d..0000000 --- a/src/speechify/tts/types/members_list_response.py +++ /dev/null @@ -1,20 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from .member import Member -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic - - -class MembersListResponse(UniversalBaseModel): - members: typing.List[Member] - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/memory.py b/src/speechify/tts/types/memory.py deleted file mode 100644 index 373c863..0000000 --- a/src/speechify/tts/types/memory.py +++ /dev/null @@ -1,54 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import pydantic -import typing -import datetime as dt -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class Memory(UniversalBaseModel): - """ - One salient fact extracted post-call about a specific caller on - a specific agent. Retrieved at the next conversation-start for - the same caller and injected into the agent's system prompt via - the `{{memory}}` template variable. - """ - - id: str - agent_id: str - caller_identity: str = pydantic.Field() - """ - Stable caller key (LiveKit participant identity) the memory is scoped to. - """ - - fact: str = pydantic.Field() - """ - Short third-person statement about the caller. - """ - - source_conversation_id: typing.Optional[str] = pydantic.Field(default=None) - """ - Conversation the memory was extracted from (may be empty if the source was deleted). - """ - - confidence: float = pydantic.Field() - """ - LLM self-reported 0-1 confidence in the fact's durability and relevance. - """ - - score: typing.Optional[float] = pydantic.Field(default=None) - """ - Populated only on retrieval hits — recency-weighted cosine similarity. - """ - - created_at: dt.datetime - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/message.py b/src/speechify/tts/types/message.py deleted file mode 100644 index 2112717..0000000 --- a/src/speechify/tts/types/message.py +++ /dev/null @@ -1,33 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -from .message_role import MessageRole -import typing -import pydantic -import datetime as dt -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class Message(UniversalBaseModel): - id: str - conversation_id: str - role: MessageRole - content: str - tool_name: typing.Optional[str] = None - tool_args: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None - tool_result: typing.Optional[typing.Optional[typing.Any]] = pydantic.Field(default=None) - """ - Arbitrary JSON value returned by the tool (object, array, string, or primitive). - """ - - started_at: dt.datetime - ended_at: typing.Optional[dt.datetime] = None - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/message_role.py b/src/speechify/tts/types/message_role.py deleted file mode 100644 index decda98..0000000 --- a/src/speechify/tts/types/message_role.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -MessageRole = typing.Union[typing.Literal["user", "assistant", "system", "tool"], typing.Any] diff --git a/src/speechify/tts/types/mocking_strategy.py b/src/speechify/tts/types/mocking_strategy.py deleted file mode 100644 index 344c9be..0000000 --- a/src/speechify/tts/types/mocking_strategy.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -MockingStrategy = typing.Union[typing.Literal["none", "all", "selected"], typing.Any] diff --git a/src/speechify/tts/types/no_match_behavior.py b/src/speechify/tts/types/no_match_behavior.py deleted file mode 100644 index 29c5374..0000000 --- a/src/speechify/tts/types/no_match_behavior.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -NoMatchBehavior = typing.Union[typing.Literal["call_real_tool", "finish_with_error", "skip"], typing.Any] diff --git a/src/speechify/tts/types/o_auth_error.py b/src/speechify/tts/types/o_auth_error.py deleted file mode 100644 index 8eaf2b7..0000000 --- a/src/speechify/tts/types/o_auth_error.py +++ /dev/null @@ -1,21 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from .o_auth_error_error import OAuthErrorError -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic - - -class OAuthError(UniversalBaseModel): - error: typing.Optional[OAuthErrorError] = None - error_description: typing.Optional[str] = None - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/o_auth_error_error.py b/src/speechify/tts/types/o_auth_error_error.py deleted file mode 100644 index 3dcbfaf..0000000 --- a/src/speechify/tts/types/o_auth_error_error.py +++ /dev/null @@ -1,10 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -OAuthErrorError = typing.Union[ - typing.Literal[ - "invalid_client", "unauthorized_client", "invalid_request", "unsupported_grant_type", "invalid_scope" - ], - typing.Any, -] diff --git a/src/speechify/tts/types/parameter_check.py b/src/speechify/tts/types/parameter_check.py deleted file mode 100644 index 773a769..0000000 --- a/src/speechify/tts/types/parameter_check.py +++ /dev/null @@ -1,41 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import pydantic -from .parameter_check_mode import ParameterCheckMode -import typing -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class ParameterCheck(UniversalBaseModel): - """ - Validates one argument of an expected tool call. `path` is a - dotted JSON path (e.g. `customer.email`); use zero-indexed - notation for arrays (`items.0.sku`). An empty path checks the - whole args object. - """ - - path: str = pydantic.Field() - """ - Dotted JSON path to the argument being checked. Empty means the whole args object. - """ - - mode: ParameterCheckMode - expected: typing.Optional[str] = pydantic.Field(default=None) - """ - Expected value string for `exact` and `regex` modes. - """ - - criteria: typing.Optional[str] = pydantic.Field(default=None) - """ - Natural-language criteria for `llm` mode (e.g. "is a valid email address"). - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/parameter_check_mode.py b/src/speechify/tts/types/parameter_check_mode.py deleted file mode 100644 index 27c6567..0000000 --- a/src/speechify/tts/types/parameter_check_mode.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -ParameterCheckMode = typing.Union[typing.Literal["exact", "regex", "llm"], typing.Any] diff --git a/src/speechify/tts/types/parameter_check_result.py b/src/speechify/tts/types/parameter_check_result.py deleted file mode 100644 index 7300a18..0000000 --- a/src/speechify/tts/types/parameter_check_result.py +++ /dev/null @@ -1,35 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -from .parameter_check_mode import ParameterCheckMode -import pydantic -import typing -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class ParameterCheckResult(UniversalBaseModel): - """ - Result of one `ParameterCheck` within a tool-call test run. - """ - - path: str - mode: ParameterCheckMode - actual_json: str = pydantic.Field() - """ - JSON-serialised actual value at `path`. - """ - - passed: bool - rationale: typing.Optional[str] = pydantic.Field(default=None) - """ - LLM rationale (populated for `llm` mode checks). - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/run_agent_tests_response.py b/src/speechify/tts/types/run_agent_tests_response.py deleted file mode 100644 index eddb061..0000000 --- a/src/speechify/tts/types/run_agent_tests_response.py +++ /dev/null @@ -1,26 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from .agent_test_run import AgentTestRun -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic - - -class RunAgentTestsResponse(UniversalBaseModel): - """ - Response from `POST /v1/agents/{id}/tests/runs`. Contains every - newly-queued run so the client can poll each for completion. - Capped at 50 runs per call. - """ - - runs: typing.List[AgentTestRun] - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/run_batch_response.py b/src/speechify/tts/types/run_batch_response.py deleted file mode 100644 index 77d0bd6..0000000 --- a/src/speechify/tts/types/run_batch_response.py +++ /dev/null @@ -1,20 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from .agent_test_run import AgentTestRun -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic - - -class RunBatchResponse(UniversalBaseModel): - runs: typing.List[AgentTestRun] - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/scenario_config.py b/src/speechify/tts/types/scenario_config.py deleted file mode 100644 index 9681422..0000000 --- a/src/speechify/tts/types/scenario_config.py +++ /dev/null @@ -1,68 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -import pydantic -from .simulation_message import SimulationMessage -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class ScenarioConfig(UniversalBaseModel): - """ - Configuration for a `scenario` test. The runner sends `context` as - a user message and asks an LLM judge to evaluate the agent response - against `success_criteria`. Optional few-shot examples sharpen the - judge's calibration. Use `initial_chat_history` to prepend prior - turns before `context`; when the history already ends with a user - message, `context` may be omitted and the agent is evaluated on - its reply to that last history turn. - """ - - context: typing.Optional[str] = pydantic.Field(default=None) - """ - User message sent to the agent to trigger the behaviour under test. Optional when `initial_chat_history` already ends with a user message. - """ - - success_criteria: str = pydantic.Field() - """ - Natural-language description of what a passing agent response looks like. - """ - - success_examples: typing.Optional[typing.List[str]] = pydantic.Field(default=None) - """ - Concrete examples of passing responses (few-shot for the judge). - """ - - failure_examples: typing.Optional[typing.List[str]] = pydantic.Field(default=None) - """ - Concrete examples of failing responses (few-shot for the judge). - """ - - initial_chat_history: typing.Optional[typing.List[SimulationMessage]] = pydantic.Field(default=None) - """ - Optional seed conversation prepended before `context`. Lets you test the agent's reply mid-conversation rather than on a cold single-turn prompt. - """ - - system_prompt_override: typing.Optional[str] = pydantic.Field(default=None) - """ - Replaces the agent's system prompt for this run only. Useful for regression-isolating prompt changes. - """ - - first_message_override: typing.Optional[str] = pydantic.Field(default=None) - """ - Replaces the agent's first message for this run only. - """ - - model_override: typing.Optional[str] = pydantic.Field(default=None) - """ - Overrides the LLM model used by the agent for this run only. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/scenario_result.py b/src/speechify/tts/types/scenario_result.py deleted file mode 100644 index c3ee1c5..0000000 --- a/src/speechify/tts/types/scenario_result.py +++ /dev/null @@ -1,42 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import pydantic -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import typing - - -class ScenarioResult(UniversalBaseModel): - """ - Result details for a `scenario` test run. - """ - - agent_response: str = pydantic.Field() - """ - The raw text response the agent produced. - """ - - passed: bool - rationale: str = pydantic.Field() - """ - LLM judge's explanation of the verdict. - """ - - score: float = pydantic.Field() - """ - 0-1 judge confidence score. - """ - - duration_ms: int = pydantic.Field() - """ - Wall-clock time for the run in milliseconds. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/search_knowledge_bases_response.py b/src/speechify/tts/types/search_knowledge_bases_response.py deleted file mode 100644 index 14d3769..0000000 --- a/src/speechify/tts/types/search_knowledge_bases_response.py +++ /dev/null @@ -1,20 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from .knowledge_base_search_hit import KnowledgeBaseSearchHit -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic - - -class SearchKnowledgeBasesResponse(UniversalBaseModel): - hits: typing.List[KnowledgeBaseSearchHit] - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/simulation_config.py b/src/speechify/tts/types/simulation_config.py deleted file mode 100644 index d2a7b38..0000000 --- a/src/speechify/tts/types/simulation_config.py +++ /dev/null @@ -1,57 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import pydantic -import typing -from .simulation_message import SimulationMessage -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class SimulationConfig(UniversalBaseModel): - """ - Configuration for a `simulation` test. An AI caller drives a - multi-turn conversation with the agent according to `scenario`. - After `max_turns` exchanges (or when the agent ends the call), an - LLM judge evaluates whether `success_condition` was met. - Use `initial_chat_history` to seed the conversation at a specific - mid-flow state. - """ - - scenario: str = pydantic.Field() - """ - Instructions for the AI caller describing who they are and what they want. - """ - - success_condition: str = pydantic.Field() - """ - Natural-language description of what a passing conversation looks like. - """ - - max_turns: int = pydantic.Field() - """ - Maximum agent turns before the simulation is cut off and judged. - """ - - initial_chat_history: typing.Optional[typing.List[SimulationMessage]] = pydantic.Field(default=None) - """ - Optional seed conversation that precedes the AI caller's first generated message. - """ - - system_prompt_override: typing.Optional[str] = pydantic.Field(default=None) - """ - Replaces the agent's system prompt for this run only. - """ - - model_override: typing.Optional[str] = pydantic.Field(default=None) - """ - Overrides the LLM model used by the agent for this run only. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/simulation_message.py b/src/speechify/tts/types/simulation_message.py deleted file mode 100644 index ffb0c0e..0000000 --- a/src/speechify/tts/types/simulation_message.py +++ /dev/null @@ -1,25 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -from .simulation_message_role import SimulationMessageRole -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import typing -import pydantic - - -class SimulationMessage(UniversalBaseModel): - """ - One turn in a simulation conversation. `role` is `user` (the AI caller) or `assistant` (the agent). - """ - - role: SimulationMessageRole - content: str - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/simulation_message_role.py b/src/speechify/tts/types/simulation_message_role.py deleted file mode 100644 index 106ec8f..0000000 --- a/src/speechify/tts/types/simulation_message_role.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -SimulationMessageRole = typing.Union[typing.Literal["user", "assistant"], typing.Any] diff --git a/src/speechify/tts/types/simulation_result.py b/src/speechify/tts/types/simulation_result.py deleted file mode 100644 index a6bfb42..0000000 --- a/src/speechify/tts/types/simulation_result.py +++ /dev/null @@ -1,46 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from .simulation_message import SimulationMessage -import pydantic -from .simulation_tool_call import SimulationToolCall -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class SimulationResult(UniversalBaseModel): - """ - Result details for a `simulation` test run. - """ - - transcript: typing.List[SimulationMessage] = pydantic.Field() - """ - Full synthetic conversation in order. - """ - - tool_calls: typing.Optional[typing.List[SimulationToolCall]] = pydantic.Field(default=None) - """ - Every tool invocation across all turns. - """ - - turns_used: int = pydantic.Field() - """ - Number of agent turns that ran before the simulation ended. - """ - - passed: bool - rationale: str = pydantic.Field() - """ - LLM judge's explanation of the verdict. - """ - - duration_ms: int - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/simulation_tool_call.py b/src/speechify/tts/types/simulation_tool_call.py deleted file mode 100644 index a2781af..0000000 --- a/src/speechify/tts/types/simulation_tool_call.py +++ /dev/null @@ -1,38 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import pydantic -import typing -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class SimulationToolCall(UniversalBaseModel): - """ - One tool invocation that occurred during a simulation run. - `mocked` is true when the call was intercepted by the run's - mock config; false when the real tool was called or when the - tool is a system tool. - """ - - turn_index: int = pydantic.Field() - """ - Zero-based index of the conversation turn in which this call occurred. - """ - - tool_name: str - args: typing.Optional[typing.Any] = None - response: typing.Optional[typing.Optional[typing.Any]] = pydantic.Field(default=None) - """ - Response returned to the agent (absent for system tools that end the call). - """ - - mocked: bool - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/system_tool_config.py b/src/speechify/tts/types/system_tool_config.py deleted file mode 100644 index a371652..0000000 --- a/src/speechify/tts/types/system_tool_config.py +++ /dev/null @@ -1,30 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -from .system_tool_config_builtin import SystemToolConfigBuiltin -import typing -from .tool_param import ToolParam -import pydantic -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class SystemToolConfig(UniversalBaseModel): - """ - Config shape for `kind=system`. - """ - - builtin: SystemToolConfigBuiltin - params: typing.Optional[typing.List[ToolParam]] = None - builtin_config: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None) - """ - Per-builtin extras (e.g. allowed_numbers for transfer_to_number). - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/system_tool_config_builtin.py b/src/speechify/tts/types/system_tool_config_builtin.py deleted file mode 100644 index 9c7a630..0000000 --- a/src/speechify/tts/types/system_tool_config_builtin.py +++ /dev/null @@ -1,8 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -SystemToolConfigBuiltin = typing.Union[ - typing.Literal["end_call", "transfer_to_number", "transfer_to_agent", "play_keypad_touch_tone", "skip_turn"], - typing.Any, -] diff --git a/src/speechify/tts/types/system_variable_doc.py b/src/speechify/tts/types/system_variable_doc.py deleted file mode 100644 index f3a8627..0000000 --- a/src/speechify/tts/types/system_variable_doc.py +++ /dev/null @@ -1,33 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import pydantic -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import typing - - -class SystemVariableDoc(UniversalBaseModel): - """ - Documents one reserved `system__*` variable that the platform - auto-populates at session start. Customers cannot define or - override these keys. - """ - - key: str = pydantic.Field() - """ - The reserved variable key (always starts with `system__`). - """ - - description: str = pydantic.Field() - """ - What the variable contains and when it is populated. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/tenant.py b/src/speechify/tts/types/tenant.py deleted file mode 100644 index b1f1263..0000000 --- a/src/speechify/tts/types/tenant.py +++ /dev/null @@ -1,57 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import pydantic -from .tenant_plan import TenantPlan -from .tenant_data_region import TenantDataRegion -import datetime as dt -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import typing - - -class Tenant(UniversalBaseModel): - """ - A workspace the caller belongs to. - """ - - id: str = pydantic.Field() - """ - Opaque workspace ID. - """ - - name: str = pydantic.Field() - """ - Display name set by the workspace owner. - """ - - plan: TenantPlan = pydantic.Field() - """ - Billing plan tier. - """ - - data_region: TenantDataRegion = pydantic.Field() - """ - Geographic region the workspace's data is pinned to. - """ - - hipaa_mode: bool = pydantic.Field() - """ - When true, HIPAA-compliant retention and logging is enforced. - """ - - zero_retention: bool = pydantic.Field() - """ - When true, no transcript / audio payloads are retained server-side. - """ - - created_at: dt.datetime - updated_at: dt.datetime - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/tenant_data_region.py b/src/speechify/tts/types/tenant_data_region.py deleted file mode 100644 index e33656f..0000000 --- a/src/speechify/tts/types/tenant_data_region.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -TenantDataRegion = typing.Union[typing.Literal["us", "eu", "in"], typing.Any] diff --git a/src/speechify/tts/types/tenant_plan.py b/src/speechify/tts/types/tenant_plan.py deleted file mode 100644 index e3f98f9..0000000 --- a/src/speechify/tts/types/tenant_plan.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -TenantPlan = typing.Union[typing.Literal["free", "pro", "business", "enterprise"], typing.Any] diff --git a/src/speechify/tts/types/tenants_list_response.py b/src/speechify/tts/types/tenants_list_response.py deleted file mode 100644 index e4b7373..0000000 --- a/src/speechify/tts/types/tenants_list_response.py +++ /dev/null @@ -1,20 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from .tenant import Tenant -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic - - -class TenantsListResponse(UniversalBaseModel): - tenants: typing.List[Tenant] - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/test_run_result.py b/src/speechify/tts/types/test_run_result.py deleted file mode 100644 index 4bfdf28..0000000 --- a/src/speechify/tts/types/test_run_result.py +++ /dev/null @@ -1,39 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -from .test_type import TestType -import pydantic -import typing -from .scenario_result import ScenarioResult -from .tool_call_result import ToolCallResult -from .simulation_result import SimulationResult -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class TestRunResult(UniversalBaseModel): - """ - Union-like result of a completed test run. Exactly one of - `scenario`, `tool_call`, or `simulation` is populated, matching - the `test_type`. - """ - - test_type: TestType - passed: bool - rationale: str = pydantic.Field() - """ - Top-level verdict explanation duplicated from the inner result for quick rendering. - """ - - duration_ms: int - scenario: typing.Optional[ScenarioResult] = None - tool_call: typing.Optional[ToolCallResult] = None - simulation: typing.Optional[SimulationResult] = None - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/test_run_status.py b/src/speechify/tts/types/test_run_status.py deleted file mode 100644 index f9924f7..0000000 --- a/src/speechify/tts/types/test_run_status.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -TestRunStatus = typing.Union[typing.Literal["queued", "running", "passed", "failed", "error"], typing.Any] diff --git a/src/speechify/tts/types/test_stats.py b/src/speechify/tts/types/test_stats.py deleted file mode 100644 index 8a946a6..0000000 --- a/src/speechify/tts/types/test_stats.py +++ /dev/null @@ -1,34 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from .test_stats_bucket import TestStatsBucket -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic - - -class TestStats(UniversalBaseModel): - """ - Aggregate run metrics over the requested window. `buckets` is - dense - one entry per day in the window, zero-filled, so a chart - never has gaps. `by_type` counts runs per test type across the - whole window. - """ - - window_days: int - buckets: typing.List[TestStatsBucket] - total_runs: int - passed_runs: int - failed_runs: int - errored_runs: int - avg_duration_ms: int - by_type: typing.Optional[typing.Dict[str, int]] = None - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/test_stats_bucket.py b/src/speechify/tts/types/test_stats_bucket.py deleted file mode 100644 index d6d7c26..0000000 --- a/src/speechify/tts/types/test_stats_bucket.py +++ /dev/null @@ -1,30 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import pydantic -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import typing - - -class TestStatsBucket(UniversalBaseModel): - """ - One daily point on the aggregate pass-rate chart. - """ - - day: str = pydantic.Field() - """ - ISO date (YYYY-MM-DD). - """ - - passed: int - failed: int - errored: int - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/test_type.py b/src/speechify/tts/types/test_type.py deleted file mode 100644 index 5afbc08..0000000 --- a/src/speechify/tts/types/test_type.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -TestType = typing.Union[typing.Literal["scenario", "tool", "simulation"], typing.Any] diff --git a/src/speechify/tts/types/tool.py b/src/speechify/tts/types/tool.py deleted file mode 100644 index 53a7563..0000000 --- a/src/speechify/tts/types/tool.py +++ /dev/null @@ -1,39 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -from .tool_kind import ToolKind -from .tool_config import ToolConfig -import pydantic -import typing -import datetime as dt -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class Tool(UniversalBaseModel): - id: str - name: str - description: str - kind: ToolKind - config: ToolConfig = pydantic.Field() - """ - One of `SystemToolConfig`, `WebhookToolConfig`, or `ClientToolConfig` depending on `kind`. - """ - - webhook_secret: typing.Optional[str] = pydantic.Field(default=None) - """ - HMAC signing secret for `kind=webhook`. Returned in full **only** on the create - response; all subsequent reads return a masked placeholder. Store it on first - create — there is no way to retrieve it later. - """ - - created_at: dt.datetime - updated_at: dt.datetime - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/tool_call_config.py b/src/speechify/tts/types/tool_call_config.py deleted file mode 100644 index 8efecf8..0000000 --- a/src/speechify/tts/types/tool_call_config.py +++ /dev/null @@ -1,57 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -import pydantic -from .parameter_check import ParameterCheck -from .simulation_message import SimulationMessage -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class ToolCallConfig(UniversalBaseModel): - """ - Configuration for a `tool` test. The runner sends `context` as a - user message and asserts that the agent calls `expected_tool` with - arguments matching all `parameter_checks`. Use - `initial_chat_history` to test tool invocations that only make - sense mid-conversation. - """ - - context: typing.Optional[str] = pydantic.Field(default=None) - """ - User message that should cause the agent to invoke the expected tool. Optional when `initial_chat_history` already ends with a user message. - """ - - expected_tool: str = pydantic.Field() - """ - Name of the tool the agent is expected to call. - """ - - parameter_checks: typing.Optional[typing.List[ParameterCheck]] = pydantic.Field(default=None) - """ - Assertions on specific arguments of the tool call. - """ - - initial_chat_history: typing.Optional[typing.List[SimulationMessage]] = pydantic.Field(default=None) - """ - Optional seed conversation prepended before `context`. - """ - - system_prompt_override: typing.Optional[str] = pydantic.Field(default=None) - """ - Replaces the agent's system prompt for this run only. - """ - - model_override: typing.Optional[str] = pydantic.Field(default=None) - """ - Overrides the LLM model used by the agent for this run only. - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/tool_call_result.py b/src/speechify/tts/types/tool_call_result.py deleted file mode 100644 index 7e9dc1c..0000000 --- a/src/speechify/tts/types/tool_call_result.py +++ /dev/null @@ -1,51 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import pydantic -import typing -from .parameter_check_result import ParameterCheckResult -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class ToolCallResult(UniversalBaseModel): - """ - Result details for a `tool` test run. - """ - - tool_called: str = pydantic.Field() - """ - Name of the tool the agent actually called (may differ from `expected_tool`). - """ - - tool_args: typing.Optional[typing.Optional[typing.Any]] = pydantic.Field(default=None) - """ - Arguments the agent passed to the tool, as a JSON object. - """ - - expected_tool: str = pydantic.Field() - """ - Name of the tool the test expected the agent to call. - """ - - tool_matched: bool = pydantic.Field() - """ - True when `tool_called` equals `expected_tool`. - """ - - parameter_results: typing.List[ParameterCheckResult] - passed: bool - rationale: str = pydantic.Field() - """ - Explanation of the overall verdict. - """ - - duration_ms: int - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/tool_config.py b/src/speechify/tts/types/tool_config.py deleted file mode 100644 index ee8576c..0000000 --- a/src/speechify/tts/types/tool_config.py +++ /dev/null @@ -1,8 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing -from .system_tool_config import SystemToolConfig -from .webhook_tool_config import WebhookToolConfig -from .client_tool_config import ClientToolConfig - -ToolConfig = typing.Union[SystemToolConfig, WebhookToolConfig, ClientToolConfig] diff --git a/src/speechify/tts/types/tool_kind.py b/src/speechify/tts/types/tool_kind.py deleted file mode 100644 index da3d6ba..0000000 --- a/src/speechify/tts/types/tool_kind.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -ToolKind = typing.Union[typing.Literal["system", "webhook", "client"], typing.Any] diff --git a/src/speechify/tts/types/tool_mock.py b/src/speechify/tts/types/tool_mock.py deleted file mode 100644 index 6fe48ca..0000000 --- a/src/speechify/tts/types/tool_mock.py +++ /dev/null @@ -1,38 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import pydantic -import typing -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class ToolMock(UniversalBaseModel): - """ - A canned response returned when the agent calls `tool_name`. If - `args_match` is set the mock only triggers when its value appears - as a substring of the JSON-serialised call arguments (a deliberately - simple v1 matcher — full expression support is planned). A mock - without `args_match` always matches for its tool. - """ - - tool_name: str = pydantic.Field() - """ - Name of the tool to intercept. - """ - - args_match: typing.Optional[str] = pydantic.Field(default=None) - """ - Optional substring of the JSON-serialised call arguments. When - absent the mock matches unconditionally for this tool. - """ - - response: typing.Optional[typing.Any] = None - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/tool_mock_config.py b/src/speechify/tts/types/tool_mock_config.py deleted file mode 100644 index 15d5c5e..0000000 --- a/src/speechify/tts/types/tool_mock_config.py +++ /dev/null @@ -1,32 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -from .mocking_strategy import MockingStrategy -import typing -from .tool_mock import ToolMock -import pydantic -from .no_match_behavior import NoMatchBehavior -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class ToolMockConfig(UniversalBaseModel): - """ - Controls tool-call interception during a test run. - """ - - strategy: MockingStrategy - mocks: typing.Optional[typing.List[ToolMock]] = pydantic.Field(default=None) - """ - Canned responses for specific tools (order matters - first match wins). - """ - - no_match_behavior: NoMatchBehavior - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/tool_param.py b/src/speechify/tts/types/tool_param.py deleted file mode 100644 index e5b253f..0000000 --- a/src/speechify/tts/types/tool_param.py +++ /dev/null @@ -1,28 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -from .tool_param_type import ToolParamType -import typing -from ...core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic - - -class ToolParam(UniversalBaseModel): - """ - One argument the LLM can pass when calling the tool. Mirrors the JSON-Schema subset standard function-calling schemas support. - """ - - name: str - type: ToolParamType - description: str - required: bool - enum: typing.Optional[typing.List[str]] = None - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/tool_param_type.py b/src/speechify/tts/types/tool_param_type.py deleted file mode 100644 index 9dc5af6..0000000 --- a/src/speechify/tts/types/tool_param_type.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -ToolParamType = typing.Union[typing.Literal["string", "number", "integer", "boolean"], typing.Any] diff --git a/src/speechify/tts/types/webhook_tool_config.py b/src/speechify/tts/types/webhook_tool_config.py deleted file mode 100644 index 468e671..0000000 --- a/src/speechify/tts/types/webhook_tool_config.py +++ /dev/null @@ -1,37 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ...core.pydantic_utilities import UniversalBaseModel -import typing -from .webhook_tool_config_method import WebhookToolConfigMethod -import pydantic -from .tool_param import ToolParam -from ...core.pydantic_utilities import IS_PYDANTIC_V2 - - -class WebhookToolConfig(UniversalBaseModel): - """ - Config shape for `kind=webhook`. - """ - - url: str - method: typing.Optional[WebhookToolConfigMethod] = None - headers: typing.Optional[typing.Dict[str, str]] = pydantic.Field(default=None) - """ - Static headers sent with every call. `Authorization` and `X-Speechify-Signature` are reserved. - """ - - timeout_ms: typing.Optional[int] = pydantic.Field(default=None) - """ - Per-call timeout in milliseconds. - """ - - params: typing.Optional[typing.List[ToolParam]] = None - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/webhook_tool_config_method.py b/src/speechify/tts/types/webhook_tool_config_method.py deleted file mode 100644 index f8968f7..0000000 --- a/src/speechify/tts/types/webhook_tool_config_method.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -WebhookToolConfigMethod = typing.Union[typing.Literal["POST", "GET"], typing.Any] diff --git a/src/speechify/tts/voices/client.py b/src/speechify/tts/voices/client.py index 8eb26e2..ddeaa3a 100644 --- a/src/speechify/tts/voices/client.py +++ b/src/speechify/tts/voices/client.py @@ -3,19 +3,25 @@ import typing from ...core.client_wrapper import SyncClientWrapper from ...core.request_options import RequestOptions -from ..types.get_voice import GetVoice +from ...types.get_voice import GetVoice from ...core.pydantic_utilities import parse_obj_as -from ..errors.unauthorized_error import UnauthorizedError -from ..errors.not_found_error import NotFoundError -from ..errors.internal_server_error import InternalServerError +from ...errors.unauthorized_error import UnauthorizedError +from ...errors.forbidden_error import ForbiddenError +from ...types.error import Error +from ...errors.too_many_requests_error import TooManyRequestsError +from ...errors.internal_server_error import InternalServerError from json.decoder import JSONDecodeError from ...core.api_error import ApiError from .types.create_voices_request_gender import CreateVoicesRequestGender from ... import core -from ..types.created_voice import CreatedVoice -from ..errors.bad_request_error import BadRequestError -from ..errors.payment_required_error import PaymentRequiredError +from ...types.created_voice import CreatedVoice +from ...errors.bad_request_error import BadRequestError +from ...errors.payment_required_error import PaymentRequiredError +from ...errors.unprocessable_entity_error import UnprocessableEntityError +from ...errors.bad_gateway_error import BadGatewayError +from ...errors.service_unavailable_error import ServiceUnavailableError from ...core.jsonable_encoder import jsonable_encoder +from ...errors.not_found_error import NotFoundError from ...core.client_wrapper import AsyncClientWrapper # this is used as the default value for optional parameters @@ -73,12 +79,22 @@ def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> ty ), ) ) - if _response.status_code == 404: - raise NotFoundError( + if _response.status_code == 403: + raise ForbiddenError( typing.cast( - typing.Optional[typing.Any], + Error, parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore object_=_response.json(), ), ) @@ -86,9 +102,9 @@ def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> ty if _response.status_code == 500: raise InternalServerError( typing.cast( - typing.Optional[typing.Any], + Error, parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore + type_=Error, # type: ignore object_=_response.json(), ), ) @@ -206,9 +222,39 @@ def create( if _response.status_code == 402: raise PaymentRequiredError( typing.cast( - typing.Optional[typing.Any], + Error, parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore object_=_response.json(), ), ) @@ -216,9 +262,29 @@ def create( if _response.status_code == 500: raise InternalServerError( typing.cast( - typing.Optional[typing.Any], + Error, parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 502: + raise BadGatewayError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 503: + raise ServiceUnavailableError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore object_=_response.json(), ), ) @@ -283,6 +349,16 @@ def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = ), ) ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: raise NotFoundError( typing.cast( @@ -293,12 +369,42 @@ def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = ), ) ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: raise InternalServerError( typing.cast( - typing.Optional[typing.Any], + Error, parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 502: + raise BadGatewayError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 503: + raise ServiceUnavailableError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore object_=_response.json(), ), ) @@ -370,6 +476,16 @@ def download_sample( ), ) ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: raise NotFoundError( typing.cast( @@ -380,12 +496,42 @@ def download_sample( ), ) ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: raise InternalServerError( typing.cast( - typing.Optional[typing.Any], + Error, parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 502: + raise BadGatewayError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 503: + raise ServiceUnavailableError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore object_=_response.json(), ), ) @@ -455,12 +601,22 @@ async def main() -> None: ), ) ) - if _response.status_code == 404: - raise NotFoundError( + if _response.status_code == 403: + raise ForbiddenError( typing.cast( - typing.Optional[typing.Any], + Error, parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore object_=_response.json(), ), ) @@ -468,9 +624,9 @@ async def main() -> None: if _response.status_code == 500: raise InternalServerError( typing.cast( - typing.Optional[typing.Any], + Error, parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore + type_=Error, # type: ignore object_=_response.json(), ), ) @@ -596,9 +752,39 @@ async def main() -> None: if _response.status_code == 402: raise PaymentRequiredError( typing.cast( - typing.Optional[typing.Any], + Error, parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore object_=_response.json(), ), ) @@ -606,9 +792,29 @@ async def main() -> None: if _response.status_code == 500: raise InternalServerError( typing.cast( - typing.Optional[typing.Any], + Error, parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 502: + raise BadGatewayError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 503: + raise ServiceUnavailableError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore object_=_response.json(), ), ) @@ -681,6 +887,16 @@ async def main() -> None: ), ) ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: raise NotFoundError( typing.cast( @@ -691,12 +907,42 @@ async def main() -> None: ), ) ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: raise InternalServerError( typing.cast( - typing.Optional[typing.Any], + Error, parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 502: + raise BadGatewayError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 503: + raise ServiceUnavailableError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore object_=_response.json(), ), ) @@ -776,6 +1022,16 @@ async def main() -> None: ), ) ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: raise NotFoundError( typing.cast( @@ -786,12 +1042,42 @@ async def main() -> None: ), ) ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: raise InternalServerError( typing.cast( - typing.Optional[typing.Any], + Error, parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 502: + raise BadGatewayError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 503: + raise ServiceUnavailableError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore object_=_response.json(), ), ) diff --git a/src/speechify/tts/workspaces/__init__.py b/src/speechify/tts/workspaces/__init__.py deleted file mode 100644 index f3ea265..0000000 --- a/src/speechify/tts/workspaces/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - diff --git a/src/speechify/tts/workspaces/client.py b/src/speechify/tts/workspaces/client.py deleted file mode 100644 index ec1fa67..0000000 --- a/src/speechify/tts/workspaces/client.py +++ /dev/null @@ -1,2186 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing -from ...core.client_wrapper import SyncClientWrapper -from ...core.request_options import RequestOptions -from ..types.tenants_list_response import TenantsListResponse -from ...core.pydantic_utilities import parse_obj_as -from ..errors.unauthorized_error import UnauthorizedError -from json.decoder import JSONDecodeError -from ...core.api_error import ApiError -from ..types.tenant import Tenant -from ..errors.bad_request_error import BadRequestError -from ..errors.not_found_error import NotFoundError -from ..types.members_list_response import MembersListResponse -from ..errors.conflict_error import ConflictError -from ...core.jsonable_encoder import jsonable_encoder -from ..errors.forbidden_error import ForbiddenError -from ..types.member_role import MemberRole -from ..types.member import Member -from ..types.invites_list_response import InvitesListResponse -from ..types.invite import Invite -from ..types.invite_preview import InvitePreview -from ...core.client_wrapper import AsyncClientWrapper - -# this is used as the default value for optional parameters -OMIT = typing.cast(typing.Any, ...) - - -class WorkspacesClient: - def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper - - def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> TenantsListResponse: - """ - List every workspace the authenticated user belongs to. Powers the workspace switcher. - - Parameters - ---------- - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - TenantsListResponse - Workspaces for the authenticated user. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.workspaces.list() - """ - _response = self._client_wrapper.httpx_client.request( - "v1/tenants", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - TenantsListResponse, - parse_obj_as( - type_=TenantsListResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def create( - self, *, name: typing.Optional[str] = OMIT, request_options: typing.Optional[RequestOptions] = None - ) -> Tenant: - """ - Create a new workspace with the authenticated user as owner. - The caller must switch their active workspace client-side via - the `X-Tenant-ID` header to act on the new tenant. - - Parameters - ---------- - name : typing.Optional[str] - Display name for the new workspace. Trimmed; must be 120 characters or fewer. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Tenant - The newly-created workspace. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.workspaces.create() - """ - _response = self._client_wrapper.httpx_client.request( - "v1/tenants", - method="POST", - json={ - "name": name, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Tenant, - parse_obj_as( - type_=Tenant, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def get_current(self, *, request_options: typing.Optional[RequestOptions] = None) -> Tenant: - """ - Retrieve the workspace currently selected by the caller (via `X-Tenant-ID` or auto-resolved). - - Parameters - ---------- - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Tenant - The current workspace. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.workspaces.get_current() - """ - _response = self._client_wrapper.httpx_client.request( - "v1/tenants/current", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Tenant, - parse_obj_as( - type_=Tenant, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def update_current(self, *, name: str, request_options: typing.Optional[RequestOptions] = None) -> Tenant: - """ - Rename the current workspace. Owner or admin only. - - Parameters - ---------- - name : str - New display name. Required; must be 120 characters or fewer. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Tenant - The updated workspace. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.workspaces.update_current( - name="name", - ) - """ - _response = self._client_wrapper.httpx_client.request( - "v1/tenants/current", - method="PATCH", - json={ - "name": name, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Tenant, - parse_obj_as( - type_=Tenant, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def list_members(self, *, request_options: typing.Optional[RequestOptions] = None) -> MembersListResponse: - """ - List every member of the current workspace. Any member may call this. - - Parameters - ---------- - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - MembersListResponse - Members of the current workspace. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.workspaces.list_members() - """ - _response = self._client_wrapper.httpx_client.request( - "v1/tenants/current/members", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - MembersListResponse, - parse_obj_as( - type_=MembersListResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def leave(self, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Remove the authenticated caller from the current workspace. - Refused with 409 when the caller is the last owner — promote - another member to owner first. - - Parameters - ---------- - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.workspaces.leave() - """ - _response = self._client_wrapper.httpx_client.request( - "v1/tenants/current/members/leave", - method="POST", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def remove_member(self, user_uid: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Remove a member from the current workspace. Owner or admin - only. The caller cannot remove themselves — use - `POST /v1/tenants/current/members/leave` instead. - - Parameters - ---------- - user_uid : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.workspaces.remove_member( - user_uid="user_uid", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/tenants/current/members/{jsonable_encoder(user_uid)}", - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def update_member_role( - self, user_uid: str, *, role: MemberRole, request_options: typing.Optional[RequestOptions] = None - ) -> Member: - """ - Change a member's role. Owner only — admins may add or remove - members but may not change roles. Refused with 409 when - demoting the last remaining owner. - - Parameters - ---------- - user_uid : str - - role : MemberRole - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Member - The updated member. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.workspaces.update_member_role( - user_uid="user_uid", - role="owner", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/tenants/current/members/{jsonable_encoder(user_uid)}", - method="PATCH", - json={ - "role": role, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Member, - parse_obj_as( - type_=Member, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def list_invites(self, *, request_options: typing.Optional[RequestOptions] = None) -> InvitesListResponse: - """ - List outstanding invites for the current workspace. Invite tokens are redacted. - - Parameters - ---------- - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - InvitesListResponse - Outstanding invites. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.workspaces.list_invites() - """ - _response = self._client_wrapper.httpx_client.request( - "v1/tenants/current/invites", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - InvitesListResponse, - parse_obj_as( - type_=InvitesListResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def create_invite(self, *, email: str, request_options: typing.Optional[RequestOptions] = None) -> Invite: - """ - Create an invite to the current workspace. Owner or admin only. - The response contains the invite token ONCE — subsequent list - calls redact it. - - Parameters - ---------- - email : str - Email of the person to invite. Validated as an RFC 5322 address. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Invite - The created invite (token included). - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.workspaces.create_invite( - email="email", - ) - """ - _response = self._client_wrapper.httpx_client.request( - "v1/tenants/current/invites", - method="POST", - json={ - "email": email, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Invite, - parse_obj_as( - type_=Invite, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def revoke_invite(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Revoke an outstanding invite. Owner or admin only. Idempotent. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.workspaces.revoke_invite( - id="id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/tenants/current/invites/{jsonable_encoder(id)}", - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def accept_invite(self, token: str, *, request_options: typing.Optional[RequestOptions] = None) -> Tenant: - """ - Accept a workspace invite. The authenticated caller is joined - to the invite's workspace as a member. Expired, revoked, or - already-accepted tokens return 404 to avoid token enumeration. - - Parameters - ---------- - token : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Tenant - The workspace the caller just joined. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.workspaces.accept_invite( - token="token", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/invites/{jsonable_encoder(token)}/accept", - method="POST", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Tenant, - parse_obj_as( - type_=Tenant, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def preview_invite(self, token: str, *, request_options: typing.Optional[RequestOptions] = None) -> InvitePreview: - """ - Preview a workspace invite without authenticating. Returns the - workspace name, inviter details, and expiry so the `/join/{token}` - page can render before the recipient signs in. Anyone with the - token can already accept, so this endpoint deliberately surfaces - the same information a caller would see after accepting. Invalid - tokens (unknown, expired, revoked, already-accepted, or pointing - at a soft-deleted workspace) collapse to a single 404 to prevent - enumeration. - - Parameters - ---------- - token : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - InvitePreview - Preview metadata for a valid, active invite. - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.workspaces.preview_invite( - token="token", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/invites/{jsonable_encoder(token)}", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - InvitePreview, - parse_obj_as( - type_=InvitePreview, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def transfer_workspace_owner( - self, *, user_uid: str, request_options: typing.Optional[RequestOptions] = None - ) -> None: - """ - Transfer ownership of the current workspace atomically. Promotes - the target member to owner and demotes the caller to admin in a - single transaction. Owner-only; admins cannot hand off a role - they were never granted. Prefer this over two PATCH calls to - `/v1/tenants/current/members/{user_uid}`: a sole-owner caller - cannot demote themselves first without tripping the last-owner - guard, which this endpoint sidesteps by promoting before - demoting. - - Parameters - ---------- - user_uid : str - Firebase UID of the member who will become the new owner. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - from speechify import Speechify - - client = Speechify( - token="YOUR_TOKEN", - ) - client.tts.workspaces.transfer_workspace_owner( - user_uid="user_uid", - ) - """ - _response = self._client_wrapper.httpx_client.request( - "v1/tenants/current/transfer-owner", - method="POST", - json={ - "user_uid": user_uid, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - -class AsyncWorkspacesClient: - def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper - - async def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> TenantsListResponse: - """ - List every workspace the authenticated user belongs to. Powers the workspace switcher. - - Parameters - ---------- - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - TenantsListResponse - Workspaces for the authenticated user. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.workspaces.list() - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/tenants", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - TenantsListResponse, - parse_obj_as( - type_=TenantsListResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def create( - self, *, name: typing.Optional[str] = OMIT, request_options: typing.Optional[RequestOptions] = None - ) -> Tenant: - """ - Create a new workspace with the authenticated user as owner. - The caller must switch their active workspace client-side via - the `X-Tenant-ID` header to act on the new tenant. - - Parameters - ---------- - name : typing.Optional[str] - Display name for the new workspace. Trimmed; must be 120 characters or fewer. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Tenant - The newly-created workspace. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.workspaces.create() - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/tenants", - method="POST", - json={ - "name": name, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Tenant, - parse_obj_as( - type_=Tenant, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def get_current(self, *, request_options: typing.Optional[RequestOptions] = None) -> Tenant: - """ - Retrieve the workspace currently selected by the caller (via `X-Tenant-ID` or auto-resolved). - - Parameters - ---------- - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Tenant - The current workspace. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.workspaces.get_current() - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/tenants/current", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Tenant, - parse_obj_as( - type_=Tenant, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def update_current(self, *, name: str, request_options: typing.Optional[RequestOptions] = None) -> Tenant: - """ - Rename the current workspace. Owner or admin only. - - Parameters - ---------- - name : str - New display name. Required; must be 120 characters or fewer. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Tenant - The updated workspace. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.workspaces.update_current( - name="name", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/tenants/current", - method="PATCH", - json={ - "name": name, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Tenant, - parse_obj_as( - type_=Tenant, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def list_members(self, *, request_options: typing.Optional[RequestOptions] = None) -> MembersListResponse: - """ - List every member of the current workspace. Any member may call this. - - Parameters - ---------- - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - MembersListResponse - Members of the current workspace. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.workspaces.list_members() - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/tenants/current/members", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - MembersListResponse, - parse_obj_as( - type_=MembersListResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def leave(self, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Remove the authenticated caller from the current workspace. - Refused with 409 when the caller is the last owner — promote - another member to owner first. - - Parameters - ---------- - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.workspaces.leave() - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/tenants/current/members/leave", - method="POST", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def remove_member(self, user_uid: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Remove a member from the current workspace. Owner or admin - only. The caller cannot remove themselves — use - `POST /v1/tenants/current/members/leave` instead. - - Parameters - ---------- - user_uid : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.workspaces.remove_member( - user_uid="user_uid", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/tenants/current/members/{jsonable_encoder(user_uid)}", - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def update_member_role( - self, user_uid: str, *, role: MemberRole, request_options: typing.Optional[RequestOptions] = None - ) -> Member: - """ - Change a member's role. Owner only — admins may add or remove - members but may not change roles. Refused with 409 when - demoting the last remaining owner. - - Parameters - ---------- - user_uid : str - - role : MemberRole - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Member - The updated member. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.workspaces.update_member_role( - user_uid="user_uid", - role="owner", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/tenants/current/members/{jsonable_encoder(user_uid)}", - method="PATCH", - json={ - "role": role, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Member, - parse_obj_as( - type_=Member, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def list_invites(self, *, request_options: typing.Optional[RequestOptions] = None) -> InvitesListResponse: - """ - List outstanding invites for the current workspace. Invite tokens are redacted. - - Parameters - ---------- - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - InvitesListResponse - Outstanding invites. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.workspaces.list_invites() - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/tenants/current/invites", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - InvitesListResponse, - parse_obj_as( - type_=InvitesListResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def create_invite(self, *, email: str, request_options: typing.Optional[RequestOptions] = None) -> Invite: - """ - Create an invite to the current workspace. Owner or admin only. - The response contains the invite token ONCE — subsequent list - calls redact it. - - Parameters - ---------- - email : str - Email of the person to invite. Validated as an RFC 5322 address. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Invite - The created invite (token included). - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.workspaces.create_invite( - email="email", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/tenants/current/invites", - method="POST", - json={ - "email": email, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Invite, - parse_obj_as( - type_=Invite, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def revoke_invite(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Revoke an outstanding invite. Owner or admin only. Idempotent. - - Parameters - ---------- - id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.workspaces.revoke_invite( - id="id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/tenants/current/invites/{jsonable_encoder(id)}", - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def accept_invite(self, token: str, *, request_options: typing.Optional[RequestOptions] = None) -> Tenant: - """ - Accept a workspace invite. The authenticated caller is joined - to the invite's workspace as a member. Expired, revoked, or - already-accepted tokens return 404 to avoid token enumeration. - - Parameters - ---------- - token : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Tenant - The workspace the caller just joined. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.workspaces.accept_invite( - token="token", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/invites/{jsonable_encoder(token)}/accept", - method="POST", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Tenant, - parse_obj_as( - type_=Tenant, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def preview_invite( - self, token: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> InvitePreview: - """ - Preview a workspace invite without authenticating. Returns the - workspace name, inviter details, and expiry so the `/join/{token}` - page can render before the recipient signs in. Anyone with the - token can already accept, so this endpoint deliberately surfaces - the same information a caller would see after accepting. Invalid - tokens (unknown, expired, revoked, already-accepted, or pointing - at a soft-deleted workspace) collapse to a single 404 to prevent - enumeration. - - Parameters - ---------- - token : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - InvitePreview - Preview metadata for a valid, active invite. - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.workspaces.preview_invite( - token="token", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/invites/{jsonable_encoder(token)}", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - InvitePreview, - parse_obj_as( - type_=InvitePreview, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def transfer_workspace_owner( - self, *, user_uid: str, request_options: typing.Optional[RequestOptions] = None - ) -> None: - """ - Transfer ownership of the current workspace atomically. Promotes - the target member to owner and demotes the caller to admin in a - single transaction. Owner-only; admins cannot hand off a role - they were never granted. Prefer this over two PATCH calls to - `/v1/tenants/current/members/{user_uid}`: a sole-owner caller - cannot demote themselves first without tripping the last-owner - guard, which this endpoint sidesteps by promoting before - demoting. - - Parameters - ---------- - user_uid : str - Firebase UID of the member who will become the new owner. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - import asyncio - - from speechify import AsyncSpeechify - - client = AsyncSpeechify( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.tts.workspaces.transfer_workspace_owner( - user_uid="user_uid", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/tenants/current/transfer-owner", - method="POST", - json={ - "user_uid": user_uid, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/speechify/types/__init__.py b/src/speechify/types/__init__.py new file mode 100644 index 0000000..4736402 --- /dev/null +++ b/src/speechify/types/__init__.py @@ -0,0 +1,47 @@ +# This file was auto-generated by Fern from our API Definition. + +from .create_voice_language import CreateVoiceLanguage +from .create_voice_model import CreateVoiceModel +from .create_voice_model_name import CreateVoiceModelName +from .created_voice import CreatedVoice +from .created_voice_gender import CreatedVoiceGender +from .created_voice_type import CreatedVoiceType +from .error import Error +from .error_code import ErrorCode +from .error_detail import ErrorDetail +from .get_speech_options_request import GetSpeechOptionsRequest +from .get_speech_response import GetSpeechResponse +from .get_speech_response_audio_format import GetSpeechResponseAudioFormat +from .get_stream_options_request import GetStreamOptionsRequest +from .get_voice import GetVoice +from .get_voice_gender import GetVoiceGender +from .get_voice_language import GetVoiceLanguage +from .get_voice_type import GetVoiceType +from .get_voices_model import GetVoicesModel +from .get_voices_model_name import GetVoicesModelName +from .nested_chunk import NestedChunk +from .speech_marks import SpeechMarks + +__all__ = [ + "CreateVoiceLanguage", + "CreateVoiceModel", + "CreateVoiceModelName", + "CreatedVoice", + "CreatedVoiceGender", + "CreatedVoiceType", + "Error", + "ErrorCode", + "ErrorDetail", + "GetSpeechOptionsRequest", + "GetSpeechResponse", + "GetSpeechResponseAudioFormat", + "GetStreamOptionsRequest", + "GetVoice", + "GetVoiceGender", + "GetVoiceLanguage", + "GetVoiceType", + "GetVoicesModel", + "GetVoicesModelName", + "NestedChunk", + "SpeechMarks", +] diff --git a/src/speechify/tts/types/create_voice_language.py b/src/speechify/types/create_voice_language.py similarity index 82% rename from src/speechify/tts/types/create_voice_language.py rename to src/speechify/types/create_voice_language.py index b60313b..16226ad 100644 --- a/src/speechify/tts/types/create_voice_language.py +++ b/src/speechify/types/create_voice_language.py @@ -1,8 +1,8 @@ # This file was auto-generated by Fern from our API Definition. -from ...core.pydantic_utilities import UniversalBaseModel +from ..core.pydantic_utilities import UniversalBaseModel import typing -from ...core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2 import pydantic diff --git a/src/speechify/tts/types/create_voice_model.py b/src/speechify/types/create_voice_model.py similarity index 85% rename from src/speechify/tts/types/create_voice_model.py rename to src/speechify/types/create_voice_model.py index 9f97b91..458d356 100644 --- a/src/speechify/tts/types/create_voice_model.py +++ b/src/speechify/types/create_voice_model.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ...core.pydantic_utilities import UniversalBaseModel +from ..core.pydantic_utilities import UniversalBaseModel import typing from .create_voice_language import CreateVoiceLanguage from .create_voice_model_name import CreateVoiceModelName -from ...core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2 import pydantic diff --git a/src/speechify/types/create_voice_model_name.py b/src/speechify/types/create_voice_model_name.py new file mode 100644 index 0000000..e82711f --- /dev/null +++ b/src/speechify/types/create_voice_model_name.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +CreateVoiceModelName = typing.Union[typing.Literal["simba-english", "simba-multilingual", "simba-3.0"], typing.Any] diff --git a/src/speechify/tts/types/created_voice.py b/src/speechify/types/created_voice.py similarity index 87% rename from src/speechify/tts/types/created_voice.py rename to src/speechify/types/created_voice.py index 6eba08b..fcbaf1f 100644 --- a/src/speechify/tts/types/created_voice.py +++ b/src/speechify/types/created_voice.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ...core.pydantic_utilities import UniversalBaseModel +from ..core.pydantic_utilities import UniversalBaseModel import typing from .created_voice_gender import CreatedVoiceGender from .create_voice_model import CreateVoiceModel from .created_voice_type import CreatedVoiceType -from ...core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2 import pydantic diff --git a/src/speechify/tts/types/created_voice_gender.py b/src/speechify/types/created_voice_gender.py similarity index 100% rename from src/speechify/tts/types/created_voice_gender.py rename to src/speechify/types/created_voice_gender.py diff --git a/src/speechify/tts/types/created_voice_type.py b/src/speechify/types/created_voice_type.py similarity index 100% rename from src/speechify/tts/types/created_voice_type.py rename to src/speechify/types/created_voice_type.py diff --git a/src/speechify/types/error.py b/src/speechify/types/error.py new file mode 100644 index 0000000..8346a5b --- /dev/null +++ b/src/speechify/types/error.py @@ -0,0 +1,38 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +from .error_detail import ErrorDetail +import typing +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class Error(UniversalBaseModel): + """ + Standard error envelope returned on every non-2xx response. + Content-Type is `application/json`. The shape mirrors OpenAI / + Anthropic / Stripe style: a machine-readable `error.code` for + SDK consumers to switch on, a human `error.message` for UI, + and an optional `error.fields` map for per-field validation + errors. `request_id` matches the `X-Request-ID` response + header and is what customers quote when filing support + tickets. + """ + + error: ErrorDetail + request_id: typing.Optional[str] = pydantic.Field(default=None) + """ + Server-side request identifier. Echoes the + `X-Request-ID` response header. Stable across the + request's lifetime, written to structured logs, and + useful when reporting issues. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/speechify/types/error_code.py b/src/speechify/types/error_code.py new file mode 100644 index 0000000..1a0139e --- /dev/null +++ b/src/speechify/types/error_code.py @@ -0,0 +1,48 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +ErrorCode = typing.Union[ + typing.Literal[ + "bad_request", + "validation_failed", + "unauthorized", + "payment_required", + "forbidden", + "not_found", + "method_not_allowed", + "conflict", + "payload_too_large", + "unsupported_media_type", + "rate_limited", + "internal_error", + "upstream_failure", + "service_unavailable", + "caller_not_found", + "credential_not_found", + "agent_not_found", + "kb_not_found", + "kb_document_not_found", + "kb_folder_not_found", + "tool_not_found", + "conversation_not_found", + "phone_number_not_found", + "sip_trunk_not_found", + "voice_not_found", + "audio_asset_not_found", + "builtin_not_found", + "batch_not_found", + "agent_test_not_found", + "workspace_not_found", + "invite_not_found", + "insufficient_scope", + "purchased_numbers_not_included", + "phone_number_quota_reached", + "batch_calls_not_included", + "voice_cloning_not_included", + "workspace_last_owner", + "workspace_last_workspace", + "invite_email_mismatch", + ], + typing.Any, +] diff --git a/src/speechify/types/error_detail.py b/src/speechify/types/error_detail.py new file mode 100644 index 0000000..e0dd4d6 --- /dev/null +++ b/src/speechify/types/error_detail.py @@ -0,0 +1,37 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +from .error_code import ErrorCode +import pydantic +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class ErrorDetail(UniversalBaseModel): + code: ErrorCode + message: str = pydantic.Field() + """ + Human-readable explanation of this specific occurrence. + Safe to surface in UI banners or pass to support. The + wording can change between releases; clients should + match on `code`, not on the message string. + """ + + fields: typing.Optional[typing.Dict[str, str]] = pydantic.Field(default=None) + """ + Per-field validation errors as `path -> message`. Only + present on 400 responses caused by request validation + (typically code=`validation_failed`). Keys are field + paths in dotted/bracket notation; values are short + human explanations safe to inline-surface next to the + offending form field. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/speechify/tts/types/get_speech_options_request.py b/src/speechify/types/get_speech_options_request.py similarity index 93% rename from src/speechify/tts/types/get_speech_options_request.py rename to src/speechify/types/get_speech_options_request.py index 3e2f52e..2c840e4 100644 --- a/src/speechify/tts/types/get_speech_options_request.py +++ b/src/speechify/types/get_speech_options_request.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ...core.pydantic_utilities import UniversalBaseModel +from ..core.pydantic_utilities import UniversalBaseModel import typing import pydantic -from ...core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2 class GetSpeechOptionsRequest(UniversalBaseModel): diff --git a/src/speechify/tts/types/get_speech_response.py b/src/speechify/types/get_speech_response.py similarity index 89% rename from src/speechify/tts/types/get_speech_response.py rename to src/speechify/types/get_speech_response.py index 3943cdf..9763919 100644 --- a/src/speechify/tts/types/get_speech_response.py +++ b/src/speechify/types/get_speech_response.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ...core.pydantic_utilities import UniversalBaseModel +from ..core.pydantic_utilities import UniversalBaseModel import pydantic from .get_speech_response_audio_format import GetSpeechResponseAudioFormat from .speech_marks import SpeechMarks -from ...core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2 import typing diff --git a/src/speechify/tts/types/get_speech_response_audio_format.py b/src/speechify/types/get_speech_response_audio_format.py similarity index 100% rename from src/speechify/tts/types/get_speech_response_audio_format.py rename to src/speechify/types/get_speech_response_audio_format.py diff --git a/src/speechify/tts/types/get_stream_options_request.py b/src/speechify/types/get_stream_options_request.py similarity index 93% rename from src/speechify/tts/types/get_stream_options_request.py rename to src/speechify/types/get_stream_options_request.py index 96ece1f..65136a0 100644 --- a/src/speechify/tts/types/get_stream_options_request.py +++ b/src/speechify/types/get_stream_options_request.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ...core.pydantic_utilities import UniversalBaseModel +from ..core.pydantic_utilities import UniversalBaseModel import typing import pydantic -from ...core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2 class GetStreamOptionsRequest(UniversalBaseModel): diff --git a/src/speechify/tts/types/get_voice.py b/src/speechify/types/get_voice.py similarity index 88% rename from src/speechify/tts/types/get_voice.py rename to src/speechify/types/get_voice.py index 0466b56..6153004 100644 --- a/src/speechify/tts/types/get_voice.py +++ b/src/speechify/types/get_voice.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ...core.pydantic_utilities import UniversalBaseModel +from ..core.pydantic_utilities import UniversalBaseModel import typing from .get_voice_gender import GetVoiceGender from .get_voices_model import GetVoicesModel from .get_voice_type import GetVoiceType -from ...core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2 import pydantic diff --git a/src/speechify/tts/types/get_voice_gender.py b/src/speechify/types/get_voice_gender.py similarity index 100% rename from src/speechify/tts/types/get_voice_gender.py rename to src/speechify/types/get_voice_gender.py diff --git a/src/speechify/tts/types/get_voice_language.py b/src/speechify/types/get_voice_language.py similarity index 81% rename from src/speechify/tts/types/get_voice_language.py rename to src/speechify/types/get_voice_language.py index 3062016..92d6cc6 100644 --- a/src/speechify/tts/types/get_voice_language.py +++ b/src/speechify/types/get_voice_language.py @@ -1,8 +1,8 @@ # This file was auto-generated by Fern from our API Definition. -from ...core.pydantic_utilities import UniversalBaseModel +from ..core.pydantic_utilities import UniversalBaseModel import typing -from ...core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2 import pydantic diff --git a/src/speechify/tts/types/get_voice_type.py b/src/speechify/types/get_voice_type.py similarity index 100% rename from src/speechify/tts/types/get_voice_type.py rename to src/speechify/types/get_voice_type.py diff --git a/src/speechify/tts/types/get_voices_model.py b/src/speechify/types/get_voices_model.py similarity index 84% rename from src/speechify/tts/types/get_voices_model.py rename to src/speechify/types/get_voices_model.py index d68df75..fec07ba 100644 --- a/src/speechify/tts/types/get_voices_model.py +++ b/src/speechify/types/get_voices_model.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ...core.pydantic_utilities import UniversalBaseModel +from ..core.pydantic_utilities import UniversalBaseModel import typing from .get_voice_language import GetVoiceLanguage from .get_voices_model_name import GetVoicesModelName -from ...core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2 import pydantic diff --git a/src/speechify/types/get_voices_model_name.py b/src/speechify/types/get_voices_model_name.py new file mode 100644 index 0000000..7ec7d98 --- /dev/null +++ b/src/speechify/types/get_voices_model_name.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +GetVoicesModelName = typing.Union[typing.Literal["simba-english", "simba-multilingual", "simba-3.0"], typing.Any] diff --git a/src/speechify/tts/types/nested_chunk.py b/src/speechify/types/nested_chunk.py similarity index 88% rename from src/speechify/tts/types/nested_chunk.py rename to src/speechify/types/nested_chunk.py index d842e83..b19d967 100644 --- a/src/speechify/tts/types/nested_chunk.py +++ b/src/speechify/types/nested_chunk.py @@ -1,8 +1,8 @@ # This file was auto-generated by Fern from our API Definition. -from ...core.pydantic_utilities import UniversalBaseModel +from ..core.pydantic_utilities import UniversalBaseModel import typing -from ...core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2 import pydantic diff --git a/src/speechify/tts/types/speech_marks.py b/src/speechify/types/speech_marks.py similarity index 88% rename from src/speechify/tts/types/speech_marks.py rename to src/speechify/types/speech_marks.py index d0bc925..dc225d2 100644 --- a/src/speechify/tts/types/speech_marks.py +++ b/src/speechify/types/speech_marks.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ...core.pydantic_utilities import UniversalBaseModel +from ..core.pydantic_utilities import UniversalBaseModel import typing from .nested_chunk import NestedChunk import pydantic -from ...core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2 class SpeechMarks(UniversalBaseModel):