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.
Files changed (137) hide show
  1. mail/__init__.py +35 -0
  2. mail/api.py +1964 -0
  3. mail/cli.py +432 -0
  4. mail/client.py +1657 -0
  5. mail/config/__init__.py +8 -0
  6. mail/config/client.py +87 -0
  7. mail/config/server.py +165 -0
  8. mail/core/__init__.py +72 -0
  9. mail/core/actions.py +69 -0
  10. mail/core/agents.py +73 -0
  11. mail/core/message.py +366 -0
  12. mail/core/runtime.py +3537 -0
  13. mail/core/tasks.py +311 -0
  14. mail/core/tools.py +1206 -0
  15. mail/db/__init__.py +0 -0
  16. mail/db/init.py +182 -0
  17. mail/db/types.py +65 -0
  18. mail/db/utils.py +523 -0
  19. mail/examples/__init__.py +27 -0
  20. mail/examples/analyst_dummy/__init__.py +15 -0
  21. mail/examples/analyst_dummy/agent.py +136 -0
  22. mail/examples/analyst_dummy/prompts.py +44 -0
  23. mail/examples/consultant_dummy/__init__.py +15 -0
  24. mail/examples/consultant_dummy/agent.py +136 -0
  25. mail/examples/consultant_dummy/prompts.py +42 -0
  26. mail/examples/data_analysis/__init__.py +40 -0
  27. mail/examples/data_analysis/analyst/__init__.py +9 -0
  28. mail/examples/data_analysis/analyst/agent.py +67 -0
  29. mail/examples/data_analysis/analyst/prompts.py +53 -0
  30. mail/examples/data_analysis/processor/__init__.py +13 -0
  31. mail/examples/data_analysis/processor/actions.py +293 -0
  32. mail/examples/data_analysis/processor/agent.py +67 -0
  33. mail/examples/data_analysis/processor/prompts.py +48 -0
  34. mail/examples/data_analysis/reporter/__init__.py +10 -0
  35. mail/examples/data_analysis/reporter/actions.py +187 -0
  36. mail/examples/data_analysis/reporter/agent.py +67 -0
  37. mail/examples/data_analysis/reporter/prompts.py +49 -0
  38. mail/examples/data_analysis/statistics/__init__.py +18 -0
  39. mail/examples/data_analysis/statistics/actions.py +343 -0
  40. mail/examples/data_analysis/statistics/agent.py +67 -0
  41. mail/examples/data_analysis/statistics/prompts.py +60 -0
  42. mail/examples/mafia/__init__.py +0 -0
  43. mail/examples/mafia/game.py +1537 -0
  44. mail/examples/mafia/narrator_tools.py +396 -0
  45. mail/examples/mafia/personas.py +240 -0
  46. mail/examples/mafia/prompts.py +489 -0
  47. mail/examples/mafia/roles.py +147 -0
  48. mail/examples/mafia/spec.md +350 -0
  49. mail/examples/math_dummy/__init__.py +23 -0
  50. mail/examples/math_dummy/actions.py +252 -0
  51. mail/examples/math_dummy/agent.py +136 -0
  52. mail/examples/math_dummy/prompts.py +46 -0
  53. mail/examples/math_dummy/types.py +5 -0
  54. mail/examples/research/__init__.py +39 -0
  55. mail/examples/research/researcher/__init__.py +9 -0
  56. mail/examples/research/researcher/agent.py +67 -0
  57. mail/examples/research/researcher/prompts.py +54 -0
  58. mail/examples/research/searcher/__init__.py +10 -0
  59. mail/examples/research/searcher/actions.py +324 -0
  60. mail/examples/research/searcher/agent.py +67 -0
  61. mail/examples/research/searcher/prompts.py +53 -0
  62. mail/examples/research/summarizer/__init__.py +18 -0
  63. mail/examples/research/summarizer/actions.py +255 -0
  64. mail/examples/research/summarizer/agent.py +67 -0
  65. mail/examples/research/summarizer/prompts.py +55 -0
  66. mail/examples/research/verifier/__init__.py +10 -0
  67. mail/examples/research/verifier/actions.py +337 -0
  68. mail/examples/research/verifier/agent.py +67 -0
  69. mail/examples/research/verifier/prompts.py +52 -0
  70. mail/examples/supervisor/__init__.py +11 -0
  71. mail/examples/supervisor/agent.py +4 -0
  72. mail/examples/supervisor/prompts.py +93 -0
  73. mail/examples/support/__init__.py +33 -0
  74. mail/examples/support/classifier/__init__.py +10 -0
  75. mail/examples/support/classifier/actions.py +307 -0
  76. mail/examples/support/classifier/agent.py +68 -0
  77. mail/examples/support/classifier/prompts.py +56 -0
  78. mail/examples/support/coordinator/__init__.py +9 -0
  79. mail/examples/support/coordinator/agent.py +67 -0
  80. mail/examples/support/coordinator/prompts.py +48 -0
  81. mail/examples/support/faq/__init__.py +10 -0
  82. mail/examples/support/faq/actions.py +182 -0
  83. mail/examples/support/faq/agent.py +67 -0
  84. mail/examples/support/faq/prompts.py +42 -0
  85. mail/examples/support/sentiment/__init__.py +15 -0
  86. mail/examples/support/sentiment/actions.py +341 -0
  87. mail/examples/support/sentiment/agent.py +67 -0
  88. mail/examples/support/sentiment/prompts.py +54 -0
  89. mail/examples/weather_dummy/__init__.py +23 -0
  90. mail/examples/weather_dummy/actions.py +75 -0
  91. mail/examples/weather_dummy/agent.py +136 -0
  92. mail/examples/weather_dummy/prompts.py +35 -0
  93. mail/examples/weather_dummy/types.py +5 -0
  94. mail/factories/__init__.py +27 -0
  95. mail/factories/action.py +223 -0
  96. mail/factories/base.py +1531 -0
  97. mail/factories/supervisor.py +241 -0
  98. mail/net/__init__.py +7 -0
  99. mail/net/registry.py +712 -0
  100. mail/net/router.py +728 -0
  101. mail/net/server_utils.py +114 -0
  102. mail/net/types.py +247 -0
  103. mail/server.py +1605 -0
  104. mail/stdlib/__init__.py +0 -0
  105. mail/stdlib/anthropic/__init__.py +0 -0
  106. mail/stdlib/fs/__init__.py +15 -0
  107. mail/stdlib/fs/actions.py +209 -0
  108. mail/stdlib/http/__init__.py +19 -0
  109. mail/stdlib/http/actions.py +333 -0
  110. mail/stdlib/interswarm/__init__.py +11 -0
  111. mail/stdlib/interswarm/actions.py +208 -0
  112. mail/stdlib/mcp/__init__.py +19 -0
  113. mail/stdlib/mcp/actions.py +294 -0
  114. mail/stdlib/openai/__init__.py +13 -0
  115. mail/stdlib/openai/agents.py +451 -0
  116. mail/summarizer.py +234 -0
  117. mail/swarms_json/__init__.py +27 -0
  118. mail/swarms_json/types.py +87 -0
  119. mail/swarms_json/utils.py +255 -0
  120. mail/url_scheme.py +51 -0
  121. mail/utils/__init__.py +53 -0
  122. mail/utils/auth.py +194 -0
  123. mail/utils/context.py +17 -0
  124. mail/utils/logger.py +73 -0
  125. mail/utils/openai.py +212 -0
  126. mail/utils/parsing.py +89 -0
  127. mail/utils/serialize.py +292 -0
  128. mail/utils/store.py +49 -0
  129. mail/utils/string_builder.py +119 -0
  130. mail/utils/version.py +20 -0
  131. mail_swarms-1.3.2.dist-info/METADATA +237 -0
  132. mail_swarms-1.3.2.dist-info/RECORD +137 -0
  133. mail_swarms-1.3.2.dist-info/WHEEL +4 -0
  134. mail_swarms-1.3.2.dist-info/entry_points.txt +2 -0
  135. mail_swarms-1.3.2.dist-info/licenses/LICENSE +202 -0
  136. mail_swarms-1.3.2.dist-info/licenses/NOTICE +10 -0
  137. mail_swarms-1.3.2.dist-info/licenses/THIRD_PARTY_NOTICES.md +12334 -0
@@ -0,0 +1,114 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Copyright (c) 2025 Addison Kline
3
+
4
+ import asyncio
5
+ import logging
6
+
7
+ from mail.api import MAILSwarm, MAILSwarmTemplate
8
+ from mail.config import ServerConfig
9
+ from mail.net.registry import SwarmRegistry
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+
14
+ def compute_external_base_url(cfg: ServerConfig) -> str:
15
+ """
16
+ Derive an externally-reachable base URL from the server config.
17
+ """
18
+
19
+ host = cfg.host
20
+ port = cfg.port
21
+
22
+ if host in {"0.0.0.0", "::"}:
23
+ # 0.0.0.0/:: listen on all interfaces; default to localhost for callbacks
24
+ host_for_url = "localhost"
25
+ else:
26
+ host_for_url = host
27
+
28
+ return f"http://{host_for_url}:{port}"
29
+
30
+
31
+ def get_default_persistent_swarm(
32
+ cfg: ServerConfig,
33
+ ) -> MAILSwarmTemplate:
34
+ """
35
+ Get the default persistent swarm template from the server config.
36
+ """
37
+ swarm_name = cfg.swarm.name
38
+ swarm_json_file = cfg.swarm.source
39
+
40
+ return MAILSwarmTemplate.from_swarm_json_file(
41
+ swarm_name=swarm_name,
42
+ json_filepath=swarm_json_file,
43
+ )
44
+
45
+
46
+ def init_mail_instances_dict() -> dict[str, MAILSwarm]:
47
+ """
48
+ Initialize the mail instances dictionary for a given role.
49
+ Should always be empty on startup.
50
+ """
51
+ return {}
52
+
53
+
54
+ def init_mail_tasks_dict() -> dict[str, asyncio.Task]:
55
+ """
56
+ Initialize the mail tasks dictionary for a given role.
57
+ Should always be empty on startup.
58
+ """
59
+ return {}
60
+
61
+
62
+ def get_default_swarm_registry(
63
+ cfg: ServerConfig, swarm: MAILSwarmTemplate
64
+ ) -> SwarmRegistry:
65
+ """
66
+ Get the default swarm registry from the server config.
67
+ """
68
+ swarm_name = swarm.name
69
+ swarm_registry_file = cfg.swarm.registry_file
70
+ local_base_url = get_default_base_url(cfg)
71
+
72
+ return SwarmRegistry(
73
+ local_swarm_name=swarm_name,
74
+ local_base_url=local_base_url,
75
+ persistence_file=swarm_registry_file,
76
+ local_swarm_description=swarm.description,
77
+ local_swarm_keywords=swarm.keywords,
78
+ local_swarm_public=swarm.public,
79
+ )
80
+
81
+
82
+ def get_default_swarm_name(
83
+ cfg: ServerConfig,
84
+ ) -> str:
85
+ """
86
+ Get the default swarm name from the server config.
87
+ """
88
+ return cfg.swarm.name
89
+
90
+
91
+ def get_default_base_url(
92
+ cfg: ServerConfig,
93
+ ) -> str:
94
+ """
95
+ Get the default base URL from the server config.
96
+ """
97
+ return compute_external_base_url(cfg)
98
+
99
+
100
+ def get_default_entrypoint_agent(
101
+ swarm_template: MAILSwarmTemplate,
102
+ ) -> str:
103
+ """
104
+ Get the default entrypoint agent from the swarm template.
105
+ """
106
+ return swarm_template.entrypoint
107
+
108
+
109
+ def init_task_bindings_dict() -> dict[str, dict[str, str]]:
110
+ """
111
+ Initialize the task bindings dictionary.
112
+ Should always be empty on startup.
113
+ """
114
+ return {}
mail/net/types.py ADDED
@@ -0,0 +1,247 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Copyright (c) 2025 Addison Kline
3
+
4
+ import datetime
5
+ from typing import Any, TypedDict
6
+
7
+ from sse_starlette import ServerSentEvent
8
+
9
+ from mail.core.message import MAILMessage
10
+
11
+
12
+ class SwarmEndpoint(TypedDict):
13
+ """
14
+ Represents a swarm endpoint for interswarm communication.
15
+ """
16
+
17
+ swarm_name: str
18
+ """The name of the swarm."""
19
+ base_url: str
20
+ """The base URL of the swarm (e.g., https://swarm1.example.com)."""
21
+ version: str
22
+ """The version of the swarm."""
23
+ health_check_url: str
24
+ """The health check endpoint URL."""
25
+ auth_token_ref: str | None
26
+ """Authentication token reference (environment variable or actual token)."""
27
+ last_seen: datetime.datetime | None
28
+ """When this swarm was last seen/heard from."""
29
+ is_active: bool
30
+ """Whether this swarm is currently active."""
31
+ latency: float | None
32
+ """The latency of the swarm in seconds."""
33
+ swarm_description: str
34
+ """The description of the swarm."""
35
+ keywords: list[str]
36
+ """The keywords of the swarm."""
37
+ metadata: dict[str, Any] | None
38
+ """Additional metadata about the swarm."""
39
+ public: bool
40
+ """Whether this swarm is publicly accessible."""
41
+ volatile: bool
42
+ """Whether this swarm is volatile (will be removed from the registry when the server shuts down)."""
43
+
44
+
45
+ class SwarmEndpointCleaned(TypedDict):
46
+ """
47
+ Represents a swarm endpoint for interswarm communication.
48
+ """
49
+
50
+ swarm_name: str
51
+ """The name of the swarm."""
52
+ base_url: str
53
+ """The base URL of the swarm (e.g., https://swarm1.example.com)."""
54
+ version: str
55
+ """The protocol version of the swarm."""
56
+ last_seen: datetime.datetime | None
57
+ """When this swarm was last seen/heard from."""
58
+ is_active: bool
59
+ """Whether this swarm is currently active."""
60
+ latency: float | None
61
+ """The latency of the swarm in seconds."""
62
+ swarm_description: str
63
+ """The description of the swarm."""
64
+ keywords: list[str]
65
+ """The keywords of the swarm."""
66
+ metadata: dict[str, Any] | None
67
+ """Additional metadata about the swarm."""
68
+
69
+
70
+ class SwarmInfo(TypedDict):
71
+ """
72
+ Information about the current swarm.
73
+ """
74
+
75
+ name: str
76
+ """The name of the swarm."""
77
+ version: str
78
+ """The protocol version of the swarm."""
79
+ description: str
80
+ """The description of the swarm."""
81
+ entrypoint: str
82
+ """The default entrypoint of the swarm."""
83
+ keywords: list[str]
84
+ """The keywords of the swarm."""
85
+ public: bool
86
+ """Whether this swarm is publicly accessible."""
87
+
88
+
89
+ class SwarmStatus(TypedDict):
90
+ """
91
+ The status of a swarm.
92
+ """
93
+
94
+ name: str | None
95
+ """The name of the swarm."""
96
+ status: str
97
+ """The status of the swarm."""
98
+
99
+
100
+ class GetRootResponse(TypedDict):
101
+ """
102
+ Response for the MAIL server endpoint `GET /`.
103
+ """
104
+
105
+ name: str
106
+ """The name of the service; should always be `mail`."""
107
+ protocol_version: str
108
+ """The version of the MAIL protocol that is being used."""
109
+ swarm: SwarmInfo
110
+ """Information about the swarm that is running."""
111
+ status: str
112
+ """The status of the service; should always be `running`."""
113
+ uptime: float
114
+ """The uptime of the service in seconds."""
115
+
116
+
117
+ class GetWhoamiResponse(TypedDict):
118
+ """
119
+ Response for the MAIL server endpoint `GET /whoami`.
120
+ """
121
+
122
+ id: str
123
+ """The ID of the caller."""
124
+ role: str
125
+ """The role of the caller."""
126
+
127
+
128
+ class GetStatusResponse(TypedDict):
129
+ """
130
+ Response for the MAIL server endpoint `GET /status`.
131
+ """
132
+
133
+ swarm: SwarmStatus
134
+ """The swarm that is running."""
135
+ active_users: int
136
+ """The number of active users."""
137
+ user_mail_ready: bool
138
+ """Whether the user MAIL instance is ready."""
139
+ user_task_running: bool
140
+ """Whether the user MAIL instance task is running."""
141
+
142
+
143
+ class PostMessageResponse(TypedDict):
144
+ """
145
+ Response for the MAIL server endpoint `POST /message`.
146
+ """
147
+
148
+ response: str
149
+ """The response from the MAIL instance."""
150
+ events: list[ServerSentEvent] | None
151
+ """The events from the MAIL instance."""
152
+
153
+
154
+ class GetHealthResponse(TypedDict):
155
+ """
156
+ Response for the MAIL server endpoint `GET /health`.
157
+ """
158
+
159
+ status: str
160
+ """The status of the MAIL instance."""
161
+ swarm_name: str
162
+ """The name of the swarm."""
163
+ timestamp: str
164
+ """The timestamp of the response."""
165
+
166
+
167
+ class GetSwarmsResponse(TypedDict):
168
+ """
169
+ Response for the MAIL server endpoint `GET /swarms`.
170
+ """
171
+
172
+ swarms: list[SwarmEndpointCleaned]
173
+ """The swarms that are running."""
174
+
175
+
176
+ class PostSwarmsResponse(TypedDict):
177
+ """
178
+ Response for the MAIL server endpoint `POST /swarms`.
179
+ """
180
+
181
+ status: str
182
+ """The status of the response."""
183
+ swarm_name: str
184
+ """The name of the swarm."""
185
+
186
+
187
+ class GetSwarmsDumpResponse(TypedDict):
188
+ """
189
+ Response for the MAIL server endpoint `GET /swarms/dump`.
190
+ """
191
+
192
+ status: str
193
+ """The status of the response."""
194
+ swarm_name: str
195
+ """The name of the swarm."""
196
+
197
+
198
+ class PostInterswarmMessageResponse(TypedDict):
199
+ """
200
+ Response for the MAIL server endpoint `POST /interswarm/message`.
201
+ """
202
+
203
+ response: MAILMessage
204
+ """The response from the MAIL instance."""
205
+ events: list[ServerSentEvent] | None
206
+ """The events from the MAIL instance."""
207
+
208
+
209
+ class PostInterswarmForwardResponse(TypedDict):
210
+ """
211
+ Response for the MAIL server endpoint `POST /interswarm/forward`.
212
+ """
213
+
214
+ swarm: str
215
+ """The name of the swarm."""
216
+ task_id: str
217
+ """The task ID of the interswarm message."""
218
+ status: str
219
+ """The status of the response."""
220
+ local_runner: str
221
+ """The local runner of the swarm (role:id@swarm)."""
222
+
223
+
224
+ class PostInterswarmBackResponse(TypedDict):
225
+ """
226
+ Response for the MAIL server endpoint `POST /interswarm/back`.
227
+ """
228
+
229
+ swarm: str
230
+ """The name of the swarm."""
231
+ task_id: str
232
+ """The task ID of the interswarm message."""
233
+ status: str
234
+ """The status of the response."""
235
+ local_runner: str
236
+ """The local runner of the swarm (role:id@swarm)."""
237
+
238
+
239
+ class PostSwarmsLoadResponse(TypedDict):
240
+ """
241
+ Response for the MAIL server endpoint `POST /swarms/load`.
242
+ """
243
+
244
+ status: str
245
+ """The status of the response."""
246
+ swarm_name: str
247
+ """The name of the swarm."""