aiecs 1.5.1__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.
- aiecs/__init__.py +72 -0
- aiecs/__main__.py +41 -0
- aiecs/aiecs_client.py +469 -0
- aiecs/application/__init__.py +10 -0
- aiecs/application/executors/__init__.py +10 -0
- aiecs/application/executors/operation_executor.py +363 -0
- aiecs/application/knowledge_graph/__init__.py +7 -0
- aiecs/application/knowledge_graph/builder/__init__.py +37 -0
- aiecs/application/knowledge_graph/builder/document_builder.py +375 -0
- aiecs/application/knowledge_graph/builder/graph_builder.py +356 -0
- aiecs/application/knowledge_graph/builder/schema_mapping.py +531 -0
- aiecs/application/knowledge_graph/builder/structured_pipeline.py +443 -0
- aiecs/application/knowledge_graph/builder/text_chunker.py +319 -0
- aiecs/application/knowledge_graph/extractors/__init__.py +27 -0
- aiecs/application/knowledge_graph/extractors/base.py +100 -0
- aiecs/application/knowledge_graph/extractors/llm_entity_extractor.py +327 -0
- aiecs/application/knowledge_graph/extractors/llm_relation_extractor.py +349 -0
- aiecs/application/knowledge_graph/extractors/ner_entity_extractor.py +244 -0
- aiecs/application/knowledge_graph/fusion/__init__.py +23 -0
- aiecs/application/knowledge_graph/fusion/entity_deduplicator.py +387 -0
- aiecs/application/knowledge_graph/fusion/entity_linker.py +343 -0
- aiecs/application/knowledge_graph/fusion/knowledge_fusion.py +580 -0
- aiecs/application/knowledge_graph/fusion/relation_deduplicator.py +189 -0
- aiecs/application/knowledge_graph/pattern_matching/__init__.py +21 -0
- aiecs/application/knowledge_graph/pattern_matching/pattern_matcher.py +344 -0
- aiecs/application/knowledge_graph/pattern_matching/query_executor.py +378 -0
- aiecs/application/knowledge_graph/profiling/__init__.py +12 -0
- aiecs/application/knowledge_graph/profiling/query_plan_visualizer.py +199 -0
- aiecs/application/knowledge_graph/profiling/query_profiler.py +223 -0
- aiecs/application/knowledge_graph/reasoning/__init__.py +27 -0
- aiecs/application/knowledge_graph/reasoning/evidence_synthesis.py +347 -0
- aiecs/application/knowledge_graph/reasoning/inference_engine.py +504 -0
- aiecs/application/knowledge_graph/reasoning/logic_form_parser.py +167 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/__init__.py +79 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/ast_builder.py +513 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/ast_nodes.py +630 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/ast_validator.py +654 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/error_handler.py +477 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/parser.py +390 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/query_context.py +217 -0
- aiecs/application/knowledge_graph/reasoning/logic_query_integration.py +169 -0
- aiecs/application/knowledge_graph/reasoning/query_planner.py +872 -0
- aiecs/application/knowledge_graph/reasoning/reasoning_engine.py +554 -0
- aiecs/application/knowledge_graph/retrieval/__init__.py +19 -0
- aiecs/application/knowledge_graph/retrieval/retrieval_strategies.py +596 -0
- aiecs/application/knowledge_graph/search/__init__.py +59 -0
- aiecs/application/knowledge_graph/search/hybrid_search.py +423 -0
- aiecs/application/knowledge_graph/search/reranker.py +295 -0
- aiecs/application/knowledge_graph/search/reranker_strategies.py +553 -0
- aiecs/application/knowledge_graph/search/text_similarity.py +398 -0
- aiecs/application/knowledge_graph/traversal/__init__.py +15 -0
- aiecs/application/knowledge_graph/traversal/enhanced_traversal.py +329 -0
- aiecs/application/knowledge_graph/traversal/path_scorer.py +269 -0
- aiecs/application/knowledge_graph/validators/__init__.py +13 -0
- aiecs/application/knowledge_graph/validators/relation_validator.py +189 -0
- aiecs/application/knowledge_graph/visualization/__init__.py +11 -0
- aiecs/application/knowledge_graph/visualization/graph_visualizer.py +321 -0
- aiecs/common/__init__.py +9 -0
- aiecs/common/knowledge_graph/__init__.py +17 -0
- aiecs/common/knowledge_graph/runnable.py +484 -0
- aiecs/config/__init__.py +16 -0
- aiecs/config/config.py +498 -0
- aiecs/config/graph_config.py +137 -0
- aiecs/config/registry.py +23 -0
- aiecs/core/__init__.py +46 -0
- aiecs/core/interface/__init__.py +34 -0
- aiecs/core/interface/execution_interface.py +152 -0
- aiecs/core/interface/storage_interface.py +171 -0
- aiecs/domain/__init__.py +289 -0
- aiecs/domain/agent/__init__.py +189 -0
- aiecs/domain/agent/base_agent.py +697 -0
- aiecs/domain/agent/exceptions.py +103 -0
- aiecs/domain/agent/graph_aware_mixin.py +559 -0
- aiecs/domain/agent/hybrid_agent.py +490 -0
- aiecs/domain/agent/integration/__init__.py +26 -0
- aiecs/domain/agent/integration/context_compressor.py +222 -0
- aiecs/domain/agent/integration/context_engine_adapter.py +252 -0
- aiecs/domain/agent/integration/retry_policy.py +219 -0
- aiecs/domain/agent/integration/role_config.py +213 -0
- aiecs/domain/agent/knowledge_aware_agent.py +646 -0
- aiecs/domain/agent/lifecycle.py +296 -0
- aiecs/domain/agent/llm_agent.py +300 -0
- aiecs/domain/agent/memory/__init__.py +12 -0
- aiecs/domain/agent/memory/conversation.py +197 -0
- aiecs/domain/agent/migration/__init__.py +14 -0
- aiecs/domain/agent/migration/conversion.py +160 -0
- aiecs/domain/agent/migration/legacy_wrapper.py +90 -0
- aiecs/domain/agent/models.py +317 -0
- aiecs/domain/agent/observability.py +407 -0
- aiecs/domain/agent/persistence.py +289 -0
- aiecs/domain/agent/prompts/__init__.py +29 -0
- aiecs/domain/agent/prompts/builder.py +161 -0
- aiecs/domain/agent/prompts/formatters.py +189 -0
- aiecs/domain/agent/prompts/template.py +255 -0
- aiecs/domain/agent/registry.py +260 -0
- aiecs/domain/agent/tool_agent.py +257 -0
- aiecs/domain/agent/tools/__init__.py +12 -0
- aiecs/domain/agent/tools/schema_generator.py +221 -0
- aiecs/domain/community/__init__.py +155 -0
- aiecs/domain/community/agent_adapter.py +477 -0
- aiecs/domain/community/analytics.py +481 -0
- aiecs/domain/community/collaborative_workflow.py +642 -0
- aiecs/domain/community/communication_hub.py +645 -0
- aiecs/domain/community/community_builder.py +320 -0
- aiecs/domain/community/community_integration.py +800 -0
- aiecs/domain/community/community_manager.py +813 -0
- aiecs/domain/community/decision_engine.py +879 -0
- aiecs/domain/community/exceptions.py +225 -0
- aiecs/domain/community/models/__init__.py +33 -0
- aiecs/domain/community/models/community_models.py +268 -0
- aiecs/domain/community/resource_manager.py +457 -0
- aiecs/domain/community/shared_context_manager.py +603 -0
- aiecs/domain/context/__init__.py +58 -0
- aiecs/domain/context/context_engine.py +989 -0
- aiecs/domain/context/conversation_models.py +354 -0
- aiecs/domain/context/graph_memory.py +467 -0
- aiecs/domain/execution/__init__.py +12 -0
- aiecs/domain/execution/model.py +57 -0
- aiecs/domain/knowledge_graph/__init__.py +19 -0
- aiecs/domain/knowledge_graph/models/__init__.py +52 -0
- aiecs/domain/knowledge_graph/models/entity.py +130 -0
- aiecs/domain/knowledge_graph/models/evidence.py +194 -0
- aiecs/domain/knowledge_graph/models/inference_rule.py +186 -0
- aiecs/domain/knowledge_graph/models/path.py +179 -0
- aiecs/domain/knowledge_graph/models/path_pattern.py +173 -0
- aiecs/domain/knowledge_graph/models/query.py +272 -0
- aiecs/domain/knowledge_graph/models/query_plan.py +187 -0
- aiecs/domain/knowledge_graph/models/relation.py +136 -0
- aiecs/domain/knowledge_graph/schema/__init__.py +23 -0
- aiecs/domain/knowledge_graph/schema/entity_type.py +135 -0
- aiecs/domain/knowledge_graph/schema/graph_schema.py +271 -0
- aiecs/domain/knowledge_graph/schema/property_schema.py +155 -0
- aiecs/domain/knowledge_graph/schema/relation_type.py +171 -0
- aiecs/domain/knowledge_graph/schema/schema_manager.py +496 -0
- aiecs/domain/knowledge_graph/schema/type_enums.py +205 -0
- aiecs/domain/task/__init__.py +13 -0
- aiecs/domain/task/dsl_processor.py +613 -0
- aiecs/domain/task/model.py +62 -0
- aiecs/domain/task/task_context.py +268 -0
- aiecs/infrastructure/__init__.py +24 -0
- aiecs/infrastructure/graph_storage/__init__.py +11 -0
- aiecs/infrastructure/graph_storage/base.py +601 -0
- aiecs/infrastructure/graph_storage/batch_operations.py +449 -0
- aiecs/infrastructure/graph_storage/cache.py +429 -0
- aiecs/infrastructure/graph_storage/distributed.py +226 -0
- aiecs/infrastructure/graph_storage/error_handling.py +390 -0
- aiecs/infrastructure/graph_storage/graceful_degradation.py +306 -0
- aiecs/infrastructure/graph_storage/health_checks.py +378 -0
- aiecs/infrastructure/graph_storage/in_memory.py +514 -0
- aiecs/infrastructure/graph_storage/index_optimization.py +483 -0
- aiecs/infrastructure/graph_storage/lazy_loading.py +410 -0
- aiecs/infrastructure/graph_storage/metrics.py +357 -0
- aiecs/infrastructure/graph_storage/migration.py +413 -0
- aiecs/infrastructure/graph_storage/pagination.py +471 -0
- aiecs/infrastructure/graph_storage/performance_monitoring.py +466 -0
- aiecs/infrastructure/graph_storage/postgres.py +871 -0
- aiecs/infrastructure/graph_storage/query_optimizer.py +635 -0
- aiecs/infrastructure/graph_storage/schema_cache.py +290 -0
- aiecs/infrastructure/graph_storage/sqlite.py +623 -0
- aiecs/infrastructure/graph_storage/streaming.py +495 -0
- aiecs/infrastructure/messaging/__init__.py +13 -0
- aiecs/infrastructure/messaging/celery_task_manager.py +383 -0
- aiecs/infrastructure/messaging/websocket_manager.py +298 -0
- aiecs/infrastructure/monitoring/__init__.py +34 -0
- aiecs/infrastructure/monitoring/executor_metrics.py +174 -0
- aiecs/infrastructure/monitoring/global_metrics_manager.py +213 -0
- aiecs/infrastructure/monitoring/structured_logger.py +48 -0
- aiecs/infrastructure/monitoring/tracing_manager.py +410 -0
- aiecs/infrastructure/persistence/__init__.py +24 -0
- aiecs/infrastructure/persistence/context_engine_client.py +187 -0
- aiecs/infrastructure/persistence/database_manager.py +333 -0
- aiecs/infrastructure/persistence/file_storage.py +754 -0
- aiecs/infrastructure/persistence/redis_client.py +220 -0
- aiecs/llm/__init__.py +86 -0
- aiecs/llm/callbacks/__init__.py +11 -0
- aiecs/llm/callbacks/custom_callbacks.py +264 -0
- aiecs/llm/client_factory.py +420 -0
- aiecs/llm/clients/__init__.py +33 -0
- aiecs/llm/clients/base_client.py +193 -0
- aiecs/llm/clients/googleai_client.py +181 -0
- aiecs/llm/clients/openai_client.py +131 -0
- aiecs/llm/clients/vertex_client.py +437 -0
- aiecs/llm/clients/xai_client.py +184 -0
- aiecs/llm/config/__init__.py +51 -0
- aiecs/llm/config/config_loader.py +275 -0
- aiecs/llm/config/config_validator.py +236 -0
- aiecs/llm/config/model_config.py +151 -0
- aiecs/llm/utils/__init__.py +10 -0
- aiecs/llm/utils/validate_config.py +91 -0
- aiecs/main.py +363 -0
- aiecs/scripts/__init__.py +3 -0
- aiecs/scripts/aid/VERSION_MANAGEMENT.md +97 -0
- aiecs/scripts/aid/__init__.py +19 -0
- aiecs/scripts/aid/version_manager.py +215 -0
- aiecs/scripts/dependance_check/DEPENDENCY_SYSTEM_SUMMARY.md +242 -0
- aiecs/scripts/dependance_check/README_DEPENDENCY_CHECKER.md +310 -0
- aiecs/scripts/dependance_check/__init__.py +17 -0
- aiecs/scripts/dependance_check/dependency_checker.py +938 -0
- aiecs/scripts/dependance_check/dependency_fixer.py +391 -0
- aiecs/scripts/dependance_check/download_nlp_data.py +396 -0
- aiecs/scripts/dependance_check/quick_dependency_check.py +270 -0
- aiecs/scripts/dependance_check/setup_nlp_data.sh +217 -0
- aiecs/scripts/dependance_patch/__init__.py +7 -0
- aiecs/scripts/dependance_patch/fix_weasel/README_WEASEL_PATCH.md +126 -0
- aiecs/scripts/dependance_patch/fix_weasel/__init__.py +11 -0
- aiecs/scripts/dependance_patch/fix_weasel/fix_weasel_validator.py +128 -0
- aiecs/scripts/dependance_patch/fix_weasel/fix_weasel_validator.sh +82 -0
- aiecs/scripts/dependance_patch/fix_weasel/patch_weasel_library.sh +188 -0
- aiecs/scripts/dependance_patch/fix_weasel/run_weasel_patch.sh +41 -0
- aiecs/scripts/tools_develop/README.md +449 -0
- aiecs/scripts/tools_develop/TOOL_AUTO_DISCOVERY.md +234 -0
- aiecs/scripts/tools_develop/__init__.py +21 -0
- aiecs/scripts/tools_develop/check_type_annotations.py +259 -0
- aiecs/scripts/tools_develop/validate_tool_schemas.py +422 -0
- aiecs/scripts/tools_develop/verify_tools.py +356 -0
- aiecs/tasks/__init__.py +1 -0
- aiecs/tasks/worker.py +172 -0
- aiecs/tools/__init__.py +299 -0
- aiecs/tools/apisource/__init__.py +99 -0
- aiecs/tools/apisource/intelligence/__init__.py +19 -0
- aiecs/tools/apisource/intelligence/data_fusion.py +381 -0
- aiecs/tools/apisource/intelligence/query_analyzer.py +413 -0
- aiecs/tools/apisource/intelligence/search_enhancer.py +388 -0
- aiecs/tools/apisource/monitoring/__init__.py +9 -0
- aiecs/tools/apisource/monitoring/metrics.py +303 -0
- aiecs/tools/apisource/providers/__init__.py +115 -0
- aiecs/tools/apisource/providers/base.py +664 -0
- aiecs/tools/apisource/providers/census.py +401 -0
- aiecs/tools/apisource/providers/fred.py +564 -0
- aiecs/tools/apisource/providers/newsapi.py +412 -0
- aiecs/tools/apisource/providers/worldbank.py +357 -0
- aiecs/tools/apisource/reliability/__init__.py +12 -0
- aiecs/tools/apisource/reliability/error_handler.py +375 -0
- aiecs/tools/apisource/reliability/fallback_strategy.py +391 -0
- aiecs/tools/apisource/tool.py +850 -0
- aiecs/tools/apisource/utils/__init__.py +9 -0
- aiecs/tools/apisource/utils/validators.py +338 -0
- aiecs/tools/base_tool.py +201 -0
- aiecs/tools/docs/__init__.py +121 -0
- aiecs/tools/docs/ai_document_orchestrator.py +599 -0
- aiecs/tools/docs/ai_document_writer_orchestrator.py +2403 -0
- aiecs/tools/docs/content_insertion_tool.py +1333 -0
- aiecs/tools/docs/document_creator_tool.py +1317 -0
- aiecs/tools/docs/document_layout_tool.py +1166 -0
- aiecs/tools/docs/document_parser_tool.py +994 -0
- aiecs/tools/docs/document_writer_tool.py +1818 -0
- aiecs/tools/knowledge_graph/__init__.py +17 -0
- aiecs/tools/knowledge_graph/graph_reasoning_tool.py +734 -0
- aiecs/tools/knowledge_graph/graph_search_tool.py +923 -0
- aiecs/tools/knowledge_graph/kg_builder_tool.py +476 -0
- aiecs/tools/langchain_adapter.py +542 -0
- aiecs/tools/schema_generator.py +275 -0
- aiecs/tools/search_tool/__init__.py +100 -0
- aiecs/tools/search_tool/analyzers.py +589 -0
- aiecs/tools/search_tool/cache.py +260 -0
- aiecs/tools/search_tool/constants.py +128 -0
- aiecs/tools/search_tool/context.py +216 -0
- aiecs/tools/search_tool/core.py +749 -0
- aiecs/tools/search_tool/deduplicator.py +123 -0
- aiecs/tools/search_tool/error_handler.py +271 -0
- aiecs/tools/search_tool/metrics.py +371 -0
- aiecs/tools/search_tool/rate_limiter.py +178 -0
- aiecs/tools/search_tool/schemas.py +277 -0
- aiecs/tools/statistics/__init__.py +80 -0
- aiecs/tools/statistics/ai_data_analysis_orchestrator.py +643 -0
- aiecs/tools/statistics/ai_insight_generator_tool.py +505 -0
- aiecs/tools/statistics/ai_report_orchestrator_tool.py +694 -0
- aiecs/tools/statistics/data_loader_tool.py +564 -0
- aiecs/tools/statistics/data_profiler_tool.py +658 -0
- aiecs/tools/statistics/data_transformer_tool.py +573 -0
- aiecs/tools/statistics/data_visualizer_tool.py +495 -0
- aiecs/tools/statistics/model_trainer_tool.py +487 -0
- aiecs/tools/statistics/statistical_analyzer_tool.py +459 -0
- aiecs/tools/task_tools/__init__.py +86 -0
- aiecs/tools/task_tools/chart_tool.py +732 -0
- aiecs/tools/task_tools/classfire_tool.py +922 -0
- aiecs/tools/task_tools/image_tool.py +447 -0
- aiecs/tools/task_tools/office_tool.py +684 -0
- aiecs/tools/task_tools/pandas_tool.py +635 -0
- aiecs/tools/task_tools/report_tool.py +635 -0
- aiecs/tools/task_tools/research_tool.py +392 -0
- aiecs/tools/task_tools/scraper_tool.py +715 -0
- aiecs/tools/task_tools/stats_tool.py +688 -0
- aiecs/tools/temp_file_manager.py +130 -0
- aiecs/tools/tool_executor/__init__.py +37 -0
- aiecs/tools/tool_executor/tool_executor.py +881 -0
- aiecs/utils/LLM_output_structor.py +445 -0
- aiecs/utils/__init__.py +34 -0
- aiecs/utils/base_callback.py +47 -0
- aiecs/utils/cache_provider.py +695 -0
- aiecs/utils/execution_utils.py +184 -0
- aiecs/utils/logging.py +1 -0
- aiecs/utils/prompt_loader.py +14 -0
- aiecs/utils/token_usage_repository.py +323 -0
- aiecs/ws/__init__.py +0 -0
- aiecs/ws/socket_server.py +52 -0
- aiecs-1.5.1.dist-info/METADATA +608 -0
- aiecs-1.5.1.dist-info/RECORD +302 -0
- aiecs-1.5.1.dist-info/WHEEL +5 -0
- aiecs-1.5.1.dist-info/entry_points.txt +10 -0
- aiecs-1.5.1.dist-info/licenses/LICENSE +225 -0
- aiecs-1.5.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,603 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Shared Context Manager
|
|
3
|
+
|
|
4
|
+
Manages shared memory and context for agents in a community,
|
|
5
|
+
with support for versioning, conflict resolution, and real-time streaming.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
import asyncio
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
from typing import Dict, List, Any, Optional, Set, Callable
|
|
12
|
+
from enum import Enum
|
|
13
|
+
from collections import defaultdict
|
|
14
|
+
import uuid
|
|
15
|
+
import copy
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ContextScope(str, Enum):
|
|
21
|
+
"""Scope levels for shared context."""
|
|
22
|
+
|
|
23
|
+
COMMUNITY = "community"
|
|
24
|
+
SESSION = "session"
|
|
25
|
+
TASK = "task"
|
|
26
|
+
AGENT = "agent"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class ConflictResolutionStrategy(str, Enum):
|
|
30
|
+
"""Strategies for resolving context conflicts."""
|
|
31
|
+
|
|
32
|
+
LAST_WRITE_WINS = "last_write_wins"
|
|
33
|
+
FIRST_WRITE_WINS = "first_write_wins"
|
|
34
|
+
MERGE = "merge"
|
|
35
|
+
MANUAL = "manual"
|
|
36
|
+
TIMESTAMP_BASED = "timestamp_based"
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class ContextVersion:
|
|
40
|
+
"""Represents a version of context data."""
|
|
41
|
+
|
|
42
|
+
def __init__(
|
|
43
|
+
self,
|
|
44
|
+
context_id: str,
|
|
45
|
+
data: Dict[str, Any],
|
|
46
|
+
version_number: int,
|
|
47
|
+
author_id: str,
|
|
48
|
+
parent_version: Optional[int] = None,
|
|
49
|
+
):
|
|
50
|
+
"""
|
|
51
|
+
Initialize a context version.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
context_id: ID of the context
|
|
55
|
+
data: Context data
|
|
56
|
+
version_number: Version number
|
|
57
|
+
author_id: ID of the author who created this version
|
|
58
|
+
parent_version: Optional parent version number
|
|
59
|
+
"""
|
|
60
|
+
self.context_id = context_id
|
|
61
|
+
self.data = copy.deepcopy(data)
|
|
62
|
+
self.version_number = version_number
|
|
63
|
+
self.author_id = author_id
|
|
64
|
+
self.parent_version = parent_version
|
|
65
|
+
self.timestamp = datetime.utcnow()
|
|
66
|
+
self.metadata: Dict[str, Any] = {}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class SharedContext:
|
|
70
|
+
"""Represents a shared context in the community."""
|
|
71
|
+
|
|
72
|
+
def __init__(
|
|
73
|
+
self,
|
|
74
|
+
context_id: str,
|
|
75
|
+
scope: ContextScope,
|
|
76
|
+
owner_id: str,
|
|
77
|
+
initial_data: Optional[Dict[str, Any]] = None,
|
|
78
|
+
):
|
|
79
|
+
"""
|
|
80
|
+
Initialize a shared context.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
context_id: Unique context identifier
|
|
84
|
+
scope: Scope level of the context
|
|
85
|
+
owner_id: ID of the context owner
|
|
86
|
+
initial_data: Optional initial data
|
|
87
|
+
"""
|
|
88
|
+
self.context_id = context_id
|
|
89
|
+
self.scope = scope
|
|
90
|
+
self.owner_id = owner_id
|
|
91
|
+
self.current_version = 0
|
|
92
|
+
self.versions: List[ContextVersion] = []
|
|
93
|
+
self.data = initial_data or {}
|
|
94
|
+
self.access_control: Set[str] = {owner_id} # IDs with access
|
|
95
|
+
self.subscribers: Set[str] = set() # IDs subscribed to updates
|
|
96
|
+
self.created_at = datetime.utcnow()
|
|
97
|
+
self.updated_at = datetime.utcnow()
|
|
98
|
+
self.metadata: Dict[str, Any] = {}
|
|
99
|
+
|
|
100
|
+
# Create initial version
|
|
101
|
+
if initial_data:
|
|
102
|
+
self._create_version(initial_data, owner_id)
|
|
103
|
+
|
|
104
|
+
def _create_version(self, data: Dict[str, Any], author_id: str) -> ContextVersion:
|
|
105
|
+
"""Create a new version of the context."""
|
|
106
|
+
version = ContextVersion(
|
|
107
|
+
self.context_id,
|
|
108
|
+
data,
|
|
109
|
+
self.current_version + 1,
|
|
110
|
+
author_id,
|
|
111
|
+
self.current_version if self.current_version > 0 else None,
|
|
112
|
+
)
|
|
113
|
+
self.versions.append(version)
|
|
114
|
+
self.current_version = version.version_number
|
|
115
|
+
self.data = copy.deepcopy(data)
|
|
116
|
+
self.updated_at = datetime.utcnow()
|
|
117
|
+
return version
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
class SharedContextManager:
|
|
121
|
+
"""
|
|
122
|
+
Manager for shared contexts in agent communities.
|
|
123
|
+
Provides versioning, conflict resolution, and streaming capabilities.
|
|
124
|
+
"""
|
|
125
|
+
|
|
126
|
+
def __init__(
|
|
127
|
+
self,
|
|
128
|
+
default_conflict_strategy: ConflictResolutionStrategy = ConflictResolutionStrategy.LAST_WRITE_WINS,
|
|
129
|
+
):
|
|
130
|
+
"""
|
|
131
|
+
Initialize the shared context manager.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
default_conflict_strategy: Default strategy for conflict resolution
|
|
135
|
+
"""
|
|
136
|
+
self.contexts: Dict[str, SharedContext] = {}
|
|
137
|
+
self.default_conflict_strategy = default_conflict_strategy
|
|
138
|
+
|
|
139
|
+
# Scope-based indexes
|
|
140
|
+
self.community_contexts: Dict[str, Set[str]] = defaultdict(set)
|
|
141
|
+
self.session_contexts: Dict[str, Set[str]] = defaultdict(set)
|
|
142
|
+
self.task_contexts: Dict[str, Set[str]] = defaultdict(set)
|
|
143
|
+
self.agent_contexts: Dict[str, Set[str]] = defaultdict(set)
|
|
144
|
+
|
|
145
|
+
# Update callbacks for streaming
|
|
146
|
+
self.update_callbacks: Dict[str, List[Callable]] = defaultdict(list)
|
|
147
|
+
|
|
148
|
+
logger.info("Shared context manager initialized")
|
|
149
|
+
|
|
150
|
+
async def create_context(
|
|
151
|
+
self,
|
|
152
|
+
scope: ContextScope,
|
|
153
|
+
owner_id: str,
|
|
154
|
+
scope_id: str,
|
|
155
|
+
initial_data: Optional[Dict[str, Any]] = None,
|
|
156
|
+
access_control: Optional[Set[str]] = None,
|
|
157
|
+
) -> str:
|
|
158
|
+
"""
|
|
159
|
+
Create a new shared context.
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
scope: Scope level of the context
|
|
163
|
+
owner_id: ID of the context owner
|
|
164
|
+
scope_id: ID of the scope (community_id, session_id, task_id, or agent_id)
|
|
165
|
+
initial_data: Optional initial data
|
|
166
|
+
access_control: Optional set of agent IDs with access
|
|
167
|
+
|
|
168
|
+
Returns:
|
|
169
|
+
Context ID
|
|
170
|
+
"""
|
|
171
|
+
context_id = str(uuid.uuid4())
|
|
172
|
+
context = SharedContext(context_id, scope, owner_id, initial_data)
|
|
173
|
+
|
|
174
|
+
if access_control:
|
|
175
|
+
context.access_control = access_control
|
|
176
|
+
|
|
177
|
+
self.contexts[context_id] = context
|
|
178
|
+
|
|
179
|
+
# Add to scope index
|
|
180
|
+
if scope == ContextScope.COMMUNITY:
|
|
181
|
+
self.community_contexts[scope_id].add(context_id)
|
|
182
|
+
elif scope == ContextScope.SESSION:
|
|
183
|
+
self.session_contexts[scope_id].add(context_id)
|
|
184
|
+
elif scope == ContextScope.TASK:
|
|
185
|
+
self.task_contexts[scope_id].add(context_id)
|
|
186
|
+
elif scope == ContextScope.AGENT:
|
|
187
|
+
self.agent_contexts[scope_id].add(context_id)
|
|
188
|
+
|
|
189
|
+
logger.info(f"Created {scope.value} context {context_id}")
|
|
190
|
+
return context_id
|
|
191
|
+
|
|
192
|
+
async def get_context(
|
|
193
|
+
self, context_id: str, requester_id: str, version: Optional[int] = None
|
|
194
|
+
) -> Optional[Dict[str, Any]]:
|
|
195
|
+
"""
|
|
196
|
+
Get context data.
|
|
197
|
+
|
|
198
|
+
Args:
|
|
199
|
+
context_id: ID of the context
|
|
200
|
+
requester_id: ID of the requester
|
|
201
|
+
version: Optional specific version to retrieve
|
|
202
|
+
|
|
203
|
+
Returns:
|
|
204
|
+
Context data or None if not found/unauthorized
|
|
205
|
+
"""
|
|
206
|
+
context = self.contexts.get(context_id)
|
|
207
|
+
if not context:
|
|
208
|
+
return None
|
|
209
|
+
|
|
210
|
+
# Check access control
|
|
211
|
+
if requester_id not in context.access_control:
|
|
212
|
+
logger.warning(f"Access denied for {requester_id} to context {context_id}")
|
|
213
|
+
return None
|
|
214
|
+
|
|
215
|
+
# Return specific version or current
|
|
216
|
+
if version is not None:
|
|
217
|
+
for v in context.versions:
|
|
218
|
+
if v.version_number == version:
|
|
219
|
+
return copy.deepcopy(v.data)
|
|
220
|
+
return None
|
|
221
|
+
|
|
222
|
+
return copy.deepcopy(context.data)
|
|
223
|
+
|
|
224
|
+
async def update_context(
|
|
225
|
+
self,
|
|
226
|
+
context_id: str,
|
|
227
|
+
updater_id: str,
|
|
228
|
+
updates: Dict[str, Any],
|
|
229
|
+
conflict_strategy: Optional[ConflictResolutionStrategy] = None,
|
|
230
|
+
create_version: bool = True,
|
|
231
|
+
) -> bool:
|
|
232
|
+
"""
|
|
233
|
+
Update context data with conflict resolution.
|
|
234
|
+
|
|
235
|
+
Args:
|
|
236
|
+
context_id: ID of the context
|
|
237
|
+
updater_id: ID of the updater
|
|
238
|
+
updates: Data updates
|
|
239
|
+
conflict_strategy: Optional conflict resolution strategy
|
|
240
|
+
create_version: Whether to create a new version
|
|
241
|
+
|
|
242
|
+
Returns:
|
|
243
|
+
True if update was successful
|
|
244
|
+
"""
|
|
245
|
+
context = self.contexts.get(context_id)
|
|
246
|
+
if not context:
|
|
247
|
+
logger.error(f"Context {context_id} not found")
|
|
248
|
+
return False
|
|
249
|
+
|
|
250
|
+
# Check access control
|
|
251
|
+
if updater_id not in context.access_control:
|
|
252
|
+
logger.warning(f"Access denied for {updater_id} to update context {context_id}")
|
|
253
|
+
return False
|
|
254
|
+
|
|
255
|
+
# Apply updates with conflict resolution
|
|
256
|
+
strategy = conflict_strategy or self.default_conflict_strategy
|
|
257
|
+
merged_data = await self._resolve_conflicts(
|
|
258
|
+
context.data, updates, strategy, context, updater_id
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
# Create new version if requested
|
|
262
|
+
if create_version:
|
|
263
|
+
context._create_version(merged_data, updater_id)
|
|
264
|
+
else:
|
|
265
|
+
context.data = merged_data
|
|
266
|
+
context.updated_at = datetime.utcnow()
|
|
267
|
+
|
|
268
|
+
# Notify subscribers via streaming
|
|
269
|
+
await self._notify_subscribers(context_id, merged_data, updater_id)
|
|
270
|
+
|
|
271
|
+
logger.debug(f"Updated context {context_id} by {updater_id}")
|
|
272
|
+
return True
|
|
273
|
+
|
|
274
|
+
async def _resolve_conflicts(
|
|
275
|
+
self,
|
|
276
|
+
current_data: Dict[str, Any],
|
|
277
|
+
updates: Dict[str, Any],
|
|
278
|
+
strategy: ConflictResolutionStrategy,
|
|
279
|
+
context: SharedContext,
|
|
280
|
+
updater_id: str,
|
|
281
|
+
) -> Dict[str, Any]:
|
|
282
|
+
"""Resolve conflicts between current data and updates."""
|
|
283
|
+
if strategy == ConflictResolutionStrategy.LAST_WRITE_WINS:
|
|
284
|
+
# Simply apply updates over current data
|
|
285
|
+
merged = copy.deepcopy(current_data)
|
|
286
|
+
merged.update(updates)
|
|
287
|
+
return merged
|
|
288
|
+
|
|
289
|
+
elif strategy == ConflictResolutionStrategy.FIRST_WRITE_WINS:
|
|
290
|
+
# Only add new keys, don't override existing
|
|
291
|
+
merged = copy.deepcopy(current_data)
|
|
292
|
+
for key, value in updates.items():
|
|
293
|
+
if key not in merged:
|
|
294
|
+
merged[key] = value
|
|
295
|
+
return merged
|
|
296
|
+
|
|
297
|
+
elif strategy == ConflictResolutionStrategy.MERGE:
|
|
298
|
+
# Intelligent merge based on data types
|
|
299
|
+
merged = copy.deepcopy(current_data)
|
|
300
|
+
for key, new_value in updates.items():
|
|
301
|
+
if key in merged:
|
|
302
|
+
current_value = merged[key]
|
|
303
|
+
# Merge lists
|
|
304
|
+
if isinstance(current_value, list) and isinstance(new_value, list):
|
|
305
|
+
merged[key] = current_value + [
|
|
306
|
+
item for item in new_value if item not in current_value
|
|
307
|
+
]
|
|
308
|
+
# Merge dicts
|
|
309
|
+
elif isinstance(current_value, dict) and isinstance(new_value, dict):
|
|
310
|
+
merged[key] = {**current_value, **new_value}
|
|
311
|
+
# Otherwise, last write wins
|
|
312
|
+
else:
|
|
313
|
+
merged[key] = new_value
|
|
314
|
+
else:
|
|
315
|
+
merged[key] = new_value
|
|
316
|
+
return merged
|
|
317
|
+
|
|
318
|
+
elif strategy == ConflictResolutionStrategy.TIMESTAMP_BASED:
|
|
319
|
+
# Use timestamps to determine which update wins
|
|
320
|
+
merged = copy.deepcopy(current_data)
|
|
321
|
+
current_time = datetime.utcnow()
|
|
322
|
+
for key, value in updates.items():
|
|
323
|
+
if key not in merged or context.updated_at < current_time:
|
|
324
|
+
merged[key] = value
|
|
325
|
+
return merged
|
|
326
|
+
|
|
327
|
+
else: # MANUAL
|
|
328
|
+
# Return updates as-is and log conflict for manual resolution
|
|
329
|
+
logger.warning(f"Manual conflict resolution required for context {context.context_id}")
|
|
330
|
+
return copy.deepcopy(updates)
|
|
331
|
+
|
|
332
|
+
async def subscribe_to_context(
|
|
333
|
+
self,
|
|
334
|
+
context_id: str,
|
|
335
|
+
subscriber_id: str,
|
|
336
|
+
callback: Optional[Callable] = None,
|
|
337
|
+
) -> bool:
|
|
338
|
+
"""
|
|
339
|
+
Subscribe to context updates (streaming).
|
|
340
|
+
|
|
341
|
+
Args:
|
|
342
|
+
context_id: ID of the context
|
|
343
|
+
subscriber_id: ID of the subscriber
|
|
344
|
+
callback: Optional callback for updates
|
|
345
|
+
|
|
346
|
+
Returns:
|
|
347
|
+
True if subscription was successful
|
|
348
|
+
"""
|
|
349
|
+
context = self.contexts.get(context_id)
|
|
350
|
+
if not context:
|
|
351
|
+
return False
|
|
352
|
+
|
|
353
|
+
# Check access control
|
|
354
|
+
if subscriber_id not in context.access_control:
|
|
355
|
+
logger.warning(
|
|
356
|
+
f"Access denied for {subscriber_id} to subscribe to context {context_id}"
|
|
357
|
+
)
|
|
358
|
+
return False
|
|
359
|
+
|
|
360
|
+
context.subscribers.add(subscriber_id)
|
|
361
|
+
|
|
362
|
+
if callback:
|
|
363
|
+
self.update_callbacks[context_id].append(callback)
|
|
364
|
+
|
|
365
|
+
logger.debug(f"Agent {subscriber_id} subscribed to context {context_id}")
|
|
366
|
+
return True
|
|
367
|
+
|
|
368
|
+
async def unsubscribe_from_context(
|
|
369
|
+
self,
|
|
370
|
+
context_id: str,
|
|
371
|
+
subscriber_id: str,
|
|
372
|
+
callback: Optional[Callable] = None,
|
|
373
|
+
) -> bool:
|
|
374
|
+
"""
|
|
375
|
+
Unsubscribe from context updates.
|
|
376
|
+
|
|
377
|
+
Args:
|
|
378
|
+
context_id: ID of the context
|
|
379
|
+
subscriber_id: ID of the subscriber
|
|
380
|
+
callback: Optional callback to remove
|
|
381
|
+
|
|
382
|
+
Returns:
|
|
383
|
+
True if unsubscription was successful
|
|
384
|
+
"""
|
|
385
|
+
context = self.contexts.get(context_id)
|
|
386
|
+
if not context:
|
|
387
|
+
return False
|
|
388
|
+
|
|
389
|
+
context.subscribers.discard(subscriber_id)
|
|
390
|
+
|
|
391
|
+
if callback and context_id in self.update_callbacks:
|
|
392
|
+
if callback in self.update_callbacks[context_id]:
|
|
393
|
+
self.update_callbacks[context_id].remove(callback)
|
|
394
|
+
|
|
395
|
+
logger.debug(f"Agent {subscriber_id} unsubscribed from context {context_id}")
|
|
396
|
+
return True
|
|
397
|
+
|
|
398
|
+
async def _notify_subscribers(
|
|
399
|
+
self, context_id: str, updated_data: Dict[str, Any], updater_id: str
|
|
400
|
+
) -> None:
|
|
401
|
+
"""Notify subscribers of context updates."""
|
|
402
|
+
context = self.contexts.get(context_id)
|
|
403
|
+
if not context:
|
|
404
|
+
return
|
|
405
|
+
|
|
406
|
+
update_notification = {
|
|
407
|
+
"context_id": context_id,
|
|
408
|
+
"updater_id": updater_id,
|
|
409
|
+
"data": copy.deepcopy(updated_data),
|
|
410
|
+
"version": context.current_version,
|
|
411
|
+
"timestamp": datetime.utcnow().isoformat(),
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
# Execute callbacks
|
|
415
|
+
if context_id in self.update_callbacks:
|
|
416
|
+
for callback in self.update_callbacks[context_id]:
|
|
417
|
+
try:
|
|
418
|
+
if asyncio.iscoroutinefunction(callback):
|
|
419
|
+
await callback(update_notification)
|
|
420
|
+
else:
|
|
421
|
+
callback(update_notification)
|
|
422
|
+
except Exception as e:
|
|
423
|
+
logger.error(f"Error executing context update callback: {e}")
|
|
424
|
+
|
|
425
|
+
async def grant_access(self, context_id: str, granter_id: str, grantee_id: str) -> bool:
|
|
426
|
+
"""
|
|
427
|
+
Grant access to a context.
|
|
428
|
+
|
|
429
|
+
Args:
|
|
430
|
+
context_id: ID of the context
|
|
431
|
+
granter_id: ID of the agent granting access (must be owner)
|
|
432
|
+
grantee_id: ID of the agent being granted access
|
|
433
|
+
|
|
434
|
+
Returns:
|
|
435
|
+
True if access was granted
|
|
436
|
+
"""
|
|
437
|
+
context = self.contexts.get(context_id)
|
|
438
|
+
if not context:
|
|
439
|
+
return False
|
|
440
|
+
|
|
441
|
+
# Only owner can grant access
|
|
442
|
+
if granter_id != context.owner_id:
|
|
443
|
+
logger.warning(f"Only owner can grant access to context {context_id}")
|
|
444
|
+
return False
|
|
445
|
+
|
|
446
|
+
context.access_control.add(grantee_id)
|
|
447
|
+
logger.info(f"Granted access to {grantee_id} for context {context_id}")
|
|
448
|
+
return True
|
|
449
|
+
|
|
450
|
+
async def revoke_access(self, context_id: str, revoker_id: str, revokee_id: str) -> bool:
|
|
451
|
+
"""
|
|
452
|
+
Revoke access to a context.
|
|
453
|
+
|
|
454
|
+
Args:
|
|
455
|
+
context_id: ID of the context
|
|
456
|
+
revoker_id: ID of the agent revoking access (must be owner)
|
|
457
|
+
revokee_id: ID of the agent losing access
|
|
458
|
+
|
|
459
|
+
Returns:
|
|
460
|
+
True if access was revoked
|
|
461
|
+
"""
|
|
462
|
+
context = self.contexts.get(context_id)
|
|
463
|
+
if not context:
|
|
464
|
+
return False
|
|
465
|
+
|
|
466
|
+
# Only owner can revoke access
|
|
467
|
+
if revoker_id != context.owner_id:
|
|
468
|
+
logger.warning(f"Only owner can revoke access to context {context_id}")
|
|
469
|
+
return False
|
|
470
|
+
|
|
471
|
+
# Can't revoke owner's access
|
|
472
|
+
if revokee_id == context.owner_id:
|
|
473
|
+
logger.warning("Cannot revoke owner's access to context")
|
|
474
|
+
return False
|
|
475
|
+
|
|
476
|
+
context.access_control.discard(revokee_id)
|
|
477
|
+
context.subscribers.discard(revokee_id)
|
|
478
|
+
logger.info(f"Revoked access from {revokee_id} for context {context_id}")
|
|
479
|
+
return True
|
|
480
|
+
|
|
481
|
+
async def get_version_history(
|
|
482
|
+
self, context_id: str, requester_id: str
|
|
483
|
+
) -> Optional[List[Dict[str, Any]]]:
|
|
484
|
+
"""
|
|
485
|
+
Get version history for a context.
|
|
486
|
+
|
|
487
|
+
Args:
|
|
488
|
+
context_id: ID of the context
|
|
489
|
+
requester_id: ID of the requester
|
|
490
|
+
|
|
491
|
+
Returns:
|
|
492
|
+
List of version information or None if unauthorized
|
|
493
|
+
"""
|
|
494
|
+
context = self.contexts.get(context_id)
|
|
495
|
+
if not context:
|
|
496
|
+
return None
|
|
497
|
+
|
|
498
|
+
# Check access control
|
|
499
|
+
if requester_id not in context.access_control:
|
|
500
|
+
return None
|
|
501
|
+
|
|
502
|
+
history = []
|
|
503
|
+
for version in context.versions:
|
|
504
|
+
history.append(
|
|
505
|
+
{
|
|
506
|
+
"version_number": version.version_number,
|
|
507
|
+
"author_id": version.author_id,
|
|
508
|
+
"timestamp": version.timestamp.isoformat(),
|
|
509
|
+
"parent_version": version.parent_version,
|
|
510
|
+
"metadata": version.metadata,
|
|
511
|
+
}
|
|
512
|
+
)
|
|
513
|
+
|
|
514
|
+
return history
|
|
515
|
+
|
|
516
|
+
async def rollback_to_version(
|
|
517
|
+
self, context_id: str, requester_id: str, target_version: int
|
|
518
|
+
) -> bool:
|
|
519
|
+
"""
|
|
520
|
+
Rollback context to a previous version.
|
|
521
|
+
|
|
522
|
+
Args:
|
|
523
|
+
context_id: ID of the context
|
|
524
|
+
requester_id: ID of the requester (must be owner)
|
|
525
|
+
target_version: Version number to rollback to
|
|
526
|
+
|
|
527
|
+
Returns:
|
|
528
|
+
True if rollback was successful
|
|
529
|
+
"""
|
|
530
|
+
context = self.contexts.get(context_id)
|
|
531
|
+
if not context:
|
|
532
|
+
return False
|
|
533
|
+
|
|
534
|
+
# Only owner can rollback
|
|
535
|
+
if requester_id != context.owner_id:
|
|
536
|
+
logger.warning(f"Only owner can rollback context {context_id}")
|
|
537
|
+
return False
|
|
538
|
+
|
|
539
|
+
# Find target version
|
|
540
|
+
target = None
|
|
541
|
+
for version in context.versions:
|
|
542
|
+
if version.version_number == target_version:
|
|
543
|
+
target = version
|
|
544
|
+
break
|
|
545
|
+
|
|
546
|
+
if not target:
|
|
547
|
+
logger.error(f"Version {target_version} not found for context {context_id}")
|
|
548
|
+
return False
|
|
549
|
+
|
|
550
|
+
# Create new version based on target (rollback is a new version)
|
|
551
|
+
context._create_version(target.data, requester_id)
|
|
552
|
+
context.metadata["rollback"] = {
|
|
553
|
+
"from_version": context.current_version - 1,
|
|
554
|
+
"to_version": target_version,
|
|
555
|
+
"timestamp": datetime.utcnow().isoformat(),
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
# Notify subscribers
|
|
559
|
+
await self._notify_subscribers(context_id, context.data, requester_id)
|
|
560
|
+
|
|
561
|
+
logger.info(f"Rolled back context {context_id} to version {target_version}")
|
|
562
|
+
return True
|
|
563
|
+
|
|
564
|
+
def get_contexts_by_scope(self, scope: ContextScope, scope_id: str) -> List[str]:
|
|
565
|
+
"""
|
|
566
|
+
Get all contexts for a specific scope.
|
|
567
|
+
|
|
568
|
+
Args:
|
|
569
|
+
scope: Scope level
|
|
570
|
+
scope_id: ID of the scope
|
|
571
|
+
|
|
572
|
+
Returns:
|
|
573
|
+
List of context IDs
|
|
574
|
+
"""
|
|
575
|
+
if scope == ContextScope.COMMUNITY:
|
|
576
|
+
return list(self.community_contexts.get(scope_id, set()))
|
|
577
|
+
elif scope == ContextScope.SESSION:
|
|
578
|
+
return list(self.session_contexts.get(scope_id, set()))
|
|
579
|
+
elif scope == ContextScope.TASK:
|
|
580
|
+
return list(self.task_contexts.get(scope_id, set()))
|
|
581
|
+
elif scope == ContextScope.AGENT:
|
|
582
|
+
return list(self.agent_contexts.get(scope_id, set()))
|
|
583
|
+
return []
|
|
584
|
+
|
|
585
|
+
def get_statistics(self) -> Dict[str, Any]:
|
|
586
|
+
"""
|
|
587
|
+
Get context manager statistics.
|
|
588
|
+
|
|
589
|
+
Returns:
|
|
590
|
+
Statistics dictionary
|
|
591
|
+
"""
|
|
592
|
+
total_versions = sum(len(ctx.versions) for ctx in self.contexts.values())
|
|
593
|
+
total_subscribers = sum(len(ctx.subscribers) for ctx in self.contexts.values())
|
|
594
|
+
|
|
595
|
+
return {
|
|
596
|
+
"total_contexts": len(self.contexts),
|
|
597
|
+
"total_versions": total_versions,
|
|
598
|
+
"total_subscribers": total_subscribers,
|
|
599
|
+
"community_contexts": sum(len(s) for s in self.community_contexts.values()),
|
|
600
|
+
"session_contexts": sum(len(s) for s in self.session_contexts.values()),
|
|
601
|
+
"task_contexts": sum(len(s) for s in self.task_contexts.values()),
|
|
602
|
+
"agent_contexts": sum(len(s) for s in self.agent_contexts.values()),
|
|
603
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Context Management Domain
|
|
3
|
+
|
|
4
|
+
This module provides advanced context and session management capabilities
|
|
5
|
+
for the Python middleware application.
|
|
6
|
+
|
|
7
|
+
Components:
|
|
8
|
+
- ContextEngine: Advanced context and session management with Redis backend
|
|
9
|
+
- Integration with TaskContext for enhanced functionality
|
|
10
|
+
- Support for BaseServiceCheckpointer and LangGraph workflows
|
|
11
|
+
|
|
12
|
+
Usage:
|
|
13
|
+
# For creating ContextEngine instances directly:
|
|
14
|
+
from aiecs.domain.context import ContextEngine
|
|
15
|
+
engine = ContextEngine(use_existing_redis=True)
|
|
16
|
+
await engine.initialize()
|
|
17
|
+
|
|
18
|
+
# For using the global singleton instance (recommended):
|
|
19
|
+
from aiecs.infrastructure.persistence import (
|
|
20
|
+
get_context_engine,
|
|
21
|
+
initialize_context_engine,
|
|
22
|
+
close_context_engine
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
# The global instance is automatically initialized in main.py lifespan
|
|
26
|
+
context_engine = get_context_engine()
|
|
27
|
+
if context_engine:
|
|
28
|
+
await context_engine.add_conversation_message(...)
|
|
29
|
+
|
|
30
|
+
Architecture Note:
|
|
31
|
+
- This package contains DOMAIN layer classes (business logic)
|
|
32
|
+
- Global instance management is in INFRASTRUCTURE layer:
|
|
33
|
+
aiecs.infrastructure.persistence.context_engine_client
|
|
34
|
+
- This separation follows Clean Architecture / DDD principles
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
from .context_engine import ContextEngine, SessionMetrics, ConversationMessage
|
|
38
|
+
from .conversation_models import (
|
|
39
|
+
ConversationParticipant,
|
|
40
|
+
ConversationSession,
|
|
41
|
+
AgentCommunicationMessage,
|
|
42
|
+
create_session_key,
|
|
43
|
+
validate_conversation_isolation_pattern,
|
|
44
|
+
)
|
|
45
|
+
from .graph_memory import GraphMemoryMixin, ContextEngineWithGraph
|
|
46
|
+
|
|
47
|
+
__all__ = [
|
|
48
|
+
"ContextEngine",
|
|
49
|
+
"SessionMetrics",
|
|
50
|
+
"ConversationMessage",
|
|
51
|
+
"ConversationParticipant",
|
|
52
|
+
"ConversationSession",
|
|
53
|
+
"AgentCommunicationMessage",
|
|
54
|
+
"create_session_key",
|
|
55
|
+
"validate_conversation_isolation_pattern",
|
|
56
|
+
"GraphMemoryMixin",
|
|
57
|
+
"ContextEngineWithGraph",
|
|
58
|
+
]
|