dial-agentframework 0.12.0__tar.gz → 0.13.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dial_agentframework-0.12.0 → dial_agentframework-0.13.0}/PKG-INFO +3 -2
- {dial_agentframework-0.12.0 → dial_agentframework-0.13.0}/README.md +1 -0
- {dial_agentframework-0.12.0 → dial_agentframework-0.13.0}/dial_agentframework/__init__.py +2 -0
- {dial_agentframework-0.12.0 → dial_agentframework-0.13.0}/dial_agentframework/tools.py +38 -0
- {dial_agentframework-0.12.0 → dial_agentframework-0.13.0}/pyproject.toml +2 -2
- {dial_agentframework-0.12.0 → dial_agentframework-0.13.0}/tests/test_tools.py +24 -1
- {dial_agentframework-0.12.0 → dial_agentframework-0.13.0}/uv.lock +2 -2
- {dial_agentframework-0.12.0 → dial_agentframework-0.13.0}/.gitignore +0 -0
- {dial_agentframework-0.12.0 → dial_agentframework-0.13.0}/examples/signup_agentframework.ipynb +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dial-agentframework
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.13.0
|
|
4
4
|
Summary: Official Dial tools for the Microsoft Agent Framework — phone numbers, SMS, OTP, and voice calls
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Requires-Dist: agent-framework-core>=1.0
|
|
7
|
-
Requires-Dist: dial-sdk>=0.
|
|
7
|
+
Requires-Dist: dial-sdk>=0.14.0
|
|
8
8
|
Description-Content-Type: text/markdown
|
|
9
9
|
|
|
10
10
|
# dial-agentframework
|
|
@@ -84,6 +84,7 @@ Each builder takes your shared `DialClient`:
|
|
|
84
84
|
| `purchase_number_tool` | `purchase_number` | Provision a new number (billable) |
|
|
85
85
|
| `set_number_properties_tool` | `set_number_properties` | Update a number's nickname / inbound instruction |
|
|
86
86
|
| `send_message_tool` | `send_message` | Send an SMS (optionally MMS) |
|
|
87
|
+
| `reply_to_message_tool` | `reply_to_message` | Reply or react to a message |
|
|
87
88
|
| `list_messages_tool` | `list_messages` | List recent messages |
|
|
88
89
|
| `make_call_tool` | `make_call` | Place an AI voice call |
|
|
89
90
|
| `list_calls_tool` | `list_calls` | List recent calls |
|
|
@@ -75,6 +75,7 @@ Each builder takes your shared `DialClient`:
|
|
|
75
75
|
| `purchase_number_tool` | `purchase_number` | Provision a new number (billable) |
|
|
76
76
|
| `set_number_properties_tool` | `set_number_properties` | Update a number's nickname / inbound instruction |
|
|
77
77
|
| `send_message_tool` | `send_message` | Send an SMS (optionally MMS) |
|
|
78
|
+
| `reply_to_message_tool` | `reply_to_message` | Reply or react to a message |
|
|
78
79
|
| `list_messages_tool` | `list_messages` | List recent messages |
|
|
79
80
|
| `make_call_tool` | `make_call` | Place an AI voice call |
|
|
80
81
|
| `list_calls_tool` | `list_calls` | List recent calls |
|
|
@@ -5,6 +5,7 @@ from .tools import (
|
|
|
5
5
|
set_number_properties_tool,
|
|
6
6
|
list_messages_tool,
|
|
7
7
|
send_message_tool,
|
|
8
|
+
reply_to_message_tool,
|
|
8
9
|
list_calls_tool,
|
|
9
10
|
make_call_tool,
|
|
10
11
|
get_call_tool,
|
|
@@ -19,6 +20,7 @@ __all__ = [
|
|
|
19
20
|
"set_number_properties_tool",
|
|
20
21
|
"list_messages_tool",
|
|
21
22
|
"send_message_tool",
|
|
23
|
+
"reply_to_message_tool",
|
|
22
24
|
"list_calls_tool",
|
|
23
25
|
"make_call_tool",
|
|
24
26
|
"get_call_tool",
|
|
@@ -226,6 +226,43 @@ def send_message_tool(client: DialClient) -> FunctionTool:
|
|
|
226
226
|
return send_message
|
|
227
227
|
|
|
228
228
|
|
|
229
|
+
def reply_to_message_tool(client: DialClient) -> FunctionTool:
|
|
230
|
+
@tool(
|
|
231
|
+
name="reply_to_message",
|
|
232
|
+
description=(
|
|
233
|
+
"Reply in-thread or react to an existing message. The reply goes out from "
|
|
234
|
+
"the Dial number the target message belongs to, to the other party — no "
|
|
235
|
+
"from/to needed. Provide exactly one of body or reaction. On iMessage "
|
|
236
|
+
"numbers replies thread and reactions are native; recipients that can only "
|
|
237
|
+
"receive SMS get an emoji reaction as a regular text, and named reactions "
|
|
238
|
+
"are rejected."
|
|
239
|
+
),
|
|
240
|
+
)
|
|
241
|
+
async def reply_to_message(
|
|
242
|
+
message_id: Annotated[
|
|
243
|
+
str, "ID of the message to reply or react to (from list_messages or a message.received event)"
|
|
244
|
+
],
|
|
245
|
+
body: Annotated[
|
|
246
|
+
Optional[str], "Reply text; on an iMessage number it threads under the target message"
|
|
247
|
+
] = None,
|
|
248
|
+
reaction: Annotated[
|
|
249
|
+
Optional[str],
|
|
250
|
+
"Reaction to send instead of a body: love, like, dislike, laugh, "
|
|
251
|
+
"emphasize, question, or a single emoji",
|
|
252
|
+
] = None,
|
|
253
|
+
) -> str:
|
|
254
|
+
if (body is None) == (reaction is None):
|
|
255
|
+
return "Provide exactly one of body or reaction."
|
|
256
|
+
if body is not None:
|
|
257
|
+
msg = await client.reply_to_message(message_id, body=body)
|
|
258
|
+
else:
|
|
259
|
+
msg = await client.reply_to_message(message_id, reaction=reaction)
|
|
260
|
+
note = f", reaction: {msg.reaction}" if getattr(msg, "reaction", None) else ""
|
|
261
|
+
return f"Reply sent successfully. ID: {msg.id}, status: {msg.status}{note}"
|
|
262
|
+
|
|
263
|
+
return reply_to_message
|
|
264
|
+
|
|
265
|
+
|
|
229
266
|
# ── Calls ────────────────────────────────────────────────────────────────────
|
|
230
267
|
|
|
231
268
|
|
|
@@ -432,6 +469,7 @@ def dial_tools(client: DialClient) -> list[FunctionTool]:
|
|
|
432
469
|
set_number_properties_tool(client),
|
|
433
470
|
list_messages_tool(client),
|
|
434
471
|
send_message_tool(client),
|
|
472
|
+
reply_to_message_tool(client),
|
|
435
473
|
list_calls_tool(client),
|
|
436
474
|
make_call_tool(client),
|
|
437
475
|
get_call_tool(client),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "dial-agentframework"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.13.0"
|
|
4
4
|
description = "Official Dial tools for the Microsoft Agent Framework — phone numbers, SMS, OTP, and voice calls"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.11"
|
|
@@ -8,7 +8,7 @@ dependencies = [
|
|
|
8
8
|
# Core has `tool` + `FunctionTool` (all this package needs). Chat clients ship in
|
|
9
9
|
# separate integration packages (agent-framework-openai, …) the user installs.
|
|
10
10
|
"agent-framework-core>=1.0",
|
|
11
|
-
"dial-sdk>=0.
|
|
11
|
+
"dial-sdk>=0.14.0",
|
|
12
12
|
]
|
|
13
13
|
|
|
14
14
|
[tool.uv.sources]
|
|
@@ -4,6 +4,7 @@ from dial_agentframework import (
|
|
|
4
4
|
dial_tools,
|
|
5
5
|
purchase_number_tool,
|
|
6
6
|
send_message_tool,
|
|
7
|
+
reply_to_message_tool,
|
|
7
8
|
make_call_tool,
|
|
8
9
|
wait_for_message_tool,
|
|
9
10
|
)
|
|
@@ -54,7 +55,7 @@ def _run(tool, **args) -> str:
|
|
|
54
55
|
# ── Tools ────────────────────────────────────────────────────────────────────
|
|
55
56
|
|
|
56
57
|
|
|
57
|
-
def
|
|
58
|
+
def test_dial_tools_bundles_all_eleven():
|
|
58
59
|
names = sorted(t.name for t in dial_tools(FakeClient()))
|
|
59
60
|
assert names == sorted(
|
|
60
61
|
[
|
|
@@ -63,6 +64,7 @@ def test_dial_tools_bundles_all_ten():
|
|
|
63
64
|
"set_number_properties",
|
|
64
65
|
"list_messages",
|
|
65
66
|
"send_message",
|
|
67
|
+
"reply_to_message",
|
|
66
68
|
"list_calls",
|
|
67
69
|
"make_call",
|
|
68
70
|
"get_call",
|
|
@@ -102,6 +104,27 @@ def test_send_message_media_only_with_force_audio_file():
|
|
|
102
104
|
assert params.media == ["https://cdn.example.com/note.m4a"]
|
|
103
105
|
|
|
104
106
|
|
|
107
|
+
def test_reply_to_message_sends_body_or_reaction():
|
|
108
|
+
client = FakeClient(reply_to_message=_FakeMessage())
|
|
109
|
+
tool = reply_to_message_tool(client)
|
|
110
|
+
out = _run(tool, message_id="msg_t", body="on my way")
|
|
111
|
+
assert "msg_1" in out
|
|
112
|
+
call = client.calls["reply_to_message"]
|
|
113
|
+
assert call["args"] == ("msg_t",)
|
|
114
|
+
assert call["kwargs"] == {"body": "on my way"}
|
|
115
|
+
|
|
116
|
+
_run(tool, message_id="msg_t", reaction="🔥")
|
|
117
|
+
assert client.calls["reply_to_message"]["kwargs"] == {"reaction": "🔥"}
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def test_reply_to_message_requires_exactly_one():
|
|
121
|
+
client = FakeClient(reply_to_message=_FakeMessage())
|
|
122
|
+
tool = reply_to_message_tool(client)
|
|
123
|
+
assert "exactly one" in _run(tool, message_id="msg_t").lower()
|
|
124
|
+
assert "exactly one" in _run(tool, message_id="msg_t", body="x", reaction="love").lower()
|
|
125
|
+
assert "reply_to_message" not in client.calls
|
|
126
|
+
|
|
127
|
+
|
|
105
128
|
def test_purchase_number_builds_params_with_consent():
|
|
106
129
|
client = FakeClient(purchase_number=_FakeNumber())
|
|
107
130
|
tool = purchase_number_tool(client)
|
|
@@ -345,7 +345,7 @@ wheels = [
|
|
|
345
345
|
|
|
346
346
|
[[package]]
|
|
347
347
|
name = "dial-agentframework"
|
|
348
|
-
version = "0.
|
|
348
|
+
version = "0.13.0"
|
|
349
349
|
source = { editable = "." }
|
|
350
350
|
dependencies = [
|
|
351
351
|
{ name = "agent-framework-core" },
|
|
@@ -368,7 +368,7 @@ dev = [{ name = "pytest", specifier = ">=8" }]
|
|
|
368
368
|
|
|
369
369
|
[[package]]
|
|
370
370
|
name = "dial-sdk"
|
|
371
|
-
version = "0.
|
|
371
|
+
version = "0.14.0"
|
|
372
372
|
source = { editable = "../sdk-python" }
|
|
373
373
|
dependencies = [
|
|
374
374
|
{ name = "httpx" },
|
|
File without changes
|
{dial_agentframework-0.12.0 → dial_agentframework-0.13.0}/examples/signup_agentframework.ipynb
RENAMED
|
File without changes
|