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.

@@ -0,0 +1,204 @@
1
+ """
2
+ Community Collaboration Models
3
+
4
+ Defines the data models for agent community collaboration,
5
+ including governance, resource sharing, and collective decision-making.
6
+ """
7
+
8
+ from datetime import datetime
9
+ from typing import Dict, List, Any, Optional, Union
10
+ from enum import Enum
11
+ from pydantic import BaseModel, Field, ConfigDict
12
+ import uuid
13
+
14
+
15
+ class CommunityRole(str, Enum):
16
+ """Roles within the agent community."""
17
+ LEADER = "leader"
18
+ COORDINATOR = "coordinator"
19
+ SPECIALIST = "specialist"
20
+ CONTRIBUTOR = "contributor"
21
+ OBSERVER = "observer"
22
+
23
+
24
+ class GovernanceType(str, Enum):
25
+ """Types of community governance."""
26
+ DEMOCRATIC = "democratic" # Voting-based decisions
27
+ CONSENSUS = "consensus" # Consensus-based decisions
28
+ HIERARCHICAL = "hierarchical" # Leader-based decisions
29
+ HYBRID = "hybrid" # Mixed governance
30
+
31
+
32
+ class DecisionStatus(str, Enum):
33
+ """Status of community decisions."""
34
+ PROPOSED = "proposed"
35
+ VOTING = "voting"
36
+ APPROVED = "approved"
37
+ REJECTED = "rejected"
38
+ IMPLEMENTED = "implemented"
39
+
40
+
41
+ class ResourceType(str, Enum):
42
+ """Types of community resources."""
43
+ KNOWLEDGE = "knowledge"
44
+ TOOL = "tool"
45
+ EXPERIENCE = "experience"
46
+ DATA = "data"
47
+ CAPABILITY = "capability"
48
+
49
+
50
+ class CommunityMember(BaseModel):
51
+ """Model representing a member of the agent community."""
52
+ member_id: str = Field(..., description="Unique identifier for the member")
53
+ agent_id: str = Field(..., description="Associated agent ID")
54
+ agent_role: str = Field(..., description="Agent's functional role")
55
+ community_role: CommunityRole = Field(..., description="Role within the community")
56
+
57
+ # Participation metrics
58
+ contribution_score: float = Field(default=0.0, description="Contribution score to the community")
59
+ reputation: float = Field(default=0.0, description="Reputation within the community")
60
+ participation_level: str = Field(default="active", description="Level of participation")
61
+
62
+ # Capabilities and specializations
63
+ specializations: List[str] = Field(default_factory=list, description="Areas of specialization")
64
+ available_resources: List[str] = Field(default_factory=list, description="Resources this member can provide")
65
+
66
+ # Status
67
+ is_active: bool = Field(default=True, description="Whether the member is active")
68
+ joined_at: datetime = Field(default_factory=datetime.utcnow, description="When the member joined")
69
+ last_active_at: Optional[datetime] = Field(None, description="Last activity timestamp")
70
+
71
+ # Metadata
72
+ metadata: Dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
73
+ model_config = ConfigDict()
74
+
75
+
76
+ class CommunityResource(BaseModel):
77
+ """Model representing a shared community resource."""
78
+ resource_id: str = Field(default_factory=lambda: str(uuid.uuid4()), description="Unique resource identifier")
79
+ name: str = Field(..., description="Name of the resource")
80
+ resource_type: ResourceType = Field(..., description="Type of resource")
81
+ description: Optional[str] = Field(None, description="Description of the resource")
82
+
83
+ # Ownership and access
84
+ owner_id: str = Field(..., description="ID of the member who owns/contributed this resource")
85
+ access_level: str = Field(default="public", description="Access level (public, restricted, private)")
86
+ allowed_members: List[str] = Field(default_factory=list, description="Members allowed to access (if restricted)")
87
+
88
+ # Content
89
+ content: Dict[str, Any] = Field(default_factory=dict, description="Resource content/data")
90
+ tags: List[str] = Field(default_factory=list, description="Tags for categorization")
91
+
92
+ # Usage metrics
93
+ usage_count: int = Field(default=0, description="Number of times this resource has been used")
94
+ rating: float = Field(default=0.0, description="Average rating from community members")
95
+
96
+ # Status
97
+ is_available: bool = Field(default=True, description="Whether the resource is available")
98
+ created_at: datetime = Field(default_factory=datetime.utcnow, description="Creation timestamp")
99
+ updated_at: Optional[datetime] = Field(None, description="Last update timestamp")
100
+
101
+ # Metadata
102
+ metadata: Dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
103
+ model_config = ConfigDict()
104
+
105
+
106
+ class CommunityDecision(BaseModel):
107
+ """Model representing a community decision or proposal."""
108
+ decision_id: str = Field(default_factory=lambda: str(uuid.uuid4()), description="Unique decision identifier")
109
+ title: str = Field(..., description="Title of the decision/proposal")
110
+ description: str = Field(..., description="Detailed description")
111
+
112
+ # Proposal details
113
+ proposer_id: str = Field(..., description="ID of the member who proposed this")
114
+ decision_type: str = Field(..., description="Type of decision (policy, resource, task, etc.)")
115
+ priority: str = Field(default="medium", description="Priority level")
116
+
117
+ # Voting and consensus
118
+ status: DecisionStatus = Field(default=DecisionStatus.PROPOSED, description="Current status")
119
+ votes_for: List[str] = Field(default_factory=list, description="Member IDs who voted for")
120
+ votes_against: List[str] = Field(default_factory=list, description="Member IDs who voted against")
121
+ abstentions: List[str] = Field(default_factory=list, description="Member IDs who abstained")
122
+
123
+ # Implementation
124
+ implementation_plan: Optional[str] = Field(None, description="Plan for implementing the decision")
125
+ assigned_members: List[str] = Field(default_factory=list, description="Members assigned to implement")
126
+ deadline: Optional[datetime] = Field(None, description="Implementation deadline")
127
+
128
+ # Status tracking
129
+ created_at: datetime = Field(default_factory=datetime.utcnow, description="Creation timestamp")
130
+ voting_ends_at: Optional[datetime] = Field(None, description="When voting ends")
131
+ implemented_at: Optional[datetime] = Field(None, description="When decision was implemented")
132
+
133
+ # Metadata
134
+ metadata: Dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
135
+ model_config = ConfigDict()
136
+
137
+
138
+ class AgentCommunity(BaseModel):
139
+ """Model representing an agent community."""
140
+ community_id: str = Field(default_factory=lambda: str(uuid.uuid4()), description="Unique community identifier")
141
+ name: str = Field(..., description="Name of the community")
142
+ description: Optional[str] = Field(None, description="Description of the community")
143
+
144
+ # Governance
145
+ governance_type: GovernanceType = Field(default=GovernanceType.DEMOCRATIC, description="Type of governance")
146
+ governance_rules: Dict[str, Any] = Field(default_factory=dict, description="Governance rules and policies")
147
+
148
+ # Membership
149
+ members: List[str] = Field(default_factory=list, description="List of member IDs")
150
+ max_members: Optional[int] = Field(None, description="Maximum number of members")
151
+ membership_criteria: Dict[str, Any] = Field(default_factory=dict, description="Criteria for membership")
152
+
153
+ # Leadership
154
+ leaders: List[str] = Field(default_factory=list, description="List of leader member IDs")
155
+ coordinators: List[str] = Field(default_factory=list, description="List of coordinator member IDs")
156
+
157
+ # Resources and capabilities
158
+ shared_resources: List[str] = Field(default_factory=list, description="List of shared resource IDs")
159
+ collective_capabilities: List[str] = Field(default_factory=list, description="Collective capabilities")
160
+ knowledge_base: Dict[str, Any] = Field(default_factory=dict, description="Community knowledge base")
161
+
162
+ # Activity and metrics
163
+ activity_level: str = Field(default="active", description="Overall activity level")
164
+ collaboration_score: float = Field(default=0.0, description="Overall collaboration effectiveness score")
165
+ decision_count: int = Field(default=0, description="Number of decisions made")
166
+ resource_count: int = Field(default=0, description="Number of shared resources")
167
+
168
+ # Status
169
+ is_active: bool = Field(default=True, description="Whether the community is active")
170
+ created_at: datetime = Field(default_factory=datetime.utcnow, description="Creation timestamp")
171
+ updated_at: Optional[datetime] = Field(None, description="Last update timestamp")
172
+
173
+ # Metadata
174
+ metadata: Dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
175
+ model_config = ConfigDict()
176
+
177
+
178
+ class CollaborationSession(BaseModel):
179
+ """Model representing a collaborative session between community members."""
180
+ session_id: str = Field(default_factory=lambda: str(uuid.uuid4()), description="Unique session identifier")
181
+ community_id: str = Field(..., description="Associated community ID")
182
+
183
+ # Participants
184
+ participants: List[str] = Field(..., description="List of participating member IDs")
185
+ session_leader: Optional[str] = Field(None, description="Session leader member ID")
186
+
187
+ # Session details
188
+ purpose: str = Field(..., description="Purpose of the collaboration session")
189
+ session_type: str = Field(..., description="Type of session (brainstorm, decision, problem-solving, etc.)")
190
+ agenda: List[str] = Field(default_factory=list, description="Session agenda items")
191
+
192
+ # Outcomes
193
+ decisions_made: List[str] = Field(default_factory=list, description="Decision IDs made during session")
194
+ resources_created: List[str] = Field(default_factory=list, description="Resource IDs created during session")
195
+ action_items: List[Dict[str, Any]] = Field(default_factory=list, description="Action items from the session")
196
+
197
+ # Status
198
+ status: str = Field(default="active", description="Session status")
199
+ started_at: datetime = Field(default_factory=datetime.utcnow, description="Session start time")
200
+ ended_at: Optional[datetime] = Field(None, description="Session end time")
201
+
202
+ # Metadata
203
+ metadata: Dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
204
+ model_config = ConfigDict()
@@ -0,0 +1,438 @@
1
+ """
2
+ Community Resource Manager
3
+
4
+ Manages shared resources, knowledge bases, and collaborative tools
5
+ within agent communities.
6
+ """
7
+
8
+ import logging
9
+ from datetime import datetime
10
+ from typing import Dict, List, Any, Optional, Set
11
+ import uuid
12
+ import json
13
+
14
+ from .models.community_models import (
15
+ CommunityResource, CommunityMember, AgentCommunity,
16
+ ResourceType
17
+ )
18
+ from ..core.exceptions.task_exceptions import TaskValidationError
19
+
20
+ logger = logging.getLogger(__name__)
21
+
22
+
23
+ class ResourceManager:
24
+ """
25
+ Manager for community resources, knowledge sharing, and collaborative tools.
26
+ """
27
+
28
+ def __init__(self, community_manager=None, context_engine=None):
29
+ """
30
+ Initialize the resource manager.
31
+
32
+ Args:
33
+ community_manager: Reference to the community manager
34
+ context_engine: Optional context engine for persistent storage
35
+ """
36
+ self.community_manager = community_manager
37
+ self.context_engine = context_engine
38
+
39
+ # Resource indexing and search
40
+ self.resource_index: Dict[str, Set[str]] = {} # tag -> set of resource_ids
41
+ self.type_index: Dict[ResourceType, Set[str]] = {} # type -> set of resource_ids
42
+ self.owner_index: Dict[str, Set[str]] = {} # owner_id -> set of resource_ids
43
+
44
+ # Knowledge graph for resource relationships
45
+ self.resource_relationships: Dict[str, Dict[str, List[str]]] = {}
46
+
47
+ # Usage analytics
48
+ self.usage_analytics: Dict[str, Dict[str, Any]] = {}
49
+
50
+ logger.info("Resource manager initialized")
51
+
52
+ async def create_knowledge_resource(
53
+ self,
54
+ community_id: str,
55
+ owner_member_id: str,
56
+ title: str,
57
+ content: str,
58
+ knowledge_type: str = "general",
59
+ tags: Optional[List[str]] = None,
60
+ related_resources: Optional[List[str]] = None
61
+ ) -> str:
62
+ """
63
+ Create a knowledge resource for the community.
64
+
65
+ Args:
66
+ community_id: ID of the community
67
+ owner_member_id: ID of the member creating the resource
68
+ title: Title of the knowledge resource
69
+ content: Knowledge content
70
+ knowledge_type: Type of knowledge (general, expertise, experience, etc.)
71
+ tags: Tags for categorization
72
+ related_resources: IDs of related resources
73
+
74
+ Returns:
75
+ Resource ID
76
+ """
77
+ resource_content = {
78
+ "title": title,
79
+ "content": content,
80
+ "knowledge_type": knowledge_type,
81
+ "created_at": datetime.utcnow().isoformat(),
82
+ "version": "1.0"
83
+ }
84
+
85
+ if related_resources:
86
+ resource_content["related_resources"] = related_resources
87
+
88
+ resource_id = await self.community_manager.create_community_resource(
89
+ community_id=community_id,
90
+ owner_member_id=owner_member_id,
91
+ name=title,
92
+ resource_type=ResourceType.KNOWLEDGE,
93
+ content=resource_content,
94
+ description=f"Knowledge resource: {knowledge_type}",
95
+ tags=tags or []
96
+ )
97
+
98
+ # Update indexes
99
+ await self._update_resource_indexes(resource_id, tags or [], ResourceType.KNOWLEDGE, owner_member_id)
100
+
101
+ # Create relationships
102
+ if related_resources:
103
+ await self._create_resource_relationships(resource_id, related_resources)
104
+
105
+ logger.info(f"Created knowledge resource: {title} ({resource_id})")
106
+ return resource_id
107
+
108
+ async def create_tool_resource(
109
+ self,
110
+ community_id: str,
111
+ owner_member_id: str,
112
+ tool_name: str,
113
+ tool_config: Dict[str, Any],
114
+ description: str,
115
+ usage_instructions: str,
116
+ tags: Optional[List[str]] = None
117
+ ) -> str:
118
+ """
119
+ Create a tool resource for community sharing.
120
+
121
+ Args:
122
+ community_id: ID of the community
123
+ owner_member_id: ID of the member creating the resource
124
+ tool_name: Name of the tool
125
+ tool_config: Tool configuration
126
+ description: Tool description
127
+ usage_instructions: Instructions for using the tool
128
+ tags: Tags for categorization
129
+
130
+ Returns:
131
+ Resource ID
132
+ """
133
+ resource_content = {
134
+ "tool_name": tool_name,
135
+ "tool_config": tool_config,
136
+ "description": description,
137
+ "usage_instructions": usage_instructions,
138
+ "created_at": datetime.utcnow().isoformat(),
139
+ "version": "1.0"
140
+ }
141
+
142
+ resource_id = await self.community_manager.create_community_resource(
143
+ community_id=community_id,
144
+ owner_member_id=owner_member_id,
145
+ name=tool_name,
146
+ resource_type=ResourceType.TOOL,
147
+ content=resource_content,
148
+ description=description,
149
+ tags=tags or []
150
+ )
151
+
152
+ # Update indexes
153
+ await self._update_resource_indexes(resource_id, tags or [], ResourceType.TOOL, owner_member_id)
154
+
155
+ logger.info(f"Created tool resource: {tool_name} ({resource_id})")
156
+ return resource_id
157
+
158
+ async def create_experience_resource(
159
+ self,
160
+ community_id: str,
161
+ owner_member_id: str,
162
+ experience_title: str,
163
+ situation: str,
164
+ actions_taken: List[str],
165
+ outcomes: Dict[str, Any],
166
+ lessons_learned: List[str],
167
+ tags: Optional[List[str]] = None
168
+ ) -> str:
169
+ """
170
+ Create an experience resource for knowledge sharing.
171
+
172
+ Args:
173
+ community_id: ID of the community
174
+ owner_member_id: ID of the member sharing the experience
175
+ experience_title: Title of the experience
176
+ situation: Description of the situation
177
+ actions_taken: List of actions taken
178
+ outcomes: Outcomes and results
179
+ lessons_learned: Key lessons learned
180
+ tags: Tags for categorization
181
+
182
+ Returns:
183
+ Resource ID
184
+ """
185
+ resource_content = {
186
+ "experience_title": experience_title,
187
+ "situation": situation,
188
+ "actions_taken": actions_taken,
189
+ "outcomes": outcomes,
190
+ "lessons_learned": lessons_learned,
191
+ "created_at": datetime.utcnow().isoformat(),
192
+ "experience_type": "case_study"
193
+ }
194
+
195
+ resource_id = await self.community_manager.create_community_resource(
196
+ community_id=community_id,
197
+ owner_member_id=owner_member_id,
198
+ name=experience_title,
199
+ resource_type=ResourceType.EXPERIENCE,
200
+ content=resource_content,
201
+ description=f"Experience sharing: {situation[:100]}...",
202
+ tags=tags or []
203
+ )
204
+
205
+ # Update indexes
206
+ await self._update_resource_indexes(resource_id, tags or [], ResourceType.EXPERIENCE, owner_member_id)
207
+
208
+ logger.info(f"Created experience resource: {experience_title} ({resource_id})")
209
+ return resource_id
210
+
211
+ async def search_resources(
212
+ self,
213
+ community_id: str,
214
+ query: Optional[str] = None,
215
+ resource_type: Optional[ResourceType] = None,
216
+ tags: Optional[List[str]] = None,
217
+ owner_id: Optional[str] = None,
218
+ limit: int = 10
219
+ ) -> List[Dict[str, Any]]:
220
+ """
221
+ Search for community resources.
222
+
223
+ Args:
224
+ community_id: ID of the community
225
+ query: Text query for searching
226
+ resource_type: Filter by resource type
227
+ tags: Filter by tags
228
+ owner_id: Filter by owner
229
+ limit: Maximum number of results
230
+
231
+ Returns:
232
+ List of matching resources
233
+ """
234
+ if not self.community_manager:
235
+ raise TaskValidationError("Community manager not available")
236
+
237
+ community = self.community_manager.communities.get(community_id)
238
+ if not community:
239
+ raise TaskValidationError(f"Community not found: {community_id}")
240
+
241
+ # Get candidate resource IDs
242
+ candidate_ids = set(community.shared_resources)
243
+
244
+ # Apply filters
245
+ if resource_type and resource_type in self.type_index:
246
+ candidate_ids &= self.type_index[resource_type]
247
+
248
+ if tags:
249
+ for tag in tags:
250
+ if tag in self.resource_index:
251
+ candidate_ids &= self.resource_index[tag]
252
+
253
+ if owner_id and owner_id in self.owner_index:
254
+ candidate_ids &= self.owner_index[owner_id]
255
+
256
+ # Get resource details and apply text search
257
+ results = []
258
+ for resource_id in candidate_ids:
259
+ resource = self.community_manager.resources.get(resource_id)
260
+ if not resource:
261
+ continue
262
+
263
+ # Text search in resource content
264
+ if query:
265
+ searchable_text = f"{resource.name} {resource.description or ''} {json.dumps(resource.content)}"
266
+ if query.lower() not in searchable_text.lower():
267
+ continue
268
+
269
+ # Add to results
270
+ results.append({
271
+ "resource_id": resource.resource_id,
272
+ "name": resource.name,
273
+ "resource_type": resource.resource_type,
274
+ "description": resource.description,
275
+ "owner_id": resource.owner_id,
276
+ "tags": resource.tags,
277
+ "usage_count": resource.usage_count,
278
+ "rating": resource.rating,
279
+ "created_at": resource.created_at,
280
+ "content_preview": self._get_content_preview(resource.content)
281
+ })
282
+
283
+ if len(results) >= limit:
284
+ break
285
+
286
+ # Sort by relevance (usage count and rating)
287
+ results.sort(key=lambda x: (x["usage_count"], x["rating"]), reverse=True)
288
+
289
+ logger.info(f"Found {len(results)} resources for query: {query}")
290
+ return results
291
+
292
+ async def get_resource_recommendations(
293
+ self,
294
+ community_id: str,
295
+ member_id: str,
296
+ context: Optional[Dict[str, Any]] = None,
297
+ limit: int = 5
298
+ ) -> List[Dict[str, Any]]:
299
+ """
300
+ Get personalized resource recommendations for a member.
301
+
302
+ Args:
303
+ community_id: ID of the community
304
+ member_id: ID of the member
305
+ context: Optional context for recommendations
306
+ limit: Maximum number of recommendations
307
+
308
+ Returns:
309
+ List of recommended resources
310
+ """
311
+ if not self.community_manager:
312
+ raise TaskValidationError("Community manager not available")
313
+
314
+ member = self.community_manager.members.get(member_id)
315
+ if not member:
316
+ raise TaskValidationError(f"Member not found: {member_id}")
317
+
318
+ # Get member's specializations and interests
319
+ member_tags = set(member.specializations)
320
+
321
+ # Find resources matching member's interests
322
+ candidate_resources = []
323
+ for tag in member_tags:
324
+ if tag in self.resource_index:
325
+ for resource_id in self.resource_index[tag]:
326
+ resource = self.community_manager.resources.get(resource_id)
327
+ if resource and resource.owner_id != member_id: # Don't recommend own resources
328
+ candidate_resources.append(resource)
329
+
330
+ # Score and rank resources
331
+ scored_resources = []
332
+ for resource in candidate_resources:
333
+ score = self._calculate_recommendation_score(resource, member, context)
334
+ scored_resources.append((score, resource))
335
+
336
+ # Sort by score and return top recommendations
337
+ scored_resources.sort(key=lambda x: x[0], reverse=True)
338
+
339
+ recommendations = []
340
+ for score, resource in scored_resources[:limit]:
341
+ recommendations.append({
342
+ "resource_id": resource.resource_id,
343
+ "name": resource.name,
344
+ "resource_type": resource.resource_type,
345
+ "description": resource.description,
346
+ "recommendation_score": score,
347
+ "tags": resource.tags,
348
+ "usage_count": resource.usage_count,
349
+ "rating": resource.rating
350
+ })
351
+
352
+ logger.info(f"Generated {len(recommendations)} recommendations for member {member_id}")
353
+ return recommendations
354
+
355
+ def _calculate_recommendation_score(
356
+ self,
357
+ resource: CommunityResource,
358
+ member: CommunityMember,
359
+ context: Optional[Dict[str, Any]] = None
360
+ ) -> float:
361
+ """Calculate recommendation score for a resource."""
362
+ score = 0.0
363
+
364
+ # Tag matching score
365
+ member_tags = set(member.specializations)
366
+ resource_tags = set(resource.tags)
367
+ tag_overlap = len(member_tags & resource_tags)
368
+ score += tag_overlap * 2.0
369
+
370
+ # Usage popularity score
371
+ score += resource.usage_count * 0.1
372
+
373
+ # Quality score
374
+ score += resource.rating * 1.0
375
+
376
+ # Recency score (newer resources get slight boost)
377
+ days_old = (datetime.utcnow() - resource.created_at).days
378
+ recency_score = max(0, 1.0 - (days_old / 365)) # Decay over a year
379
+ score += recency_score * 0.5
380
+
381
+ return score
382
+
383
+ async def _update_resource_indexes(
384
+ self,
385
+ resource_id: str,
386
+ tags: List[str],
387
+ resource_type: ResourceType,
388
+ owner_id: str
389
+ ) -> None:
390
+ """Update resource indexes for efficient searching."""
391
+ # Tag index
392
+ for tag in tags:
393
+ if tag not in self.resource_index:
394
+ self.resource_index[tag] = set()
395
+ self.resource_index[tag].add(resource_id)
396
+
397
+ # Type index
398
+ if resource_type not in self.type_index:
399
+ self.type_index[resource_type] = set()
400
+ self.type_index[resource_type].add(resource_id)
401
+
402
+ # Owner index
403
+ if owner_id not in self.owner_index:
404
+ self.owner_index[owner_id] = set()
405
+ self.owner_index[owner_id].add(resource_id)
406
+
407
+ async def _create_resource_relationships(
408
+ self,
409
+ resource_id: str,
410
+ related_resource_ids: List[str]
411
+ ) -> None:
412
+ """Create relationships between resources."""
413
+ if resource_id not in self.resource_relationships:
414
+ self.resource_relationships[resource_id] = {"related_to": [], "referenced_by": []}
415
+
416
+ for related_id in related_resource_ids:
417
+ # Add forward relationship
418
+ if related_id not in self.resource_relationships[resource_id]["related_to"]:
419
+ self.resource_relationships[resource_id]["related_to"].append(related_id)
420
+
421
+ # Add backward relationship
422
+ if related_id not in self.resource_relationships:
423
+ self.resource_relationships[related_id] = {"related_to": [], "referenced_by": []}
424
+ if resource_id not in self.resource_relationships[related_id]["referenced_by"]:
425
+ self.resource_relationships[related_id]["referenced_by"].append(resource_id)
426
+
427
+ def _get_content_preview(self, content: Dict[str, Any], max_length: int = 200) -> str:
428
+ """Get a preview of resource content."""
429
+ if "content" in content:
430
+ text = str(content["content"])
431
+ elif "description" in content:
432
+ text = str(content["description"])
433
+ else:
434
+ text = str(content)
435
+
436
+ if len(text) > max_length:
437
+ return text[:max_length] + "..."
438
+ return text
@@ -5,8 +5,20 @@ Contains data persistence and storage infrastructure.
5
5
 
6
6
  from .database_manager import DatabaseManager
7
7
  from .redis_client import RedisClient
8
+ from .context_engine_client import (
9
+ initialize_context_engine,
10
+ get_context_engine,
11
+ close_context_engine,
12
+ is_context_engine_initialized,
13
+ reset_context_engine
14
+ )
8
15
 
9
16
  __all__ = [
10
17
  "DatabaseManager",
11
18
  "RedisClient",
19
+ "initialize_context_engine",
20
+ "get_context_engine",
21
+ "close_context_engine",
22
+ "is_context_engine_initialized",
23
+ "reset_context_engine"
12
24
  ]