swarms 7.6.1__py3-none-any.whl → 7.6.4__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 (42) hide show
  1. swarms/__init__.py +1 -0
  2. swarms/agents/__init__.py +4 -5
  3. swarms/agents/flexion_agent.py +2 -1
  4. swarms/agents/reasoning_agents.py +10 -0
  5. swarms/client/__init__.py +15 -0
  6. swarms/prompts/multi_agent_collab_prompt.py +313 -0
  7. swarms/structs/__init__.py +10 -17
  8. swarms/structs/agent.py +178 -262
  9. swarms/structs/base_swarm.py +0 -7
  10. swarms/structs/concurrent_workflow.py +2 -2
  11. swarms/structs/conversation.py +16 -2
  12. swarms/structs/de_hallucination_swarm.py +8 -4
  13. swarms/structs/dynamic_conversational_swarm.py +226 -0
  14. swarms/structs/groupchat.py +80 -84
  15. swarms/structs/hiearchical_swarm.py +1 -1
  16. swarms/structs/hybrid_hiearchical_peer_swarm.py +256 -0
  17. swarms/structs/majority_voting.py +1 -1
  18. swarms/structs/mixture_of_agents.py +1 -1
  19. swarms/structs/multi_agent_exec.py +63 -139
  20. swarms/structs/multi_agent_orchestrator.py +1 -1
  21. swarms/structs/output_types.py +3 -0
  22. swarms/structs/rearrange.py +66 -205
  23. swarms/structs/sequential_workflow.py +34 -47
  24. swarms/structs/swarm_router.py +3 -2
  25. swarms/telemetry/bootup.py +19 -38
  26. swarms/telemetry/main.py +62 -22
  27. swarms/tools/tool_schema_base_model.py +57 -0
  28. swarms/utils/auto_download_check_packages.py +2 -2
  29. swarms/utils/disable_logging.py +0 -17
  30. swarms/utils/history_output_formatter.py +8 -3
  31. swarms/utils/litellm_wrapper.py +117 -1
  32. {swarms-7.6.1.dist-info → swarms-7.6.4.dist-info}/METADATA +1 -5
  33. {swarms-7.6.1.dist-info → swarms-7.6.4.dist-info}/RECORD +37 -37
  34. swarms/structs/agent_security.py +0 -318
  35. swarms/structs/airflow_swarm.py +0 -430
  36. swarms/structs/output_type.py +0 -18
  37. swarms/utils/agent_ops_check.py +0 -26
  38. swarms/utils/pandas_utils.py +0 -92
  39. /swarms/{structs/swarms_api.py → client/main.py} +0 -0
  40. {swarms-7.6.1.dist-info → swarms-7.6.4.dist-info}/LICENSE +0 -0
  41. {swarms-7.6.1.dist-info → swarms-7.6.4.dist-info}/WHEEL +0 -0
  42. {swarms-7.6.1.dist-info → swarms-7.6.4.dist-info}/entry_points.txt +0 -0
@@ -1,318 +0,0 @@
1
- import base64
2
- import json
3
- import uuid
4
- from datetime import datetime
5
- from dataclasses import dataclass
6
- from typing import Optional, Union, Dict, List
7
-
8
- from cryptography.fernet import Fernet
9
- from cryptography.hazmat.primitives import hashes, serialization
10
- from cryptography.hazmat.primitives.asymmetric import padding, rsa
11
- from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
12
-
13
-
14
- @dataclass
15
- class EncryptedMessage:
16
- """Structure for encrypted messages between agents"""
17
-
18
- sender_id: str
19
- receiver_id: str
20
- encrypted_content: bytes
21
- timestamp: float
22
- message_id: str
23
- session_id: str
24
-
25
-
26
- class EncryptionSession:
27
- """Represents an encrypted communication session between agents"""
28
-
29
- def __init__(
30
- self,
31
- session_id: str,
32
- agent_ids: List[str],
33
- encrypted_keys: Dict[str, bytes],
34
- created_at: datetime,
35
- ):
36
- self.session_id = session_id
37
- self.agent_ids = agent_ids
38
- self.encrypted_keys = encrypted_keys
39
- self.created_at = created_at
40
-
41
-
42
- class AgentEncryption:
43
- """
44
- Handles encryption for agent data both at rest and in transit.
45
- Supports both symmetric (for data at rest) and asymmetric (for data in transit) encryption.
46
- Also supports secure multi-agent communication.
47
- """
48
-
49
- def __init__(
50
- self,
51
- agent_id: Optional[str] = None,
52
- encryption_key: Optional[str] = None,
53
- enable_transit_encryption: bool = False,
54
- enable_rest_encryption: bool = False,
55
- enable_multi_agent: bool = False,
56
- ):
57
- self.agent_id = agent_id or str(uuid.uuid4())
58
- self.enable_transit_encryption = enable_transit_encryption
59
- self.enable_rest_encryption = enable_rest_encryption
60
- self.enable_multi_agent = enable_multi_agent
61
-
62
- # Multi-agent communication storage
63
- self.sessions: Dict[str, EncryptionSession] = {}
64
- self.known_agents: Dict[str, "AgentEncryption"] = {}
65
-
66
- if enable_rest_encryption:
67
- # Initialize encryption for data at rest
68
- if encryption_key:
69
- self.encryption_key = base64.urlsafe_b64encode(
70
- PBKDF2HMAC(
71
- algorithm=hashes.SHA256(),
72
- length=32,
73
- salt=f"agent_{self.agent_id}".encode(), # Unique salt per agent
74
- iterations=100000,
75
- ).derive(encryption_key.encode())
76
- )
77
- else:
78
- self.encryption_key = Fernet.generate_key()
79
-
80
- self.cipher_suite = Fernet(self.encryption_key)
81
-
82
- if enable_transit_encryption or enable_multi_agent:
83
- # Generate RSA key pair for transit encryption
84
- self.private_key = rsa.generate_private_key(
85
- public_exponent=65537, key_size=2048
86
- )
87
- self.public_key = self.private_key.public_key()
88
-
89
- def register_agent(
90
- self, agent_id: str, agent_encryption: "AgentEncryption"
91
- ) -> None:
92
- """Register another agent for secure communication"""
93
- if not self.enable_multi_agent:
94
- raise ValueError("Multi-agent support is not enabled")
95
- self.known_agents[agent_id] = agent_encryption
96
-
97
- def create_session(self, agent_ids: List[str]) -> str:
98
- """Create a new encrypted session between multiple agents"""
99
- if not self.enable_multi_agent:
100
- raise ValueError("Multi-agent support is not enabled")
101
-
102
- session_id = str(uuid.uuid4())
103
-
104
- # Generate a shared session key
105
- session_key = Fernet.generate_key()
106
-
107
- # Create encrypted copies of the session key for each agent
108
- encrypted_keys = {}
109
- for agent_id in agent_ids:
110
- if (
111
- agent_id not in self.known_agents
112
- and agent_id != self.agent_id
113
- ):
114
- raise ValueError(f"Agent {agent_id} not registered")
115
-
116
- if agent_id == self.agent_id:
117
- agent_public_key = self.public_key
118
- else:
119
- agent_public_key = self.known_agents[
120
- agent_id
121
- ].public_key
122
-
123
- encrypted_key = agent_public_key.encrypt(
124
- session_key,
125
- padding.OAEP(
126
- mgf=padding.MGF1(algorithm=hashes.SHA256()),
127
- algorithm=hashes.SHA256(),
128
- label=None,
129
- ),
130
- )
131
- encrypted_keys[agent_id] = encrypted_key
132
-
133
- # Store session information
134
- self.sessions[session_id] = EncryptionSession(
135
- session_id=session_id,
136
- agent_ids=agent_ids,
137
- encrypted_keys=encrypted_keys,
138
- created_at=datetime.now(),
139
- )
140
-
141
- return session_id
142
-
143
- def encrypt_message(
144
- self,
145
- content: Union[str, dict],
146
- receiver_id: str,
147
- session_id: str,
148
- ) -> EncryptedMessage:
149
- """Encrypt a message for another agent within a session"""
150
- if not self.enable_multi_agent:
151
- raise ValueError("Multi-agent support is not enabled")
152
-
153
- if session_id not in self.sessions:
154
- raise ValueError("Invalid session ID")
155
-
156
- session = self.sessions[session_id]
157
- if (
158
- self.agent_id not in session.agent_ids
159
- or receiver_id not in session.agent_ids
160
- ):
161
- raise ValueError("Sender or receiver not in session")
162
-
163
- # Serialize content if it's a dictionary
164
- if isinstance(content, dict):
165
- content = json.dumps(content)
166
-
167
- # Get the session key
168
- encrypted_session_key = session.encrypted_keys[self.agent_id]
169
- session_key = self.decrypt_session_key(encrypted_session_key)
170
-
171
- # Create Fernet cipher with session key
172
- cipher = Fernet(session_key)
173
-
174
- # Encrypt the message
175
- encrypted_content = cipher.encrypt(content.encode())
176
-
177
- return EncryptedMessage(
178
- sender_id=self.agent_id,
179
- receiver_id=receiver_id,
180
- encrypted_content=encrypted_content,
181
- timestamp=datetime.now().timestamp(),
182
- message_id=str(uuid.uuid4()),
183
- session_id=session_id,
184
- )
185
-
186
- def decrypt_message(
187
- self, message: EncryptedMessage
188
- ) -> Union[str, dict]:
189
- """Decrypt a message from another agent"""
190
- if not self.enable_multi_agent:
191
- raise ValueError("Multi-agent support is not enabled")
192
-
193
- if message.session_id not in self.sessions:
194
- raise ValueError("Invalid session ID")
195
-
196
- if self.agent_id != message.receiver_id:
197
- raise ValueError("Message not intended for this agent")
198
-
199
- session = self.sessions[message.session_id]
200
-
201
- # Get the session key
202
- encrypted_session_key = session.encrypted_keys[self.agent_id]
203
- session_key = self.decrypt_session_key(encrypted_session_key)
204
-
205
- # Create Fernet cipher with session key
206
- cipher = Fernet(session_key)
207
-
208
- # Decrypt the message
209
- decrypted_content = cipher.decrypt(
210
- message.encrypted_content
211
- ).decode()
212
-
213
- # Try to parse as JSON
214
- try:
215
- return json.loads(decrypted_content)
216
- except json.JSONDecodeError:
217
- return decrypted_content
218
-
219
- def decrypt_session_key(self, encrypted_key: bytes) -> bytes:
220
- """Decrypt a session key using the agent's private key"""
221
- return self.private_key.decrypt(
222
- encrypted_key,
223
- padding.OAEP(
224
- mgf=padding.MGF1(algorithm=hashes.SHA256()),
225
- algorithm=hashes.SHA256(),
226
- label=None,
227
- ),
228
- )
229
-
230
- # Original methods preserved below
231
- def encrypt_at_rest(self, data: Union[str, dict, bytes]) -> bytes:
232
- """Encrypts data for storage"""
233
- if not self.enable_rest_encryption:
234
- return (
235
- data
236
- if isinstance(data, bytes)
237
- else str(data).encode()
238
- )
239
-
240
- if isinstance(data, dict):
241
- data = json.dumps(data)
242
- if isinstance(data, str):
243
- data = data.encode()
244
-
245
- return self.cipher_suite.encrypt(data)
246
-
247
- def decrypt_at_rest(
248
- self, encrypted_data: bytes
249
- ) -> Union[str, dict]:
250
- """Decrypts stored data"""
251
- if not self.enable_rest_encryption:
252
- return encrypted_data.decode()
253
-
254
- decrypted_data = self.cipher_suite.decrypt(encrypted_data)
255
-
256
- try:
257
- return json.loads(decrypted_data)
258
- except json.JSONDecodeError:
259
- return decrypted_data.decode()
260
-
261
- def encrypt_for_transit(self, data: Union[str, dict]) -> bytes:
262
- """Encrypts data for transmission"""
263
- if not self.enable_transit_encryption:
264
- return str(data).encode()
265
-
266
- if isinstance(data, dict):
267
- data = json.dumps(data)
268
-
269
- return self.public_key.encrypt(
270
- data.encode(),
271
- padding.OAEP(
272
- mgf=padding.MGF1(algorithm=hashes.SHA256()),
273
- algorithm=hashes.SHA256(),
274
- label=None,
275
- ),
276
- )
277
-
278
- def decrypt_from_transit(
279
- self, data: Union[bytes, str]
280
- ) -> Union[str, dict]:
281
- """Decrypts received data, handling both encrypted and unencrypted inputs"""
282
- if not self.enable_transit_encryption:
283
- return data.decode() if isinstance(data, bytes) else data
284
-
285
- try:
286
- if isinstance(data, bytes) and len(data) == 256:
287
- decrypted_data = self.private_key.decrypt(
288
- data,
289
- padding.OAEP(
290
- mgf=padding.MGF1(algorithm=hashes.SHA256()),
291
- algorithm=hashes.SHA256(),
292
- label=None,
293
- ),
294
- ).decode()
295
- else:
296
- return (
297
- data.decode() if isinstance(data, bytes) else data
298
- )
299
-
300
- try:
301
- return json.loads(decrypted_data)
302
- except json.JSONDecodeError:
303
- return decrypted_data
304
- except ValueError:
305
- return data.decode() if isinstance(data, bytes) else data
306
-
307
- def get_public_key_pem(self) -> bytes:
308
- """Returns the public key in PEM format for sharing"""
309
- if (
310
- not self.enable_transit_encryption
311
- and not self.enable_multi_agent
312
- ):
313
- return b""
314
-
315
- return self.public_key.public_bytes(
316
- encoding=serialization.Encoding.PEM,
317
- format=serialization.PublicFormat.SubjectPublicKeyInfo,
318
- )