Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions signalwire/signalwire/core/function_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,7 @@ def execute_swml(
"""
# Detect input type and normalize to appropriate format
if isinstance(swml_content, str):
# Raw SWML string - parse to dict so we can add transfer key if needed
# Raw SWML string - parse to dict so the action carries a document
try:
import json

Expand All @@ -496,11 +496,15 @@ def execute_swml(
else:
raise TypeError("swml_content must be string, dict, or SWML object")

action = swml_data
# transfer rides BESIDE the SWML document, not inside it — the same
# shape connect() and swml_transfer() emit. Inside the document it is
# not a SWML key and the call never exits the agent.
action: dict[str, Any] = {"SWML": swml_data}
if transfer:
action["transfer"] = "true"

return self.add_action("SWML", action)
self.action.append(action)
return self

def hangup(self) -> "FunctionResult":
"""
Expand Down
15 changes: 11 additions & 4 deletions tests/unit/core/test_function_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -542,8 +542,8 @@ def test_execute_swml_dict_does_not_mutate_original(self) -> None:

# The original dict should NOT have 'transfer' key added
assert "transfer" not in original
# But the action's SWML should have it
assert result.action[0]["SWML"]["transfer"] == "true"
# The action carries it beside the document
assert result.action[0]["transfer"] == "true"

def test_execute_swml_sdk_object_with_to_dict(self) -> None:
"""Test execute_swml with an SDK object that has to_dict()"""
Expand All @@ -568,19 +568,26 @@ def test_execute_swml_invalid_type_list(self) -> None:
FunctionResult().execute_swml([1, 2, 3])

def test_execute_swml_with_transfer_true(self) -> None:
"""Test execute_swml with transfer=True adds transfer key"""
"""transfer is a SIBLING of the SWML key — the platform's documented
action shape, and the one connect()/swml_transfer() emit. Inside the
document it is not a SWML key and the call never exits the agent."""
swml_dict = {"version": "1.0.0", "sections": {"main": []}}
result = FunctionResult().execute_swml(swml_dict, transfer=True)

action = result.action[0]
assert action["SWML"]["transfer"] == "true"
assert action["transfer"] == "true"
assert "transfer" not in action["SWML"]
# Same action shape as the live-proven connect() helper
connect_action = FunctionResult().connect("+15551234567").action[0]
assert set(action.keys()) == set(connect_action.keys())

def test_execute_swml_with_transfer_false(self) -> None:
"""Test execute_swml with transfer=False does not add transfer key"""
swml_dict = {"version": "1.0.0", "sections": {"main": []}}
result = FunctionResult().execute_swml(swml_dict, transfer=False)

action = result.action[0]
assert "transfer" not in action
assert "transfer" not in action["SWML"]

def test_execute_swml_chaining(self) -> None:
Expand Down
Loading