aiecs 1.0.4__py3-none-any.whl → 1.0.6__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.
Potentially problematic release.
This version of aiecs might be problematic. Click here for more details.
- aiecs/__init__.py +1 -1
- aiecs/config/config.py +1 -0
- aiecs/domain/community/collaborative_workflow.py +407 -0
- aiecs/domain/community/community_integration.py +439 -0
- aiecs/domain/community/community_manager.py +337 -0
- aiecs/domain/community/decision_engine.py +354 -0
- aiecs/domain/community/models/community_models.py +204 -0
- aiecs/domain/community/resource_manager.py +438 -0
- aiecs/infrastructure/persistence/__init__.py +12 -0
- aiecs/infrastructure/persistence/context_engine_client.py +176 -0
- aiecs/llm/base_client.py +1 -0
- aiecs/llm/client_factory.py +4 -0
- aiecs/llm/custom_callbacks.py +3 -3
- aiecs/llm/googleai_client.py +165 -0
- aiecs/llm/openai_client.py +1 -1
- aiecs/llm/vertex_client.py +72 -34
- aiecs/llm/xai_client.py +1 -1
- aiecs/main.py +2 -2
- aiecs/utils/token_usage_repository.py +1 -1
- {aiecs-1.0.4.dist-info → aiecs-1.0.6.dist-info}/METADATA +2 -2
- {aiecs-1.0.4.dist-info → aiecs-1.0.6.dist-info}/RECORD +25 -17
- {aiecs-1.0.4.dist-info → aiecs-1.0.6.dist-info}/WHEEL +0 -0
- {aiecs-1.0.4.dist-info → aiecs-1.0.6.dist-info}/entry_points.txt +0 -0
- {aiecs-1.0.4.dist-info → aiecs-1.0.6.dist-info}/licenses/LICENSE +0 -0
- {aiecs-1.0.4.dist-info → aiecs-1.0.6.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Community Integration Module
|
|
3
|
+
|
|
4
|
+
Integrates community collaboration features with the existing agent system,
|
|
5
|
+
providing seamless community-aware agent management and collaboration.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
from typing import Dict, List, Any, Optional
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
|
|
12
|
+
from .community_manager import CommunityManager
|
|
13
|
+
from .decision_engine import DecisionEngine, ConsensusAlgorithm
|
|
14
|
+
from .resource_manager import ResourceManager
|
|
15
|
+
from .collaborative_workflow import CollaborativeWorkflowEngine
|
|
16
|
+
from .models.community_models import CommunityRole, GovernanceType
|
|
17
|
+
from ..core.exceptions.task_exceptions import TaskValidationError
|
|
18
|
+
|
|
19
|
+
logger = logging.getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class CommunityIntegration:
|
|
23
|
+
"""
|
|
24
|
+
Integration layer for community collaboration features.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, agent_manager=None, context_engine=None):
|
|
28
|
+
"""
|
|
29
|
+
Initialize community integration.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
agent_manager: Reference to the agent manager
|
|
33
|
+
context_engine: Context engine for persistent storage
|
|
34
|
+
"""
|
|
35
|
+
self.agent_manager = agent_manager
|
|
36
|
+
self.context_engine = context_engine
|
|
37
|
+
|
|
38
|
+
# Initialize community components
|
|
39
|
+
self.community_manager = CommunityManager(context_engine)
|
|
40
|
+
self.decision_engine = DecisionEngine(self.community_manager)
|
|
41
|
+
self.resource_manager = ResourceManager(self.community_manager, context_engine)
|
|
42
|
+
self.workflow_engine = CollaborativeWorkflowEngine(
|
|
43
|
+
self.community_manager,
|
|
44
|
+
self.resource_manager,
|
|
45
|
+
self.decision_engine
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
# Community-aware agent tracking
|
|
49
|
+
self.agent_community_mapping: Dict[str, List[str]] = {} # agent_id -> community_ids
|
|
50
|
+
self.community_agent_mapping: Dict[str, List[str]] = {} # community_id -> agent_ids
|
|
51
|
+
|
|
52
|
+
self._initialized = False
|
|
53
|
+
logger.info("Community integration initialized")
|
|
54
|
+
|
|
55
|
+
async def initialize(self) -> None:
|
|
56
|
+
"""Initialize all community components."""
|
|
57
|
+
if self._initialized:
|
|
58
|
+
return
|
|
59
|
+
|
|
60
|
+
await self.community_manager.initialize()
|
|
61
|
+
self._initialized = True
|
|
62
|
+
logger.info("Community integration initialization completed")
|
|
63
|
+
|
|
64
|
+
async def create_agent_community(
|
|
65
|
+
self,
|
|
66
|
+
name: str,
|
|
67
|
+
description: str,
|
|
68
|
+
agent_roles: List[str],
|
|
69
|
+
governance_type: GovernanceType = GovernanceType.DEMOCRATIC,
|
|
70
|
+
creator_agent_id: Optional[str] = None
|
|
71
|
+
) -> str:
|
|
72
|
+
"""
|
|
73
|
+
Create a new agent community with specified agent roles.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
name: Name of the community
|
|
77
|
+
description: Description of the community
|
|
78
|
+
agent_roles: List of agent roles to include
|
|
79
|
+
governance_type: Type of governance
|
|
80
|
+
creator_agent_id: ID of the creating agent
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
Community ID
|
|
84
|
+
"""
|
|
85
|
+
if not self.agent_manager:
|
|
86
|
+
raise TaskValidationError("Agent manager not available")
|
|
87
|
+
|
|
88
|
+
# Create the community
|
|
89
|
+
community_id = await self.community_manager.create_community(
|
|
90
|
+
name=name,
|
|
91
|
+
description=description,
|
|
92
|
+
governance_type=governance_type,
|
|
93
|
+
creator_agent_id=creator_agent_id
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
# Add agents to the community
|
|
97
|
+
for role in agent_roles:
|
|
98
|
+
# Get agents with this role from agent manager
|
|
99
|
+
agents = self.agent_manager.agent_registry.get_agents_by_role(role)
|
|
100
|
+
|
|
101
|
+
for agent in agents:
|
|
102
|
+
await self._add_agent_to_community(community_id, agent.agent_id, role)
|
|
103
|
+
|
|
104
|
+
logger.info(f"Created agent community '{name}' with {len(agent_roles)} role types")
|
|
105
|
+
return community_id
|
|
106
|
+
|
|
107
|
+
async def _add_agent_to_community(
|
|
108
|
+
self,
|
|
109
|
+
community_id: str,
|
|
110
|
+
agent_id: str,
|
|
111
|
+
agent_role: str,
|
|
112
|
+
community_role: CommunityRole = CommunityRole.CONTRIBUTOR
|
|
113
|
+
) -> str:
|
|
114
|
+
"""Add an agent to a community."""
|
|
115
|
+
# Add to community manager
|
|
116
|
+
member_id = await self.community_manager.add_member_to_community(
|
|
117
|
+
community_id=community_id,
|
|
118
|
+
agent_id=agent_id,
|
|
119
|
+
agent_role=agent_role,
|
|
120
|
+
community_role=community_role
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
# Update mappings
|
|
124
|
+
if agent_id not in self.agent_community_mapping:
|
|
125
|
+
self.agent_community_mapping[agent_id] = []
|
|
126
|
+
self.agent_community_mapping[agent_id].append(community_id)
|
|
127
|
+
|
|
128
|
+
if community_id not in self.community_agent_mapping:
|
|
129
|
+
self.community_agent_mapping[community_id] = []
|
|
130
|
+
self.community_agent_mapping[community_id].append(agent_id)
|
|
131
|
+
|
|
132
|
+
return member_id
|
|
133
|
+
|
|
134
|
+
async def initiate_community_collaboration(
|
|
135
|
+
self,
|
|
136
|
+
community_id: str,
|
|
137
|
+
collaboration_type: str,
|
|
138
|
+
purpose: str,
|
|
139
|
+
leader_agent_id: Optional[str] = None,
|
|
140
|
+
specific_participants: Optional[List[str]] = None,
|
|
141
|
+
session_config: Optional[Dict[str, Any]] = None
|
|
142
|
+
) -> str:
|
|
143
|
+
"""
|
|
144
|
+
Initiate a collaborative session within a community.
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
community_id: ID of the community
|
|
148
|
+
collaboration_type: Type of collaboration (brainstorming, problem_solving, etc.)
|
|
149
|
+
purpose: Purpose of the collaboration
|
|
150
|
+
leader_agent_id: Optional leader agent ID
|
|
151
|
+
specific_participants: Optional specific participants
|
|
152
|
+
session_config: Optional session configuration
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
Session ID
|
|
156
|
+
"""
|
|
157
|
+
community = self.community_manager.communities.get(community_id)
|
|
158
|
+
if not community:
|
|
159
|
+
raise TaskValidationError(f"Community not found: {community_id}")
|
|
160
|
+
|
|
161
|
+
# Determine participants
|
|
162
|
+
if specific_participants:
|
|
163
|
+
participants = specific_participants
|
|
164
|
+
else:
|
|
165
|
+
# Use all community members
|
|
166
|
+
participants = community.members
|
|
167
|
+
|
|
168
|
+
# Determine leader
|
|
169
|
+
if not leader_agent_id:
|
|
170
|
+
# Use first leader or coordinator
|
|
171
|
+
if community.leaders:
|
|
172
|
+
leader_member = self.community_manager.members.get(community.leaders[0])
|
|
173
|
+
leader_agent_id = leader_member.agent_id if leader_member else None
|
|
174
|
+
elif community.coordinators:
|
|
175
|
+
coordinator_member = self.community_manager.members.get(community.coordinators[0])
|
|
176
|
+
leader_agent_id = coordinator_member.agent_id if coordinator_member else None
|
|
177
|
+
|
|
178
|
+
# Start collaborative session
|
|
179
|
+
session_id = await self.workflow_engine.start_collaborative_session(
|
|
180
|
+
community_id=community_id,
|
|
181
|
+
session_leader_id=leader_agent_id,
|
|
182
|
+
session_type=collaboration_type,
|
|
183
|
+
purpose=purpose,
|
|
184
|
+
participants=participants,
|
|
185
|
+
session_config=session_config
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
logger.info(f"Initiated {collaboration_type} collaboration in community {community_id}")
|
|
189
|
+
return session_id
|
|
190
|
+
|
|
191
|
+
async def propose_community_decision(
|
|
192
|
+
self,
|
|
193
|
+
community_id: str,
|
|
194
|
+
proposer_agent_id: str,
|
|
195
|
+
title: str,
|
|
196
|
+
description: str,
|
|
197
|
+
decision_type: str,
|
|
198
|
+
implementation_plan: Optional[str] = None
|
|
199
|
+
) -> str:
|
|
200
|
+
"""
|
|
201
|
+
Propose a decision for community consideration.
|
|
202
|
+
|
|
203
|
+
Args:
|
|
204
|
+
community_id: ID of the community
|
|
205
|
+
proposer_agent_id: ID of the proposing agent
|
|
206
|
+
title: Title of the proposal
|
|
207
|
+
description: Detailed description
|
|
208
|
+
decision_type: Type of decision
|
|
209
|
+
implementation_plan: Optional implementation plan
|
|
210
|
+
|
|
211
|
+
Returns:
|
|
212
|
+
Decision ID
|
|
213
|
+
"""
|
|
214
|
+
# Find the member ID for the proposing agent
|
|
215
|
+
proposer_member_id = None
|
|
216
|
+
for member_id, member in self.community_manager.members.items():
|
|
217
|
+
if member.agent_id == proposer_agent_id:
|
|
218
|
+
proposer_member_id = member_id
|
|
219
|
+
break
|
|
220
|
+
|
|
221
|
+
if not proposer_member_id:
|
|
222
|
+
raise TaskValidationError(f"Agent {proposer_agent_id} is not a community member")
|
|
223
|
+
|
|
224
|
+
decision_id = await self.community_manager.propose_decision(
|
|
225
|
+
community_id=community_id,
|
|
226
|
+
proposer_member_id=proposer_member_id,
|
|
227
|
+
title=title,
|
|
228
|
+
description=description,
|
|
229
|
+
decision_type=decision_type,
|
|
230
|
+
implementation_plan=implementation_plan
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
logger.info(f"Agent {proposer_agent_id} proposed decision '{title}' in community {community_id}")
|
|
234
|
+
return decision_id
|
|
235
|
+
|
|
236
|
+
async def agent_vote_on_decision(
|
|
237
|
+
self,
|
|
238
|
+
decision_id: str,
|
|
239
|
+
agent_id: str,
|
|
240
|
+
vote: str
|
|
241
|
+
) -> bool:
|
|
242
|
+
"""
|
|
243
|
+
Cast a vote on behalf of an agent.
|
|
244
|
+
|
|
245
|
+
Args:
|
|
246
|
+
decision_id: ID of the decision
|
|
247
|
+
agent_id: ID of the voting agent
|
|
248
|
+
vote: Vote choice ("for", "against", "abstain")
|
|
249
|
+
|
|
250
|
+
Returns:
|
|
251
|
+
True if vote was cast successfully
|
|
252
|
+
"""
|
|
253
|
+
# Find the member ID for the voting agent
|
|
254
|
+
member_id = None
|
|
255
|
+
for mid, member in self.community_manager.members.items():
|
|
256
|
+
if member.agent_id == agent_id:
|
|
257
|
+
member_id = mid
|
|
258
|
+
break
|
|
259
|
+
|
|
260
|
+
if not member_id:
|
|
261
|
+
raise TaskValidationError(f"Agent {agent_id} is not a community member")
|
|
262
|
+
|
|
263
|
+
success = await self.community_manager.vote_on_decision(
|
|
264
|
+
decision_id=decision_id,
|
|
265
|
+
member_id=member_id,
|
|
266
|
+
vote=vote
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
logger.info(f"Agent {agent_id} voted '{vote}' on decision {decision_id}")
|
|
270
|
+
return success
|
|
271
|
+
|
|
272
|
+
async def evaluate_community_decision(
|
|
273
|
+
self,
|
|
274
|
+
decision_id: str,
|
|
275
|
+
community_id: str,
|
|
276
|
+
algorithm: ConsensusAlgorithm = ConsensusAlgorithm.SIMPLE_MAJORITY
|
|
277
|
+
) -> Dict[str, Any]:
|
|
278
|
+
"""
|
|
279
|
+
Evaluate a community decision using consensus algorithm.
|
|
280
|
+
|
|
281
|
+
Args:
|
|
282
|
+
decision_id: ID of the decision
|
|
283
|
+
community_id: ID of the community
|
|
284
|
+
algorithm: Consensus algorithm to use
|
|
285
|
+
|
|
286
|
+
Returns:
|
|
287
|
+
Evaluation result
|
|
288
|
+
"""
|
|
289
|
+
passed, details = await self.decision_engine.evaluate_decision(
|
|
290
|
+
decision_id=decision_id,
|
|
291
|
+
community_id=community_id,
|
|
292
|
+
algorithm=algorithm
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
result = {
|
|
296
|
+
"decision_id": decision_id,
|
|
297
|
+
"passed": passed,
|
|
298
|
+
"algorithm": algorithm,
|
|
299
|
+
"details": details,
|
|
300
|
+
"evaluated_at": datetime.utcnow().isoformat()
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
logger.info(f"Decision {decision_id} evaluation: {'PASSED' if passed else 'REJECTED'}")
|
|
304
|
+
return result
|
|
305
|
+
|
|
306
|
+
async def create_community_knowledge_resource(
|
|
307
|
+
self,
|
|
308
|
+
community_id: str,
|
|
309
|
+
creator_agent_id: str,
|
|
310
|
+
title: str,
|
|
311
|
+
content: str,
|
|
312
|
+
knowledge_type: str = "general",
|
|
313
|
+
tags: Optional[List[str]] = None
|
|
314
|
+
) -> str:
|
|
315
|
+
"""
|
|
316
|
+
Create a knowledge resource on behalf of an agent.
|
|
317
|
+
|
|
318
|
+
Args:
|
|
319
|
+
community_id: ID of the community
|
|
320
|
+
creator_agent_id: ID of the creating agent
|
|
321
|
+
title: Title of the knowledge resource
|
|
322
|
+
content: Knowledge content
|
|
323
|
+
knowledge_type: Type of knowledge
|
|
324
|
+
tags: Tags for categorization
|
|
325
|
+
|
|
326
|
+
Returns:
|
|
327
|
+
Resource ID
|
|
328
|
+
"""
|
|
329
|
+
# Find the member ID for the creating agent
|
|
330
|
+
creator_member_id = None
|
|
331
|
+
for member_id, member in self.community_manager.members.items():
|
|
332
|
+
if member.agent_id == creator_agent_id:
|
|
333
|
+
creator_member_id = member_id
|
|
334
|
+
break
|
|
335
|
+
|
|
336
|
+
if not creator_member_id:
|
|
337
|
+
raise TaskValidationError(f"Agent {creator_agent_id} is not a community member")
|
|
338
|
+
|
|
339
|
+
resource_id = await self.resource_manager.create_knowledge_resource(
|
|
340
|
+
community_id=community_id,
|
|
341
|
+
owner_member_id=creator_member_id,
|
|
342
|
+
title=title,
|
|
343
|
+
content=content,
|
|
344
|
+
knowledge_type=knowledge_type,
|
|
345
|
+
tags=tags
|
|
346
|
+
)
|
|
347
|
+
|
|
348
|
+
logger.info(f"Agent {creator_agent_id} created knowledge resource '{title}'")
|
|
349
|
+
return resource_id
|
|
350
|
+
|
|
351
|
+
async def get_agent_communities(self, agent_id: str) -> List[Dict[str, Any]]:
|
|
352
|
+
"""
|
|
353
|
+
Get all communities that an agent belongs to.
|
|
354
|
+
|
|
355
|
+
Args:
|
|
356
|
+
agent_id: ID of the agent
|
|
357
|
+
|
|
358
|
+
Returns:
|
|
359
|
+
List of community information
|
|
360
|
+
"""
|
|
361
|
+
communities = []
|
|
362
|
+
|
|
363
|
+
if agent_id in self.agent_community_mapping:
|
|
364
|
+
for community_id in self.agent_community_mapping[agent_id]:
|
|
365
|
+
community = self.community_manager.communities.get(community_id)
|
|
366
|
+
if community:
|
|
367
|
+
# Find agent's role in this community
|
|
368
|
+
agent_role = None
|
|
369
|
+
community_role = None
|
|
370
|
+
for member_id in community.members:
|
|
371
|
+
member = self.community_manager.members.get(member_id)
|
|
372
|
+
if member and member.agent_id == agent_id:
|
|
373
|
+
agent_role = member.agent_role
|
|
374
|
+
community_role = member.community_role
|
|
375
|
+
break
|
|
376
|
+
|
|
377
|
+
communities.append({
|
|
378
|
+
"community_id": community_id,
|
|
379
|
+
"name": community.name,
|
|
380
|
+
"description": community.description,
|
|
381
|
+
"governance_type": community.governance_type,
|
|
382
|
+
"agent_role": agent_role,
|
|
383
|
+
"community_role": community_role,
|
|
384
|
+
"member_count": len(community.members),
|
|
385
|
+
"is_leader": member_id in community.leaders if member_id else False,
|
|
386
|
+
"is_coordinator": member_id in community.coordinators if member_id else False
|
|
387
|
+
})
|
|
388
|
+
|
|
389
|
+
return communities
|
|
390
|
+
|
|
391
|
+
async def get_community_status(self, community_id: str) -> Dict[str, Any]:
|
|
392
|
+
"""
|
|
393
|
+
Get comprehensive status of a community.
|
|
394
|
+
|
|
395
|
+
Args:
|
|
396
|
+
community_id: ID of the community
|
|
397
|
+
|
|
398
|
+
Returns:
|
|
399
|
+
Community status information
|
|
400
|
+
"""
|
|
401
|
+
community = self.community_manager.communities.get(community_id)
|
|
402
|
+
if not community:
|
|
403
|
+
raise TaskValidationError(f"Community not found: {community_id}")
|
|
404
|
+
|
|
405
|
+
# Get active sessions
|
|
406
|
+
active_sessions = [
|
|
407
|
+
session_id for session_id, session in self.workflow_engine.active_sessions.items()
|
|
408
|
+
if session.community_id == community_id
|
|
409
|
+
]
|
|
410
|
+
|
|
411
|
+
# Get recent decisions
|
|
412
|
+
recent_decisions = [
|
|
413
|
+
decision for decision in self.community_manager.decisions.values()
|
|
414
|
+
if any(member.agent_id in self.community_agent_mapping.get(community_id, [])
|
|
415
|
+
for member_id in [decision.proposer_id]
|
|
416
|
+
for member in [self.community_manager.members.get(member_id)]
|
|
417
|
+
if member)
|
|
418
|
+
]
|
|
419
|
+
|
|
420
|
+
status = {
|
|
421
|
+
"community_id": community_id,
|
|
422
|
+
"name": community.name,
|
|
423
|
+
"description": community.description,
|
|
424
|
+
"governance_type": community.governance_type,
|
|
425
|
+
"member_count": len(community.members),
|
|
426
|
+
"leader_count": len(community.leaders),
|
|
427
|
+
"coordinator_count": len(community.coordinators),
|
|
428
|
+
"resource_count": community.resource_count,
|
|
429
|
+
"decision_count": community.decision_count,
|
|
430
|
+
"activity_level": community.activity_level,
|
|
431
|
+
"collaboration_score": community.collaboration_score,
|
|
432
|
+
"active_sessions": len(active_sessions),
|
|
433
|
+
"recent_decisions": len(recent_decisions),
|
|
434
|
+
"is_active": community.is_active,
|
|
435
|
+
"created_at": community.created_at.isoformat(),
|
|
436
|
+
"updated_at": community.updated_at.isoformat() if community.updated_at else None
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
return status
|