mail-swarms 1.3.2__py3-none-any.whl
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.
- mail/__init__.py +35 -0
- mail/api.py +1964 -0
- mail/cli.py +432 -0
- mail/client.py +1657 -0
- mail/config/__init__.py +8 -0
- mail/config/client.py +87 -0
- mail/config/server.py +165 -0
- mail/core/__init__.py +72 -0
- mail/core/actions.py +69 -0
- mail/core/agents.py +73 -0
- mail/core/message.py +366 -0
- mail/core/runtime.py +3537 -0
- mail/core/tasks.py +311 -0
- mail/core/tools.py +1206 -0
- mail/db/__init__.py +0 -0
- mail/db/init.py +182 -0
- mail/db/types.py +65 -0
- mail/db/utils.py +523 -0
- mail/examples/__init__.py +27 -0
- mail/examples/analyst_dummy/__init__.py +15 -0
- mail/examples/analyst_dummy/agent.py +136 -0
- mail/examples/analyst_dummy/prompts.py +44 -0
- mail/examples/consultant_dummy/__init__.py +15 -0
- mail/examples/consultant_dummy/agent.py +136 -0
- mail/examples/consultant_dummy/prompts.py +42 -0
- mail/examples/data_analysis/__init__.py +40 -0
- mail/examples/data_analysis/analyst/__init__.py +9 -0
- mail/examples/data_analysis/analyst/agent.py +67 -0
- mail/examples/data_analysis/analyst/prompts.py +53 -0
- mail/examples/data_analysis/processor/__init__.py +13 -0
- mail/examples/data_analysis/processor/actions.py +293 -0
- mail/examples/data_analysis/processor/agent.py +67 -0
- mail/examples/data_analysis/processor/prompts.py +48 -0
- mail/examples/data_analysis/reporter/__init__.py +10 -0
- mail/examples/data_analysis/reporter/actions.py +187 -0
- mail/examples/data_analysis/reporter/agent.py +67 -0
- mail/examples/data_analysis/reporter/prompts.py +49 -0
- mail/examples/data_analysis/statistics/__init__.py +18 -0
- mail/examples/data_analysis/statistics/actions.py +343 -0
- mail/examples/data_analysis/statistics/agent.py +67 -0
- mail/examples/data_analysis/statistics/prompts.py +60 -0
- mail/examples/mafia/__init__.py +0 -0
- mail/examples/mafia/game.py +1537 -0
- mail/examples/mafia/narrator_tools.py +396 -0
- mail/examples/mafia/personas.py +240 -0
- mail/examples/mafia/prompts.py +489 -0
- mail/examples/mafia/roles.py +147 -0
- mail/examples/mafia/spec.md +350 -0
- mail/examples/math_dummy/__init__.py +23 -0
- mail/examples/math_dummy/actions.py +252 -0
- mail/examples/math_dummy/agent.py +136 -0
- mail/examples/math_dummy/prompts.py +46 -0
- mail/examples/math_dummy/types.py +5 -0
- mail/examples/research/__init__.py +39 -0
- mail/examples/research/researcher/__init__.py +9 -0
- mail/examples/research/researcher/agent.py +67 -0
- mail/examples/research/researcher/prompts.py +54 -0
- mail/examples/research/searcher/__init__.py +10 -0
- mail/examples/research/searcher/actions.py +324 -0
- mail/examples/research/searcher/agent.py +67 -0
- mail/examples/research/searcher/prompts.py +53 -0
- mail/examples/research/summarizer/__init__.py +18 -0
- mail/examples/research/summarizer/actions.py +255 -0
- mail/examples/research/summarizer/agent.py +67 -0
- mail/examples/research/summarizer/prompts.py +55 -0
- mail/examples/research/verifier/__init__.py +10 -0
- mail/examples/research/verifier/actions.py +337 -0
- mail/examples/research/verifier/agent.py +67 -0
- mail/examples/research/verifier/prompts.py +52 -0
- mail/examples/supervisor/__init__.py +11 -0
- mail/examples/supervisor/agent.py +4 -0
- mail/examples/supervisor/prompts.py +93 -0
- mail/examples/support/__init__.py +33 -0
- mail/examples/support/classifier/__init__.py +10 -0
- mail/examples/support/classifier/actions.py +307 -0
- mail/examples/support/classifier/agent.py +68 -0
- mail/examples/support/classifier/prompts.py +56 -0
- mail/examples/support/coordinator/__init__.py +9 -0
- mail/examples/support/coordinator/agent.py +67 -0
- mail/examples/support/coordinator/prompts.py +48 -0
- mail/examples/support/faq/__init__.py +10 -0
- mail/examples/support/faq/actions.py +182 -0
- mail/examples/support/faq/agent.py +67 -0
- mail/examples/support/faq/prompts.py +42 -0
- mail/examples/support/sentiment/__init__.py +15 -0
- mail/examples/support/sentiment/actions.py +341 -0
- mail/examples/support/sentiment/agent.py +67 -0
- mail/examples/support/sentiment/prompts.py +54 -0
- mail/examples/weather_dummy/__init__.py +23 -0
- mail/examples/weather_dummy/actions.py +75 -0
- mail/examples/weather_dummy/agent.py +136 -0
- mail/examples/weather_dummy/prompts.py +35 -0
- mail/examples/weather_dummy/types.py +5 -0
- mail/factories/__init__.py +27 -0
- mail/factories/action.py +223 -0
- mail/factories/base.py +1531 -0
- mail/factories/supervisor.py +241 -0
- mail/net/__init__.py +7 -0
- mail/net/registry.py +712 -0
- mail/net/router.py +728 -0
- mail/net/server_utils.py +114 -0
- mail/net/types.py +247 -0
- mail/server.py +1605 -0
- mail/stdlib/__init__.py +0 -0
- mail/stdlib/anthropic/__init__.py +0 -0
- mail/stdlib/fs/__init__.py +15 -0
- mail/stdlib/fs/actions.py +209 -0
- mail/stdlib/http/__init__.py +19 -0
- mail/stdlib/http/actions.py +333 -0
- mail/stdlib/interswarm/__init__.py +11 -0
- mail/stdlib/interswarm/actions.py +208 -0
- mail/stdlib/mcp/__init__.py +19 -0
- mail/stdlib/mcp/actions.py +294 -0
- mail/stdlib/openai/__init__.py +13 -0
- mail/stdlib/openai/agents.py +451 -0
- mail/summarizer.py +234 -0
- mail/swarms_json/__init__.py +27 -0
- mail/swarms_json/types.py +87 -0
- mail/swarms_json/utils.py +255 -0
- mail/url_scheme.py +51 -0
- mail/utils/__init__.py +53 -0
- mail/utils/auth.py +194 -0
- mail/utils/context.py +17 -0
- mail/utils/logger.py +73 -0
- mail/utils/openai.py +212 -0
- mail/utils/parsing.py +89 -0
- mail/utils/serialize.py +292 -0
- mail/utils/store.py +49 -0
- mail/utils/string_builder.py +119 -0
- mail/utils/version.py +20 -0
- mail_swarms-1.3.2.dist-info/METADATA +237 -0
- mail_swarms-1.3.2.dist-info/RECORD +137 -0
- mail_swarms-1.3.2.dist-info/WHEEL +4 -0
- mail_swarms-1.3.2.dist-info/entry_points.txt +2 -0
- mail_swarms-1.3.2.dist-info/licenses/LICENSE +202 -0
- mail_swarms-1.3.2.dist-info/licenses/NOTICE +10 -0
- mail_swarms-1.3.2.dist-info/licenses/THIRD_PARTY_NOTICES.md +12334 -0
mail/core/message.py
ADDED
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
# Copyright (c) 2025 Addison Kline, Jacob Hahn
|
|
3
|
+
|
|
4
|
+
import datetime
|
|
5
|
+
from typing import Any, Literal, TypedDict
|
|
6
|
+
|
|
7
|
+
from dict2xml import dict2xml
|
|
8
|
+
|
|
9
|
+
MAIL_MESSAGE_TYPES = [
|
|
10
|
+
"request",
|
|
11
|
+
"response",
|
|
12
|
+
"broadcast",
|
|
13
|
+
"interrupt",
|
|
14
|
+
"broadcast_complete",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class MAILAddress(TypedDict):
|
|
19
|
+
"""
|
|
20
|
+
An address representing the sender or recipient of a MAIL message.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
address_type: Literal["admin", "agent", "system", "user"]
|
|
24
|
+
"""The type of address."""
|
|
25
|
+
address: str
|
|
26
|
+
"""The address of the sender or recipient."""
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
MAIL_ALL_LOCAL_AGENTS = MAILAddress(address_type="agent", address="all")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class MAILRequest(TypedDict):
|
|
33
|
+
"""
|
|
34
|
+
A request to an agent using the MAIL protocol.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
task_id: str
|
|
38
|
+
"""The unique identifier for the task."""
|
|
39
|
+
request_id: str
|
|
40
|
+
"""The unique identifier for the request."""
|
|
41
|
+
sender: MAILAddress
|
|
42
|
+
"""The sender of the request."""
|
|
43
|
+
recipient: MAILAddress
|
|
44
|
+
"""The recipient of the request."""
|
|
45
|
+
subject: str
|
|
46
|
+
"""The subject of the request."""
|
|
47
|
+
body: str
|
|
48
|
+
"""The body of the request."""
|
|
49
|
+
# Interswarm fields
|
|
50
|
+
sender_swarm: str | None
|
|
51
|
+
"""The swarm name of the sender (for interswarm messages)."""
|
|
52
|
+
recipient_swarm: str | None
|
|
53
|
+
"""The swarm name of the recipient (for interswarm messages)."""
|
|
54
|
+
routing_info: dict[str, Any] | None
|
|
55
|
+
"""Additional routing information for interswarm messages."""
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class MAILResponse(TypedDict):
|
|
59
|
+
"""
|
|
60
|
+
A response from an agent using the MAIL protocol.
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
task_id: str
|
|
64
|
+
"""The unique identifier for the task."""
|
|
65
|
+
request_id: str
|
|
66
|
+
"""The unique identifier of the request being responded to."""
|
|
67
|
+
sender: MAILAddress
|
|
68
|
+
"""The sender of the response."""
|
|
69
|
+
recipient: MAILAddress
|
|
70
|
+
"""The recipient of the response."""
|
|
71
|
+
subject: str
|
|
72
|
+
"""The status of the response."""
|
|
73
|
+
body: str
|
|
74
|
+
"""The body of the response."""
|
|
75
|
+
# Interswarm fields
|
|
76
|
+
sender_swarm: str | None
|
|
77
|
+
"""The swarm name of the sender (for interswarm messages)."""
|
|
78
|
+
recipient_swarm: str | None
|
|
79
|
+
"""The swarm name of the recipient (for interswarm messages)."""
|
|
80
|
+
routing_info: dict[str, Any] | None
|
|
81
|
+
"""Additional routing information for interswarm messages."""
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class MAILBroadcast(TypedDict):
|
|
85
|
+
"""
|
|
86
|
+
A broadcast message using the MAIL protocol.
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
task_id: str
|
|
90
|
+
"""The unique identifier for the task."""
|
|
91
|
+
broadcast_id: str
|
|
92
|
+
"""The unique identifier for the broadcast."""
|
|
93
|
+
sender: MAILAddress
|
|
94
|
+
"""The sender of the broadcast."""
|
|
95
|
+
recipients: list[MAILAddress]
|
|
96
|
+
"""The recipients of the broadcast."""
|
|
97
|
+
subject: str
|
|
98
|
+
"""The subject of the broadcast."""
|
|
99
|
+
body: str
|
|
100
|
+
"""The full details of the broadcast."""
|
|
101
|
+
# Interswarm fields
|
|
102
|
+
sender_swarm: str | None
|
|
103
|
+
"""The swarm name of the sender (for interswarm messages)."""
|
|
104
|
+
recipient_swarms: list[str] | None
|
|
105
|
+
"""The swarm names of the recipients (for interswarm messages)."""
|
|
106
|
+
routing_info: dict[str, Any] | None
|
|
107
|
+
"""Additional routing information for interswarm messages."""
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class MAILInterrupt(TypedDict):
|
|
111
|
+
"""
|
|
112
|
+
An interrupt using the MAIL protocol.
|
|
113
|
+
"""
|
|
114
|
+
|
|
115
|
+
task_id: str
|
|
116
|
+
"""The unique identifier for the task."""
|
|
117
|
+
interrupt_id: str
|
|
118
|
+
"""The unique identifier for the interrupt."""
|
|
119
|
+
sender: MAILAddress
|
|
120
|
+
"""The sender of the interrupt."""
|
|
121
|
+
recipients: list[MAILAddress]
|
|
122
|
+
"""The recipients of the interrupt."""
|
|
123
|
+
subject: str
|
|
124
|
+
"""The description of the interrupt."""
|
|
125
|
+
body: str
|
|
126
|
+
"""The full details of the interrupt, including what tasks to halt, conditions for resuming, and if interrupted tasks should be discarded."""
|
|
127
|
+
# Interswarm fields
|
|
128
|
+
sender_swarm: str | None
|
|
129
|
+
"""The swarm name of the sender (for interswarm messages)."""
|
|
130
|
+
recipient_swarms: list[str] | None
|
|
131
|
+
"""The swarm names of the recipients (for interswarm messages)."""
|
|
132
|
+
routing_info: dict[str, Any] | None
|
|
133
|
+
"""Additional routing information for interswarm messages."""
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
class MAILInterswarmMessage(TypedDict):
|
|
137
|
+
"""
|
|
138
|
+
An interswarm message wrapper for HTTP transport.
|
|
139
|
+
"""
|
|
140
|
+
|
|
141
|
+
message_id: str
|
|
142
|
+
"""The unique identifier for the interswarm message."""
|
|
143
|
+
source_swarm: str
|
|
144
|
+
"""The source swarm name."""
|
|
145
|
+
target_swarm: str
|
|
146
|
+
"""The target swarm name."""
|
|
147
|
+
timestamp: str
|
|
148
|
+
"""The timestamp of the message."""
|
|
149
|
+
payload: MAILRequest | MAILResponse | MAILBroadcast | MAILInterrupt
|
|
150
|
+
"""The wrapped MAIL message."""
|
|
151
|
+
msg_type: Literal["request", "response", "broadcast", "interrupt"]
|
|
152
|
+
"""The type of the message."""
|
|
153
|
+
auth_token: str | None
|
|
154
|
+
"""Authentication token for interswarm communication."""
|
|
155
|
+
task_owner: str
|
|
156
|
+
"""The owner of the task (role:id@swarm)."""
|
|
157
|
+
task_contributors: list[str]
|
|
158
|
+
"""The contributors to the task (role:id@swarm)."""
|
|
159
|
+
metadata: dict[str, Any] | None
|
|
160
|
+
"""Additional metadata for routing and processing."""
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def parse_task_contributors(contributors: list[str]) -> list[tuple[str, str, str]]:
|
|
164
|
+
"""
|
|
165
|
+
Parse a list of task contributors in the format `role:id@swarm`.
|
|
166
|
+
"""
|
|
167
|
+
return [parse_task_contributor(contributor) for contributor in contributors]
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def parse_task_contributor(contributor: str) -> tuple[str, str, str]:
|
|
171
|
+
"""
|
|
172
|
+
Parse an individual task contributor in the format `role:id@swarm`.
|
|
173
|
+
"""
|
|
174
|
+
if ":" not in contributor:
|
|
175
|
+
raise ValueError("task contributor must be in the format 'role:id@swarm'")
|
|
176
|
+
if "@" not in contributor:
|
|
177
|
+
raise ValueError("task contributor must be in the format 'role:id@swarm'")
|
|
178
|
+
|
|
179
|
+
role = contributor.split(":")[0]
|
|
180
|
+
id = contributor.split(":")[1].split("@")[0]
|
|
181
|
+
swarm = contributor.split("@")[1]
|
|
182
|
+
|
|
183
|
+
return role, id, swarm
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def parse_agent_address(address: str) -> tuple[str, str | None]:
|
|
187
|
+
"""
|
|
188
|
+
Parse an agent address in the format 'agent-name' or 'agent-name@swarm-name'.
|
|
189
|
+
|
|
190
|
+
Returns:
|
|
191
|
+
tuple: (agent_name, swarm_name or None)
|
|
192
|
+
"""
|
|
193
|
+
if "@" in address:
|
|
194
|
+
agent_name, swarm_name = address.split("@", 1)
|
|
195
|
+
return agent_name.strip(), swarm_name.strip()
|
|
196
|
+
else:
|
|
197
|
+
return address.strip(), None
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def format_agent_address(agent_name: str, swarm_name: str | None = None) -> MAILAddress:
|
|
201
|
+
"""
|
|
202
|
+
Format an agent address from agent name and optional swarm name.
|
|
203
|
+
|
|
204
|
+
Returns:
|
|
205
|
+
MAILAddress: Formatted address
|
|
206
|
+
"""
|
|
207
|
+
if swarm_name:
|
|
208
|
+
return MAILAddress(address_type="agent", address=f"{agent_name}@{swarm_name}")
|
|
209
|
+
else:
|
|
210
|
+
return MAILAddress(address_type="agent", address=agent_name)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def create_address(
|
|
214
|
+
address: str, address_type: Literal["admin", "agent", "system", "user"]
|
|
215
|
+
) -> MAILAddress:
|
|
216
|
+
"""
|
|
217
|
+
Create a MAILAddress object with the specified type.
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
address: The address string
|
|
221
|
+
address_type: The type of address ("admin", "agent", "system", or "user")
|
|
222
|
+
|
|
223
|
+
Returns:
|
|
224
|
+
MAILAddress: A properly formatted address object
|
|
225
|
+
"""
|
|
226
|
+
return MAILAddress(address_type=address_type, address=address)
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def create_admin_address(address: str) -> MAILAddress:
|
|
230
|
+
"""
|
|
231
|
+
Create a MAILAddress for an admin.
|
|
232
|
+
"""
|
|
233
|
+
return create_address(address, "admin")
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def create_agent_address(address: str) -> MAILAddress:
|
|
237
|
+
"""
|
|
238
|
+
Create a MAILAddress for an AI agent.
|
|
239
|
+
"""
|
|
240
|
+
return create_address(address, "agent")
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def create_system_address(address: str) -> MAILAddress:
|
|
244
|
+
"""
|
|
245
|
+
Create a MAILAddress for the system.
|
|
246
|
+
"""
|
|
247
|
+
return create_address(address, "system")
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def create_user_address(address: str) -> MAILAddress:
|
|
251
|
+
"""
|
|
252
|
+
Create a MAILAddress for a human user.
|
|
253
|
+
"""
|
|
254
|
+
return create_address(address, "user")
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
def get_address_string(address: MAILAddress) -> str:
|
|
258
|
+
"""
|
|
259
|
+
Extract the address string from a MAILAddress.
|
|
260
|
+
"""
|
|
261
|
+
return address["address"]
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def get_address_type(
|
|
265
|
+
address: MAILAddress,
|
|
266
|
+
) -> Literal["admin", "agent", "system", "user"]:
|
|
267
|
+
"""
|
|
268
|
+
Extract the address type from a MAILAddress.
|
|
269
|
+
"""
|
|
270
|
+
return address["address_type"]
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def build_body_xml(content: dict[str, Any]) -> str:
|
|
274
|
+
"""
|
|
275
|
+
Build the XML representation a MAIL body section.
|
|
276
|
+
"""
|
|
277
|
+
return str(dict2xml(content, wrap="body", indent=""))
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def build_mail_xml(message: "MAILMessage", is_manual: bool = False) -> dict[str, str]:
|
|
281
|
+
"""
|
|
282
|
+
Build the XML representation of a MAIL message.
|
|
283
|
+
"""
|
|
284
|
+
if is_manual:
|
|
285
|
+
return {
|
|
286
|
+
"role": "user",
|
|
287
|
+
"content": message["message"]["body"],
|
|
288
|
+
}
|
|
289
|
+
to = (
|
|
290
|
+
message["message"]["recipient"] # type: ignore
|
|
291
|
+
if "recipient" in message["message"]
|
|
292
|
+
else message["message"]["recipients"]
|
|
293
|
+
)
|
|
294
|
+
to = [to] if isinstance(to, dict) else to
|
|
295
|
+
|
|
296
|
+
# Extract sender and recipient information with type metadata
|
|
297
|
+
sender = message["message"]["sender"]
|
|
298
|
+
sender_str = get_address_string(sender)
|
|
299
|
+
sender_type = get_address_type(sender)
|
|
300
|
+
return {
|
|
301
|
+
"role": "user",
|
|
302
|
+
"content": f"""
|
|
303
|
+
<incoming_message>
|
|
304
|
+
<timestamp>{datetime.datetime.fromisoformat(message["timestamp"]).astimezone(datetime.UTC).isoformat()}</timestamp>
|
|
305
|
+
<from type="{sender_type}">{sender_str}</from>
|
|
306
|
+
<to>
|
|
307
|
+
{[f'<address type="{get_address_type(recipient)}">{get_address_string(recipient)}</address>' for recipient in to]}
|
|
308
|
+
</to>
|
|
309
|
+
<subject>{message["message"]["subject"]}</subject>
|
|
310
|
+
<body>{message["message"]["body"]}</body>
|
|
311
|
+
</incoming_message>
|
|
312
|
+
""",
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
def build_interswarm_mail_xml(message: MAILInterswarmMessage) -> dict[str, str]:
|
|
317
|
+
"""
|
|
318
|
+
Build the XML representation of an interswarm MAIL message.
|
|
319
|
+
"""
|
|
320
|
+
return {
|
|
321
|
+
"role": "user",
|
|
322
|
+
"content": f"""
|
|
323
|
+
<incoming_message>
|
|
324
|
+
<timestamp>{
|
|
325
|
+
datetime.datetime.fromisoformat(message["timestamp"])
|
|
326
|
+
.astimezone(datetime.UTC)
|
|
327
|
+
.isoformat()
|
|
328
|
+
}</timestamp>
|
|
329
|
+
<from type="agent">{message["payload"]["sender"]["address"]}</from>
|
|
330
|
+
<to>
|
|
331
|
+
{
|
|
332
|
+
[
|
|
333
|
+
f'<address type="agent">{recipient["address"]}</address>'
|
|
334
|
+
for recipient in message["payload"]["recipients"] # type: ignore
|
|
335
|
+
]
|
|
336
|
+
if "recipients" in message["payload"] # type: ignore
|
|
337
|
+
else f'<address type="agent">{message["payload"]["recipient"]["address"]}</address>'
|
|
338
|
+
}
|
|
339
|
+
</to>
|
|
340
|
+
<subject>{message["payload"]["subject"]}</subject>
|
|
341
|
+
<body>{message["payload"]["body"]}</body>
|
|
342
|
+
</incoming_message>
|
|
343
|
+
""",
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
class MAILMessage(TypedDict):
|
|
348
|
+
"""
|
|
349
|
+
A message using the MAIL protocol.
|
|
350
|
+
"""
|
|
351
|
+
|
|
352
|
+
id: str
|
|
353
|
+
"""The unique identifier for the message."""
|
|
354
|
+
timestamp: str
|
|
355
|
+
"""The timestamp of the message."""
|
|
356
|
+
message: MAILRequest | MAILResponse | MAILBroadcast | MAILInterrupt
|
|
357
|
+
"""The message content."""
|
|
358
|
+
msg_type: Literal[
|
|
359
|
+
"request",
|
|
360
|
+
"response",
|
|
361
|
+
"broadcast",
|
|
362
|
+
"interrupt",
|
|
363
|
+
"broadcast_complete",
|
|
364
|
+
"buffered",
|
|
365
|
+
]
|
|
366
|
+
"""The type of the message."""
|