diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 7af0e66d..e7dafb47 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "4.150.0" + ".": "4.151.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 1b4cff95..e1653505 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 1047 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/telnyx/telnyx-1d40dd48b29a34bbfcc793ac13312e30f9e7f6ac213f743f44d4d7a019132211.yml -openapi_spec_hash: 811911fb01d3e42b62305264c779829f +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/telnyx/telnyx-f0b674236fbd66f50b5a1706fafd8cb681459cf05379967fd1f043d38d6d476d.yml +openapi_spec_hash: 7ae2cfe4f10fc24e4376fd15cd3455e8 config_hash: da8cae8a6100e4d90af920e222524d09 diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ab568f7..3aac0bfb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 4.151.0 (2026-06-05) + +Full Changelog: [v4.150.0...v4.151.0](https://github.com/team-telnyx/telnyx-python/compare/v4.150.0...v4.151.0) + +### Features + +* Conversation flow update ([222a515](https://github.com/team-telnyx/telnyx-python/commit/222a515891253a53bbfe47ca6750ebb5daf5855f)) + ## 4.150.0 (2026-06-04) Full Changelog: [v4.149.1...v4.150.0](https://github.com/team-telnyx/telnyx-python/compare/v4.149.1...v4.150.0) diff --git a/pyproject.toml b/pyproject.toml index 8e92e843..14022cae 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "telnyx" -version = "4.150.0" +version = "4.151.0" description = "The official Python library for the telnyx API" dynamic = ["readme"] license = "MIT" diff --git a/src/telnyx/_version.py b/src/telnyx/_version.py index 5208a293..5841a80c 100644 --- a/src/telnyx/_version.py +++ b/src/telnyx/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "telnyx" -__version__ = "4.150.0" # x-release-please-version +__version__ = "4.151.0" # x-release-please-version diff --git a/src/telnyx/types/ai/assistant_create_params.py b/src/telnyx/types/ai/assistant_create_params.py index 24515f62..656a379e 100644 --- a/src/telnyx/types/ai/assistant_create_params.py +++ b/src/telnyx/types/ai/assistant_create_params.py @@ -31,6 +31,8 @@ "ConversationFlowNodeFlowNodeReqPosition", "ConversationFlowNodeToolNodeReq", "ConversationFlowNodeToolNodeReqPosition", + "ConversationFlowNodeSpeakNodeReq", + "ConversationFlowNodeSpeakNodeReqPosition", "ConversationFlowEdge", "ConversationFlowEdgeCondition", "ConversationFlowEdgeConditionLlmCondition", @@ -40,6 +42,7 @@ "ConversationFlowEdgeConditionExpressionConditionExpressionStringLiteralExpression", "ConversationFlowEdgeConditionExpressionConditionExpressionNumberLiteralExpression", "ConversationFlowEdgeConditionExpressionConditionExpressionBooleanLiteralExpression", + "ConversationFlowEdgeConditionDefaultCondition", "ConversationFlowEdgeTarget", "ConversationFlowEdgeTargetNodeTarget", "ConversationFlowEdgeTargetAssistantTarget", @@ -349,7 +352,58 @@ class ConversationFlowNodeToolNodeReq(TypedDict, total=False): """Node kind discriminator. Always `tool` for a tool node.""" -ConversationFlowNode: TypeAlias = Union[ConversationFlowNodeFlowNodeReq, ConversationFlowNodeToolNodeReq] +class ConversationFlowNodeSpeakNodeReqPosition(TypedDict, total=False): + """Optional canvas coordinates used by authoring UIs to lay out the graph. + + Ignored by the runtime; round-trips so frontends can persist graph layout across reloads. + """ + + x: Required[float] + """Horizontal coordinate in the authoring canvas.""" + + y: Required[float] + """Vertical coordinate in the authoring canvas.""" + + +class ConversationFlowNodeSpeakNodeReq(TypedDict, total=False): + """A standalone scripted-message step in a flow, as supplied by clients. + + Unlike a prompt node, a speak node has no instructions or model — it isn't + an LLM turn. Reaching it delivers `message` to the user verbatim (with + `{{variable}}` interpolation), then routes via outgoing `llm` / + `expression` edges. + """ + + id: Required[str] + """Caller-supplied unique identifier for this node within the flow.""" + + message: Required[str] + """Message delivered to the user verbatim when the flow reaches this node. + + No LLM turn — the text is spoken/sent exactly as written. `{{variable}}` + placeholders are interpolated from the conversation's dynamic variables; an + unresolved placeholder renders as an empty string. After delivering, the flow + routes via the node's outgoing `llm` / `expression` edges (commonly a single + unconditional edge). + """ + + name: str + """Optional human-readable label, displayed in authoring UIs.""" + + position: ConversationFlowNodeSpeakNodeReqPosition + """Optional canvas coordinates used by authoring UIs to lay out the graph. + + Ignored by the runtime; round-trips so frontends can persist graph layout across + reloads. + """ + + type: Literal["speak"] + """Node kind discriminator. Always `speak` for a speak node.""" + + +ConversationFlowNode: TypeAlias = Union[ + ConversationFlowNodeFlowNodeReq, ConversationFlowNodeToolNodeReq, ConversationFlowNodeSpeakNodeReq +] class ConversationFlowEdgeConditionLlmCondition(TypedDict, total=False): @@ -438,8 +492,25 @@ class ConversationFlowEdgeConditionExpressionCondition(TypedDict, total=False): type: Required[Literal["expression"]] +class ConversationFlowEdgeConditionDefaultCondition(TypedDict, total=False): + """Fallback edge condition: fires only when no other edge's condition is true. + + Evaluated after every conditioned (`llm` / `expression`) edge regardless + of declaration order, so it routes the flow whenever none of the node's + other outgoing edges match. Valid **only** on edges leaving a `tool` or + `speak` node, where the deterministic step auto-advances and must always + have somewhere to go. A tool/speak node with any outgoing edge is required + to carry exactly one `default` edge so it never dead-ends; a tool/speak + node with no outgoing edges is a valid terminal step. Carries no parameters. + """ + + type: Required[Literal["default"]] + + ConversationFlowEdgeCondition: TypeAlias = Union[ - ConversationFlowEdgeConditionLlmCondition, ConversationFlowEdgeConditionExpressionCondition + ConversationFlowEdgeConditionLlmCondition, + ConversationFlowEdgeConditionExpressionCondition, + ConversationFlowEdgeConditionDefaultCondition, ] diff --git a/src/telnyx/types/ai/assistant_update_params.py b/src/telnyx/types/ai/assistant_update_params.py index da3cf492..221e0e62 100644 --- a/src/telnyx/types/ai/assistant_update_params.py +++ b/src/telnyx/types/ai/assistant_update_params.py @@ -31,6 +31,8 @@ "ConversationFlowNodeFlowNodeReqPosition", "ConversationFlowNodeToolNodeReq", "ConversationFlowNodeToolNodeReqPosition", + "ConversationFlowNodeSpeakNodeReq", + "ConversationFlowNodeSpeakNodeReqPosition", "ConversationFlowEdge", "ConversationFlowEdgeCondition", "ConversationFlowEdgeConditionLlmCondition", @@ -40,6 +42,7 @@ "ConversationFlowEdgeConditionExpressionConditionExpressionStringLiteralExpression", "ConversationFlowEdgeConditionExpressionConditionExpressionNumberLiteralExpression", "ConversationFlowEdgeConditionExpressionConditionExpressionBooleanLiteralExpression", + "ConversationFlowEdgeConditionDefaultCondition", "ConversationFlowEdgeTarget", "ConversationFlowEdgeTargetNodeTarget", "ConversationFlowEdgeTargetAssistantTarget", @@ -358,7 +361,58 @@ class ConversationFlowNodeToolNodeReq(TypedDict, total=False): """Node kind discriminator. Always `tool` for a tool node.""" -ConversationFlowNode: TypeAlias = Union[ConversationFlowNodeFlowNodeReq, ConversationFlowNodeToolNodeReq] +class ConversationFlowNodeSpeakNodeReqPosition(TypedDict, total=False): + """Optional canvas coordinates used by authoring UIs to lay out the graph. + + Ignored by the runtime; round-trips so frontends can persist graph layout across reloads. + """ + + x: Required[float] + """Horizontal coordinate in the authoring canvas.""" + + y: Required[float] + """Vertical coordinate in the authoring canvas.""" + + +class ConversationFlowNodeSpeakNodeReq(TypedDict, total=False): + """A standalone scripted-message step in a flow, as supplied by clients. + + Unlike a prompt node, a speak node has no instructions or model — it isn't + an LLM turn. Reaching it delivers `message` to the user verbatim (with + `{{variable}}` interpolation), then routes via outgoing `llm` / + `expression` edges. + """ + + id: Required[str] + """Caller-supplied unique identifier for this node within the flow.""" + + message: Required[str] + """Message delivered to the user verbatim when the flow reaches this node. + + No LLM turn — the text is spoken/sent exactly as written. `{{variable}}` + placeholders are interpolated from the conversation's dynamic variables; an + unresolved placeholder renders as an empty string. After delivering, the flow + routes via the node's outgoing `llm` / `expression` edges (commonly a single + unconditional edge). + """ + + name: str + """Optional human-readable label, displayed in authoring UIs.""" + + position: ConversationFlowNodeSpeakNodeReqPosition + """Optional canvas coordinates used by authoring UIs to lay out the graph. + + Ignored by the runtime; round-trips so frontends can persist graph layout across + reloads. + """ + + type: Literal["speak"] + """Node kind discriminator. Always `speak` for a speak node.""" + + +ConversationFlowNode: TypeAlias = Union[ + ConversationFlowNodeFlowNodeReq, ConversationFlowNodeToolNodeReq, ConversationFlowNodeSpeakNodeReq +] class ConversationFlowEdgeConditionLlmCondition(TypedDict, total=False): @@ -447,8 +501,25 @@ class ConversationFlowEdgeConditionExpressionCondition(TypedDict, total=False): type: Required[Literal["expression"]] +class ConversationFlowEdgeConditionDefaultCondition(TypedDict, total=False): + """Fallback edge condition: fires only when no other edge's condition is true. + + Evaluated after every conditioned (`llm` / `expression`) edge regardless + of declaration order, so it routes the flow whenever none of the node's + other outgoing edges match. Valid **only** on edges leaving a `tool` or + `speak` node, where the deterministic step auto-advances and must always + have somewhere to go. A tool/speak node with any outgoing edge is required + to carry exactly one `default` edge so it never dead-ends; a tool/speak + node with no outgoing edges is a valid terminal step. Carries no parameters. + """ + + type: Required[Literal["default"]] + + ConversationFlowEdgeCondition: TypeAlias = Union[ - ConversationFlowEdgeConditionLlmCondition, ConversationFlowEdgeConditionExpressionCondition + ConversationFlowEdgeConditionLlmCondition, + ConversationFlowEdgeConditionExpressionCondition, + ConversationFlowEdgeConditionDefaultCondition, ] diff --git a/src/telnyx/types/ai/assistants/version_update_params.py b/src/telnyx/types/ai/assistants/version_update_params.py index 7ed44b47..13f9cde0 100644 --- a/src/telnyx/types/ai/assistants/version_update_params.py +++ b/src/telnyx/types/ai/assistants/version_update_params.py @@ -31,6 +31,8 @@ "ConversationFlowNodeFlowNodeReqPosition", "ConversationFlowNodeToolNodeReq", "ConversationFlowNodeToolNodeReqPosition", + "ConversationFlowNodeSpeakNodeReq", + "ConversationFlowNodeSpeakNodeReqPosition", "ConversationFlowEdge", "ConversationFlowEdgeCondition", "ConversationFlowEdgeConditionLlmCondition", @@ -40,6 +42,7 @@ "ConversationFlowEdgeConditionExpressionConditionExpressionStringLiteralExpression", "ConversationFlowEdgeConditionExpressionConditionExpressionNumberLiteralExpression", "ConversationFlowEdgeConditionExpressionConditionExpressionBooleanLiteralExpression", + "ConversationFlowEdgeConditionDefaultCondition", "ConversationFlowEdgeTarget", "ConversationFlowEdgeTargetNodeTarget", "ConversationFlowEdgeTargetAssistantTarget", @@ -354,7 +357,58 @@ class ConversationFlowNodeToolNodeReq(TypedDict, total=False): """Node kind discriminator. Always `tool` for a tool node.""" -ConversationFlowNode: TypeAlias = Union[ConversationFlowNodeFlowNodeReq, ConversationFlowNodeToolNodeReq] +class ConversationFlowNodeSpeakNodeReqPosition(TypedDict, total=False): + """Optional canvas coordinates used by authoring UIs to lay out the graph. + + Ignored by the runtime; round-trips so frontends can persist graph layout across reloads. + """ + + x: Required[float] + """Horizontal coordinate in the authoring canvas.""" + + y: Required[float] + """Vertical coordinate in the authoring canvas.""" + + +class ConversationFlowNodeSpeakNodeReq(TypedDict, total=False): + """A standalone scripted-message step in a flow, as supplied by clients. + + Unlike a prompt node, a speak node has no instructions or model — it isn't + an LLM turn. Reaching it delivers `message` to the user verbatim (with + `{{variable}}` interpolation), then routes via outgoing `llm` / + `expression` edges. + """ + + id: Required[str] + """Caller-supplied unique identifier for this node within the flow.""" + + message: Required[str] + """Message delivered to the user verbatim when the flow reaches this node. + + No LLM turn — the text is spoken/sent exactly as written. `{{variable}}` + placeholders are interpolated from the conversation's dynamic variables; an + unresolved placeholder renders as an empty string. After delivering, the flow + routes via the node's outgoing `llm` / `expression` edges (commonly a single + unconditional edge). + """ + + name: str + """Optional human-readable label, displayed in authoring UIs.""" + + position: ConversationFlowNodeSpeakNodeReqPosition + """Optional canvas coordinates used by authoring UIs to lay out the graph. + + Ignored by the runtime; round-trips so frontends can persist graph layout across + reloads. + """ + + type: Literal["speak"] + """Node kind discriminator. Always `speak` for a speak node.""" + + +ConversationFlowNode: TypeAlias = Union[ + ConversationFlowNodeFlowNodeReq, ConversationFlowNodeToolNodeReq, ConversationFlowNodeSpeakNodeReq +] class ConversationFlowEdgeConditionLlmCondition(TypedDict, total=False): @@ -443,8 +497,25 @@ class ConversationFlowEdgeConditionExpressionCondition(TypedDict, total=False): type: Required[Literal["expression"]] +class ConversationFlowEdgeConditionDefaultCondition(TypedDict, total=False): + """Fallback edge condition: fires only when no other edge's condition is true. + + Evaluated after every conditioned (`llm` / `expression`) edge regardless + of declaration order, so it routes the flow whenever none of the node's + other outgoing edges match. Valid **only** on edges leaving a `tool` or + `speak` node, where the deterministic step auto-advances and must always + have somewhere to go. A tool/speak node with any outgoing edge is required + to carry exactly one `default` edge so it never dead-ends; a tool/speak + node with no outgoing edges is a valid terminal step. Carries no parameters. + """ + + type: Required[Literal["default"]] + + ConversationFlowEdgeCondition: TypeAlias = Union[ - ConversationFlowEdgeConditionLlmCondition, ConversationFlowEdgeConditionExpressionCondition + ConversationFlowEdgeConditionLlmCondition, + ConversationFlowEdgeConditionExpressionCondition, + ConversationFlowEdgeConditionDefaultCondition, ] diff --git a/src/telnyx/types/ai/inference_embedding.py b/src/telnyx/types/ai/inference_embedding.py index ac936e83..a9fa32e1 100644 --- a/src/telnyx/types/ai/inference_embedding.py +++ b/src/telnyx/types/ai/inference_embedding.py @@ -32,6 +32,8 @@ "ConversationFlowNodeFlowNodePosition", "ConversationFlowNodeToolNode", "ConversationFlowNodeToolNodePosition", + "ConversationFlowNodeSpeakNode", + "ConversationFlowNodeSpeakNodePosition", "ConversationFlowEdge", "ConversationFlowEdgeCondition", "ConversationFlowEdgeConditionLlmCondition", @@ -41,6 +43,7 @@ "ConversationFlowEdgeConditionExpressionConditionExpressionStringLiteralExpression", "ConversationFlowEdgeConditionExpressionConditionExpressionNumberLiteralExpression", "ConversationFlowEdgeConditionExpressionConditionExpressionBooleanLiteralExpression", + "ConversationFlowEdgeConditionDefaultCondition", "ConversationFlowEdgeTarget", "ConversationFlowEdgeTargetNodeTarget", "ConversationFlowEdgeTargetAssistantTarget", @@ -195,8 +198,52 @@ class ConversationFlowNodeToolNode(BaseModel): """Node kind discriminator. Always `tool` for a tool node.""" +class ConversationFlowNodeSpeakNodePosition(BaseModel): + """Optional canvas coordinates used by authoring UIs to lay out the graph. + + Ignored by the runtime; round-trips so frontends can persist graph layout across reloads. + """ + + x: float + """Horizontal coordinate in the authoring canvas.""" + + y: float + """Vertical coordinate in the authoring canvas.""" + + +class ConversationFlowNodeSpeakNode(BaseModel): + """A standalone scripted-message step in a flow, as returned by the API.""" + + id: str + """Caller-supplied unique identifier for this node within the flow.""" + + message: str + """Message delivered to the user verbatim when the flow reaches this node. + + No LLM turn — the text is spoken/sent exactly as written. `{{variable}}` + placeholders are interpolated from the conversation's dynamic variables; an + unresolved placeholder renders as an empty string. After delivering, the flow + routes via the node's outgoing `llm` / `expression` edges (commonly a single + unconditional edge). + """ + + name: Optional[str] = None + """Optional human-readable label, displayed in authoring UIs.""" + + position: Optional[ConversationFlowNodeSpeakNodePosition] = None + """Optional canvas coordinates used by authoring UIs to lay out the graph. + + Ignored by the runtime; round-trips so frontends can persist graph layout across + reloads. + """ + + type: Optional[Literal["speak"]] = None + """Node kind discriminator. Always `speak` for a speak node.""" + + ConversationFlowNode: TypeAlias = Annotated[ - Union[ConversationFlowNodeFlowNode, ConversationFlowNodeToolNode], PropertyInfo(discriminator="type") + Union[ConversationFlowNodeFlowNode, ConversationFlowNodeToolNode, ConversationFlowNodeSpeakNode], + PropertyInfo(discriminator="type"), ] @@ -286,8 +333,27 @@ class ConversationFlowEdgeConditionExpressionCondition(BaseModel): type: Literal["expression"] +class ConversationFlowEdgeConditionDefaultCondition(BaseModel): + """Fallback edge condition: fires only when no other edge's condition is true. + + Evaluated after every conditioned (`llm` / `expression`) edge regardless + of declaration order, so it routes the flow whenever none of the node's + other outgoing edges match. Valid **only** on edges leaving a `tool` or + `speak` node, where the deterministic step auto-advances and must always + have somewhere to go. A tool/speak node with any outgoing edge is required + to carry exactly one `default` edge so it never dead-ends; a tool/speak + node with no outgoing edges is a valid terminal step. Carries no parameters. + """ + + type: Literal["default"] + + ConversationFlowEdgeCondition: TypeAlias = Annotated[ - Union[ConversationFlowEdgeConditionLlmCondition, ConversationFlowEdgeConditionExpressionCondition], + Union[ + ConversationFlowEdgeConditionLlmCondition, + ConversationFlowEdgeConditionExpressionCondition, + ConversationFlowEdgeConditionDefaultCondition, + ], PropertyInfo(discriminator="type"), ]