From 648f2a2594021ad6034e7dfcccf3a5c1e9c56f37 Mon Sep 17 00:00:00 2001 From: Anthony Minessale II Date: Mon, 10 Aug 2026 14:55:49 -0500 Subject: [PATCH 1/3] fix(release): green the publish gate set against porting-sdk main MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Publishing is gated on the full run-ci, and publish-release.yml checks porting-sdk out at a hard `ref: main` — deliberately, so a release can never ship from an unmerged wave branch (porting-sdk/COORDINATED_PASS.md). So the release path is judged against porting-sdk MAIN, not the wave6 branch that test.yml is currently pinned to via PORTING_SDK_REF. This makes that path green. GEN-FRESH — revert the generated files to what porting-sdk MAIN's specs produce. My earlier commit regenerated them against the wave6 specs, which greened test.yml's copy of the gate but broke the release copy. Only one of the two can be satisfied while the pin is set, and per COORDINATED_PASS.md the release path is the one that must hold: publish never builds from a wave. Verified: `--check` clean against porting-sdk main. DOC-AUDIT — `get_stats` is a real method on SearchEngine (signalwire/search/search_engine.py), and `signalwire.search.` is excluded from the oracle by design ("RAG / vector-search BACKEND (approved py-only)"). Added to DOC_AUDIT_IGNORE.md under the existing Search-subsystem section, which already names examples/local_search_agent.py. `router` needed nothing — it resolves once the oracle knows about ChatGateway. DOC-SURFACE — documented the public symbols the ai_chat commits added without docstrings: GatewayRejection.__init__, ChatGateway.__init__/close/check_key, AIChatError.__init__, AIChatClient.__init__/close, and the ConversationInfo / ChatResponse / ChatLog dataclasses. Real Args/Returns/Raises, including the things worth knowing: check_key uses compare_digest so it cannot be walked a character at a time, ChatLog.messages holds the system prompt and tool traffic and must not be relayed to a browser, and an omitted gateway secret is per-process so handles stop verifying across a restart. Pairs with porting-sdk: the oracle regen (ChatGateway is new surface the committed oracle predates) and a doc_surface.py fix. Verified against porting-sdk main: DRIFT, SEMVER-DIFF, GEN-FRESH, DOC-AUDIT, DOC-SURFACE, LINT, FMT, NO-CHEAT and ~30 other gates all PASS. The only local reds are TYPECHECK and TEST, both environment-only: 16 mypy findings in mcp_gateway/search that CI does not report (its 8 files are entirely different) and the 6 mcp_gateway tests that fail identically on unmodified main. 5940 tests pass. --- DOC_AUDIT_IGNORE.md | 1 + signalwire/signalwire/ai_chat/client.py | 61 + signalwire/signalwire/ai_chat/gateway.py | 52 + .../signalwire/core/post_prompt_generated.py | 51 +- .../core/swaig_actions_generated.py | 155 +- .../core/swaig_request_generated.py | 8 +- .../signalwire/core/swml_verbs_generated.py | 2037 +++++++++++++---- .../relay/protocol_types_generated.py | 8 +- tests/unit/rest/fabric_generated_test.py | 16 +- tests/unit/rest/mfa_generated_test.py | 4 +- 10 files changed, 1783 insertions(+), 610 deletions(-) diff --git a/DOC_AUDIT_IGNORE.md b/DOC_AUDIT_IGNORE.md index 5d7806a3..351441ab 100644 --- a/DOC_AUDIT_IGNORE.md +++ b/DOC_AUDIT_IGNORE.md @@ -98,6 +98,7 @@ similarity_search: langchain/pinecone Pinecone.similarity_search — search comp build_index: real IndexBuilder.build_index (signalwire/search/index_builder.py) — Python-only search skill, absent from the cross-port surface build_index_from_sources: real IndexBuilder.build_index_from_sources (signalwire/search/index_builder.py) — Python-only search skill, absent from the cross-port surface migrate_sqlite_to_pgvector: real migration helper (signalwire/search/migration.py) — Python-only search skill, absent from the cross-port surface +get_stats: real SearchEngine.get_stats (signalwire/search/search_engine.py) — Python-only search skill, absent from the cross-port surface argsort: numpy.argsort — DIY search example in docs/search_overview.md md: filename-extension regex false positive (matches `file.md (…`) in docs/search_overview.md processing listing do_search: user-defined method inside a caching example in docs/search_deployment.md diff --git a/signalwire/signalwire/ai_chat/client.py b/signalwire/signalwire/ai_chat/client.py index a33ce25b..7f3259a3 100644 --- a/signalwire/signalwire/ai_chat/client.py +++ b/signalwire/signalwire/ai_chat/client.py @@ -66,6 +66,14 @@ class AIChatError(Exception): """Base error for AI Chat service failures.""" def __init__(self, code: int | None, message: str) -> None: + """Carry the service's own failure code alongside its message. + + Args: + code: JSON-RPC error code from the service (e.g. -32001 unknown + conversation, -32009 rejected identity), or None when the + failure happened below the JSON-RPC layer (transport, bad HTTP). + message: Human-readable description from the service. + """ self.code = code self.message = message super().__init__(f"[{code}] {message}") @@ -109,6 +117,16 @@ class SummaryError(AIChatError): @dataclass class ConversationInfo: + """A conversation as the service reports it after create/end. + + Attributes: + id: Service-assigned conversation id. This, not anything the caller + supplies, is what later turns must reference. + status: Lifecycle state reported by the service (e.g. "created", + "ended"). + initial_message: Opening line when the agent speaks first, else None. + """ + id: str status: str initial_message: str | None = None @@ -116,6 +134,17 @@ class ConversationInfo: @dataclass class ChatResponse: + """One assistant turn. + + Attributes: + text: What the assistant said — the only field a simple client needs. + conversation_id: Conversation this turn belongs to, for the next turn. + user_event: Structured payload the agent emitted alongside the text + (a SWML user_event), or None. This is how an agent asks the client + to do something — render a form, show a keypad — rather than only + speak. + """ + text: str conversation_id: str user_event: dict[str, Any] | None = None @@ -123,6 +152,16 @@ class ChatResponse: @dataclass class ChatLog: + """A conversation transcript as the service stores it. + + Attributes: + messages: Every turn, INCLUDING the substituted system prompt and tool + traffic. Do not relay this to a browser verbatim — see + `ChatGateway.visible_messages`, which reduces it to the dialogue. + call_timeline: Timed events for the conversation, when the service + reports them. + """ + messages: list[dict[str, Any]] = field(default_factory=list) call_timeline: list[dict[str, Any]] = field(default_factory=list) @@ -141,6 +180,23 @@ def __init__( url: str | None = None, session: aiohttp.ClientSession | None = None, ) -> None: + """Build a client for the AI Chat service. + + Each argument falls back to its environment variable, so a configured + environment needs no arguments at all. + + Args: + project: Project id. Falls back to `SIGNALWIRE_PROJECT_ID`. + token: API token. Falls back to `SIGNALWIRE_API_TOKEN`. + space: Space name used to build the default URL. Falls back to + `SIGNALWIRE_SPACE`. + url: Full service URL, overriding the one derived from `space`. + session: An existing aiohttp session to reuse. Omit and the client + creates (and owns, and closes) its own. + + Raises: + ValueError: If no project id is available from either source. + """ self._project = project or os.environ.get("SIGNALWIRE_PROJECT_ID", "") self._token = token or os.environ.get("SIGNALWIRE_API_TOKEN", "") space = space or os.environ.get("SIGNALWIRE_SPACE", "") @@ -201,6 +257,11 @@ async def _ensure_session(self) -> aiohttp.ClientSession: return self._session async def close(self) -> None: + """Close the HTTP session, if this client owns it. + + A session passed in via `session=` belongs to the caller and is left + open; only one the client created for itself is closed here. + """ if self._owns_session and self._session is not None: await self._session.close() self._session = None diff --git a/signalwire/signalwire/ai_chat/gateway.py b/signalwire/signalwire/ai_chat/gateway.py index 4d27e259..4f904c7b 100644 --- a/signalwire/signalwire/ai_chat/gateway.py +++ b/signalwire/signalwire/ai_chat/gateway.py @@ -99,6 +99,14 @@ class GatewayRejection(Exception): """ def __init__(self, status: int, reason: str) -> None: + """Refuse a browser request with the HTTP status the route should return. + + Args: + status: HTTP status to send back (401 bad key, 403 origin/handle, + 400 disallowed method, 429 a cap was hit). + reason: Short, non-leaking explanation. It reaches the browser, so + it must not disclose why a handle failed to verify. + """ self.status = status self.reason = reason super().__init__(f"{status}: {reason}") @@ -156,6 +164,34 @@ def __init__( max_turns: int = DEFAULT_MAX_TURNS, window_seconds: int = DEFAULT_WINDOW_SECONDS, ) -> None: + """Build a gateway that fronts one agent for browser traffic. + + Args: + config_url: SWML config the gateway always sends upstream. Required, + and never taken from the request body — if a browser could name + it, whoever holds a key would pick which agent runs and which + project pays for it. + key: Publishable key the browser presents. Safe to ship in a page: + it names no credential and the caps below bound what it can cost. + allowed_origins: Origins permitted to call in. localhost is always + allowed so `pip install` → run works without shipping + open-by-default; every other origin must be listed. + client: An `AIChatClient` to reuse. Omit and the gateway builds (and + owns) its own from the ambient credentials. + secret: HMAC key for signing conversation handles. Omit to generate + one per process — handles then stop verifying across a restart + or a second worker, so set it in production. + handle_ttl: Seconds a signed handle stays valid. + conversation_timeout: Idle seconds before the service ends a + conversation. Omit to report the service default. + max_new_conversations: Cap on conversations minted per window — the + control that makes a leaked key a bill rather than a breach. + max_turns: Cap on turns per conversation. + window_seconds: Length of the rolling window the caps count over. + + Raises: + ValueError: If `config_url` is empty. + """ if not config_url: raise ValueError("config_url is required — it is what a key is scoped to.") @@ -223,6 +259,11 @@ def effective_timeout(self) -> int: return self.conversation_timeout or SERVICE_DEFAULT_CONVERSATION_TIMEOUT async def close(self) -> None: + """Release the upstream HTTP session, if this gateway owns it. + + A client passed in via `client=` belongs to the caller and is left + open; only a client the gateway built for itself is closed here. + """ if self._owns_client: await self._client.close() @@ -288,6 +329,17 @@ def check_origin(self, origin: str | None) -> None: raise GatewayRejection(403, "origin not allowed") def check_key(self, presented: str | None) -> None: + """Verify the publishable key the browser sent. + + Compared with `hmac.compare_digest` rather than `==` so the check does + not leak the key a character at a time through timing. + + Args: + presented: Key from the request, or None when the header is absent. + + Raises: + GatewayRejection: 401 if the key is missing or does not match. + """ if not presented or not hmac.compare_digest(presented, self.key): raise GatewayRejection(401, "bad key") diff --git a/signalwire/signalwire/core/post_prompt_generated.py b/signalwire/signalwire/core/post_prompt_generated.py index b677404b..659fa3e5 100644 --- a/signalwire/signalwire/core/post_prompt_generated.py +++ b/signalwire/signalwire/core/post_prompt_generated.py @@ -9,10 +9,9 @@ from typing import Any, Literal, TypeAlias, TypedDict from typing import TYPE_CHECKING -# Types owned by sibling swaig specs, imported so the cross-file -# $ref fields below resolve to the real type rather than a dict. +# SwaigRequest is generated in swaig_request_generated; aliased here for the +# swaig_log entry's post_data field. if TYPE_CHECKING: - from signalwire.core.swaig_actions_generated import SwaigResponse as SwaigResponse from signalwire.core.swaig_request_generated import SwaigRequest as SwaigRequest @@ -70,7 +69,7 @@ class PostPrompt(TypedDict, total=False): class PostPromptData(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - parsed: list[dict[str, Any] | list[Any]] + parsed: list[dict[str, Any]] raw: str substituted: str @@ -161,40 +160,14 @@ class PostPromptSystemLogEntry(TypedDict, total=False): role: str content: str timestamp: int - action: Literal[ - "attention_timeout", - "attention_wait", - "auto_correct", - "change_step_failed", - "check_for_input", - "context_enter", - "double_turn", - "filler", - "function_call", - "function_error", - "function_loop", - "gather_answer", - "gather_complete", - "gather_question", - "gather_reject", - "gather_start", - "hangup_hook", - "hearing_hint", - "inner_dialog", - "inner_dialog_scorecard", - "manual_say", - "reset", - "session_end", - "session_start", - "startup_hook", - "step_change", - "summarize_start", - "swaig_problem", - ] + action: str lang: str tokens: int content_type: str metadata: dict[str, Any] + context: str + step: str + step_index: int class PostPromptSystemEntry(TypedDict, total=False): @@ -211,16 +184,16 @@ class PostPromptSwaigLogEntry(TypedDict, total=False): command_name: str command_arg: str epoch_time: int - native: Literal[True] + native: bool active_count: int | Literal["endless"] url: str post_data: SwaigRequest - post_response: SwaigResponse - delayed_post_response: SwaigResponse + post_response: dict[str, Any] + delayed_post_response: dict[str, Any] mcp_url: str mcp_tool: str - mcp_response: str - mcp_error: Literal[True] + mcp_response: dict[str, Any] + mcp_error: str class PostPromptTimesEntry(TypedDict, total=False): diff --git a/signalwire/signalwire/core/swaig_actions_generated.py b/signalwire/signalwire/core/swaig_actions_generated.py index 9faf4083..f967a192 100644 --- a/signalwire/signalwire/core/swaig_actions_generated.py +++ b/signalwire/signalwire/core/swaig_actions_generated.py @@ -17,228 +17,171 @@ class ContextSwitchAction(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - consolidate: bool | str - full_reset: bool | str - system_pom: dict[str, Any] - system_prompt: str - user_pom: dict[str, Any] - user_prompt: str + system_prompt: Any + user_prompt: Any + system_pom: Any + user_pom: Any + consolidate: bool + full_reset: bool class HoldAction(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - timeout: float | str + timeout: int class PlaybackBgAction(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - file: str - wait: bool | str + file: Any + wait: bool class TransferAction(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - dest: str - summarize: bool | str - - -class SwaigAction(TypedDict, total=False): - """A response-action object. The keys below are the full vocabulary dispatched by actions.c::process_action; an action object sets one or more of them. Each key's source line is the engine dispatch site. - - Open shape: extra server keys permitted; not validated at runtime. - """ - - SWML: str | dict[str, Any] - add_dynamic_hints: list[dict[str, Any] | str] - back_to_back_functions: bool | Literal["forever"] | str - change_context: str - change_step: str - clear_dynamic_hints: bool | str - context_switch: str | ContextSwitchAction - end_of_speech_timeout: int - extensive_data: bool | str - functions_on_speaker_timeout: bool | str - hangup: bool | str - hold: int | str | HoldAction - playback_bg: str | PlaybackBgAction - replace_in_history: str | Literal[True] - say: str - set_global_data: dict[str, Any] - set_meta_data: dict[str, Any] - settings: dict[str, Any] - speech_event_timeout: int - stop: bool | str - stop_playback_bg: bool | str | int | dict[str, Any] | list[Any] | None - toggle_functions: list[dict[str, Any]] - transfer: str | TransferAction - unset_global_data: str | list[str] - unset_meta_data: str | list[str] - user_event: dict[str, Any] - user_input: str - wait_for_user: bool | int | Literal["answer_first"] | str - - -class SwaigResponse(TypedDict, total=False): - """Parsed at actions.c:2228-2276. - - Open shape: extra server keys are permitted and partial payloads are valid; - not validated at runtime (a TypedDict is a plain ``dict``). - """ - - response: str - action: SwaigAction | list[SwaigAction] - post_process: bool + dest: Any + summarize: bool class _SwaigActions: """Typed SWAIG response-action builders (one per wire action). The host class provides ``self.action`` (the list serialized to the wire).""" - def SWML(self: _Self, value: str | dict[str, Any]) -> _Self: - """Execute a SWML document inline, or with sibling `transfer:true` transfer the call into it. Gated by `swaig_allow_swml`. **Transfer additionally requires `from_relay`** (`actions.c:142-145`); inline execution captures an optional `ai_response` SWML var back into the conversation""" # actions.c:129 - self.action.append({"SWML": value}) # type: ignore[attr-defined] - return self - - def add_dynamic_hints(self: _Self, value: list[dict[str, Any] | str]) -> _Self: - """Add ASR hints. Strings go to `dynamic_hints`; `{hint, ...}` objects go to `dynamic_hearing_hints` (and the `hint` value is also added to `dynamic_hints`). Restarts speech detection""" # actions.c:550 + def add_dynamic_hints(self: _Self, value: list[Any]) -> _Self: + """Add ASR hints. Strings go to `dynamic_hints`; `{hint, ...}` objects go to `dynamic_hearing_hints` (and the `hint` value is also added to `dynamic_hints`). Restarts speech detection""" # actions.c:547 self.action.append({"add_dynamic_hints": value}) # type: ignore[attr-defined] return self - def back_to_back_functions( - self: _Self, value: bool | Literal["forever"] | str - ) -> _Self: - """Allow consecutive function calls without a user turn. `true` = `1`, `"forever"` = `2`""" # actions.c:362 + def back_to_back_functions(self: _Self, value: bool | Literal["forever"]) -> _Self: + """Allow consecutive function calls without a user turn. `true` = `1`, `"forever"` = `2`""" # actions.c:359 self.action.append({"back_to_back_functions": value}) # type: ignore[attr-defined] return self def change_context(self: _Self, value: str) -> _Self: - """Switch to a named **context** (same machinery as the `change_context` function)""" # actions.c:241 + """Switch to a named **context** (same machinery as the `change_context` function)""" # actions.c:238 self.action.append({"change_context": value}) # type: ignore[attr-defined] return self def change_step(self: _Self, value: str) -> _Self: - """Switch to a named **step** (or `"next"`)""" # actions.c:251 + """Switch to a named **step** (or `"next"`)""" # actions.c:248 self.action.append({"change_step": value}) # type: ignore[attr-defined] return self - def clear_dynamic_hints(self: _Self, value: bool | str) -> _Self: - """Clear both dynamic hint lists and restart speech detection""" # actions.c:582 + def clear_dynamic_hints(self: _Self, value: dict[str, Any]) -> _Self: + """Clear both dynamic hint lists and restart speech detection""" # actions.c:579 self.action.append({"clear_dynamic_hints": value}) # type: ignore[attr-defined] return self def context_switch(self: _Self, value: str | ContextSwitchAction) -> _Self: - """Replace the system prompt / start a new conversation context. Object form: `{system_prompt, user_prompt, system_pom, user_pom, consolidate, full_reset}`. `system_pom`/`user_pom` render to prompt text; prompts are expanded against prompt vars + post_data; `consolidate:true` summarizes first""" # actions.c:597 + """Replace the system prompt / start a new conversation context. Object form: `{system_prompt, user_prompt, system_pom, user_pom, consolidate, full_reset}`. `system_pom`/`user_pom` render to prompt text; prompts are expanded against prompt vars + post_data; `consolidate:true` summarizes first""" # actions.c:594 self.action.append({"context_switch": value}) # type: ignore[attr-defined] return self def end_of_speech_timeout(self: _Self, value: int) -> _Self: - """Set end-of-speech detection timeout (must be >0)""" # actions.c:315 + """Set end-of-speech detection timeout (must be >0)""" # actions.c:312 self.action.append({"end_of_speech_timeout": value}) # type: ignore[attr-defined] return self - def extensive_data(self: _Self, value: bool | str) -> _Self: - """Enable extensive data in the function/conversation log""" # actions.c:376 + def extensive_data(self: _Self, value: bool) -> _Self: + """Enable extensive data in the function/conversation log""" # actions.c:373 self.action.append({"extensive_data": value}) # type: ignore[attr-defined] return self - def functions_on_speaker_timeout(self: _Self, value: bool | str) -> _Self: - """Set whether functions may fire on speaker timeout""" # actions.c:372 + def functions_on_speaker_timeout(self: _Self, value: bool) -> _Self: + """Set whether functions may fire on speaker timeout""" # actions.c:369 self.action.append({"functions_on_speaker_timeout": value}) # type: ignore[attr-defined] return self - def hangup(self: _Self, value: bool | str) -> _Self: - """Set `offhook = 0` (hang up). Note: a graceful "say goodbye" hangup is the **built-in `hangup` function**, not this action""" # actions.c:297 + def hangup(self: _Self, value: dict[str, Any]) -> _Self: + """Set `offhook = 0` (hang up). Note: a graceful "say goodbye" hangup is the **built-in `hangup` function**, not this action""" # actions.c:294 self.action.append({"hangup": value}) # type: ignore[attr-defined] return self def hold(self: _Self, value: int | str | HoldAction) -> _Self: - """Put the call on hold for N seconds. Accepts a number, a time string (`"5m"`, `"1:30"` via `parse_time`), or `{timeout}`. Default 300s; values <0 or >900 clamp to 300""" # actions.c:261 + """Put the call on hold for N seconds. Accepts a number, a time string (`"5m"`, `"1:30"` via `parse_time`), or `{timeout}`. Default 300s; values <0 or >900 clamp to 300""" # actions.c:258 self.action.append({"hold": value}) # type: ignore[attr-defined] return self def playback_bg(self: _Self, value: str | PlaybackBgAction) -> _Self: - """Play an audio file in the background. `{wait:true}` makes the agent wait for it. Replaces any currently-open background file""" # actions.c:698 + """Play an audio file in the background. `{wait:true}` makes the agent wait for it. Replaces any currently-open background file""" # actions.c:695 self.action.append({"playback_bg": value}) # type: ignore[attr-defined] return self def replace_in_history(self: _Self, value: str | Literal[True]) -> _Self: - """Replace the function call's text in conversation history. A string is stored prefixed with `~LN()-; `; `true` stores an empty string""" # actions.c:382 + """Replace the function call's text in conversation history. A string is stored prefixed with `~LN()-; `; `true` stores an empty string""" # actions.c:379 self.action.append({"replace_in_history": value}) # type: ignore[attr-defined] return self def say(self: _Self, value: str) -> _Self: - """Speak text immediately via TTS, then wait for speaking to finish. Also logs `tl_manual_say`""" # actions.c:437 + """Speak text immediately via TTS, then wait for speaking to finish. Also logs `tl_manual_say`""" # actions.c:434 self.action.append({"say": value}) # type: ignore[attr-defined] return self def set_global_data(self: _Self, value: dict[str, Any]) -> _Self: - """Merge keys into global data, then refresh prompt vars. Gated by `swaig_set_global_data`""" # actions.c:501 + """Merge keys into global data, then refresh prompt vars. Gated by `swaig_set_global_data`""" # actions.c:498 self.action.append({"set_global_data": value}) # type: ignore[attr-defined] return self def set_meta_data(self: _Self, value: dict[str, Any]) -> _Self: - """Merge keys into the calling function's metadata store (keyed by its `meta_data_token`)""" # actions.c:462 + """Merge keys into the calling function's metadata store (keyed by its `meta_data_token`)""" # actions.c:459 self.action.append({"set_meta_data": value}) # type: ignore[attr-defined] return self def settings(self: _Self, value: dict[str, Any]) -> _Self: - """Modify LLM settings at runtime (`parse_json_settings`). Gated by `swaig_allow_settings`""" # actions.c:445 + """Modify LLM settings at runtime (`parse_json_settings`). Gated by `swaig_allow_settings`""" # actions.c:442 self.action.append({"settings": value}) # type: ignore[attr-defined] return self def speech_event_timeout(self: _Self, value: int) -> _Self: - """Set speech event timeout (must be >0)""" # actions.c:329 + """Set speech event timeout (must be >0)""" # actions.c:326 self.action.append({"speech_event_timeout": value}) # type: ignore[attr-defined] return self - def stop(self: _Self, value: bool | str) -> _Self: - """Stop the AI agent immediately (interrupt + `running = 0`)""" # actions.c:455 + def stop(self: _Self, value: dict[str, Any]) -> _Self: + """Stop the AI agent immediately (interrupt + `running = 0`)""" # actions.c:452 self.action.append({"stop": value}) # type: ignore[attr-defined] return self - def stop_playback_bg( - self: _Self, value: bool | str | int | dict[str, Any] | list[Any] | None - ) -> _Self: - """Stop/close the background audio file""" # actions.c:688 + def stop_playback_bg(self: _Self, value: dict[str, Any]) -> _Self: + """Stop/close the background audio file""" # actions.c:685 self.action.append({"stop_playback_bg": value}) # type: ignore[attr-defined] return self def toggle_functions(self: _Self, value: list[dict[str, Any]]) -> _Self: - """Enable/disable functions. `active` via `check_active`: `-1` default/toggle, `0` off, `1+` use-count. **Only affects functions sharing the calling function's `meta_data_token`** (`actions.c:419-420`)""" # actions.c:392 + """Enable/disable functions. `active` via `check_active`: `-1` default/toggle, `0` off, `1+` use-count. **Only affects functions sharing the calling function's `meta_data_token`** (`actions.c:419-420`)""" # actions.c:389 self.action.append({"toggle_functions": value}) # type: ignore[attr-defined] return self def transfer(self: _Self, value: str | TransferAction) -> _Self: - """Transfer the call to `dest`. `summarize:true` sets `transfer_summary`. Sets `openai_transfer_check` var, interrupts, stops the loop. Ignored if already interrupted""" # actions.c:343 + """Transfer the call to `dest`. `summarize:true` sets `transfer_summary`. Sets `openai_transfer_check` var, interrupts, stops the loop. Ignored if already interrupted""" # actions.c:136 self.action.append({"transfer": value}) # type: ignore[attr-defined] return self - def unset_global_data(self: _Self, value: str | list[str]) -> _Self: - """Remove key(s) from global data, then refresh prompt vars. Gated by `swaig_set_global_data`""" # actions.c:518 + def unset_global_data(self: _Self, value: str | list[Any]) -> _Self: + """Remove key(s) from global data, then refresh prompt vars. Gated by `swaig_set_global_data`""" # actions.c:515 self.action.append({"unset_global_data": value}) # type: ignore[attr-defined] return self - def unset_meta_data(self: _Self, value: str | list[str]) -> _Self: - """Remove key(s) from the calling function's metadata store""" # actions.c:480 + def unset_meta_data(self: _Self, value: str | list[Any]) -> _Self: + """Remove key(s) from the calling function's metadata store""" # actions.c:477 self.action.append({"unset_meta_data": value}) # type: ignore[attr-defined] return self def user_event(self: _Self, value: dict[str, Any]) -> _Self: - """Fire relay event `calling.user_event` with the object as payload""" # actions.c:234 + """Fire relay event `calling.user_event` with the object as payload""" # actions.c:231 self.action.append({"user_event": value}) # type: ignore[attr-defined] return self def user_input(self: _Self, value: str) -> _Self: - """Push text onto the input queue as if the user spoke it""" # actions.c:544 + """Push text onto the input queue as if the user spoke it""" # actions.c:541 self.action.append({"user_input": value}) # type: ignore[attr-defined] return self def wait_for_user( - self: _Self, value: bool | int | Literal["answer_first"] | str + self: _Self, value: bool | int | Literal["answer_first"] ) -> _Self: - """`true` = `1`, a number sets a count, `"answer_first"` = `2` (require caller answer)""" # actions.c:303 + """`true` = `1`, a number sets a count, `"answer_first"` = `2` (require caller answer)""" # actions.c:300 self.action.append({"wait_for_user": value}) # type: ignore[attr-defined] return self diff --git a/signalwire/signalwire/core/swaig_request_generated.py b/signalwire/signalwire/core/swaig_request_generated.py index 68563576..a8bb56c0 100644 --- a/signalwire/signalwire/core/swaig_request_generated.py +++ b/signalwire/signalwire/core/swaig_request_generated.py @@ -13,7 +13,7 @@ class SwaigArgument(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - parsed: list[dict[str, Any] | list[Any]] + parsed: list[Any] raw: str substituted: str @@ -21,15 +21,13 @@ class SwaigArgument(TypedDict, total=False): class SwaigRequest(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - SWMLCall: dict[str, Any] - SWMLVars: dict[str, Any] ai_session_id: str app_name: str args: str argument: SwaigArgument argument_desc: dict[str, Any] call_id: str - call_log: list[dict[str, Any]] + call_log: list[Any] caller_id_name: str caller_id_num: str channel_active: bool @@ -47,6 +45,6 @@ class SwaigRequest(TypedDict, total=False): meta_data: dict[str, Any] meta_data_token: str project_id: str - raw_call_log: list[dict[str, Any]] + raw_call_log: list[Any] space_id: str version: Literal["2.0"] diff --git a/signalwire/signalwire/core/swml_verbs_generated.py b/signalwire/signalwire/core/swml_verbs_generated.py index 93d32995..0c981eae 100644 --- a/signalwire/signalwire/core/swml_verbs_generated.py +++ b/signalwire/signalwire/core/swml_verbs_generated.py @@ -14,889 +14,2040 @@ _Self = TypeVar("_Self", bound="_SwmlVerbs") +class Section(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + main: list[SWMLMethod] + + +SWMLMethod: TypeAlias = "Answer | AI | AmazonBedrock | Cond | Connect | Denoise | EnterQueue | Execute | Goto | Label | LiveTranscribe | AiSidecar | LiveTranslate | Hangup | JoinRoom | JoinConference | Play | Prompt | ReceiveFax | Record | RecordCall | Request | Return | SendDigits | SendFax | SendSMS | Set | Sleep | SIPRefer | StopDenoise | StopRecordCall | StopTap | Switch | Tap | Transfer | Unset | Pay | DetectMachine | UserEvent" + + +class Answer(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + answer: dict[str, Any] + + class AI(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - ai: dict[str, Any] | list[Any] + ai: AIObject + + +class AmazonBedrock(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + amazon_bedrock: AmazonBedrockObject + + +class Cond(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + cond: list[CondParams] + + +class Connect(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + connect: ( + ConnectDeviceSingle + | ConnectDeviceSerial + | ConnectDeviceParallel + | ConnectDeviceSerialParallel + ) + + +class Denoise(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + denoise: dict[str, Any] + + +class EnterQueue(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + enter_queue: EnterQueueObject + + +class Execute(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + execute: dict[str, Any] + + +class Goto(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + goto: dict[str, Any] + + +class Label(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + label: str + + +class LiveTranscribe(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + live_transcribe: dict[str, Any] + + +class LiveTranslate(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + live_translate: dict[str, Any] + + +class Hangup(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + hangup: dict[str, Any] + + +class JoinRoom(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + join_room: dict[str, Any] + + +class JoinConference(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + join_conference: JoinConferenceObject + + +class Play(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + play: PlayWithURL | PlayWithURLS + + +class Prompt(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + prompt: dict[str, Any] + + +class ReceiveFax(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + receive_fax: dict[str, Any] + + +class Record(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + record: dict[str, Any] + + +class RecordCall(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + record_call: dict[str, Any] + + +class Request(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + request: dict[str, Any] + + +class Return(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + # non-identifier field 'return': dict[str, Any] + + +class SendDigits(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + send_digits: dict[str, Any] + + +class SendFax(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + send_fax: dict[str, Any] + + +class SendSMS(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + send_sms: SMSWithBody | SMSWithMedia + + +class Set(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + set: dict[str, Any] + + +class Sleep(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + sleep: dict[str, Any] | int | SWMLVar + + +class SIPRefer(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + sip_refer: dict[str, Any] + + +class StopDenoise(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + stop_denoise: dict[str, Any] + + +class StopRecordCall(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + stop_record_call: dict[str, Any] + + +class StopTap(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + stop_tap: dict[str, Any] + + +class Switch(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + switch: dict[str, Any] + + +class Tap(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + tap: dict[str, Any] + + +class Transfer(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + transfer: dict[str, Any] + + +class Unset(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + unset: str | list[str] + + +class Pay(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + pay: dict[str, Any] + + +class DetectMachine(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + detect_machine: dict[str, Any] + + +class UserEvent(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + user_event: dict[str, Any] + + +SWMLVar: TypeAlias = "str" + + +class AIObject(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + global_data: dict[str, Any] + hints: list[str | Hint] + languages: list[Languages] + params: AIParams + post_prompt: AIPostPrompt + post_prompt_url: str + pronounce: list[Pronounce] + prompt: AIPrompt + SWAIG: SWAIG + + +class AmazonBedrockObject(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + global_data: dict[str, Any] + params: BedrockParams + post_prompt: BedrockPostPrompt + post_prompt_url: str + prompt: BedrockPrompt + SWAIG: BedrockSWAIG + + +CondParams: TypeAlias = "CondReg | CondElse" + + +class ConnectDeviceSingle(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + # non-identifier field 'from': str + headers: list[ConnectHeaders] + codecs: str + webrtc_media: bool | SWMLVar + session_timeout: int | SWMLVar + ringback: list[str] | RingbackConfig + result: ConnectSwitch | list[CondParams] + timeout: int | SWMLVar + max_duration: int | SWMLVar + answer_on_bridge: bool | SWMLVar + confirm: str | list[ValidConfirmMethods] + confirm_timeout: int | SWMLVar + username: str + password: str + encryption: Literal["mandatory"] | Literal["optional"] | Literal["forbidden"] + call_state_url: str + transfer_after_bridge: str | SWMLVar + call_state_events: list[CallStatus] + to: str + + +class ConnectDeviceSerial(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + # non-identifier field 'from': str + headers: list[ConnectHeaders] + codecs: str + webrtc_media: bool | SWMLVar + session_timeout: int | SWMLVar + ringback: list[str] | RingbackConfig + result: ConnectSwitch | list[CondParams] + timeout: int | SWMLVar + max_duration: int | SWMLVar + answer_on_bridge: bool | SWMLVar + confirm: str | list[ValidConfirmMethods] + confirm_timeout: int | SWMLVar + username: str + password: str + encryption: Literal["mandatory"] | Literal["optional"] | Literal["forbidden"] + call_state_url: str + transfer_after_bridge: str | SWMLVar + call_state_events: list[CallStatus] + serial: list[ConnectDeviceSingle] + + +class ConnectDeviceParallel(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + # non-identifier field 'from': str + headers: list[ConnectHeaders] + codecs: str + webrtc_media: bool | SWMLVar + session_timeout: int | SWMLVar + ringback: list[str] | RingbackConfig + result: ConnectSwitch | list[CondParams] + timeout: int | SWMLVar + max_duration: int | SWMLVar + answer_on_bridge: bool | SWMLVar + confirm: str | list[ValidConfirmMethods] + confirm_timeout: int | SWMLVar + username: str + password: str + encryption: Literal["mandatory"] | Literal["optional"] | Literal["forbidden"] + call_state_url: str + transfer_after_bridge: str | SWMLVar + call_state_events: list[CallStatus] + parallel: list[ConnectDeviceSingle] + + +class ConnectDeviceSerialParallel(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + # non-identifier field 'from': str + headers: list[ConnectHeaders] + codecs: str + webrtc_media: bool | SWMLVar + session_timeout: int | SWMLVar + ringback: list[str] | RingbackConfig + result: ConnectSwitch | list[CondParams] + timeout: int | SWMLVar + max_duration: int | SWMLVar + answer_on_bridge: bool | SWMLVar + confirm: str | list[ValidConfirmMethods] + confirm_timeout: int | SWMLVar + username: str + password: str + encryption: Literal["mandatory"] | Literal["optional"] | Literal["forbidden"] + call_state_url: str + transfer_after_bridge: str | SWMLVar + call_state_events: list[CallStatus] + serial_parallel: list[list[ConnectDeviceSingle]] + + +class EnterQueueObject(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + queue_name: str + transfer_after_bridge: str | SWMLVar + status_url: str + wait_url: str | SWMLVar + wait_time: int | SWMLVar + + +class ExecuteSwitch(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + variable: str + case: dict[str, Any] + default: list[SWMLMethod] + + +TranscribeAction: TypeAlias = ( + "TranscribeStartAction | Literal['stop'] | TranscribeSummarizeActionUnion" +) + + +TranslateAction: TypeAlias = ( + "StartAction | Literal['stop'] | SummarizeActionUnion | InjectAction" +) + + +class JoinConferenceObject(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + name: str + muted: bool | SWMLVar + beep: Literal["true"] | Literal["false"] | Literal["onEnter"] | Literal["onExit"] + start_on_enter: bool | SWMLVar + end_on_exit: bool | SWMLVar + wait_url: str | SWMLVar + max_participants: int | SWMLVar + record: Literal["do-not-record"] | Literal["record-from-start"] + region: str + trim: Literal["trim-silence"] | Literal["do-not-trim"] + coach: str + status_callback_event: ( + Literal["start"] + | Literal["end"] + | Literal["join"] + | Literal["leave"] + | Literal["mute"] + | Literal["hold"] + | Literal["modify"] + | Literal["speaker"] + | Literal["announcement"] + ) + status_callback: str + status_callback_method: Literal["GET"] | Literal["POST"] + recording_status_callback: str + recording_status_callback_method: Literal["GET"] | Literal["POST"] + recording_status_callback_event: ( + Literal["in-progress"] | Literal["completed"] | Literal["absent"] + ) + result: dict[str, Any] | list[CondParams] + + +class PlayWithURL(TypedDict, total=False): + """Play with a single URL + + Open shape: extra server keys are permitted and partial payloads are valid; + not validated at runtime (a TypedDict is a plain ``dict``). + """ + + auto_answer: bool | SWMLVar + volume: float | SWMLVar + say_voice: str + say_language: str + say_gender: Literal["male", "female"] + status_url: str + url: play_url | SWMLVar -class AiSidecar(TypedDict, total=False): +class PlayWithURLS(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - ai_sidecar: dict[str, Any] + auto_answer: bool | SWMLVar + volume: float | SWMLVar + say_voice: str + say_language: str + say_gender: Literal["male", "female"] + status_url: str + urls: list[play_url] | list[SWMLVar] -class AmazonBedrock(TypedDict, total=False): +play_url: TypeAlias = "str" + + +class SMSWithBody(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - amazon_bedrock: dict[str, Any] + to_number: str + from_number: str + region: str + tags: list[str] + body: str -class Answer(TypedDict, total=False): +class SMSWithMedia(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - answer: dict[str, Any] | list[Any] + to_number: str + from_number: str + region: str + tags: list[str] + media: list[str] + body: str -class CallDeviceStream(TypedDict, total=False): +class PayParameters(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - authorization_bearer_token: str - codec: str - custom_parameters: Any name: str - realtime: bool - status_url: str - status_url_method: Literal["GET", "POST"] - url: str + value: str + + +class PayPrompts(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + actions: list[PayPromptAction] + # non-identifier field 'for': str + attempts: str + card_type: str + error_type: str + + +class Hint(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + hint: str + pattern: str + replace: str + ignore_case: bool | SWMLVar + + +Languages: TypeAlias = "LanguagesWithSoloFillers | LanguagesWithFillers" + + +class AIParams(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + acknowledge_interruptions: bool | SWMLVar + ai_model: ( + Literal["gpt-4o-mini"] | Literal["gpt-4.1-mini"] | Literal["gpt-4.1-nano"] | str + ) + ai_name: str + ai_volume: int | SWMLVar + app_name: str + asr_smart_format: bool | SWMLVar + attention_timeout: AttentionTimeout | Literal[0] | SWMLVar + attention_timeout_prompt: str + asr_diarize: bool | SWMLVar + asr_speaker_affinity: bool | SWMLVar + background_file: str + background_file_loops: int | None | SWMLVar + background_file_volume: int | SWMLVar + enable_barge: str | bool | SWMLVar + enable_inner_dialog: bool | SWMLVar + enable_pause: bool | SWMLVar + enable_turn_detection: bool | SWMLVar + barge_match_string: str + barge_min_words: int | SWMLVar + barge_functions: bool | SWMLVar + conscience: str + convo: list[ConversationMessage] + conversation_id: str + conversation_sliding_window: int | SWMLVar + debug_webhook_level: int | SWMLVar + debug_webhook_url: str + debug: bool | int | SWMLVar + direction: Direction | SWMLVar + digit_terminators: str + digit_timeout: int | SWMLVar + end_of_speech_timeout: int | SWMLVar + enable_thinking: bool | SWMLVar + enable_vision: bool | SWMLVar + energy_level: float | SWMLVar + first_word_timeout: int | SWMLVar + function_wait_for_talking: bool | SWMLVar + functions_on_no_response: bool | SWMLVar + hard_stop_prompt: str + hard_stop_time: str | SWMLVar + hold_music: str + hold_on_process: bool | SWMLVar + inactivity_timeout: int | SWMLVar + inner_dialog_model: ( + Literal["gpt-4o-mini"] | Literal["gpt-4.1-mini"] | Literal["gpt-4.1-nano"] | str + ) + inner_dialog_prompt: str + inner_dialog_synced: bool | SWMLVar + initial_sleep_ms: int | SWMLVar + input_poll_freq: int | SWMLVar + interrupt_on_noise: bool | SWMLVar + interrupt_prompt: str + # deprecated: languages_enabled + languages_enabled: bool | SWMLVar + local_tz: str + llm_diarize_aware: bool | SWMLVar + max_emotion: int | SWMLVar + max_response_tokens: int | SWMLVar + openai_asr_engine: str + outbound_attention_timeout: int | SWMLVar + persist_global_data: bool | SWMLVar + pom_format: Literal["markdown"] | Literal["xml"] + save_conversation: bool | SWMLVar + speech_event_timeout: int | SWMLVar + speech_gen_quick_stops: int | SWMLVar + speech_timeout: int | SWMLVar + speak_when_spoken_to: bool | SWMLVar + start_paused: bool | SWMLVar + static_greeting: str + static_greeting_no_barge: bool | SWMLVar + summary_mode: Literal["string"] | Literal["original"] | SWMLVar + swaig_allow_settings: bool | SWMLVar + swaig_allow_swml: bool | SWMLVar + swaig_post_conversation: bool | SWMLVar + swaig_set_global_data: bool | SWMLVar + swaig_post_swml_vars: bool | list[str] | SWMLVar + thinking_model: ( + Literal["gpt-4o-mini"] | Literal["gpt-4.1-mini"] | Literal["gpt-4.1-nano"] | str + ) + transparent_barge: bool | SWMLVar + transparent_barge_max_time: int | SWMLVar + transfer_summary: bool | SWMLVar + turn_detection_timeout: int | SWMLVar + tts_number_format: Literal["international"] | Literal["national"] + video_listening_file: str + video_idle_file: str + video_talking_file: str + vision_model: ( + Literal["gpt-4o-mini"] | Literal["gpt-4.1-mini"] | Literal["gpt-4.1-nano"] | str + ) + vad_config: str + wait_for_user: bool | SWMLVar + wake_prefix: str + eleven_labs_stability: float | SWMLVar + eleven_labs_similarity: float | SWMLVar + + +AIPostPrompt: TypeAlias = "AIPostPromptText | AIPostPromptPom" + + +class Pronounce(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + replace: str + # non-identifier field 'with': str + ignore_case: bool | SWMLVar + + +AIPrompt: TypeAlias = "AIPromptText | AIPromptPom" + + +class SWAIG(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + defaults: SWAIGDefaults + native_functions: list[SWAIGNativeFunction] + includes: list[SWAIGIncludes] + functions: list[SWAIGFunction] + internal_fillers: SWAIGInternalFiller + + +class BedrockParams(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + attention_timeout: AttentionTimeout | Literal[0] | SWMLVar + hard_stop_time: str | SWMLVar + inactivity_timeout: int | SWMLVar + video_listening_file: str + video_idle_file: str + video_talking_file: str + hard_stop_prompt: str + + +BedrockPostPrompt: TypeAlias = "OmitPropertiesBedrockPostPomptTextOmittedPromptProps | OmitPropertiesBedrockPostPromptPomOmittedPromptProps" + + +BedrockPrompt: TypeAlias = "OmitPropertiesBedrockPromptTextOmittedPromptProps | OmitPropertiesBedrockPromptPomOmittedPromptProps" + + +class BedrockSWAIG(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + functions: list[BedrockSWAIGFunction] + defaults: SWAIGDefaults + native_functions: list[SWAIGNativeFunction] + includes: list[SWAIGIncludes] + + +class CondReg(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + when: str + then: list[SWMLMethod] + # non-identifier field 'else': list[SWMLMethod] -class CallPayParameters(TypedDict, total=False): + +class CondElse(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + # non-identifier field 'else': list[SWMLMethod] + + +class ConnectHeaders(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" name: str value: str -class CallPayPrompts(TypedDict, total=False): +class ConnectSwitch(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - actions: list[CallPayPromptsActions] - attempt: str - card_type: str - error_type: str - # non-identifier field 'for': Literal['payment-card-number', 'expiration-date', 'security-code', 'postal-code', 'bank-routing-number', 'bank-account-number', 'payment-processing', 'payment-completed', 'payment-failed', 'payment-canceled'] - play: list[RingbackConfig] - require_matching_inputs: str + variable: str + case: dict[str, Any] + default: list[SWMLMethod] -class CallPayPromptsActions(TypedDict, total=False): +ValidConfirmMethods: TypeAlias = "Cond | Set | Unset | Hangup | Play | Prompt | Record | RecordCall | StopRecordCall | Tap | StopTap | SendDigits | SendSMS | Denoise | StopDenoise" + + +CallStatus: TypeAlias = "Literal['created', 'ringing', 'answered', 'ended']" + + +class TranscribeStartAction(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - type: Literal["Say", "Play"] - phrase: str + start: dict[str, Any] -class Cond(TypedDict, total=False): +TranscribeSummarizeActionUnion: TypeAlias = ( + "TranscribeSummarizeAction | Literal['summarize']" +) + + +class StartAction(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - cond: list[dict[str, Any]] + start: dict[str, Any] -class Connect(TypedDict, total=False): +SummarizeActionUnion: TypeAlias = "SummarizeAction | Literal['summarize']" + + +class InjectAction(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + inject: dict[str, Any] + + +PayPromptAction: TypeAlias = "PayPromptSayAction | PayPromptPlayAction" + + +class LanguagesWithSoloFillers(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + name: str + code: str + voice: str + model: str + emotion: Literal["auto"] + speed: Literal["auto"] + engine: str + params: LanguageParams + fillers: list[str] + + +class LanguagesWithFillers(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - connect: dict[str, Any] + name: str + code: str + voice: str + model: str + emotion: Literal["auto"] + speed: Literal["auto"] + engine: str + params: LanguageParams + function_fillers: list[str] + speech_fillers: list[str] + +AttentionTimeout: TypeAlias = "int" -class ConnectDevice(TypedDict, total=False): - """Body shape enforced by CHECK_swml_connect_device, swml_schema.c. + +class ConversationMessage(TypedDict, total=False): + """A message object representing a single turn in the conversation history. Open shape: extra server keys are permitted and partial payloads are valid; not validated at runtime (a TypedDict is a plain ``dict``). """ - authorization_bearer_token: str - call_state_events: list[str] - call_state_url: str - codec: str - codecs: str | list[Any] - confirm: str | list[SWMLMethod] | dict[str, Any] - confirm_timeout: int - custom_parameters: dict[str, str] - encryption: Literal["mandatory", "optional", "forbidden"] - # non-identifier field 'from': str - from_name: str - fsvars: dict[str, str] - headers: list[ConnectSipHeader] - name: str - password: str - realtime: bool - session_timeout: float - status_url: str - status_url_method: Literal["GET", "POST"] - timeout: float - to: str - username: str - webrtc_media: bool + role: ConversationRole + content: str + lang: str -ConnectSerialParallel: TypeAlias = "list[ConnectDevice]" +Direction: TypeAlias = "Literal['inbound', 'outbound']" -class ConnectSipHeader(TypedDict, total=False): +class AIPostPromptText(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - name: str - value: str + max_tokens: int + temperature: float | SWMLVar + top_p: float | SWMLVar + confidence: float | SWMLVar + presence_penalty: float | SWMLVar + frequency_penalty: float | SWMLVar + text: str + + +class AIPostPromptPom(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + max_tokens: int + temperature: float | SWMLVar + top_p: float | SWMLVar + confidence: float | SWMLVar + presence_penalty: float | SWMLVar + frequency_penalty: float | SWMLVar + pom: list[POM] + + +class AIPromptText(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + max_tokens: int + temperature: float | SWMLVar + top_p: float | SWMLVar + confidence: float | SWMLVar + presence_penalty: float | SWMLVar + frequency_penalty: float | SWMLVar + text: str + contexts: Contexts + + +class AIPromptPom(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + max_tokens: int + temperature: float | SWMLVar + top_p: float | SWMLVar + confidence: float | SWMLVar + presence_penalty: float | SWMLVar + frequency_penalty: float | SWMLVar + pom: list[POM] + contexts: Contexts + + +class SWAIGDefaults(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + web_hook_url: str + + +SWAIGNativeFunction: TypeAlias = ( + "Literal['check_time', 'wait_seconds', 'wait_for_user', 'adjust_response_latency']" +) + + +class SWAIGIncludes(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + functions: list[str] + url: str + meta_data: dict[str, Any] + + +SWAIGFunction: TypeAlias = "UserSWAIGFunction | StartUpHookSWAIGFunction | HangUpHookSWAIGFunction | SummarizeConversationSWAIGFunction" + + +class SWAIGInternalFiller(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + hangup: FunctionFillers + check_time: FunctionFillers + wait_for_user: FunctionFillers + wait_seconds: FunctionFillers + adjust_response_latency: FunctionFillers + next_step: FunctionFillers + change_context: FunctionFillers + get_visual_input: FunctionFillers + get_ideal_strategy: FunctionFillers + + +class OmitPropertiesBedrockPostPomptTextOmittedPromptProps(TypedDict, total=False): + """The template for omitting properties. + + Open shape: extra server keys are permitted and partial payloads are valid; + not validated at runtime (a TypedDict is a plain ``dict``). + """ + + max_tokens: int + temperature: float | SWMLVar + top_p: float | SWMLVar + confidence: float | SWMLVar + presence_penalty: float | SWMLVar + frequency_penalty: float | SWMLVar + text: str + + +class OmitPropertiesBedrockPostPromptPomOmittedPromptProps(TypedDict, total=False): + """The template for omitting properties. + + Open shape: extra server keys are permitted and partial payloads are valid; + not validated at runtime (a TypedDict is a plain ``dict``). + """ + + max_tokens: int + temperature: float | SWMLVar + top_p: float | SWMLVar + confidence: float | SWMLVar + presence_penalty: float | SWMLVar + frequency_penalty: float | SWMLVar + pom: list[POM] + + +class OmitPropertiesBedrockPromptTextOmittedPromptProps(TypedDict, total=False): + """The template for omitting properties. + + Open shape: extra server keys are permitted and partial payloads are valid; + not validated at runtime (a TypedDict is a plain ``dict``). + """ + + voice_id: ( + Literal["tiffany"] + | Literal["matthew"] + | Literal["amy"] + | Literal["lupe"] + | Literal["carlos"] + ) + max_tokens: int + temperature: float | SWMLVar + top_p: float | SWMLVar + confidence: float | SWMLVar + presence_penalty: float | SWMLVar + frequency_penalty: float | SWMLVar + text: str + + +class OmitPropertiesBedrockPromptPomOmittedPromptProps(TypedDict, total=False): + """The template for omitting properties. + + Open shape: extra server keys are permitted and partial payloads are valid; + not validated at runtime (a TypedDict is a plain ``dict``). + """ + + voice_id: ( + Literal["tiffany"] + | Literal["matthew"] + | Literal["amy"] + | Literal["lupe"] + | Literal["carlos"] + ) + max_tokens: int + temperature: float | SWMLVar + top_p: float | SWMLVar + confidence: float | SWMLVar + presence_penalty: float | SWMLVar + frequency_penalty: float | SWMLVar + pom: list[POM] + + +BedrockSWAIGFunction: TypeAlias = "PickPropertiesUserSWAIGFunctionPickedSWAIGFunctionProps | PickPropertiesStartUpHookSWAIGFunctionPickedSWAIGFunctionProps | PickPropertiesHangUpHookSWAIGFunctionPickedSWAIGFunctionProps | PickPropertiesSummarizeConversationSWAIGFunctionPickedSWAIGFunctionProps" + + +TranscribeDirection: TypeAlias = "Literal['remote-caller', 'local-caller']" + + +SpeechEngine: TypeAlias = "Literal['deepgram', 'google']" + + +class TranscribeSummarizeAction(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + summarize: dict[str, Any] + + +TranslationFilterPreset: TypeAlias = ( + "Literal['polite', 'rude', 'professional', 'shakespeare', 'gen-z']" +) + + +CustomTranslationFilter: TypeAlias = "str" + + +TranslateDirection: TypeAlias = "Literal['remote-caller', 'local-caller']" + + +class SummarizeAction(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + summarize: dict[str, Any] + + +class PayPromptSayAction(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + type: Literal["Say"] + phrase: str + + +class PayPromptPlayAction(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + type: Literal["Play"] + phrase: str + + +class LanguageParams(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + stability: float | SWMLVar + similarity: float | SWMLVar + + +ConversationRole: TypeAlias = "Literal['user', 'assistant', 'system']" + + +POM: TypeAlias = "PomSectionBodyContent | PomSectionBulletsContent" + + +class Contexts(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + default: ContextsObject + + +class UserSWAIGFunction(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + description: str + purpose: str + parameters: FunctionParameters + fillers: FunctionFillers + argument: FunctionParameters + active: bool | SWMLVar + meta_data: dict[str, Any] + meta_data_token: str + data_map: DataMap + skip_fillers: bool | SWMLVar + web_hook_url: str + wait_file: str + wait_file_loops: int | str + wait_for_fillers: bool | SWMLVar + function: str + + +class StartUpHookSWAIGFunction(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + description: str + purpose: str + parameters: FunctionParameters + fillers: FunctionFillers + argument: FunctionParameters + active: bool | SWMLVar + meta_data: dict[str, Any] + meta_data_token: str + data_map: DataMap + skip_fillers: bool | SWMLVar + web_hook_url: str + wait_file: str + wait_file_loops: int | str + wait_for_fillers: bool | SWMLVar + function: Literal["startup_hook"] + + +class HangUpHookSWAIGFunction(TypedDict, total=False): + """Open shape: extra server keys permitted; not validated at runtime.""" + + description: str + purpose: str + parameters: FunctionParameters + fillers: FunctionFillers + argument: FunctionParameters + active: bool | SWMLVar + meta_data: dict[str, Any] + meta_data_token: str + data_map: DataMap + skip_fillers: bool | SWMLVar + web_hook_url: str + wait_file: str + wait_file_loops: int | str + wait_for_fillers: bool | SWMLVar + function: Literal["hangup_hook"] + + +class SummarizeConversationSWAIGFunction(TypedDict, total=False): + """An internal reserved function that generates a summary of the conversation and sends any specified properties to the configured webhook after the conversation has ended. + + Open shape: extra server keys are permitted and partial payloads are valid; + not validated at runtime (a TypedDict is a plain ``dict``). + """ + + description: str + purpose: str + parameters: FunctionParameters + fillers: FunctionFillers + argument: FunctionParameters + active: bool | SWMLVar + meta_data: dict[str, Any] + meta_data_token: str + data_map: DataMap + skip_fillers: bool | SWMLVar + web_hook_url: str + wait_file: str + wait_file_loops: int | str + wait_for_fillers: bool | SWMLVar + function: Literal["summarize_conversation"] + + +FunctionFillers: TypeAlias = "dict[str, Any]" + + +class PickPropertiesUserSWAIGFunctionPickedSWAIGFunctionProps(TypedDict, total=False): + """The template for picking properties. + + Open shape: extra server keys are permitted and partial payloads are valid; + not validated at runtime (a TypedDict is a plain ``dict``). + """ + + description: str + parameters: FunctionParameters + active: bool | SWMLVar + meta_data: dict[str, Any] + meta_data_token: str + data_map: DataMap + web_hook_url: str + function: str + + +class PickPropertiesStartUpHookSWAIGFunctionPickedSWAIGFunctionProps( + TypedDict, total=False +): + """The template for picking properties. + + Open shape: extra server keys are permitted and partial payloads are valid; + not validated at runtime (a TypedDict is a plain ``dict``). + """ + + description: str + parameters: FunctionParameters + active: bool | SWMLVar + meta_data: dict[str, Any] + meta_data_token: str + data_map: DataMap + web_hook_url: str + function: Literal["startup_hook"] + + +class PickPropertiesHangUpHookSWAIGFunctionPickedSWAIGFunctionProps( + TypedDict, total=False +): + """The template for picking properties. + + Open shape: extra server keys are permitted and partial payloads are valid; + not validated at runtime (a TypedDict is a plain ``dict``). + """ + + description: str + parameters: FunctionParameters + active: bool | SWMLVar + meta_data: dict[str, Any] + meta_data_token: str + data_map: DataMap + web_hook_url: str + function: Literal["hangup_hook"] + + +class PickPropertiesSummarizeConversationSWAIGFunctionPickedSWAIGFunctionProps( + TypedDict, total=False +): + """The template for picking properties. + + Open shape: extra server keys are permitted and partial payloads are valid; + not validated at runtime (a TypedDict is a plain ``dict``). + """ + + description: str + parameters: FunctionParameters + active: bool | SWMLVar + meta_data: dict[str, Any] + meta_data_token: str + data_map: DataMap + web_hook_url: str + function: Literal["summarize_conversation"] + + +class PomSectionBodyContent(TypedDict, total=False): + """Content model with body text and optional bullets + + Open shape: extra server keys are permitted and partial payloads are valid; + not validated at runtime (a TypedDict is a plain ``dict``). + """ + title: str + subsections: list[POM] + numbered: bool | SWMLVar + numberedBullets: bool | SWMLVar + body: str + bullets: list[str] -class Denoise(TypedDict, total=False): - """Open shape: extra server keys permitted; not validated at runtime.""" - denoise: dict[str, Any] +class PomSectionBulletsContent(TypedDict, total=False): + """Content model with bullets and optional body + Open shape: extra server keys are permitted and partial payloads are valid; + not validated at runtime (a TypedDict is a plain ``dict``). + """ -class DetectMachine(TypedDict, total=False): - """Open shape: extra server keys permitted; not validated at runtime.""" + title: str + subsections: list[POM] + numbered: bool | SWMLVar + numberedBullets: bool | SWMLVar + body: str + bullets: list[str] - detect_machine: dict[str, Any] + +ContextsObject: TypeAlias = "ContextsPOMObject | ContextsTextObject" -class Dial(TypedDict, total=False): +class FunctionParameters(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - dial: dict[str, Any] + type: Literal["object"] + properties: dict[str, Any] + required: list[str] -class Echo(TypedDict, total=False): +class DataMap(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - echo: dict[str, Any] | list[Any] + output: Output + expressions: list[Expression] + webhooks: list[Webhook] -class EnterQueue(TypedDict, total=False): +class ContextsPOMObject(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - enter_queue: dict[str, Any] + steps: list[ContextSteps] + isolated: bool + enter_fillers: list[FunctionFillers] + exit_fillers: list[FunctionFillers] + pom: list[POM] -class Eval(TypedDict, total=False): +class ContextsTextObject(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - eval: dict[str, Any] - + steps: list[ContextSteps] + isolated: bool + enter_fillers: list[FunctionFillers] + exit_fillers: list[FunctionFillers] + text: str -class Execute(TypedDict, total=False): - """Open shape: extra server keys permitted; not validated at runtime.""" - execute: dict[str, Any] | list[Any] +SchemaType: TypeAlias = "StringProperty | IntegerProperty | NumberProperty | BooleanProperty | ArrayProperty | ObjectProperty | NullProperty | OneOfProperty | AllOfProperty | AnyOfProperty | ConstProperty" -class ExecuteRpc(TypedDict, total=False): +class Output(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - execute_rpc: dict[str, Any] + response: str + action: list[Action] -class Goto(TypedDict, total=False): +class Expression(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - goto: dict[str, Any] | list[Any] + string: str + pattern: str + output: Output -class Hangup(TypedDict, total=False): +class Webhook(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - hangup: dict[str, Any] | list[Any] - + expressions: list[Expression] + error_keys: str | list[str] + url: str + foreach: dict[str, Any] + headers: dict[str, Any] + method: Literal["GET"] | Literal["POST"] | Literal["PUT"] | Literal["DELETE"] + input_args_as_params: bool | SWMLVar + params: dict[str, Any] + require_args: str | list[str] + output: Output -class If(TypedDict, total=False): - """Open shape: extra server keys permitted; not validated at runtime.""" - # non-identifier field 'if': dict[str, Any] +ContextSteps: TypeAlias = "ContextPOMSteps | ContextTextSteps" -class JoinConference(TypedDict, total=False): - """Open shape: extra server keys permitted; not validated at runtime.""" +class StringProperty(TypedDict, total=False): + """Base interface for all property types - join_conference: dict[str, Any] | list[Any] + Open shape: extra server keys are permitted and partial payloads are valid; + not validated at runtime (a TypedDict is a plain ``dict``). + """ + description: str + nullable: bool | SWMLVar + type: Literal["string"] + enum: list[str] + default: str + pattern: str + format: StringFormat -class JoinRoom(TypedDict, total=False): - """Open shape: extra server keys permitted; not validated at runtime.""" - join_room: dict[str, Any] | list[Any] +class IntegerProperty(TypedDict, total=False): + """Base interface for all property types + Open shape: extra server keys are permitted and partial payloads are valid; + not validated at runtime (a TypedDict is a plain ``dict``). + """ -class Label(TypedDict, total=False): - """Open shape: extra server keys permitted; not validated at runtime.""" + description: str + nullable: bool | SWMLVar + type: Literal["integer"] + enum: list[int] + default: int | SWMLVar - label: dict[str, Any] | list[Any] +class NumberProperty(TypedDict, total=False): + """Base interface for all property types -class LiveTranscribe(TypedDict, total=False): - """Open shape: extra server keys permitted; not validated at runtime.""" + Open shape: extra server keys are permitted and partial payloads are valid; + not validated at runtime (a TypedDict is a plain ``dict``). + """ - live_transcribe: dict[str, Any] + description: str + nullable: bool | SWMLVar + type: Literal["number"] + enum: list[int | float] | list[SWMLVar] + default: int | float | SWMLVar -class LiveTranslate(TypedDict, total=False): - """Open shape: extra server keys permitted; not validated at runtime.""" +class BooleanProperty(TypedDict, total=False): + """Base interface for all property types - live_translate: dict[str, Any] + Open shape: extra server keys are permitted and partial payloads are valid; + not validated at runtime (a TypedDict is a plain ``dict``). + """ + description: str + nullable: bool | SWMLVar + type: Literal["boolean"] + default: bool | SWMLVar -class Pay(TypedDict, total=False): - """Open shape: extra server keys permitted; not validated at runtime.""" - pay: dict[str, Any] | list[Any] +class ArrayProperty(TypedDict, total=False): + """Base interface for all property types + Open shape: extra server keys are permitted and partial payloads are valid; + not validated at runtime (a TypedDict is a plain ``dict``). + """ -class Play(TypedDict, total=False): - """Open shape: extra server keys permitted; not validated at runtime.""" + description: str + nullable: bool | SWMLVar + type: Literal["array"] + default: list[Any] + items: SchemaType - play: dict[str, Any] | list[Any] +class ObjectProperty(TypedDict, total=False): + """Base interface for all property types -class Prompt(TypedDict, total=False): - """Open shape: extra server keys permitted; not validated at runtime.""" + Open shape: extra server keys are permitted and partial payloads are valid; + not validated at runtime (a TypedDict is a plain ``dict``). + """ - prompt: dict[str, Any] | list[Any] + description: str + nullable: bool | SWMLVar + type: Literal["object"] + default: dict[str, Any] + properties: dict[str, Any] + required: list[str] -class ReceiveFax(TypedDict, total=False): +class NullProperty(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - receive_fax: dict[str, Any] | list[Any] + type: Literal["null"] + description: str -class Record(TypedDict, total=False): +class OneOfProperty(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - record: dict[str, Any] + oneOf: list[SchemaType] -class RecordCall(TypedDict, total=False): +class AllOfProperty(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - record_call: dict[str, Any] + allOf: list[SchemaType] -class Request(TypedDict, total=False): +class AnyOfProperty(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - request: dict[str, Any] + anyOf: list[SchemaType] -class Return(TypedDict, total=False): +class ConstProperty(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - # non-identifier field 'return': dict[str, Any] + const: dict[str, Any] -RingbackConfig: TypeAlias = "dict[str, Any] | list[Any]" +Action: TypeAlias = "SWMLAction | ChangeContextAction | ChangeStepAction | ContextSwitchAction | HangupAction | HoldAction | PlaybackBGAction | SayAction | SetGlobalDataAction | SetMetaDataAction | StopAction | StopPlaybackBGAction | ToggleFunctionsAction | UnsetGlobalDataAction | UnsetMetaDataAction | UserInputAction" -class SIPRefer(TypedDict, total=False): +class ContextPOMSteps(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - sip_refer: dict[str, Any] | list[Any] - - -SWMLMethod: TypeAlias = "AI | AiSidecar | AmazonBedrock | Answer | Cond | Connect | Denoise | DetectMachine | Dial | Echo | EnterQueue | Eval | Execute | ExecuteRpc | Goto | Hangup | If | JoinConference | JoinRoom | Label | LiveTranscribe | LiveTranslate | Pay | Play | Prompt | ReceiveFax | Record | RecordCall | Request | Return | SIPRefer | SendDigits | SendFax | SendSMS | Set | SetMeta | Sleep | StopDenoise | StopRecordCall | StopStream | StopTap | Stream | Switch | Tap | Transcribe | TranscribeStop | Transfer | Unset | UserEvent" - - -SWMLVar: TypeAlias = "str" + name: str + step_criteria: str + functions: list[str] + valid_contexts: list[str] + skip_user_turn: bool | SWMLVar + end: bool + valid_steps: list[str] + pom: list[POM] -class Section(TypedDict, total=False): +class ContextTextSteps(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - main: list[SWMLMethod] - + name: str + step_criteria: str + functions: list[str] + valid_contexts: list[str] + skip_user_turn: bool | SWMLVar + end: bool + valid_steps: list[str] + text: str -class SendDigits(TypedDict, total=False): - """Open shape: extra server keys permitted; not validated at runtime.""" - send_digits: dict[str, Any] | list[Any] +StringFormat: TypeAlias = "Literal['date_time', 'time', 'date', 'duration', 'email', 'hostname', 'ipv4', 'ipv6', 'uri', 'uuid']" -class SendFax(TypedDict, total=False): +class SWMLAction(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - send_fax: dict[str, Any] | list[Any] + SWML: dict[str, Any] -class SendSMS(TypedDict, total=False): +class ChangeContextAction(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - send_sms: dict[str, Any] + change_context: str -class Set(TypedDict, total=False): +class ChangeStepAction(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - set: dict[str, Any] + change_step: str -class SetMeta(TypedDict, total=False): +class ContextSwitchAction(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - set_meta: dict[str, Any] + context_switch: dict[str, Any] -class Sleep(TypedDict, total=False): +class HangupAction(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - sleep: dict[str, Any] | list[Any] + hangup: bool | SWMLVar -class StopDenoise(TypedDict, total=False): +class HoldAction(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - stop_denoise: dict[str, Any] + hold: int | SWMLVar | dict[str, Any] -class StopRecordCall(TypedDict, total=False): +class PlaybackBGAction(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - stop_record_call: dict[str, Any] | list[Any] + playback_bg: dict[str, Any] -class StopStream(TypedDict, total=False): +class SayAction(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - stop_stream: dict[str, Any] | list[Any] + say: str -class StopTap(TypedDict, total=False): +class SetGlobalDataAction(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - stop_tap: dict[str, Any] | list[Any] + set_global_data: dict[str, Any] -class Stream(TypedDict, total=False): +class SetMetaDataAction(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - stream: dict[str, Any] | list[Any] + set_meta_data: dict[str, Any] -class Switch(TypedDict, total=False): +class StopAction(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - switch: dict[str, Any] + stop: bool | SWMLVar -class Tap(TypedDict, total=False): +class StopPlaybackBGAction(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - tap: dict[str, Any] | list[Any] + stop_playback_bg: bool | SWMLVar -class Transcribe(TypedDict, total=False): +class ToggleFunctionsAction(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - transcribe: dict[str, Any] + toggle_functions: list[dict[str, Any]] -class TranscribeStop(TypedDict, total=False): +class UnsetGlobalDataAction(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - transcribe_stop: dict[str, Any] + unset_global_data: str | dict[str, Any] -class Transfer(TypedDict, total=False): +class UnsetMetaDataAction(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - transfer: dict[str, Any] | list[Any] + unset_meta_data: str | dict[str, Any] -class Unset(TypedDict, total=False): +class UserInputAction(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - unset: list[str] | str + user_input: str -class UserEvent(TypedDict, total=False): +class AiSidecar(TypedDict, total=False): """Open shape: extra server keys permitted; not validated at runtime.""" - user_event: dict[str, Any] + ai_sidecar: dict[str, Any] -class AiSidecarConfig(TypedDict, total=False): - """Attach an AI sidecar observer to the call. Requires an active live_transcribe. +class RingbackConfig(TypedDict, total=False): + """Ringback configuration (the modern object form). Declared as a named $defs entry so every generator emits a TYPED shape via $ref rather than collapsing an inline object to an untyped map; the legacy URI array remains the other oneOf branch. Open shape: extra server keys are permitted and partial payloads are valid; not validated at runtime (a TypedDict is a plain ``dict``). """ - SWAIG: dict[str, Any] | SWMLVar - action: dict[str, Any] | SWMLVar - customer_role: Literal["remote-caller", "local-caller"] | SWMLVar - direction: list[Literal["remote-caller", "local-caller"]] | SWMLVar - global_data: dict[str, Any] | SWMLVar - hints: list[str] | SWMLVar - lang: str | SWMLVar - model: str | SWMLVar - params: dict[str, Any] | SWMLVar - permissions: dict[str, Any] | SWMLVar - prompt: dict[str, Any] | str | SWMLVar - url: str | SWMLVar + url: str + urls: list[str] + volume: float + auto_answer: bool + say_voice: str + say_language: str + say_gender: Literal["male", "female"] + status_url: str + loop: int -class AmazonBedrockConfig(TypedDict, total=False): - """Invoke an Amazon Bedrock AI model. +class ConnectConfig(TypedDict, total=False): + """Dial a SIP URI or phone number. Open shape: extra server keys are permitted and partial payloads are valid; not validated at runtime (a TypedDict is a plain ``dict``). """ - SWAIG: list[dict[str, Any]] | dict[str, Any] - global_data: dict[str, Any] - params: dict[str, Any] - post_prompt: dict[str, Any] - post_prompt_url: str - prompt: dict[str, Any] + # non-identifier field 'from': str + headers: list[ConnectHeaders] + codecs: str + webrtc_media: bool | SWMLVar + session_timeout: int | SWMLVar + ringback: list[str] | RingbackConfig + result: ConnectSwitch | list[CondParams] + timeout: int | SWMLVar + max_duration: int | SWMLVar + answer_on_bridge: bool | SWMLVar + confirm: str | list[ValidConfirmMethods] + confirm_timeout: int | SWMLVar + username: str + password: str + encryption: Literal["mandatory"] | Literal["optional"] | Literal["forbidden"] + call_state_url: str + transfer_after_bridge: str | SWMLVar + call_state_events: list[CallStatus] + to: str + serial: list[ConnectDeviceSingle] + parallel: list[ConnectDeviceSingle] + serial_parallel: list[list[ConnectDeviceSingle]] -class ConnectConfig(TypedDict, total=False): - """Connect the call to other endpoints (phone, SIP, etc.). +class ExecuteConfig(TypedDict, total=False): + """Execute a specified section or URL as a subroutine, and upon completion, return to the current document. Open shape: extra server keys are permitted and partial payloads are valid; not validated at runtime (a TypedDict is a plain ``dict``). """ - answer_on_bridge: bool | str | SWMLVar - authorization_bearer_token: Any - call_state_events: list[str] | SWMLVar - call_state_url: str | SWMLVar - codec: Any - codecs: str | list[Any] | SWMLVar - confirm: str | list[SWMLMethod] | dict[str, Any] | SWMLVar - confirm_timeout: int | SWMLVar - custom_parameters: Any - encryption: Literal["mandatory", "optional", "forbidden"] | SWMLVar - execute_after_queue: str | SWMLVar - # non-identifier field 'from': str | SWMLVar - from_name: str | SWMLVar - fsvars: dict[str, str] | SWMLVar - headers: list[ConnectSipHeader] - max_duration: float | SWMLVar - name: Any - parallel: list[ConnectDevice] - password: str | SWMLVar - realtime: Any - result: list[Any] | dict[str, Any] - ringback: bool | str | list[RingbackConfig] | dict[str, Any] - serial: list[ConnectDevice] - serial_parallel: list[ConnectSerialParallel] - session_timeout: float | SWMLVar - status_url: str | SWMLVar - status_url_method: Any - timeout: float | SWMLVar - to: str | SWMLVar - username: str | SWMLVar - webrtc_media: bool | SWMLVar + dest: str + params: dict[str, Any] + meta: dict[str, Any] + on_return: list[SWMLMethod] + result: ExecuteSwitch | list[CondParams] -class DetectMachineConfig(TypedDict, total=False): - """Start answering machine detection. +class GotoConfig(TypedDict, total=False): + """Jump to a label within the current section, optionally based on a condition. Open shape: extra server keys are permitted and partial payloads are valid; not validated at runtime (a TypedDict is a plain ``dict``). """ - detect_interruptions: bool | SWMLVar - detect_message_end: bool | SWMLVar - detectors: str | SWMLVar - end_silence_timeout: float | SWMLVar - initial_timeout: float | SWMLVar - machine_ready_timeout: float | SWMLVar - machine_voice_threshold: float | SWMLVar - machine_words_threshold: int | SWMLVar - status_url: str | SWMLVar - timeout: float | SWMLVar - tone: Literal["CNG", "CED", "cng", "ced"] | SWMLVar - wait: bool | SWMLVar + label: str + when: str + max: int | SWMLVar -class DialConfig(TypedDict, total=False): - """Dial out to one or more endpoints. +class LiveTranscribeConfig(TypedDict, total=False): + """Start live transcription of the call. The transcription will be sent to the specified webhook URL. Open shape: extra server keys are permitted and partial payloads are valid; not validated at runtime (a TypedDict is a plain ``dict``). """ - answer_on_bridge: bool | str - call_state_events: list[str] | SWMLVar - call_state_url: str | SWMLVar - codecs: str | list[Any] | SWMLVar - confirm: str | list[SWMLMethod] | dict[str, Any] | SWMLVar - confirm_timeout: int | SWMLVar - dest_swml: str | dict[str, Any] | list[Any] - encryption: Literal["mandatory", "optional", "forbidden"] | SWMLVar - execute_after_queue: str | SWMLVar - # non-identifier field 'from': str | SWMLVar - from_name: str | SWMLVar - fsvars: dict[str, str] | SWMLVar - headers: list[ConnectSipHeader] - max_duration: float | SWMLVar - parallel: list[ConnectDevice] - password: str | SWMLVar - result: Any - ringback: RingbackConfig - serial: list[ConnectDevice] - serial_parallel: list[ConnectSerialParallel] - session_timeout: float | SWMLVar - status_url: str | SWMLVar - timeout: float | SWMLVar - to: str | SWMLVar - username: str | SWMLVar - webrtc_media: bool | SWMLVar + action: TranscribeAction -class EnterQueueConfig(TypedDict, total=False): - """Place the call into a queue. +class AiSidecarConfig(TypedDict, total=False): + """Start ai_sidecar mode — live_transcribe with an LLM/SWAIG/MCP loop on top. Open shape: extra server keys are permitted and partial payloads are valid; not validated at runtime (a TypedDict is a plain ``dict``). """ - control_id: str | SWMLVar - execute_after_queue: str | SWMLVar - queue_name: str | SWMLVar - status_url: str | SWMLVar - wait_time: int | SWMLVar - wait_url: str | SWMLVar - whisper_url: str | SWMLVar + prompt: str | dict[str, Any] + lang: str + model: str + direction: list[Literal["remote-caller", "local-caller"]] + customer_role: Literal["remote-caller", "local-caller"] + url: str + SWAIG: SWAIG + permissions: dict[str, Any] + global_data: dict[str, Any] + hints: list[str] + params: dict[str, Any] + action: dict[str, Any] -class ExecuteRpcConfig(TypedDict, total=False): - """Execute a remote procedure call. +class LiveTranslateConfig(TypedDict, total=False): + """Start live translation of the call. The translation will be sent to the specified webhook URL. Open shape: extra server keys are permitted and partial payloads are valid; not validated at runtime (a TypedDict is a plain ``dict``). """ - call_id: str | SWMLVar - method: str | SWMLVar - node_id: str | SWMLVar - params: dict[str, Any] | SWMLVar + action: TranslateAction -class IfConfig(TypedDict, total=False): - """Conditional branching (deprecated). +class JoinRoomConfig(TypedDict, total=False): + """Join a RELAY room. If the room doesn't exist, it creates a new room. Open shape: extra server keys are permitted and partial payloads are valid; not validated at runtime (a TypedDict is a plain ``dict``). """ - condition: str | SWMLVar - # non-identifier field 'else': list[SWMLMethod] | dict[str, Any] - then: list[SWMLMethod] | dict[str, Any] + name: str -class LiveTranscribeConfig(TypedDict, total=False): - """Start live transcription of the call. +class PromptConfig(TypedDict, total=False): + """Play a prompt and wait for input. The input can be received either as digits from the keypad, Open shape: extra server keys are permitted and partial payloads are valid; not validated at runtime (a TypedDict is a plain ``dict``). """ - action: Literal["start", "stop", "summarize"] | dict[str, Any] | SWMLVar - hints: list[dict[str, Any] | str] | SWMLVar + play: play_url | list[play_url] | SWMLVar | list[SWMLVar] + volume: float + say_voice: str + say_language: str + say_gender: Literal["male", "female"] + max_digits: int | SWMLVar + terminators: str + digit_timeout: float | SWMLVar + initial_timeout: float | SWMLVar + speech_timeout: float | SWMLVar + speech_end_timeout: float | SWMLVar + speech_language: str + speech_hints: list[str] | list[SWMLVar] + speech_engine: str + status_url: str -class LiveTranslateConfig(TypedDict, total=False): - """Start live translation of the call. +class ReceiveFaxConfig(TypedDict, total=False): + """Receive a fax being delivered to this call. Open shape: extra server keys are permitted and partial payloads are valid; not validated at runtime (a TypedDict is a plain ``dict``). """ - action: Literal["inject", "start", "stop", "summarize"] | dict[str, Any] | SWMLVar + status_url: str class RecordConfig(TypedDict, total=False): - """Record audio from the call. + """Record the call audio in the foreground, pausing further SWML execution until recording ends. Open shape: extra server keys are permitted and partial payloads are valid; not validated at runtime (a TypedDict is a plain ``dict``). """ - format: Literal["wav", "mp3", "mp4"] | SWMLVar + stereo: bool | SWMLVar + format: Literal["wav"] | Literal["mp3"] | Literal["mp4"] + direction: Literal["speak"] | Literal["listen"] + terminators: str beep: bool | SWMLVar - direction: Literal["listen", "speak", "both"] | SWMLVar - end_silence_timeout: float | SWMLVar - initial_timeout: float | SWMLVar input_sensitivity: float | SWMLVar - max_length: int | SWMLVar - status_url: str | SWMLVar - stereo: bool | SWMLVar - terminators: str | SWMLVar + initial_timeout: float | SWMLVar + end_silence_timeout: float | SWMLVar + max_length: float | SWMLVar + status_url: str class RecordCallConfig(TypedDict, total=False): - """Start recording the entire call. + """Record call in the background. Open shape: extra server keys are permitted and partial payloads are valid; not validated at runtime (a TypedDict is a plain ``dict``). """ - format: Literal["wav", "mp3", "mp4"] | SWMLVar + control_id: str + stereo: bool | SWMLVar + format: Literal["wav"] | Literal["mp3"] | Literal["mp4"] + direction: Literal["speak"] | Literal["listen"] | Literal["both"] + terminators: str beep: bool | SWMLVar - control_id: str | SWMLVar - direction: Literal["listen", "speak", "both"] | SWMLVar - end_silence_timeout: float | SWMLVar - initial_timeout: float | SWMLVar input_sensitivity: float | SWMLVar - max_length: int | SWMLVar - status_url: str | SWMLVar - stereo: bool | SWMLVar - terminators: str | SWMLVar + initial_timeout: float | SWMLVar + end_silence_timeout: float | SWMLVar + max_length: float | SWMLVar + status_url: str class RequestConfig(TypedDict, total=False): - """Make an HTTP request and store the result. + """Send a GET, POST, PUT, or DELETE request to a remote URL. Open shape: extra server keys are permitted and partial payloads are valid; not validated at runtime (a TypedDict is a plain ``dict``). """ - body: dict[str, Any] | list[Any] | str | float | bool - connect_timeout: int | SWMLVar + url: str + method: Literal["GET"] | Literal["POST"] | Literal["PUT"] | Literal["DELETE"] headers: dict[str, Any] - method: ( - Literal["get", "GET", "put", "PUT", "POST", "post", "DELETE", "delete"] - | SWMLVar - ) + body: str | dict[str, Any] + timeout: float | SWMLVar + connect_timeout: float | SWMLVar save_variables: bool | SWMLVar - timeout: int | SWMLVar - url: str | SWMLVar -class SendSmsConfig(TypedDict, total=False): - """Send an SMS message. +class SendDigitsConfig(TypedDict, total=False): + """Send digit presses as DTMF tones. Open shape: extra server keys are permitted and partial payloads are valid; not validated at runtime (a TypedDict is a plain ``dict``). """ - body: str | SWMLVar - from_number: str | SWMLVar - media: list[str] - region: str | SWMLVar - status_callback: str | SWMLVar - tags: list[str] - to_number: str | SWMLVar + digits: str + + +class SendFaxConfig(TypedDict, total=False): + """Send a fax. + + Open shape: extra server keys are permitted and partial payloads are valid; + not validated at runtime (a TypedDict is a plain ``dict``). + """ + + document: str + header_info: str + identity: str + status_url: str + + +class SipReferConfig(TypedDict, total=False): + """Send SIP REFER to a SIP call. + + Open shape: extra server keys are permitted and partial payloads are valid; + not validated at runtime (a TypedDict is a plain ``dict``). + """ + + to_uri: str + status_url: str + username: str + password: str + + +class StopRecordCallConfig(TypedDict, total=False): + """Stop an active background recording. + Open shape: extra server keys are permitted and partial payloads are valid; + not validated at runtime (a TypedDict is a plain ``dict``). + """ + + control_id: str -class SetMetaConfig(TypedDict, total=False): - """Add customer metadata to call and conference events + +class StopTapConfig(TypedDict, total=False): + """Stop an active tap stream. Open shape: extra server keys are permitted and partial payloads are valid; not validated at runtime (a TypedDict is a plain ``dict``). """ - meta: dict[str, Any] | SWMLVar - private: Any - public: Any + control_id: str class SwitchConfig(TypedDict, total=False): - """Conditional branching based on variable value. + """Execute different instructions based on a variable's value. Open shape: extra server keys are permitted and partial payloads are valid; not validated at runtime (a TypedDict is a plain ``dict``). """ - default: list[SWMLMethod] | dict[str, Any] + variable: str case: dict[str, Any] - variable: str | SWMLVar + default: list[SWMLMethod] -class TranscribeConfig(TypedDict, total=False): - """Start transcription on the call. +class TapConfig(TypedDict, total=False): + """Start background call tap. Media is streamed over Websocket or RTP to customer controlled URI. Open shape: extra server keys are permitted and partial payloads are valid; not validated at runtime (a TypedDict is a plain ``dict``). """ - status_url: str | SWMLVar + uri: str + control_id: str + direction: Literal["speak"] | Literal["listen"] | Literal["both"] + codec: Literal["PCMU"] | Literal["PCMA"] + rtp_ptime: int | SWMLVar + status_url: str -class UserEventConfig(TypedDict, total=False): - """Fire a custom user event. +class TransferConfig(TypedDict, total=False): + """Transfer the execution of the script to a different SWML section, URL, or Relay application. Open shape: extra server keys are permitted and partial payloads are valid; not validated at runtime (a TypedDict is a plain ``dict``). """ - event: dict[str, Any] | SWMLVar + dest: str + params: dict[str, Any] + meta: dict[str, Any] + +class PayConfig(TypedDict, total=False): + """Enables secure payment processing during voice calls. When implemented, it manages the entire payment flow -class _SwmlVerbs: - """The SWML verb methods SwmlBuilder installs at runtime (static view).""" + Open shape: extra server keys are permitted and partial payloads are valid; + not validated at runtime (a TypedDict is a plain ``dict``). + """ - def ai_sidecar(self: _Self, config: AiSidecarConfig | None = None) -> _Self: - """Attach an AI sidecar observer to the call. Requires an active live_transcribe.""" - raise NotImplementedError # installed dynamically at runtime + payment_connector_url: str + charge_amount: str + currency: str + description: str + input: Literal["dtmf"] + language: str + max_attempts: int | SWMLVar + min_postal_code_length: int | SWMLVar + parameters: list[PayParameters] + payment_method: Literal["credit-card"] + postal_code: bool | str + prompts: list[PayPrompts] + security_code: bool | SWMLVar + status_url: str + timeout: int | SWMLVar + token_type: Literal["one-time"] | Literal["reusable"] + valid_card_types: str + voice: str - def amazon_bedrock(self: _Self, config: AmazonBedrockConfig | None = None) -> _Self: - """Invoke an Amazon Bedrock AI model.""" - raise NotImplementedError # installed dynamically at runtime - def cond(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: - """Body shape enforced by is_valid_cond_method, swml_schema.c:1249.""" - raise NotImplementedError # installed dynamically at runtime +class DetectMachineConfig(TypedDict, total=False): + """A detection method that combines AMD (Answering Machine Detection) and fax detection. - def connect(self: _Self, config: ConnectConfig | None = None) -> _Self: - """Connect the call to other endpoints (phone, SIP, etc.).""" - raise NotImplementedError # installed dynamically at runtime + Open shape: extra server keys are permitted and partial payloads are valid; + not validated at runtime (a TypedDict is a plain ``dict``). + """ - def denoise(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: - """Enable noise reduction on audio.""" - raise NotImplementedError # installed dynamically at runtime + detect_message_end: bool | SWMLVar + detectors: str + end_silence_timeout: float | SWMLVar + initial_timeout: float | SWMLVar + machine_ready_timeout: float | SWMLVar + machine_voice_threshold: float | SWMLVar + machine_words_threshold: int | SWMLVar + status_url: str + timeout: float | SWMLVar + tone: Literal["CED"] | Literal["CNG"] + wait: bool | SWMLVar - def detect_machine(self: _Self, config: DetectMachineConfig | None = None) -> _Self: - """Start answering machine detection.""" - raise NotImplementedError # installed dynamically at runtime - def dial(self: _Self, config: DialConfig | None = None) -> _Self: - """Dial out to one or more endpoints.""" - raise NotImplementedError # installed dynamically at runtime +class UserEventConfig(TypedDict, total=False): + """Allows the user to set and send events to the connected client on the call. - def echo(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: - """Add the echo verb.""" - raise NotImplementedError # installed dynamically at runtime + Open shape: extra server keys are permitted and partial payloads are valid; + not validated at runtime (a TypedDict is a plain ``dict``). + """ + + event: dict[str, Any] - def enter_queue(self: _Self, config: EnterQueueConfig | None = None) -> _Self: - """Place the call into a queue.""" - raise NotImplementedError # installed dynamically at runtime - def eval(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: - """Evaluate expressions and assign to variables (deprecated).""" +class _SwmlVerbs: + """The SWML verb methods SwmlBuilder installs at runtime (static view).""" + + def amazon_bedrock(self: _Self, config: AmazonBedrockObject | None = None) -> _Self: + """Creates a new Bedrock AI Agent""" raise NotImplementedError # installed dynamically at runtime - def execute(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: - """Add the execute verb.""" + def cond(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: + """Execute a sequence of instructions depending on the value of a JavaScript condition.""" raise NotImplementedError # installed dynamically at runtime - def execute_rpc(self: _Self, config: ExecuteRpcConfig | None = None) -> _Self: - """Execute a remote procedure call.""" + def connect(self: _Self, config: ConnectConfig | None = None) -> _Self: + """Dial a SIP URI or phone number.""" raise NotImplementedError # installed dynamically at runtime - def goto(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: - """Add the goto verb.""" + def denoise(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: + """Start noise reduction. You can stop it at any time using `stop_denoise`.""" raise NotImplementedError # installed dynamically at runtime - def if_(self: _Self, config: IfConfig | None = None) -> _Self: - """Conditional branching (deprecated).""" + def enter_queue(self: _Self, config: EnterQueueObject | None = None) -> _Self: + """Place the current call in a named queue where it will wait to be connected to an available agent or resource.""" raise NotImplementedError # installed dynamically at runtime - def join_conference(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: - """Add the join_conference verb.""" + def execute(self: _Self, config: ExecuteConfig | None = None) -> _Self: + """Execute a specified section or URL as a subroutine, and upon completion, return to the current document.""" raise NotImplementedError # installed dynamically at runtime - def join_room(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: - """Add the join_room verb.""" + def goto(self: _Self, config: GotoConfig | None = None) -> _Self: + """Jump to a label within the current section, optionally based on a condition.""" raise NotImplementedError # installed dynamically at runtime - def label(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: - """Add the label verb.""" + def label(self: _Self, value: str) -> _Self: + """Mark any point of the SWML section with a label so that goto can jump to it.""" raise NotImplementedError # installed dynamically at runtime def live_transcribe( self: _Self, config: LiveTranscribeConfig | None = None ) -> _Self: - """Start live transcription of the call.""" + """Start live transcription of the call. The transcription will be sent to the specified webhook URL.""" + raise NotImplementedError # installed dynamically at runtime + + def ai_sidecar(self: _Self, config: AiSidecarConfig | None = None) -> _Self: + """Start ai_sidecar mode — live_transcribe with an LLM/SWAIG/MCP loop on top.""" raise NotImplementedError # installed dynamically at runtime def live_translate(self: _Self, config: LiveTranslateConfig | None = None) -> _Self: - """Start live translation of the call.""" + """Start live translation of the call. The translation will be sent to the specified webhook URL.""" + raise NotImplementedError # installed dynamically at runtime + + def join_room(self: _Self, config: JoinRoomConfig | None = None) -> _Self: + """Join a RELAY room. If the room doesn't exist, it creates a new room.""" raise NotImplementedError # installed dynamically at runtime - def pay(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: - """Add the pay verb.""" + def join_conference( + self: _Self, config: JoinConferenceObject | None = None + ) -> _Self: + """Join an ad-hoc audio conference started on either the SignalWire or Compatibility API.""" raise NotImplementedError # installed dynamically at runtime - def prompt(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: - """Add the prompt verb.""" + def prompt(self: _Self, config: PromptConfig | None = None) -> _Self: + """Play a prompt and wait for input. The input can be received either as digits from the keypad,""" raise NotImplementedError # installed dynamically at runtime - def receive_fax(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: - """Add the receive_fax verb.""" + def receive_fax(self: _Self, config: ReceiveFaxConfig | None = None) -> _Self: + """Receive a fax being delivered to this call.""" raise NotImplementedError # installed dynamically at runtime def record(self: _Self, config: RecordConfig | None = None) -> _Self: - """Record audio from the call.""" + """Record the call audio in the foreground, pausing further SWML execution until recording ends.""" raise NotImplementedError # installed dynamically at runtime def record_call(self: _Self, config: RecordCallConfig | None = None) -> _Self: - """Start recording the entire call.""" + """Record call in the background.""" raise NotImplementedError # installed dynamically at runtime def request(self: _Self, config: RequestConfig | None = None) -> _Self: - """Make an HTTP request and store the result.""" + """Send a GET, POST, PUT, or DELETE request to a remote URL.""" raise NotImplementedError # installed dynamically at runtime def return_(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: - """Return from the current section.""" + """Return a value from an execute call or exit the script. The value can be any type.""" raise NotImplementedError # installed dynamically at runtime - def sip_refer(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: - """Add the sip_refer verb.""" + def send_digits(self: _Self, config: SendDigitsConfig | None = None) -> _Self: + """Send digit presses as DTMF tones.""" raise NotImplementedError # installed dynamically at runtime - def send_digits(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: - """Add the send_digits verb.""" + def send_fax(self: _Self, config: SendFaxConfig | None = None) -> _Self: + """Send a fax.""" raise NotImplementedError # installed dynamically at runtime - def send_fax(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: - """Add the send_fax verb.""" - raise NotImplementedError # installed dynamically at runtime - - def send_sms(self: _Self, config: SendSmsConfig | None = None) -> _Self: - """Send an SMS message.""" + def send_sms(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: + """Send an outbound SMS or MMS message to a PSTN phone number.""" raise NotImplementedError # installed dynamically at runtime def set(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: - """Set one or more variables.""" - raise NotImplementedError # installed dynamically at runtime - - def set_meta(self: _Self, config: SetMetaConfig | None = None) -> _Self: - """Add customer metadata to call and conference events""" + """Set script variables to the specified values.""" raise NotImplementedError # installed dynamically at runtime def sleep(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: - """Add the sleep verb.""" + """Pause execution for a specified duration.""" raise NotImplementedError # installed dynamically at runtime - def stop_denoise(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: - """Disable noise reduction on audio.""" - raise NotImplementedError # installed dynamically at runtime - - def stop_record_call(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: - """Add the stop_record_call verb.""" + def sip_refer(self: _Self, config: SipReferConfig | None = None) -> _Self: + """Send SIP REFER to a SIP call.""" raise NotImplementedError # installed dynamically at runtime - def stop_stream(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: - """Add the stop_stream verb.""" + def stop_denoise(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: + """Stop noise reduction that was started with denoise.""" raise NotImplementedError # installed dynamically at runtime - def stop_tap(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: - """Add the stop_tap verb.""" + def stop_record_call( + self: _Self, config: StopRecordCallConfig | None = None + ) -> _Self: + """Stop an active background recording.""" raise NotImplementedError # installed dynamically at runtime - def stream(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: - """Add the stream verb.""" + def stop_tap(self: _Self, config: StopTapConfig | None = None) -> _Self: + """Stop an active tap stream.""" raise NotImplementedError # installed dynamically at runtime def switch(self: _Self, config: SwitchConfig | None = None) -> _Self: - """Conditional branching based on variable value.""" + """Execute different instructions based on a variable's value.""" raise NotImplementedError # installed dynamically at runtime - def tap(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: - """Add the tap verb.""" + def tap(self: _Self, config: TapConfig | None = None) -> _Self: + """Start background call tap. Media is streamed over Websocket or RTP to customer controlled URI.""" raise NotImplementedError # installed dynamically at runtime - def transcribe(self: _Self, config: TranscribeConfig | None = None) -> _Self: - """Start transcription on the call.""" + def transfer(self: _Self, config: TransferConfig | None = None) -> _Self: + """Transfer the execution of the script to a different SWML section, URL, or Relay application.""" raise NotImplementedError # installed dynamically at runtime - def transcribe_stop(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: - """Stop transcription on the call.""" + def unset(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: + """Unset specified variables. The variables may have been set using the set method""" raise NotImplementedError # installed dynamically at runtime - def transfer(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: - """Add the transfer verb.""" + def pay(self: _Self, config: PayConfig | None = None) -> _Self: + """Enables secure payment processing during voice calls. When implemented, it manages the entire payment flow""" raise NotImplementedError # installed dynamically at runtime - def unset(self: _Self, config: Mapping[str, Any] | None = None) -> _Self: - """Body shape enforced by CHECK_swml_method_unset, swml_schema.c.""" + def detect_machine(self: _Self, config: DetectMachineConfig | None = None) -> _Self: + """A detection method that combines AMD (Answering Machine Detection) and fax detection.""" raise NotImplementedError # installed dynamically at runtime def user_event(self: _Self, config: UserEventConfig | None = None) -> _Self: - """Fire a custom user event.""" + """Allows the user to set and send events to the connected client on the call.""" raise NotImplementedError # installed dynamically at runtime diff --git a/signalwire/signalwire/relay/protocol_types_generated.py b/signalwire/signalwire/relay/protocol_types_generated.py index cbd20e34..8756b49a 100644 --- a/signalwire/signalwire/relay/protocol_types_generated.py +++ b/signalwire/signalwire/relay/protocol_types_generated.py @@ -176,9 +176,6 @@ class CallingCollectStopParams(TypedDict, total=False): node_id: str -CallingConferenceParams: TypeAlias = "dict[str, Any]" - - class CallingConnectParams(TypedDict, total=False): """Wire schema for the JSON payload of `calling.connect` (params). Extracted from switchblade `PublicCallConnectParams.cs`. @@ -1040,9 +1037,6 @@ class CallingCollectStopResult(TypedDict, total=False): message: str -CallingConferenceResult: TypeAlias = "dict[str, Any]" - - class CallingConnectResult(TypedDict, total=False): """Wire schema for the JSON payload of `calling.connect` (result). Extracted from switchblade `PublicCallConnectResult.cs`. @@ -1725,4 +1719,4 @@ class SignalwireReauthenticateResult(TypedDict, total=False): authentication: str authorization: dict[str, Any] ice_servers: list[Any] - result: dict[str, Any] + result: Any diff --git a/tests/unit/rest/fabric_generated_test.py b/tests/unit/rest/fabric_generated_test.py index 75486ae8..c0dcc9b1 100644 --- a/tests/unit/rest/fabric_generated_test.py +++ b/tests/unit/rest/fabric_generated_test.py @@ -656,7 +656,7 @@ def test_cxml_webhooks_update_error( def test_freeswitch_connectors_create( self, signalwire_client: RestClient, mock: _MockHarness ) -> None: - signalwire_client.fabric.freeswitch_connectors.create(name="x", token="x") + signalwire_client.fabric.freeswitch_connectors.create(name="x", token="x") # noqa: S106 last = mock.last_request() assert last.method == "POST" assert last.matched_route == "fabric.create_freeswitch_connector" @@ -666,7 +666,7 @@ def test_freeswitch_connectors_create_error( ) -> None: mock.push_scenario("fabric.create_freeswitch_connector", 500, {"error": "x"}) with pytest.raises(SignalWireRestError) as exc: - signalwire_client.fabric.freeswitch_connectors.create(name="x", token="x") + signalwire_client.fabric.freeswitch_connectors.create(name="x", token="x") # noqa: S106 assert exc.value.status_code == 500 def test_freeswitch_connectors_delete( @@ -1198,7 +1198,7 @@ def test_subscribers_create_sip_endpoint( ) -> None: signalwire_client.fabric.subscribers.create_sip_endpoint( "test-id", username="x", password="x" - ) + ) # noqa: S106 last = mock.last_request() assert last.method == "POST" assert last.matched_route == "fabric.create_subscriber_sip_endpoint" @@ -1210,7 +1210,7 @@ def test_subscribers_create_sip_endpoint_error( with pytest.raises(SignalWireRestError) as exc: signalwire_client.fabric.subscribers.create_sip_endpoint( "test-id", username="x", password="x" - ) + ) # noqa: S106 assert exc.value.status_code == 500 def test_subscribers_delete( @@ -1556,7 +1556,7 @@ def test_swml_webhooks_update_error( def test_tokens_create_embed_token( self, signalwire_client: RestClient, mock: _MockHarness ) -> None: - signalwire_client.fabric.tokens.create_embed_token(token="x") + signalwire_client.fabric.tokens.create_embed_token(token="x") # noqa: S106 last = mock.last_request() assert last.method == "POST" assert last.matched_route == "fabric.create_embeds_token" @@ -1566,7 +1566,7 @@ def test_tokens_create_embed_token_error( ) -> None: mock.push_scenario("fabric.create_embeds_token", 500, {"error": "x"}) with pytest.raises(SignalWireRestError) as exc: - signalwire_client.fabric.tokens.create_embed_token(token="x") + signalwire_client.fabric.tokens.create_embed_token(token="x") # noqa: S106 assert exc.value.status_code == 500 def test_tokens_create_guest_token( @@ -1620,7 +1620,7 @@ def test_tokens_create_subscriber_token_error( def test_tokens_refresh_subscriber_token( self, signalwire_client: RestClient, mock: _MockHarness ) -> None: - signalwire_client.fabric.tokens.refresh_subscriber_token(refresh_token="x") + signalwire_client.fabric.tokens.refresh_subscriber_token(refresh_token="x") # noqa: S106 last = mock.last_request() assert last.method == "POST" assert last.matched_route == "fabric.refresh_subscriber_token" @@ -1630,5 +1630,5 @@ def test_tokens_refresh_subscriber_token_error( ) -> None: mock.push_scenario("fabric.refresh_subscriber_token", 500, {"error": "x"}) with pytest.raises(SignalWireRestError) as exc: - signalwire_client.fabric.tokens.refresh_subscriber_token(refresh_token="x") + signalwire_client.fabric.tokens.refresh_subscriber_token(refresh_token="x") # noqa: S106 assert exc.value.status_code == 500 diff --git a/tests/unit/rest/mfa_generated_test.py b/tests/unit/rest/mfa_generated_test.py index af3927da..9ac38e50 100644 --- a/tests/unit/rest/mfa_generated_test.py +++ b/tests/unit/rest/mfa_generated_test.py @@ -54,7 +54,7 @@ def test_mfa_sms_error( def test_mfa_verify( self, signalwire_client: RestClient, mock: _MockHarness ) -> None: - signalwire_client.mfa.verify("test-id", token="x") + signalwire_client.mfa.verify("test-id", token="x") # noqa: S106 last = mock.last_request() assert last.method == "POST" assert last.matched_route == "relay-rest.verify_mfa_token" @@ -64,5 +64,5 @@ def test_mfa_verify_error( ) -> None: mock.push_scenario("relay-rest.verify_mfa_token", 500, {"error": "x"}) with pytest.raises(SignalWireRestError) as exc: - signalwire_client.mfa.verify("test-id", token="x") + signalwire_client.mfa.verify("test-id", token="x") # noqa: S106 assert exc.value.status_code == 500 From 91a8890bc11afe26f50b814198267b1d6c712b63 Mon Sep 17 00:00:00 2001 From: Anthony Minessale II Date: Wed, 12 Aug 2026 14:33:07 -0500 Subject: [PATCH 2/3] ci: re-run against the coordinated porting-sdk pin From f4f22a6a6200053f8e4ee4e358a4739e0ad2b6a3 Mon Sep 17 00:00:00 2001 From: Anthony Minessale II Date: Wed, 12 Aug 2026 15:40:36 -0500 Subject: [PATCH 3/3] ci: re-run against porting-sdk main (oracle landed in #137)