powermem 0.1.0__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 (123) hide show
  1. powermem/__init__.py +103 -0
  2. powermem/agent/__init__.py +35 -0
  3. powermem/agent/abstract/__init__.py +22 -0
  4. powermem/agent/abstract/collaboration.py +259 -0
  5. powermem/agent/abstract/context.py +187 -0
  6. powermem/agent/abstract/manager.py +232 -0
  7. powermem/agent/abstract/permission.py +217 -0
  8. powermem/agent/abstract/privacy.py +267 -0
  9. powermem/agent/abstract/scope.py +199 -0
  10. powermem/agent/agent.py +791 -0
  11. powermem/agent/components/__init__.py +18 -0
  12. powermem/agent/components/collaboration_coordinator.py +645 -0
  13. powermem/agent/components/permission_controller.py +586 -0
  14. powermem/agent/components/privacy_protector.py +767 -0
  15. powermem/agent/components/scope_controller.py +685 -0
  16. powermem/agent/factories/__init__.py +16 -0
  17. powermem/agent/factories/agent_factory.py +266 -0
  18. powermem/agent/factories/config_factory.py +308 -0
  19. powermem/agent/factories/memory_factory.py +229 -0
  20. powermem/agent/implementations/__init__.py +16 -0
  21. powermem/agent/implementations/hybrid.py +728 -0
  22. powermem/agent/implementations/multi_agent.py +1040 -0
  23. powermem/agent/implementations/multi_user.py +1020 -0
  24. powermem/agent/types.py +53 -0
  25. powermem/agent/wrappers/__init__.py +14 -0
  26. powermem/agent/wrappers/agent_memory_wrapper.py +427 -0
  27. powermem/agent/wrappers/compatibility_wrapper.py +520 -0
  28. powermem/config_loader.py +318 -0
  29. powermem/configs.py +249 -0
  30. powermem/core/__init__.py +19 -0
  31. powermem/core/async_memory.py +1493 -0
  32. powermem/core/audit.py +258 -0
  33. powermem/core/base.py +165 -0
  34. powermem/core/memory.py +1567 -0
  35. powermem/core/setup.py +162 -0
  36. powermem/core/telemetry.py +215 -0
  37. powermem/integrations/__init__.py +17 -0
  38. powermem/integrations/embeddings/__init__.py +13 -0
  39. powermem/integrations/embeddings/aws_bedrock.py +100 -0
  40. powermem/integrations/embeddings/azure_openai.py +55 -0
  41. powermem/integrations/embeddings/base.py +31 -0
  42. powermem/integrations/embeddings/config/base.py +132 -0
  43. powermem/integrations/embeddings/configs.py +31 -0
  44. powermem/integrations/embeddings/factory.py +48 -0
  45. powermem/integrations/embeddings/gemini.py +39 -0
  46. powermem/integrations/embeddings/huggingface.py +41 -0
  47. powermem/integrations/embeddings/langchain.py +35 -0
  48. powermem/integrations/embeddings/lmstudio.py +29 -0
  49. powermem/integrations/embeddings/mock.py +11 -0
  50. powermem/integrations/embeddings/ollama.py +53 -0
  51. powermem/integrations/embeddings/openai.py +49 -0
  52. powermem/integrations/embeddings/qwen.py +102 -0
  53. powermem/integrations/embeddings/together.py +31 -0
  54. powermem/integrations/embeddings/vertexai.py +54 -0
  55. powermem/integrations/llm/__init__.py +18 -0
  56. powermem/integrations/llm/anthropic.py +87 -0
  57. powermem/integrations/llm/base.py +132 -0
  58. powermem/integrations/llm/config/anthropic.py +56 -0
  59. powermem/integrations/llm/config/azure.py +56 -0
  60. powermem/integrations/llm/config/base.py +62 -0
  61. powermem/integrations/llm/config/deepseek.py +56 -0
  62. powermem/integrations/llm/config/ollama.py +56 -0
  63. powermem/integrations/llm/config/openai.py +79 -0
  64. powermem/integrations/llm/config/qwen.py +68 -0
  65. powermem/integrations/llm/config/qwen_asr.py +46 -0
  66. powermem/integrations/llm/config/vllm.py +56 -0
  67. powermem/integrations/llm/configs.py +26 -0
  68. powermem/integrations/llm/deepseek.py +106 -0
  69. powermem/integrations/llm/factory.py +118 -0
  70. powermem/integrations/llm/gemini.py +201 -0
  71. powermem/integrations/llm/langchain.py +65 -0
  72. powermem/integrations/llm/ollama.py +106 -0
  73. powermem/integrations/llm/openai.py +166 -0
  74. powermem/integrations/llm/openai_structured.py +80 -0
  75. powermem/integrations/llm/qwen.py +207 -0
  76. powermem/integrations/llm/qwen_asr.py +171 -0
  77. powermem/integrations/llm/vllm.py +106 -0
  78. powermem/integrations/rerank/__init__.py +20 -0
  79. powermem/integrations/rerank/base.py +43 -0
  80. powermem/integrations/rerank/config/__init__.py +7 -0
  81. powermem/integrations/rerank/config/base.py +27 -0
  82. powermem/integrations/rerank/configs.py +23 -0
  83. powermem/integrations/rerank/factory.py +68 -0
  84. powermem/integrations/rerank/qwen.py +159 -0
  85. powermem/intelligence/__init__.py +17 -0
  86. powermem/intelligence/ebbinghaus_algorithm.py +354 -0
  87. powermem/intelligence/importance_evaluator.py +361 -0
  88. powermem/intelligence/intelligent_memory_manager.py +284 -0
  89. powermem/intelligence/manager.py +148 -0
  90. powermem/intelligence/plugin.py +229 -0
  91. powermem/prompts/__init__.py +29 -0
  92. powermem/prompts/graph/graph_prompts.py +217 -0
  93. powermem/prompts/graph/graph_tools_prompts.py +469 -0
  94. powermem/prompts/importance_evaluation.py +246 -0
  95. powermem/prompts/intelligent_memory_prompts.py +163 -0
  96. powermem/prompts/templates.py +193 -0
  97. powermem/storage/__init__.py +14 -0
  98. powermem/storage/adapter.py +896 -0
  99. powermem/storage/base.py +109 -0
  100. powermem/storage/config/base.py +13 -0
  101. powermem/storage/config/oceanbase.py +58 -0
  102. powermem/storage/config/pgvector.py +52 -0
  103. powermem/storage/config/sqlite.py +27 -0
  104. powermem/storage/configs.py +159 -0
  105. powermem/storage/factory.py +59 -0
  106. powermem/storage/migration_manager.py +438 -0
  107. powermem/storage/oceanbase/__init__.py +8 -0
  108. powermem/storage/oceanbase/constants.py +162 -0
  109. powermem/storage/oceanbase/oceanbase.py +1384 -0
  110. powermem/storage/oceanbase/oceanbase_graph.py +1441 -0
  111. powermem/storage/pgvector/__init__.py +7 -0
  112. powermem/storage/pgvector/pgvector.py +420 -0
  113. powermem/storage/sqlite/__init__.py +0 -0
  114. powermem/storage/sqlite/sqlite.py +218 -0
  115. powermem/storage/sqlite/sqlite_vector_store.py +311 -0
  116. powermem/utils/__init__.py +35 -0
  117. powermem/utils/utils.py +605 -0
  118. powermem/version.py +23 -0
  119. powermem-0.1.0.dist-info/METADATA +187 -0
  120. powermem-0.1.0.dist-info/RECORD +123 -0
  121. powermem-0.1.0.dist-info/WHEEL +5 -0
  122. powermem-0.1.0.dist-info/licenses/LICENSE +206 -0
  123. powermem-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,18 @@
1
+ """
2
+ Component classes for agent memory management system.
3
+
4
+ This module provides concrete implementations of the agent memory management
5
+ components, migrated from the original multi_agent directory.
6
+ """
7
+
8
+ from .scope_controller import ScopeController
9
+ from .permission_controller import PermissionController
10
+ from .collaboration_coordinator import CollaborationCoordinator
11
+ from .privacy_protector import PrivacyProtector
12
+
13
+ __all__ = [
14
+ "ScopeController",
15
+ "PermissionController",
16
+ "CollaborationCoordinator",
17
+ "PrivacyProtector"
18
+ ]
@@ -0,0 +1,645 @@
1
+ """
2
+ Multi-Agent Collaboration Coordinator
3
+
4
+ Manages collaboration and coordination between agents in the memory system.
5
+ Handles collaborative memory creation, conflict resolution, and consensus.
6
+ """
7
+
8
+ import logging
9
+ from datetime import datetime
10
+ from typing import Any, Dict, List, Optional
11
+ import uuid
12
+
13
+ from typing import Any, Dict
14
+ from powermem.agent.types import CollaborationType, CollaborationStatus
15
+ from powermem.agent.abstract.collaboration import AgentCollaborationManagerBase
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ class CollaborationCoordinator(AgentCollaborationManagerBase):
21
+ """
22
+ Multi-agent collaboration coordinator implementation.
23
+
24
+ Manages collaboration and coordination between agents, handles
25
+ collaborative memory creation, conflict resolution, and consensus.
26
+ """
27
+
28
+ def __init__(self, config: Dict[str, Any]):
29
+ """
30
+ Initialize the collaboration coordinator.
31
+
32
+ Args:
33
+ config: Memory configuration object
34
+ """
35
+ super().__init__(config.agent_memory.multi_agent_config.collaborative_memory_config)
36
+ self.config = config
37
+ self.multi_agent_config = config.agent_memory.multi_agent_config
38
+
39
+ # Collaboration storage
40
+ self.collaborations: Dict[str, Dict[str, Any]] = {}
41
+ self.collaboration_memories: Dict[str, List[str]] = {}
42
+ self.collaboration_participants: Dict[str, List[str]] = {}
43
+
44
+ # Conflict resolution
45
+ self.conflicts: Dict[str, Dict[str, Any]] = {}
46
+ self.resolutions: Dict[str, Dict[str, Any]] = {}
47
+
48
+ # Consensus tracking
49
+ self.consensus_votes: Dict[str, Dict[str, Any]] = {}
50
+ self.consensus_results: Dict[str, Dict[str, Any]] = {}
51
+
52
+ # Initialize settings immediately
53
+ self._initialize_collaboration_settings()
54
+
55
+ def initialize(self) -> None:
56
+ """
57
+ Initialize the collaboration coordinator.
58
+ """
59
+ try:
60
+ # Initialize collaboration settings
61
+ self._initialize_collaboration_settings()
62
+ self.initialized = True
63
+ logger.info("Collaboration coordinator initialized successfully")
64
+
65
+ except Exception as e:
66
+ logger.error(f"Failed to initialize collaboration coordinator: {e}")
67
+ raise
68
+
69
+ def _initialize_collaboration_settings(self) -> None:
70
+ """Initialize collaboration settings from configuration."""
71
+ self.collaboration_config = self.multi_agent_config.collaborative_memory_config
72
+ self.max_participants = self.collaboration_config.get('max_participants', 10)
73
+ self.consensus_required = self.collaboration_config.get('consensus_required', True)
74
+ self.voting_threshold = self.collaboration_config.get('voting_threshold', 0.6)
75
+ self.merge_strategy = self.collaboration_config.get('merge_strategy', 'weighted_average')
76
+ self.conflict_resolution = self.collaboration_config.get('conflict_resolution', 'llm_arbitration')
77
+
78
+ # Initialize collaboration storage
79
+ self.collaborations: Dict[str, Dict[str, Any]] = {}
80
+ self.collaboration_memories: Dict[str, List[str]] = {}
81
+ self.collaboration_participants: Dict[str, List[str]] = {}
82
+ self.conflicts: Dict[str, Dict[str, Any]] = {}
83
+ self.resolutions: Dict[str, Dict[str, Any]] = {}
84
+ self.consensus_votes: Dict[str, Dict[str, Any]] = {}
85
+ self.consensus_results: Dict[str, Dict[str, Any]] = {}
86
+
87
+ def initiate_collaboration(
88
+ self,
89
+ initiator_id: str,
90
+ participant_ids: List[str],
91
+ collaboration_type: CollaborationType,
92
+ context: Optional[Dict[str, Any]] = None
93
+ ) -> Dict[str, Any]:
94
+ """
95
+ Initiate a collaboration between agents.
96
+
97
+ Args:
98
+ initiator_id: ID of the agent initiating the collaboration
99
+ participant_ids: List of agent IDs participating in the collaboration
100
+ collaboration_type: Type of collaboration
101
+ context: Optional context information
102
+
103
+ Returns:
104
+ Dictionary containing the collaboration initiation result
105
+ """
106
+ try:
107
+ # Validate participants
108
+ if len(participant_ids) > self.max_participants:
109
+ raise ValueError(f"Too many participants. Maximum allowed: {self.max_participants}")
110
+
111
+ # Create collaboration ID
112
+ collaboration_id = str(uuid.uuid4())
113
+
114
+ # Create collaboration record
115
+ collaboration = {
116
+ 'id': collaboration_id,
117
+ 'initiator_id': initiator_id,
118
+ 'participants': [initiator_id] + participant_ids,
119
+ 'collaboration_type': collaboration_type.value,
120
+ 'status': CollaborationStatus.INITIATED.value,
121
+ 'context': context or {},
122
+ 'created_at': datetime.now().isoformat(),
123
+ 'updated_at': datetime.now().isoformat(),
124
+ 'memories': [],
125
+ 'conflicts': [],
126
+ 'consensus_votes': {},
127
+ }
128
+
129
+ # Store collaboration
130
+ self.collaborations[collaboration_id] = collaboration
131
+ self.collaboration_participants[collaboration_id] = collaboration['participants']
132
+ self.collaboration_memories[collaboration_id] = []
133
+
134
+ logger.info(f"Initiated collaboration {collaboration_id} with {len(collaboration['participants'])} participants")
135
+
136
+ return {
137
+ 'success': True,
138
+ 'collaboration_id': collaboration_id,
139
+ 'participants': collaboration['participants'],
140
+ 'collaboration_type': collaboration_type.value,
141
+ 'status': CollaborationStatus.INITIATED.value,
142
+ }
143
+
144
+ except Exception as e:
145
+ logger.error(f"Failed to initiate collaboration: {e}")
146
+ return {
147
+ 'success': False,
148
+ 'error': str(e),
149
+ 'initiator_id': initiator_id,
150
+ }
151
+
152
+ def join_collaboration(
153
+ self,
154
+ collaboration_id: str,
155
+ agent_id: str
156
+ ) -> Dict[str, Any]:
157
+ """
158
+ Join an existing collaboration.
159
+
160
+ Args:
161
+ collaboration_id: ID of the collaboration
162
+ agent_id: ID of the agent joining
163
+
164
+ Returns:
165
+ Dictionary containing the join result
166
+ """
167
+ try:
168
+ if collaboration_id not in self.collaborations:
169
+ raise ValueError(f"Collaboration {collaboration_id} not found")
170
+
171
+ collaboration = self.collaborations[collaboration_id]
172
+
173
+ # Check if agent is already a participant
174
+ if agent_id in collaboration['participants']:
175
+ return {
176
+ 'success': True,
177
+ 'collaboration_id': collaboration_id,
178
+ 'agent_id': agent_id,
179
+ 'message': 'Agent is already a participant',
180
+ }
181
+
182
+ # Check participant limit
183
+ if len(collaboration['participants']) >= self.max_participants:
184
+ raise ValueError(f"Collaboration has reached maximum participants: {self.max_participants}")
185
+
186
+ # Add agent to collaboration
187
+ collaboration['participants'].append(agent_id)
188
+ collaboration['updated_at'] = datetime.now().isoformat()
189
+
190
+ # Update participants tracking
191
+ self.collaboration_participants[collaboration_id] = collaboration['participants']
192
+
193
+ logger.info(f"Agent {agent_id} joined collaboration {collaboration_id}")
194
+
195
+ return {
196
+ 'success': True,
197
+ 'collaboration_id': collaboration_id,
198
+ 'agent_id': agent_id,
199
+ 'participants': collaboration['participants'],
200
+ }
201
+
202
+ except Exception as e:
203
+ logger.error(f"Failed to join collaboration: {e}")
204
+ return {
205
+ 'success': False,
206
+ 'error': str(e),
207
+ 'collaboration_id': collaboration_id,
208
+ 'agent_id': agent_id,
209
+ }
210
+
211
+ def leave_collaboration(
212
+ self,
213
+ collaboration_id: str,
214
+ agent_id: str
215
+ ) -> Dict[str, Any]:
216
+ """
217
+ Leave a collaboration.
218
+
219
+ Args:
220
+ collaboration_id: ID of the collaboration
221
+ agent_id: ID of the agent leaving
222
+
223
+ Returns:
224
+ Dictionary containing the leave result
225
+ """
226
+ try:
227
+ if collaboration_id not in self.collaborations:
228
+ raise ValueError(f"Collaboration {collaboration_id} not found")
229
+
230
+ collaboration = self.collaborations[collaboration_id]
231
+
232
+ # Check if agent is a participant
233
+ if agent_id not in collaboration['participants']:
234
+ return {
235
+ 'success': False,
236
+ 'error': 'Agent is not a participant in this collaboration',
237
+ 'collaboration_id': collaboration_id,
238
+ 'agent_id': agent_id,
239
+ }
240
+
241
+ # Remove agent from collaboration
242
+ collaboration['participants'].remove(agent_id)
243
+ collaboration['updated_at'] = datetime.now().isoformat()
244
+
245
+ # Update participants tracking
246
+ self.collaboration_participants[collaboration_id] = collaboration['participants']
247
+
248
+ # If no participants left, mark collaboration as completed
249
+ if not collaboration['participants']:
250
+ collaboration['status'] = CollaborationStatus.COMPLETED.value
251
+
252
+ logger.info(f"Agent {agent_id} left collaboration {collaboration_id}")
253
+
254
+ return {
255
+ 'success': True,
256
+ 'collaboration_id': collaboration_id,
257
+ 'agent_id': agent_id,
258
+ 'participants': collaboration['participants'],
259
+ }
260
+
261
+ except Exception as e:
262
+ logger.error(f"Failed to leave collaboration: {e}")
263
+ return {
264
+ 'success': False,
265
+ 'error': str(e),
266
+ 'collaboration_id': collaboration_id,
267
+ 'agent_id': agent_id,
268
+ }
269
+
270
+ def get_collaboration_status(
271
+ self,
272
+ collaboration_id: str
273
+ ) -> CollaborationStatus:
274
+ """
275
+ Get the status of a collaboration.
276
+
277
+ Args:
278
+ collaboration_id: ID of the collaboration
279
+
280
+ Returns:
281
+ CollaborationStatus enum value
282
+ """
283
+ try:
284
+ if collaboration_id not in self.collaborations:
285
+ return CollaborationStatus.FAILED
286
+
287
+ status_str = self.collaborations[collaboration_id]['status']
288
+ return CollaborationStatus(status_str)
289
+
290
+ except Exception as e:
291
+ logger.error(f"Failed to get collaboration status: {e}")
292
+ return CollaborationStatus.FAILED
293
+
294
+ def update_collaboration_status(
295
+ self,
296
+ collaboration_id: str,
297
+ status: CollaborationStatus,
298
+ updated_by: str
299
+ ) -> Dict[str, Any]:
300
+ """
301
+ Update the status of a collaboration.
302
+
303
+ Args:
304
+ collaboration_id: ID of the collaboration
305
+ status: New status
306
+ updated_by: ID of the agent updating the status
307
+
308
+ Returns:
309
+ Dictionary containing the update result
310
+ """
311
+ try:
312
+ if collaboration_id not in self.collaborations:
313
+ raise ValueError(f"Collaboration {collaboration_id} not found")
314
+
315
+ collaboration = self.collaborations[collaboration_id]
316
+
317
+ # Check if agent is a participant
318
+ if updated_by not in collaboration['participants']:
319
+ raise PermissionError(f"Agent {updated_by} is not a participant in this collaboration")
320
+
321
+ # Update status
322
+ old_status = collaboration['status']
323
+ collaboration['status'] = status.value
324
+ collaboration['updated_at'] = datetime.now().isoformat()
325
+ collaboration['updated_by'] = updated_by
326
+
327
+ logger.info(f"Updated collaboration {collaboration_id} status from {old_status} to {status.value}")
328
+
329
+ return {
330
+ 'success': True,
331
+ 'collaboration_id': collaboration_id,
332
+ 'old_status': old_status,
333
+ 'new_status': status.value,
334
+ 'updated_by': updated_by,
335
+ }
336
+
337
+ except Exception as e:
338
+ logger.error(f"Failed to update collaboration status: {e}")
339
+ return {
340
+ 'success': False,
341
+ 'error': str(e),
342
+ 'collaboration_id': collaboration_id,
343
+ }
344
+
345
+ def get_collaboration_participants(
346
+ self,
347
+ collaboration_id: str
348
+ ) -> List[str]:
349
+ """
350
+ Get list of participants in a collaboration.
351
+
352
+ Args:
353
+ collaboration_id: ID of the collaboration
354
+
355
+ Returns:
356
+ List of agent IDs participating in the collaboration
357
+ """
358
+ try:
359
+ if collaboration_id not in self.collaboration_participants:
360
+ return []
361
+
362
+ return self.collaboration_participants[collaboration_id].copy()
363
+
364
+ except Exception as e:
365
+ logger.error(f"Failed to get collaboration participants: {e}")
366
+ return []
367
+
368
+ def share_memory_in_collaboration(
369
+ self,
370
+ collaboration_id: str,
371
+ memory_id: str,
372
+ shared_by: str
373
+ ) -> Dict[str, Any]:
374
+ """
375
+ Share a memory within a collaboration.
376
+
377
+ Args:
378
+ collaboration_id: ID of the collaboration
379
+ memory_id: ID of the memory to share
380
+ shared_by: ID of the agent sharing the memory
381
+
382
+ Returns:
383
+ Dictionary containing the share result
384
+ """
385
+ try:
386
+ if collaboration_id not in self.collaborations:
387
+ raise ValueError(f"Collaboration {collaboration_id} not found")
388
+
389
+ collaboration = self.collaborations[collaboration_id]
390
+
391
+ # Check if agent is a participant
392
+ if shared_by not in collaboration['participants']:
393
+ raise PermissionError(f"Agent {shared_by} is not a participant in this collaboration")
394
+
395
+ # Add memory to collaboration
396
+ if memory_id not in collaboration['memories']:
397
+ collaboration['memories'].append(memory_id)
398
+ collaboration['updated_at'] = datetime.now().isoformat()
399
+
400
+ # Update collaboration memories tracking
401
+ self.collaboration_memories[collaboration_id] = collaboration['memories']
402
+
403
+ logger.info(f"Shared memory {memory_id} in collaboration {collaboration_id}")
404
+
405
+ return {
406
+ 'success': True,
407
+ 'collaboration_id': collaboration_id,
408
+ 'memory_id': memory_id,
409
+ 'shared_by': shared_by,
410
+ 'participants': collaboration['participants'],
411
+ }
412
+
413
+ except Exception as e:
414
+ logger.error(f"Failed to share memory in collaboration: {e}")
415
+ return {
416
+ 'success': False,
417
+ 'error': str(e),
418
+ 'collaboration_id': collaboration_id,
419
+ 'memory_id': memory_id,
420
+ }
421
+
422
+ def get_collaboration_memories(
423
+ self,
424
+ collaboration_id: str,
425
+ agent_id: Optional[str] = None
426
+ ) -> List[Dict[str, Any]]:
427
+ """
428
+ Get memories shared in a collaboration.
429
+
430
+ Args:
431
+ collaboration_id: ID of the collaboration
432
+ agent_id: Optional ID of the agent requesting
433
+
434
+ Returns:
435
+ List of memory dictionaries
436
+ """
437
+ try:
438
+ if collaboration_id not in self.collaborations:
439
+ return []
440
+
441
+ collaboration = self.collaborations[collaboration_id]
442
+
443
+ # Check if agent is a participant
444
+ if agent_id and agent_id not in collaboration['participants']:
445
+ return []
446
+
447
+ # Return memory IDs (actual memory data would be retrieved from memory manager)
448
+ memories = []
449
+ for memory_id in collaboration['memories']:
450
+ memories.append({
451
+ 'id': memory_id,
452
+ 'collaboration_id': collaboration_id,
453
+ 'shared_in_collaboration': True,
454
+ })
455
+
456
+ return memories
457
+
458
+ except Exception as e:
459
+ logger.error(f"Failed to get collaboration memories: {e}")
460
+ return []
461
+
462
+ def resolve_collaboration_conflict(
463
+ self,
464
+ collaboration_id: str,
465
+ conflict_data: Dict[str, Any],
466
+ resolver_id: str
467
+ ) -> Dict[str, Any]:
468
+ """
469
+ Resolve a conflict in a collaboration.
470
+
471
+ Args:
472
+ collaboration_id: ID of the collaboration
473
+ conflict_data: Data about the conflict
474
+ resolver_id: ID of the agent resolving the conflict
475
+
476
+ Returns:
477
+ Dictionary containing the resolution result
478
+ """
479
+ try:
480
+ if collaboration_id not in self.collaborations:
481
+ raise ValueError(f"Collaboration {collaboration_id} not found")
482
+
483
+ collaboration = self.collaborations[collaboration_id]
484
+
485
+ # Check if agent is a participant
486
+ if resolver_id not in collaboration['participants']:
487
+ raise PermissionError(f"Agent {resolver_id} is not a participant in this collaboration")
488
+
489
+ # Create conflict record
490
+ conflict_id = str(uuid.uuid4())
491
+ conflict = {
492
+ 'id': conflict_id,
493
+ 'collaboration_id': collaboration_id,
494
+ 'conflict_data': conflict_data,
495
+ 'resolver_id': resolver_id,
496
+ 'resolved_at': datetime.now().isoformat(),
497
+ 'resolution_method': self.conflict_resolution,
498
+ }
499
+
500
+ # Store conflict and resolution
501
+ self.conflicts[conflict_id] = conflict
502
+ self.resolutions[conflict_id] = conflict
503
+
504
+ # Add to collaboration conflicts
505
+ collaboration['conflicts'].append(conflict_id)
506
+ collaboration['updated_at'] = datetime.now().isoformat()
507
+
508
+ logger.info(f"Resolved conflict {conflict_id} in collaboration {collaboration_id}")
509
+
510
+ return {
511
+ 'success': True,
512
+ 'conflict_id': conflict_id,
513
+ 'collaboration_id': collaboration_id,
514
+ 'resolver_id': resolver_id,
515
+ 'resolution_method': self.conflict_resolution,
516
+ }
517
+
518
+ except Exception as e:
519
+ logger.error(f"Failed to resolve collaboration conflict: {e}")
520
+ return {
521
+ 'success': False,
522
+ 'error': str(e),
523
+ 'collaboration_id': collaboration_id,
524
+ }
525
+
526
+ def get_collaboration_history(
527
+ self,
528
+ collaboration_id: str,
529
+ limit: Optional[int] = None
530
+ ) -> List[Dict[str, Any]]:
531
+ """
532
+ Get history of a collaboration.
533
+
534
+ Args:
535
+ collaboration_id: ID of the collaboration
536
+ limit: Optional limit on number of entries
537
+
538
+ Returns:
539
+ List of collaboration history entries
540
+ """
541
+ try:
542
+ if collaboration_id not in self.collaborations:
543
+ return []
544
+
545
+ collaboration = self.collaborations[collaboration_id]
546
+
547
+ # Build history from collaboration data
548
+ history = [
549
+ {
550
+ 'timestamp': collaboration['created_at'],
551
+ 'event': 'collaboration_initiated',
552
+ 'agent_id': collaboration['initiator_id'],
553
+ 'data': {
554
+ 'participants': collaboration['participants'],
555
+ 'collaboration_type': collaboration['collaboration_type'],
556
+ },
557
+ },
558
+ {
559
+ 'timestamp': collaboration['updated_at'],
560
+ 'event': 'collaboration_updated',
561
+ 'agent_id': collaboration.get('updated_by'),
562
+ 'data': {
563
+ 'status': collaboration['status'],
564
+ },
565
+ },
566
+ ]
567
+
568
+ # Add memory sharing events
569
+ for memory_id in collaboration['memories']:
570
+ history.append({
571
+ 'timestamp': collaboration['updated_at'],
572
+ 'event': 'memory_shared',
573
+ 'data': {
574
+ 'memory_id': memory_id,
575
+ },
576
+ })
577
+
578
+ # Add conflict resolution events
579
+ for conflict_id in collaboration['conflicts']:
580
+ if conflict_id in self.resolutions:
581
+ resolution = self.resolutions[conflict_id]
582
+ history.append({
583
+ 'timestamp': resolution['resolved_at'],
584
+ 'event': 'conflict_resolved',
585
+ 'agent_id': resolution['resolver_id'],
586
+ 'data': {
587
+ 'conflict_id': conflict_id,
588
+ 'resolution_method': resolution['resolution_method'],
589
+ },
590
+ })
591
+
592
+ # Sort by timestamp
593
+ history.sort(key=lambda x: x['timestamp'])
594
+
595
+ # Apply limit if specified
596
+ if limit:
597
+ history = history[-limit:]
598
+
599
+ return history
600
+
601
+ except Exception as e:
602
+ logger.error(f"Failed to get collaboration history: {e}")
603
+ return []
604
+
605
+ def get_agent_collaborations(
606
+ self,
607
+ agent_id: str,
608
+ status: Optional[CollaborationStatus] = None
609
+ ) -> List[Dict[str, Any]]:
610
+ """
611
+ Get collaborations for an agent.
612
+
613
+ Args:
614
+ agent_id: ID of the agent
615
+ status: Optional status filter
616
+
617
+ Returns:
618
+ List of collaboration dictionaries
619
+ """
620
+ try:
621
+ agent_collaborations = []
622
+
623
+ for collaboration_id, collaboration in self.collaborations.items():
624
+ if agent_id in collaboration['participants']:
625
+ # Apply status filter if specified
626
+ if status and CollaborationStatus(collaboration['status']) != status:
627
+ continue
628
+
629
+ agent_collaborations.append({
630
+ 'collaboration_id': collaboration_id,
631
+ 'initiator_id': collaboration['initiator_id'],
632
+ 'participants': collaboration['participants'],
633
+ 'collaboration_type': collaboration['collaboration_type'],
634
+ 'status': collaboration['status'],
635
+ 'created_at': collaboration['created_at'],
636
+ 'updated_at': collaboration['updated_at'],
637
+ 'memory_count': len(collaboration['memories']),
638
+ 'conflict_count': len(collaboration['conflicts']),
639
+ })
640
+
641
+ return agent_collaborations
642
+
643
+ except Exception as e:
644
+ logger.error(f"Failed to get agent collaborations: {e}")
645
+ return []