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
mail/db/__init__.py ADDED
File without changes
mail/db/init.py ADDED
@@ -0,0 +1,182 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Copyright (c) 2025 Addison Kline
3
+
4
+ """
5
+ Database initialization for MAIL persistence (agent histories, tasks, events, responses).
6
+ """
7
+
8
+ import os
9
+ import sys
10
+
11
+ import asyncpg
12
+ import dotenv
13
+
14
+
15
+ async def create_tables() -> None:
16
+ """
17
+ Create all MAIL persistence tables and indexes in the database.
18
+ """
19
+ dotenv.load_dotenv()
20
+ database_url = os.getenv("DATABASE_URL")
21
+
22
+ if not database_url:
23
+ print("ERROR: DATABASE_URL environment variable is not set")
24
+ print("Please set DATABASE_URL in your .env file or environment")
25
+ print("Example: DATABASE_URL=postgresql://user:password@localhost:5432/mail")
26
+ sys.exit(1)
27
+
28
+ print("Connecting to database...")
29
+
30
+ try:
31
+ conn = await asyncpg.connect(database_url)
32
+ except Exception as e:
33
+ print(f"ERROR: Failed to connect to database: {e}")
34
+ sys.exit(1)
35
+
36
+ print("Connected successfully")
37
+
38
+ # ==========================================================================
39
+ # Table: agent_histories
40
+ # ==========================================================================
41
+ create_agent_histories_sql = """
42
+ CREATE TABLE IF NOT EXISTS agent_histories (
43
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
44
+ swarm_name TEXT NOT NULL,
45
+ caller_role TEXT NOT NULL,
46
+ caller_id TEXT NOT NULL,
47
+ tool_format TEXT NOT NULL,
48
+ task_id TEXT NOT NULL,
49
+ agent_name TEXT NOT NULL,
50
+ history JSONB NOT NULL,
51
+ created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
52
+ updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
53
+ );
54
+ """
55
+
56
+ agent_histories_indexes = [
57
+ "CREATE INDEX IF NOT EXISTS idx_agent_histories_swarm_name ON agent_histories (swarm_name);",
58
+ "CREATE INDEX IF NOT EXISTS idx_agent_histories_task_id ON agent_histories (task_id);",
59
+ "CREATE INDEX IF NOT EXISTS idx_agent_histories_caller ON agent_histories (caller_role, caller_id);",
60
+ "CREATE INDEX IF NOT EXISTS idx_agent_histories_agent_name ON agent_histories (agent_name);",
61
+ "CREATE INDEX IF NOT EXISTS idx_agent_histories_created_at ON agent_histories (created_at DESC);",
62
+ ]
63
+
64
+ # ==========================================================================
65
+ # Table: tasks
66
+ # ==========================================================================
67
+ create_tasks_sql = """
68
+ CREATE TABLE IF NOT EXISTS tasks (
69
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
70
+ task_id TEXT NOT NULL,
71
+ swarm_name TEXT NOT NULL,
72
+ caller_role TEXT NOT NULL,
73
+ caller_id TEXT NOT NULL,
74
+ task_owner TEXT NOT NULL,
75
+ task_contributors JSONB NOT NULL DEFAULT '[]',
76
+ remote_swarms JSONB NOT NULL DEFAULT '[]',
77
+ is_running BOOLEAN NOT NULL DEFAULT FALSE,
78
+ completed BOOLEAN NOT NULL DEFAULT FALSE,
79
+ title TEXT,
80
+ start_time TIMESTAMP WITH TIME ZONE NOT NULL,
81
+ created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
82
+ updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
83
+ UNIQUE(task_id, swarm_name, caller_role, caller_id)
84
+ );
85
+ """
86
+
87
+ tasks_indexes = [
88
+ "CREATE INDEX IF NOT EXISTS idx_tasks_lookup ON tasks (swarm_name, caller_role, caller_id);",
89
+ "CREATE INDEX IF NOT EXISTS idx_tasks_task_id ON tasks (task_id);",
90
+ ]
91
+
92
+ # ==========================================================================
93
+ # Table: task_events
94
+ # ==========================================================================
95
+ create_task_events_sql = """
96
+ CREATE TABLE IF NOT EXISTS task_events (
97
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
98
+ task_id TEXT NOT NULL,
99
+ swarm_name TEXT NOT NULL,
100
+ caller_role TEXT NOT NULL,
101
+ caller_id TEXT NOT NULL,
102
+ event_type TEXT,
103
+ event_data TEXT,
104
+ event_id TEXT,
105
+ created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
106
+ );
107
+ """
108
+
109
+ task_events_indexes = [
110
+ "CREATE INDEX IF NOT EXISTS idx_task_events_lookup ON task_events (task_id, swarm_name, caller_role, caller_id);",
111
+ "CREATE INDEX IF NOT EXISTS idx_task_events_created ON task_events (created_at);",
112
+ ]
113
+
114
+ # ==========================================================================
115
+ # Table: task_responses
116
+ # ==========================================================================
117
+ create_task_responses_sql = """
118
+ CREATE TABLE IF NOT EXISTS task_responses (
119
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
120
+ task_id TEXT NOT NULL,
121
+ swarm_name TEXT NOT NULL,
122
+ caller_role TEXT NOT NULL,
123
+ caller_id TEXT NOT NULL,
124
+ response JSONB NOT NULL,
125
+ created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
126
+ UNIQUE(task_id, swarm_name, caller_role, caller_id)
127
+ );
128
+ """
129
+
130
+ task_responses_indexes = [
131
+ "CREATE INDEX IF NOT EXISTS idx_task_responses_lookup ON task_responses (task_id, swarm_name, caller_role, caller_id);",
132
+ ]
133
+
134
+ try:
135
+ # Create agent_histories table
136
+ print("Creating agent_histories table...")
137
+ await conn.execute(create_agent_histories_sql)
138
+ for idx_sql in agent_histories_indexes:
139
+ await conn.execute(idx_sql)
140
+ print(" agent_histories table created")
141
+
142
+ # Create tasks table
143
+ print("Creating tasks table...")
144
+ await conn.execute(create_tasks_sql)
145
+ for idx_sql in tasks_indexes:
146
+ await conn.execute(idx_sql)
147
+ print(" tasks table created")
148
+
149
+ # Create task_events table
150
+ print("Creating task_events table...")
151
+ await conn.execute(create_task_events_sql)
152
+ for idx_sql in task_events_indexes:
153
+ await conn.execute(idx_sql)
154
+ print(" task_events table created")
155
+
156
+ # Create task_responses table
157
+ print("Creating task_responses table...")
158
+ await conn.execute(create_task_responses_sql)
159
+ for idx_sql in task_responses_indexes:
160
+ await conn.execute(idx_sql)
161
+ print(" task_responses table created")
162
+
163
+ # Verify tables exist
164
+ print("\nVerifying tables...")
165
+ tables = ["agent_histories", "tasks", "task_events", "task_responses"]
166
+ for table_name in tables:
167
+ result = await conn.fetchrow(
168
+ "SELECT EXISTS (SELECT FROM information_schema.tables WHERE table_name = $1);",
169
+ table_name,
170
+ )
171
+ if result and result[0]:
172
+ print(f" {table_name}: OK")
173
+ else:
174
+ print(f" {table_name}: MISSING")
175
+
176
+ except Exception as e:
177
+ print(f"ERROR: Failed to create tables: {e}")
178
+ sys.exit(1)
179
+ finally:
180
+ await conn.close()
181
+
182
+ print("\nDatabase initialization complete!")
mail/db/types.py ADDED
@@ -0,0 +1,65 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Copyright (c) 2025 Addison Kline
3
+
4
+ from typing import Any, Literal, TypedDict
5
+
6
+
7
+ class AgentHistoriesDB(TypedDict):
8
+ """
9
+ A database record for storing agent histories.
10
+ """
11
+
12
+ id: str
13
+ swarm_name: str
14
+ caller_role: Literal["admin", "agent", "user"]
15
+ caller_id: str
16
+ tool_format: Literal["completions", "responses"]
17
+ task_id: str
18
+ agent_name: str
19
+ history: list[dict[str, Any]]
20
+
21
+
22
+ class TaskDB(TypedDict):
23
+ """
24
+ A database record for storing MAILTask metadata.
25
+ """
26
+
27
+ id: str
28
+ task_id: str
29
+ swarm_name: str
30
+ caller_role: Literal["admin", "agent", "user"]
31
+ caller_id: str
32
+ task_owner: str
33
+ task_contributors: list[str]
34
+ remote_swarms: list[str]
35
+ is_running: bool
36
+ completed: bool
37
+ start_time: str # ISO format timestamp
38
+
39
+
40
+ class TaskEventDB(TypedDict):
41
+ """
42
+ A database record for storing task SSE events.
43
+ """
44
+
45
+ id: str
46
+ task_id: str
47
+ swarm_name: str
48
+ caller_role: Literal["admin", "agent", "user"]
49
+ caller_id: str
50
+ event_type: str | None
51
+ event_data: str | None
52
+ event_id: str | None
53
+
54
+
55
+ class TaskResponseDB(TypedDict):
56
+ """
57
+ A database record for storing task response messages.
58
+ """
59
+
60
+ id: str
61
+ task_id: str
62
+ swarm_name: str
63
+ caller_role: Literal["admin", "agent", "user"]
64
+ caller_id: str
65
+ response: dict[str, Any]