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.
- powermem/__init__.py +103 -0
- powermem/agent/__init__.py +35 -0
- powermem/agent/abstract/__init__.py +22 -0
- powermem/agent/abstract/collaboration.py +259 -0
- powermem/agent/abstract/context.py +187 -0
- powermem/agent/abstract/manager.py +232 -0
- powermem/agent/abstract/permission.py +217 -0
- powermem/agent/abstract/privacy.py +267 -0
- powermem/agent/abstract/scope.py +199 -0
- powermem/agent/agent.py +791 -0
- powermem/agent/components/__init__.py +18 -0
- powermem/agent/components/collaboration_coordinator.py +645 -0
- powermem/agent/components/permission_controller.py +586 -0
- powermem/agent/components/privacy_protector.py +767 -0
- powermem/agent/components/scope_controller.py +685 -0
- powermem/agent/factories/__init__.py +16 -0
- powermem/agent/factories/agent_factory.py +266 -0
- powermem/agent/factories/config_factory.py +308 -0
- powermem/agent/factories/memory_factory.py +229 -0
- powermem/agent/implementations/__init__.py +16 -0
- powermem/agent/implementations/hybrid.py +728 -0
- powermem/agent/implementations/multi_agent.py +1040 -0
- powermem/agent/implementations/multi_user.py +1020 -0
- powermem/agent/types.py +53 -0
- powermem/agent/wrappers/__init__.py +14 -0
- powermem/agent/wrappers/agent_memory_wrapper.py +427 -0
- powermem/agent/wrappers/compatibility_wrapper.py +520 -0
- powermem/config_loader.py +318 -0
- powermem/configs.py +249 -0
- powermem/core/__init__.py +19 -0
- powermem/core/async_memory.py +1493 -0
- powermem/core/audit.py +258 -0
- powermem/core/base.py +165 -0
- powermem/core/memory.py +1567 -0
- powermem/core/setup.py +162 -0
- powermem/core/telemetry.py +215 -0
- powermem/integrations/__init__.py +17 -0
- powermem/integrations/embeddings/__init__.py +13 -0
- powermem/integrations/embeddings/aws_bedrock.py +100 -0
- powermem/integrations/embeddings/azure_openai.py +55 -0
- powermem/integrations/embeddings/base.py +31 -0
- powermem/integrations/embeddings/config/base.py +132 -0
- powermem/integrations/embeddings/configs.py +31 -0
- powermem/integrations/embeddings/factory.py +48 -0
- powermem/integrations/embeddings/gemini.py +39 -0
- powermem/integrations/embeddings/huggingface.py +41 -0
- powermem/integrations/embeddings/langchain.py +35 -0
- powermem/integrations/embeddings/lmstudio.py +29 -0
- powermem/integrations/embeddings/mock.py +11 -0
- powermem/integrations/embeddings/ollama.py +53 -0
- powermem/integrations/embeddings/openai.py +49 -0
- powermem/integrations/embeddings/qwen.py +102 -0
- powermem/integrations/embeddings/together.py +31 -0
- powermem/integrations/embeddings/vertexai.py +54 -0
- powermem/integrations/llm/__init__.py +18 -0
- powermem/integrations/llm/anthropic.py +87 -0
- powermem/integrations/llm/base.py +132 -0
- powermem/integrations/llm/config/anthropic.py +56 -0
- powermem/integrations/llm/config/azure.py +56 -0
- powermem/integrations/llm/config/base.py +62 -0
- powermem/integrations/llm/config/deepseek.py +56 -0
- powermem/integrations/llm/config/ollama.py +56 -0
- powermem/integrations/llm/config/openai.py +79 -0
- powermem/integrations/llm/config/qwen.py +68 -0
- powermem/integrations/llm/config/qwen_asr.py +46 -0
- powermem/integrations/llm/config/vllm.py +56 -0
- powermem/integrations/llm/configs.py +26 -0
- powermem/integrations/llm/deepseek.py +106 -0
- powermem/integrations/llm/factory.py +118 -0
- powermem/integrations/llm/gemini.py +201 -0
- powermem/integrations/llm/langchain.py +65 -0
- powermem/integrations/llm/ollama.py +106 -0
- powermem/integrations/llm/openai.py +166 -0
- powermem/integrations/llm/openai_structured.py +80 -0
- powermem/integrations/llm/qwen.py +207 -0
- powermem/integrations/llm/qwen_asr.py +171 -0
- powermem/integrations/llm/vllm.py +106 -0
- powermem/integrations/rerank/__init__.py +20 -0
- powermem/integrations/rerank/base.py +43 -0
- powermem/integrations/rerank/config/__init__.py +7 -0
- powermem/integrations/rerank/config/base.py +27 -0
- powermem/integrations/rerank/configs.py +23 -0
- powermem/integrations/rerank/factory.py +68 -0
- powermem/integrations/rerank/qwen.py +159 -0
- powermem/intelligence/__init__.py +17 -0
- powermem/intelligence/ebbinghaus_algorithm.py +354 -0
- powermem/intelligence/importance_evaluator.py +361 -0
- powermem/intelligence/intelligent_memory_manager.py +284 -0
- powermem/intelligence/manager.py +148 -0
- powermem/intelligence/plugin.py +229 -0
- powermem/prompts/__init__.py +29 -0
- powermem/prompts/graph/graph_prompts.py +217 -0
- powermem/prompts/graph/graph_tools_prompts.py +469 -0
- powermem/prompts/importance_evaluation.py +246 -0
- powermem/prompts/intelligent_memory_prompts.py +163 -0
- powermem/prompts/templates.py +193 -0
- powermem/storage/__init__.py +14 -0
- powermem/storage/adapter.py +896 -0
- powermem/storage/base.py +109 -0
- powermem/storage/config/base.py +13 -0
- powermem/storage/config/oceanbase.py +58 -0
- powermem/storage/config/pgvector.py +52 -0
- powermem/storage/config/sqlite.py +27 -0
- powermem/storage/configs.py +159 -0
- powermem/storage/factory.py +59 -0
- powermem/storage/migration_manager.py +438 -0
- powermem/storage/oceanbase/__init__.py +8 -0
- powermem/storage/oceanbase/constants.py +162 -0
- powermem/storage/oceanbase/oceanbase.py +1384 -0
- powermem/storage/oceanbase/oceanbase_graph.py +1441 -0
- powermem/storage/pgvector/__init__.py +7 -0
- powermem/storage/pgvector/pgvector.py +420 -0
- powermem/storage/sqlite/__init__.py +0 -0
- powermem/storage/sqlite/sqlite.py +218 -0
- powermem/storage/sqlite/sqlite_vector_store.py +311 -0
- powermem/utils/__init__.py +35 -0
- powermem/utils/utils.py +605 -0
- powermem/version.py +23 -0
- powermem-0.1.0.dist-info/METADATA +187 -0
- powermem-0.1.0.dist-info/RECORD +123 -0
- powermem-0.1.0.dist-info/WHEEL +5 -0
- powermem-0.1.0.dist-info/licenses/LICENSE +206 -0
- 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 []
|