aiecs 1.0.1__py3-none-any.whl → 1.7.17__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 +13 -16
- aiecs/__main__.py +7 -7
- aiecs/aiecs_client.py +269 -75
- aiecs/application/executors/operation_executor.py +79 -54
- aiecs/application/knowledge_graph/__init__.py +7 -0
- aiecs/application/knowledge_graph/builder/__init__.py +37 -0
- aiecs/application/knowledge_graph/builder/data_quality.py +302 -0
- aiecs/application/knowledge_graph/builder/data_reshaping.py +293 -0
- aiecs/application/knowledge_graph/builder/document_builder.py +369 -0
- aiecs/application/knowledge_graph/builder/graph_builder.py +490 -0
- aiecs/application/knowledge_graph/builder/import_optimizer.py +396 -0
- aiecs/application/knowledge_graph/builder/schema_inference.py +462 -0
- aiecs/application/knowledge_graph/builder/schema_mapping.py +563 -0
- aiecs/application/knowledge_graph/builder/structured_pipeline.py +1384 -0
- aiecs/application/knowledge_graph/builder/text_chunker.py +317 -0
- aiecs/application/knowledge_graph/extractors/__init__.py +27 -0
- aiecs/application/knowledge_graph/extractors/base.py +98 -0
- aiecs/application/knowledge_graph/extractors/llm_entity_extractor.py +422 -0
- aiecs/application/knowledge_graph/extractors/llm_relation_extractor.py +347 -0
- aiecs/application/knowledge_graph/extractors/ner_entity_extractor.py +241 -0
- aiecs/application/knowledge_graph/fusion/__init__.py +78 -0
- aiecs/application/knowledge_graph/fusion/ab_testing.py +395 -0
- aiecs/application/knowledge_graph/fusion/abbreviation_expander.py +327 -0
- aiecs/application/knowledge_graph/fusion/alias_index.py +597 -0
- aiecs/application/knowledge_graph/fusion/alias_matcher.py +384 -0
- aiecs/application/knowledge_graph/fusion/cache_coordinator.py +343 -0
- aiecs/application/knowledge_graph/fusion/entity_deduplicator.py +433 -0
- aiecs/application/knowledge_graph/fusion/entity_linker.py +511 -0
- aiecs/application/knowledge_graph/fusion/evaluation_dataset.py +240 -0
- aiecs/application/knowledge_graph/fusion/knowledge_fusion.py +632 -0
- aiecs/application/knowledge_graph/fusion/matching_config.py +489 -0
- aiecs/application/knowledge_graph/fusion/name_normalizer.py +352 -0
- aiecs/application/knowledge_graph/fusion/relation_deduplicator.py +183 -0
- aiecs/application/knowledge_graph/fusion/semantic_name_matcher.py +464 -0
- aiecs/application/knowledge_graph/fusion/similarity_pipeline.py +534 -0
- aiecs/application/knowledge_graph/pattern_matching/__init__.py +21 -0
- aiecs/application/knowledge_graph/pattern_matching/pattern_matcher.py +342 -0
- aiecs/application/knowledge_graph/pattern_matching/query_executor.py +366 -0
- aiecs/application/knowledge_graph/profiling/__init__.py +12 -0
- aiecs/application/knowledge_graph/profiling/query_plan_visualizer.py +195 -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 +341 -0
- aiecs/application/knowledge_graph/reasoning/inference_engine.py +500 -0
- aiecs/application/knowledge_graph/reasoning/logic_form_parser.py +163 -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 +913 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/ast_validator.py +866 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/error_handler.py +475 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/parser.py +396 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/query_context.py +208 -0
- aiecs/application/knowledge_graph/reasoning/logic_query_integration.py +170 -0
- aiecs/application/knowledge_graph/reasoning/query_planner.py +855 -0
- aiecs/application/knowledge_graph/reasoning/reasoning_engine.py +518 -0
- aiecs/application/knowledge_graph/retrieval/__init__.py +27 -0
- aiecs/application/knowledge_graph/retrieval/query_intent_classifier.py +211 -0
- aiecs/application/knowledge_graph/retrieval/retrieval_strategies.py +592 -0
- aiecs/application/knowledge_graph/retrieval/strategy_types.py +23 -0
- aiecs/application/knowledge_graph/search/__init__.py +59 -0
- aiecs/application/knowledge_graph/search/hybrid_search.py +457 -0
- aiecs/application/knowledge_graph/search/reranker.py +293 -0
- aiecs/application/knowledge_graph/search/reranker_strategies.py +535 -0
- aiecs/application/knowledge_graph/search/text_similarity.py +392 -0
- aiecs/application/knowledge_graph/traversal/__init__.py +15 -0
- aiecs/application/knowledge_graph/traversal/enhanced_traversal.py +305 -0
- aiecs/application/knowledge_graph/traversal/path_scorer.py +271 -0
- aiecs/application/knowledge_graph/validators/__init__.py +13 -0
- aiecs/application/knowledge_graph/validators/relation_validator.py +239 -0
- aiecs/application/knowledge_graph/visualization/__init__.py +11 -0
- aiecs/application/knowledge_graph/visualization/graph_visualizer.py +313 -0
- aiecs/common/__init__.py +9 -0
- aiecs/common/knowledge_graph/__init__.py +17 -0
- aiecs/common/knowledge_graph/runnable.py +471 -0
- aiecs/config/__init__.py +20 -5
- aiecs/config/config.py +762 -31
- aiecs/config/graph_config.py +131 -0
- aiecs/config/tool_config.py +435 -0
- aiecs/core/__init__.py +29 -13
- aiecs/core/interface/__init__.py +2 -2
- aiecs/core/interface/execution_interface.py +22 -22
- aiecs/core/interface/storage_interface.py +37 -88
- aiecs/core/registry/__init__.py +31 -0
- aiecs/core/registry/service_registry.py +92 -0
- aiecs/domain/__init__.py +270 -1
- aiecs/domain/agent/__init__.py +191 -0
- aiecs/domain/agent/base_agent.py +3949 -0
- aiecs/domain/agent/exceptions.py +99 -0
- aiecs/domain/agent/graph_aware_mixin.py +569 -0
- aiecs/domain/agent/hybrid_agent.py +1731 -0
- aiecs/domain/agent/integration/__init__.py +29 -0
- aiecs/domain/agent/integration/context_compressor.py +216 -0
- aiecs/domain/agent/integration/context_engine_adapter.py +587 -0
- aiecs/domain/agent/integration/protocols.py +281 -0
- aiecs/domain/agent/integration/retry_policy.py +218 -0
- aiecs/domain/agent/integration/role_config.py +213 -0
- aiecs/domain/agent/knowledge_aware_agent.py +1892 -0
- aiecs/domain/agent/lifecycle.py +291 -0
- aiecs/domain/agent/llm_agent.py +692 -0
- aiecs/domain/agent/memory/__init__.py +12 -0
- aiecs/domain/agent/memory/conversation.py +1124 -0
- aiecs/domain/agent/migration/__init__.py +14 -0
- aiecs/domain/agent/migration/conversion.py +163 -0
- aiecs/domain/agent/migration/legacy_wrapper.py +86 -0
- aiecs/domain/agent/models.py +894 -0
- aiecs/domain/agent/observability.py +479 -0
- aiecs/domain/agent/persistence.py +449 -0
- aiecs/domain/agent/prompts/__init__.py +29 -0
- aiecs/domain/agent/prompts/builder.py +159 -0
- aiecs/domain/agent/prompts/formatters.py +187 -0
- aiecs/domain/agent/prompts/template.py +255 -0
- aiecs/domain/agent/registry.py +253 -0
- aiecs/domain/agent/tool_agent.py +444 -0
- aiecs/domain/agent/tools/__init__.py +15 -0
- aiecs/domain/agent/tools/schema_generator.py +377 -0
- aiecs/domain/community/__init__.py +155 -0
- aiecs/domain/community/agent_adapter.py +469 -0
- aiecs/domain/community/analytics.py +432 -0
- aiecs/domain/community/collaborative_workflow.py +648 -0
- aiecs/domain/community/communication_hub.py +634 -0
- aiecs/domain/community/community_builder.py +320 -0
- aiecs/domain/community/community_integration.py +796 -0
- aiecs/domain/community/community_manager.py +803 -0
- aiecs/domain/community/decision_engine.py +849 -0
- aiecs/domain/community/exceptions.py +231 -0
- aiecs/domain/community/models/__init__.py +33 -0
- aiecs/domain/community/models/community_models.py +234 -0
- aiecs/domain/community/resource_manager.py +461 -0
- aiecs/domain/community/shared_context_manager.py +589 -0
- aiecs/domain/context/__init__.py +40 -10
- aiecs/domain/context/context_engine.py +1910 -0
- aiecs/domain/context/conversation_models.py +87 -53
- aiecs/domain/context/graph_memory.py +582 -0
- aiecs/domain/execution/model.py +12 -4
- aiecs/domain/knowledge_graph/__init__.py +19 -0
- aiecs/domain/knowledge_graph/models/__init__.py +52 -0
- aiecs/domain/knowledge_graph/models/entity.py +148 -0
- aiecs/domain/knowledge_graph/models/evidence.py +178 -0
- aiecs/domain/knowledge_graph/models/inference_rule.py +184 -0
- aiecs/domain/knowledge_graph/models/path.py +171 -0
- aiecs/domain/knowledge_graph/models/path_pattern.py +171 -0
- aiecs/domain/knowledge_graph/models/query.py +261 -0
- aiecs/domain/knowledge_graph/models/query_plan.py +181 -0
- aiecs/domain/knowledge_graph/models/relation.py +202 -0
- aiecs/domain/knowledge_graph/schema/__init__.py +23 -0
- aiecs/domain/knowledge_graph/schema/entity_type.py +131 -0
- aiecs/domain/knowledge_graph/schema/graph_schema.py +253 -0
- aiecs/domain/knowledge_graph/schema/property_schema.py +143 -0
- aiecs/domain/knowledge_graph/schema/relation_type.py +163 -0
- aiecs/domain/knowledge_graph/schema/schema_manager.py +691 -0
- aiecs/domain/knowledge_graph/schema/type_enums.py +209 -0
- aiecs/domain/task/dsl_processor.py +172 -56
- aiecs/domain/task/model.py +20 -8
- aiecs/domain/task/task_context.py +27 -24
- aiecs/infrastructure/__init__.py +0 -2
- aiecs/infrastructure/graph_storage/__init__.py +11 -0
- aiecs/infrastructure/graph_storage/base.py +837 -0
- aiecs/infrastructure/graph_storage/batch_operations.py +458 -0
- aiecs/infrastructure/graph_storage/cache.py +424 -0
- aiecs/infrastructure/graph_storage/distributed.py +223 -0
- aiecs/infrastructure/graph_storage/error_handling.py +380 -0
- aiecs/infrastructure/graph_storage/graceful_degradation.py +294 -0
- aiecs/infrastructure/graph_storage/health_checks.py +378 -0
- aiecs/infrastructure/graph_storage/in_memory.py +1197 -0
- aiecs/infrastructure/graph_storage/index_optimization.py +446 -0
- aiecs/infrastructure/graph_storage/lazy_loading.py +431 -0
- aiecs/infrastructure/graph_storage/metrics.py +344 -0
- aiecs/infrastructure/graph_storage/migration.py +400 -0
- aiecs/infrastructure/graph_storage/pagination.py +483 -0
- aiecs/infrastructure/graph_storage/performance_monitoring.py +456 -0
- aiecs/infrastructure/graph_storage/postgres.py +1563 -0
- aiecs/infrastructure/graph_storage/property_storage.py +353 -0
- aiecs/infrastructure/graph_storage/protocols.py +76 -0
- aiecs/infrastructure/graph_storage/query_optimizer.py +642 -0
- aiecs/infrastructure/graph_storage/schema_cache.py +290 -0
- aiecs/infrastructure/graph_storage/sqlite.py +1373 -0
- aiecs/infrastructure/graph_storage/streaming.py +487 -0
- aiecs/infrastructure/graph_storage/tenant.py +412 -0
- aiecs/infrastructure/messaging/celery_task_manager.py +92 -54
- aiecs/infrastructure/messaging/websocket_manager.py +51 -35
- aiecs/infrastructure/monitoring/__init__.py +22 -0
- aiecs/infrastructure/monitoring/executor_metrics.py +45 -11
- aiecs/infrastructure/monitoring/global_metrics_manager.py +212 -0
- aiecs/infrastructure/monitoring/structured_logger.py +3 -7
- aiecs/infrastructure/monitoring/tracing_manager.py +63 -35
- aiecs/infrastructure/persistence/__init__.py +14 -1
- aiecs/infrastructure/persistence/context_engine_client.py +184 -0
- aiecs/infrastructure/persistence/database_manager.py +67 -43
- aiecs/infrastructure/persistence/file_storage.py +180 -103
- aiecs/infrastructure/persistence/redis_client.py +74 -21
- aiecs/llm/__init__.py +73 -25
- aiecs/llm/callbacks/__init__.py +11 -0
- aiecs/llm/{custom_callbacks.py → callbacks/custom_callbacks.py} +26 -19
- aiecs/llm/client_factory.py +230 -37
- aiecs/llm/client_resolver.py +155 -0
- aiecs/llm/clients/__init__.py +38 -0
- aiecs/llm/clients/base_client.py +328 -0
- aiecs/llm/clients/google_function_calling_mixin.py +415 -0
- aiecs/llm/clients/googleai_client.py +314 -0
- aiecs/llm/clients/openai_client.py +158 -0
- aiecs/llm/clients/openai_compatible_mixin.py +367 -0
- aiecs/llm/clients/vertex_client.py +1186 -0
- aiecs/llm/clients/xai_client.py +201 -0
- aiecs/llm/config/__init__.py +51 -0
- aiecs/llm/config/config_loader.py +272 -0
- aiecs/llm/config/config_validator.py +206 -0
- aiecs/llm/config/model_config.py +143 -0
- aiecs/llm/protocols.py +149 -0
- aiecs/llm/utils/__init__.py +10 -0
- aiecs/llm/utils/validate_config.py +89 -0
- aiecs/main.py +140 -121
- aiecs/scripts/aid/VERSION_MANAGEMENT.md +138 -0
- aiecs/scripts/aid/__init__.py +19 -0
- aiecs/scripts/aid/module_checker.py +499 -0
- aiecs/scripts/aid/version_manager.py +235 -0
- aiecs/scripts/{DEPENDENCY_SYSTEM_SUMMARY.md → dependance_check/DEPENDENCY_SYSTEM_SUMMARY.md} +1 -0
- aiecs/scripts/{README_DEPENDENCY_CHECKER.md → dependance_check/README_DEPENDENCY_CHECKER.md} +1 -0
- aiecs/scripts/dependance_check/__init__.py +15 -0
- aiecs/scripts/dependance_check/dependency_checker.py +1835 -0
- aiecs/scripts/{dependency_fixer.py → dependance_check/dependency_fixer.py} +192 -90
- aiecs/scripts/{download_nlp_data.py → dependance_check/download_nlp_data.py} +203 -71
- aiecs/scripts/dependance_patch/__init__.py +7 -0
- aiecs/scripts/dependance_patch/fix_weasel/__init__.py +11 -0
- aiecs/scripts/{fix_weasel_validator.py → dependance_patch/fix_weasel/fix_weasel_validator.py} +21 -14
- aiecs/scripts/{patch_weasel_library.sh → dependance_patch/fix_weasel/patch_weasel_library.sh} +1 -1
- aiecs/scripts/knowledge_graph/__init__.py +3 -0
- aiecs/scripts/knowledge_graph/run_threshold_experiments.py +212 -0
- aiecs/scripts/migrations/multi_tenancy/README.md +142 -0
- aiecs/scripts/tools_develop/README.md +671 -0
- aiecs/scripts/tools_develop/README_CONFIG_CHECKER.md +273 -0
- aiecs/scripts/tools_develop/TOOLS_CONFIG_GUIDE.md +1287 -0
- aiecs/scripts/tools_develop/TOOL_AUTO_DISCOVERY.md +234 -0
- aiecs/scripts/tools_develop/__init__.py +21 -0
- aiecs/scripts/tools_develop/check_all_tools_config.py +548 -0
- aiecs/scripts/tools_develop/check_type_annotations.py +257 -0
- aiecs/scripts/tools_develop/pre-commit-schema-coverage.sh +66 -0
- aiecs/scripts/tools_develop/schema_coverage.py +511 -0
- aiecs/scripts/tools_develop/validate_tool_schemas.py +475 -0
- aiecs/scripts/tools_develop/verify_executor_config_fix.py +98 -0
- aiecs/scripts/tools_develop/verify_tools.py +352 -0
- aiecs/tasks/__init__.py +0 -1
- aiecs/tasks/worker.py +115 -47
- aiecs/tools/__init__.py +194 -72
- aiecs/tools/apisource/__init__.py +99 -0
- aiecs/tools/apisource/intelligence/__init__.py +19 -0
- aiecs/tools/apisource/intelligence/data_fusion.py +632 -0
- aiecs/tools/apisource/intelligence/query_analyzer.py +417 -0
- aiecs/tools/apisource/intelligence/search_enhancer.py +385 -0
- aiecs/tools/apisource/monitoring/__init__.py +9 -0
- aiecs/tools/apisource/monitoring/metrics.py +330 -0
- aiecs/tools/apisource/providers/__init__.py +112 -0
- aiecs/tools/apisource/providers/base.py +671 -0
- aiecs/tools/apisource/providers/census.py +397 -0
- aiecs/tools/apisource/providers/fred.py +535 -0
- aiecs/tools/apisource/providers/newsapi.py +409 -0
- aiecs/tools/apisource/providers/worldbank.py +352 -0
- aiecs/tools/apisource/reliability/__init__.py +12 -0
- aiecs/tools/apisource/reliability/error_handler.py +363 -0
- aiecs/tools/apisource/reliability/fallback_strategy.py +376 -0
- aiecs/tools/apisource/tool.py +832 -0
- aiecs/tools/apisource/utils/__init__.py +9 -0
- aiecs/tools/apisource/utils/validators.py +334 -0
- aiecs/tools/base_tool.py +415 -21
- aiecs/tools/docs/__init__.py +121 -0
- aiecs/tools/docs/ai_document_orchestrator.py +607 -0
- aiecs/tools/docs/ai_document_writer_orchestrator.py +2350 -0
- aiecs/tools/docs/content_insertion_tool.py +1320 -0
- aiecs/tools/docs/document_creator_tool.py +1464 -0
- aiecs/tools/docs/document_layout_tool.py +1160 -0
- aiecs/tools/docs/document_parser_tool.py +1016 -0
- aiecs/tools/docs/document_writer_tool.py +2008 -0
- aiecs/tools/knowledge_graph/__init__.py +17 -0
- aiecs/tools/knowledge_graph/graph_reasoning_tool.py +807 -0
- aiecs/tools/knowledge_graph/graph_search_tool.py +944 -0
- aiecs/tools/knowledge_graph/kg_builder_tool.py +524 -0
- aiecs/tools/langchain_adapter.py +300 -138
- aiecs/tools/schema_generator.py +455 -0
- aiecs/tools/search_tool/__init__.py +100 -0
- aiecs/tools/search_tool/analyzers.py +581 -0
- aiecs/tools/search_tool/cache.py +264 -0
- aiecs/tools/search_tool/constants.py +128 -0
- aiecs/tools/search_tool/context.py +224 -0
- aiecs/tools/search_tool/core.py +778 -0
- aiecs/tools/search_tool/deduplicator.py +119 -0
- aiecs/tools/search_tool/error_handler.py +242 -0
- aiecs/tools/search_tool/metrics.py +343 -0
- aiecs/tools/search_tool/rate_limiter.py +172 -0
- aiecs/tools/search_tool/schemas.py +275 -0
- aiecs/tools/statistics/__init__.py +80 -0
- aiecs/tools/statistics/ai_data_analysis_orchestrator.py +646 -0
- aiecs/tools/statistics/ai_insight_generator_tool.py +508 -0
- aiecs/tools/statistics/ai_report_orchestrator_tool.py +684 -0
- aiecs/tools/statistics/data_loader_tool.py +555 -0
- aiecs/tools/statistics/data_profiler_tool.py +638 -0
- aiecs/tools/statistics/data_transformer_tool.py +580 -0
- aiecs/tools/statistics/data_visualizer_tool.py +498 -0
- aiecs/tools/statistics/model_trainer_tool.py +507 -0
- aiecs/tools/statistics/statistical_analyzer_tool.py +472 -0
- aiecs/tools/task_tools/__init__.py +49 -36
- aiecs/tools/task_tools/chart_tool.py +200 -184
- aiecs/tools/task_tools/classfire_tool.py +268 -267
- aiecs/tools/task_tools/image_tool.py +220 -141
- aiecs/tools/task_tools/office_tool.py +226 -146
- aiecs/tools/task_tools/pandas_tool.py +477 -121
- aiecs/tools/task_tools/report_tool.py +390 -142
- aiecs/tools/task_tools/research_tool.py +149 -79
- aiecs/tools/task_tools/scraper_tool.py +339 -145
- aiecs/tools/task_tools/stats_tool.py +448 -209
- aiecs/tools/temp_file_manager.py +26 -24
- aiecs/tools/tool_executor/__init__.py +18 -16
- aiecs/tools/tool_executor/tool_executor.py +364 -52
- aiecs/utils/LLM_output_structor.py +74 -48
- aiecs/utils/__init__.py +14 -3
- aiecs/utils/base_callback.py +0 -3
- aiecs/utils/cache_provider.py +696 -0
- aiecs/utils/execution_utils.py +50 -31
- aiecs/utils/prompt_loader.py +1 -0
- aiecs/utils/token_usage_repository.py +37 -11
- aiecs/ws/socket_server.py +14 -4
- {aiecs-1.0.1.dist-info → aiecs-1.7.17.dist-info}/METADATA +52 -15
- aiecs-1.7.17.dist-info/RECORD +337 -0
- aiecs-1.7.17.dist-info/entry_points.txt +13 -0
- aiecs/config/registry.py +0 -19
- aiecs/domain/context/content_engine.py +0 -982
- aiecs/llm/base_client.py +0 -99
- aiecs/llm/openai_client.py +0 -125
- aiecs/llm/vertex_client.py +0 -186
- aiecs/llm/xai_client.py +0 -184
- aiecs/scripts/dependency_checker.py +0 -857
- aiecs/scripts/quick_dependency_check.py +0 -269
- aiecs/tools/task_tools/search_api.py +0 -7
- aiecs-1.0.1.dist-info/RECORD +0 -90
- aiecs-1.0.1.dist-info/entry_points.txt +0 -7
- /aiecs/scripts/{setup_nlp_data.sh → dependance_check/setup_nlp_data.sh} +0 -0
- /aiecs/scripts/{README_WEASEL_PATCH.md → dependance_patch/fix_weasel/README_WEASEL_PATCH.md} +0 -0
- /aiecs/scripts/{fix_weasel_validator.sh → dependance_patch/fix_weasel/fix_weasel_validator.sh} +0 -0
- /aiecs/scripts/{run_weasel_patch.sh → dependance_patch/fix_weasel/run_weasel_patch.sh} +0 -0
- {aiecs-1.0.1.dist-info → aiecs-1.7.17.dist-info}/WHEEL +0 -0
- {aiecs-1.0.1.dist-info → aiecs-1.7.17.dist-info}/licenses/LICENSE +0 -0
- {aiecs-1.0.1.dist-info → aiecs-1.7.17.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Global ContextEngine Manager
|
|
3
|
+
|
|
4
|
+
This module provides a singleton ContextEngine instance that can be shared
|
|
5
|
+
across all components in the application. It follows the same pattern as
|
|
6
|
+
the Redis client initialization in aiecs.infrastructure.persistence.redis_client.
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
# In main.py startup:
|
|
10
|
+
await initialize_context_engine()
|
|
11
|
+
|
|
12
|
+
# In any component:
|
|
13
|
+
from aiecs.infrastructure.persistence.context_engine_client import get_context_engine
|
|
14
|
+
context_engine = get_context_engine()
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import logging
|
|
18
|
+
from typing import Optional, TYPE_CHECKING
|
|
19
|
+
import asyncio
|
|
20
|
+
|
|
21
|
+
if TYPE_CHECKING:
|
|
22
|
+
from aiecs.domain.context.context_engine import ContextEngine
|
|
23
|
+
|
|
24
|
+
logger = logging.getLogger(__name__)
|
|
25
|
+
|
|
26
|
+
# Global singleton instance
|
|
27
|
+
_global_context_engine: Optional["ContextEngine"] = None
|
|
28
|
+
_initialization_lock = asyncio.Lock()
|
|
29
|
+
_initialized = False
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _get_context_engine_class():
|
|
33
|
+
"""Lazy import of ContextEngine to avoid circular dependencies."""
|
|
34
|
+
try:
|
|
35
|
+
from aiecs.domain.context.context_engine import ContextEngine
|
|
36
|
+
|
|
37
|
+
return ContextEngine
|
|
38
|
+
except ImportError as e:
|
|
39
|
+
logger.warning(f"ContextEngine not available - {e}")
|
|
40
|
+
return None
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
async def initialize_context_engine(
|
|
44
|
+
use_existing_redis: bool = True,
|
|
45
|
+
) -> Optional["ContextEngine"]:
|
|
46
|
+
"""
|
|
47
|
+
Initialize the global ContextEngine instance.
|
|
48
|
+
|
|
49
|
+
This should be called once during application startup (in main.py lifespan).
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
use_existing_redis: Whether to use existing Redis client (default: True)
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
The initialized ContextEngine instance or None if initialization fails
|
|
56
|
+
|
|
57
|
+
Example:
|
|
58
|
+
@asynccontextmanager
|
|
59
|
+
async def lifespan(app: FastAPI):
|
|
60
|
+
# Startup
|
|
61
|
+
await initialize_redis_client()
|
|
62
|
+
await initialize_context_engine() # Initialize after Redis
|
|
63
|
+
yield
|
|
64
|
+
# Shutdown
|
|
65
|
+
await close_context_engine()
|
|
66
|
+
await close_redis_client()
|
|
67
|
+
"""
|
|
68
|
+
global _global_context_engine, _initialized
|
|
69
|
+
|
|
70
|
+
if _initialized and _global_context_engine:
|
|
71
|
+
logger.info("ContextEngine already initialized")
|
|
72
|
+
return _global_context_engine
|
|
73
|
+
|
|
74
|
+
async with _initialization_lock:
|
|
75
|
+
# Double-check after acquiring lock
|
|
76
|
+
if _initialized and _global_context_engine:
|
|
77
|
+
return _global_context_engine
|
|
78
|
+
|
|
79
|
+
ContextEngine = _get_context_engine_class()
|
|
80
|
+
if not ContextEngine:
|
|
81
|
+
logger.error("ContextEngine class not available - cannot initialize")
|
|
82
|
+
return None
|
|
83
|
+
|
|
84
|
+
try:
|
|
85
|
+
logger.info("Initializing global ContextEngine...")
|
|
86
|
+
_global_context_engine = ContextEngine(use_existing_redis=use_existing_redis)
|
|
87
|
+
await _global_context_engine.initialize()
|
|
88
|
+
_initialized = True
|
|
89
|
+
logger.info("✅ Global ContextEngine initialized successfully")
|
|
90
|
+
return _global_context_engine
|
|
91
|
+
|
|
92
|
+
except Exception as e:
|
|
93
|
+
logger.error(f"❌ Failed to initialize global ContextEngine: {e}")
|
|
94
|
+
logger.warning("Application will continue without ContextEngine (degraded mode)")
|
|
95
|
+
_global_context_engine = None
|
|
96
|
+
_initialized = False
|
|
97
|
+
return None
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def get_context_engine() -> Optional["ContextEngine"]:
|
|
101
|
+
"""
|
|
102
|
+
Get the global ContextEngine instance.
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
The global ContextEngine instance or None if not initialized
|
|
106
|
+
|
|
107
|
+
Example:
|
|
108
|
+
from aiecs.infrastructure.persistence.context_engine_client import get_context_engine
|
|
109
|
+
|
|
110
|
+
context_engine = get_context_engine()
|
|
111
|
+
if context_engine:
|
|
112
|
+
await context_engine.add_conversation_message(...)
|
|
113
|
+
else:
|
|
114
|
+
# Fallback to local storage
|
|
115
|
+
logger.warning("ContextEngine not available")
|
|
116
|
+
"""
|
|
117
|
+
if not _initialized:
|
|
118
|
+
logger.warning("ContextEngine not initialized. Call initialize_context_engine() " "during application startup.")
|
|
119
|
+
return _global_context_engine
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
async def close_context_engine() -> None:
|
|
123
|
+
"""
|
|
124
|
+
Close and cleanup the global ContextEngine instance.
|
|
125
|
+
|
|
126
|
+
This should be called during application shutdown (in main.py lifespan).
|
|
127
|
+
|
|
128
|
+
Example:
|
|
129
|
+
@asynccontextmanager
|
|
130
|
+
async def lifespan(app: FastAPI):
|
|
131
|
+
# Startup
|
|
132
|
+
await initialize_context_engine()
|
|
133
|
+
yield
|
|
134
|
+
# Shutdown
|
|
135
|
+
await close_context_engine()
|
|
136
|
+
"""
|
|
137
|
+
global _global_context_engine, _initialized
|
|
138
|
+
|
|
139
|
+
async with _initialization_lock:
|
|
140
|
+
if _global_context_engine:
|
|
141
|
+
try:
|
|
142
|
+
logger.info("Closing global ContextEngine...")
|
|
143
|
+
# ContextEngine cleanup if needed
|
|
144
|
+
if hasattr(_global_context_engine, "close"):
|
|
145
|
+
await _global_context_engine.close()
|
|
146
|
+
logger.info("✅ Global ContextEngine closed successfully")
|
|
147
|
+
except Exception as e:
|
|
148
|
+
logger.error(f"Error closing ContextEngine: {e}")
|
|
149
|
+
finally:
|
|
150
|
+
_global_context_engine = None
|
|
151
|
+
_initialized = False
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def is_context_engine_initialized() -> bool:
|
|
155
|
+
"""
|
|
156
|
+
Check if the global ContextEngine is initialized.
|
|
157
|
+
|
|
158
|
+
Returns:
|
|
159
|
+
True if ContextEngine is initialized and available, False otherwise
|
|
160
|
+
"""
|
|
161
|
+
return _initialized and _global_context_engine is not None
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
# Convenience function for testing
|
|
165
|
+
async def reset_context_engine() -> None:
|
|
166
|
+
"""
|
|
167
|
+
Reset the global ContextEngine instance.
|
|
168
|
+
|
|
169
|
+
This is primarily for testing purposes to allow re-initialization.
|
|
170
|
+
Should NOT be used in production code.
|
|
171
|
+
"""
|
|
172
|
+
global _global_context_engine, _initialized
|
|
173
|
+
|
|
174
|
+
async with _initialization_lock:
|
|
175
|
+
if _global_context_engine:
|
|
176
|
+
try:
|
|
177
|
+
if hasattr(_global_context_engine, "close"):
|
|
178
|
+
await _global_context_engine.close()
|
|
179
|
+
except Exception as e:
|
|
180
|
+
logger.warning(f"Error during ContextEngine reset: {e}")
|
|
181
|
+
|
|
182
|
+
_global_context_engine = None
|
|
183
|
+
_initialized = False
|
|
184
|
+
logger.info("ContextEngine reset completed")
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import asyncpg
|
|
1
|
+
import asyncpg # type: ignore[import-untyped]
|
|
2
2
|
import json
|
|
3
3
|
import logging
|
|
4
4
|
from datetime import datetime
|
|
@@ -41,11 +41,7 @@ class DatabaseManager:
|
|
|
41
41
|
async def init_connection_pool(self, min_size: int = 10, max_size: int = 20):
|
|
42
42
|
"""Initialize database connection pool"""
|
|
43
43
|
try:
|
|
44
|
-
self.connection_pool = await asyncpg.create_pool(
|
|
45
|
-
**self.db_config,
|
|
46
|
-
min_size=min_size,
|
|
47
|
-
max_size=max_size
|
|
48
|
-
)
|
|
44
|
+
self.connection_pool = await asyncpg.create_pool(**self.db_config, min_size=min_size, max_size=max_size)
|
|
49
45
|
logger.info("Database connection pool initialized successfully")
|
|
50
46
|
except Exception as e:
|
|
51
47
|
logger.error(f"Failed to initialize database connection pool: {e}")
|
|
@@ -80,7 +76,8 @@ class DatabaseManager:
|
|
|
80
76
|
|
|
81
77
|
async def _create_tables(self, conn):
|
|
82
78
|
"""Create database tables"""
|
|
83
|
-
await conn.execute(
|
|
79
|
+
await conn.execute(
|
|
80
|
+
"""
|
|
84
81
|
CREATE TABLE IF NOT EXISTS task_history (
|
|
85
82
|
id SERIAL PRIMARY KEY,
|
|
86
83
|
user_id TEXT NOT NULL,
|
|
@@ -94,9 +91,16 @@ class DatabaseManager:
|
|
|
94
91
|
CREATE INDEX IF NOT EXISTS idx_task_history_task_id ON task_history (task_id);
|
|
95
92
|
CREATE INDEX IF NOT EXISTS idx_task_history_status ON task_history (status);
|
|
96
93
|
CREATE INDEX IF NOT EXISTS idx_task_history_timestamp ON task_history (timestamp);
|
|
97
|
-
|
|
94
|
+
"""
|
|
95
|
+
)
|
|
98
96
|
|
|
99
|
-
async def save_task_history(
|
|
97
|
+
async def save_task_history(
|
|
98
|
+
self,
|
|
99
|
+
user_id: str,
|
|
100
|
+
task_id: str,
|
|
101
|
+
step: int,
|
|
102
|
+
step_result: TaskStepResult,
|
|
103
|
+
):
|
|
100
104
|
"""Save task execution history"""
|
|
101
105
|
if not self._initialized:
|
|
102
106
|
await self.init_database_schema()
|
|
@@ -105,15 +109,25 @@ class DatabaseManager:
|
|
|
105
109
|
if self.connection_pool:
|
|
106
110
|
async with self.connection_pool.acquire() as conn:
|
|
107
111
|
await conn.execute(
|
|
108
|
-
|
|
109
|
-
user_id,
|
|
112
|
+
"INSERT INTO task_history (user_id, task_id, step, result, timestamp, status) VALUES ($1, $2, $3, $4, $5, $6)",
|
|
113
|
+
user_id,
|
|
114
|
+
task_id,
|
|
115
|
+
step,
|
|
116
|
+
json.dumps(step_result.dict()),
|
|
117
|
+
datetime.now(),
|
|
118
|
+
step_result.status,
|
|
110
119
|
)
|
|
111
120
|
else:
|
|
112
121
|
conn = await asyncpg.connect(**self.db_config)
|
|
113
122
|
try:
|
|
114
123
|
await conn.execute(
|
|
115
|
-
|
|
116
|
-
user_id,
|
|
124
|
+
"INSERT INTO task_history (user_id, task_id, step, result, timestamp, status) VALUES ($1, $2, $3, $4, $5, $6)",
|
|
125
|
+
user_id,
|
|
126
|
+
task_id,
|
|
127
|
+
step,
|
|
128
|
+
json.dumps(step_result.dict()),
|
|
129
|
+
datetime.now(),
|
|
130
|
+
step_result.status,
|
|
117
131
|
)
|
|
118
132
|
finally:
|
|
119
133
|
await conn.close()
|
|
@@ -133,25 +147,27 @@ class DatabaseManager:
|
|
|
133
147
|
if self.connection_pool:
|
|
134
148
|
async with self.connection_pool.acquire() as conn:
|
|
135
149
|
records = await conn.fetch(
|
|
136
|
-
|
|
137
|
-
user_id,
|
|
150
|
+
"SELECT step, result, timestamp, status FROM task_history WHERE user_id = $1 AND task_id = $2 ORDER BY step ASC",
|
|
151
|
+
user_id,
|
|
152
|
+
task_id,
|
|
138
153
|
)
|
|
139
154
|
else:
|
|
140
155
|
conn = await asyncpg.connect(**self.db_config)
|
|
141
156
|
try:
|
|
142
157
|
records = await conn.fetch(
|
|
143
|
-
|
|
144
|
-
user_id,
|
|
158
|
+
"SELECT step, result, timestamp, status FROM task_history WHERE user_id = $1 AND task_id = $2 ORDER BY step ASC",
|
|
159
|
+
user_id,
|
|
160
|
+
task_id,
|
|
145
161
|
)
|
|
146
162
|
finally:
|
|
147
163
|
await conn.close()
|
|
148
164
|
|
|
149
165
|
return [
|
|
150
166
|
{
|
|
151
|
-
"step": r[
|
|
152
|
-
"result": json.loads(r[
|
|
153
|
-
"timestamp": r[
|
|
154
|
-
"status": r[
|
|
167
|
+
"step": r["step"],
|
|
168
|
+
"result": json.loads(r["result"]),
|
|
169
|
+
"timestamp": r["timestamp"].isoformat(),
|
|
170
|
+
"status": r["status"],
|
|
155
171
|
}
|
|
156
172
|
for r in records
|
|
157
173
|
]
|
|
@@ -168,15 +184,19 @@ class DatabaseManager:
|
|
|
168
184
|
if self.connection_pool:
|
|
169
185
|
async with self.connection_pool.acquire() as conn:
|
|
170
186
|
await conn.execute(
|
|
171
|
-
|
|
172
|
-
TaskStatus.CANCELLED.value,
|
|
187
|
+
"UPDATE task_history SET status = $1 WHERE user_id = $2 AND task_id = $3",
|
|
188
|
+
TaskStatus.CANCELLED.value,
|
|
189
|
+
user_id,
|
|
190
|
+
task_id,
|
|
173
191
|
)
|
|
174
192
|
else:
|
|
175
193
|
conn = await asyncpg.connect(**self.db_config)
|
|
176
194
|
try:
|
|
177
195
|
await conn.execute(
|
|
178
|
-
|
|
179
|
-
TaskStatus.CANCELLED.value,
|
|
196
|
+
"UPDATE task_history SET status = $1 WHERE user_id = $2 AND task_id = $3",
|
|
197
|
+
TaskStatus.CANCELLED.value,
|
|
198
|
+
user_id,
|
|
199
|
+
task_id,
|
|
180
200
|
)
|
|
181
201
|
finally:
|
|
182
202
|
await conn.close()
|
|
@@ -196,20 +216,22 @@ class DatabaseManager:
|
|
|
196
216
|
if self.connection_pool:
|
|
197
217
|
async with self.connection_pool.acquire() as conn:
|
|
198
218
|
record = await conn.fetchrow(
|
|
199
|
-
|
|
200
|
-
user_id,
|
|
219
|
+
"SELECT status FROM task_history WHERE user_id = $1 AND task_id = $2 ORDER BY step DESC LIMIT 1",
|
|
220
|
+
user_id,
|
|
221
|
+
task_id,
|
|
201
222
|
)
|
|
202
223
|
else:
|
|
203
224
|
conn = await asyncpg.connect(**self.db_config)
|
|
204
225
|
try:
|
|
205
226
|
record = await conn.fetchrow(
|
|
206
|
-
|
|
207
|
-
user_id,
|
|
227
|
+
"SELECT status FROM task_history WHERE user_id = $1 AND task_id = $2 ORDER BY step DESC LIMIT 1",
|
|
228
|
+
user_id,
|
|
229
|
+
task_id,
|
|
208
230
|
)
|
|
209
231
|
finally:
|
|
210
232
|
await conn.close()
|
|
211
233
|
|
|
212
|
-
return TaskStatus(record[
|
|
234
|
+
return TaskStatus(record["status"]) if record else TaskStatus.PENDING
|
|
213
235
|
except Exception as e:
|
|
214
236
|
logger.error(f"Database error checking task status: {e}")
|
|
215
237
|
raise Exception(f"Database error: {e}")
|
|
@@ -223,7 +245,7 @@ class DatabaseManager:
|
|
|
223
245
|
if self.connection_pool:
|
|
224
246
|
async with self.connection_pool.acquire() as conn:
|
|
225
247
|
records = await conn.fetch(
|
|
226
|
-
|
|
248
|
+
"""SELECT DISTINCT task_id,
|
|
227
249
|
MAX(timestamp) as last_updated,
|
|
228
250
|
(SELECT status FROM task_history th2
|
|
229
251
|
WHERE th2.user_id = $1 AND th2.task_id = th1.task_id
|
|
@@ -232,14 +254,15 @@ class DatabaseManager:
|
|
|
232
254
|
WHERE user_id = $1
|
|
233
255
|
GROUP BY task_id
|
|
234
256
|
ORDER BY last_updated DESC
|
|
235
|
-
LIMIT $2
|
|
236
|
-
user_id,
|
|
257
|
+
LIMIT $2""",
|
|
258
|
+
user_id,
|
|
259
|
+
limit,
|
|
237
260
|
)
|
|
238
261
|
else:
|
|
239
262
|
conn = await asyncpg.connect(**self.db_config)
|
|
240
263
|
try:
|
|
241
264
|
records = await conn.fetch(
|
|
242
|
-
|
|
265
|
+
"""SELECT DISTINCT task_id,
|
|
243
266
|
MAX(timestamp) as last_updated,
|
|
244
267
|
(SELECT status FROM task_history th2
|
|
245
268
|
WHERE th2.user_id = $1 AND th2.task_id = th1.task_id
|
|
@@ -248,17 +271,18 @@ class DatabaseManager:
|
|
|
248
271
|
WHERE user_id = $1
|
|
249
272
|
GROUP BY task_id
|
|
250
273
|
ORDER BY last_updated DESC
|
|
251
|
-
LIMIT $2
|
|
252
|
-
user_id,
|
|
274
|
+
LIMIT $2""",
|
|
275
|
+
user_id,
|
|
276
|
+
limit,
|
|
253
277
|
)
|
|
254
278
|
finally:
|
|
255
279
|
await conn.close()
|
|
256
280
|
|
|
257
281
|
return [
|
|
258
282
|
{
|
|
259
|
-
"task_id": r[
|
|
260
|
-
"last_updated": r[
|
|
261
|
-
"status": r[
|
|
283
|
+
"task_id": r["task_id"],
|
|
284
|
+
"last_updated": r["last_updated"].isoformat(),
|
|
285
|
+
"status": r["status"],
|
|
262
286
|
}
|
|
263
287
|
for r in records
|
|
264
288
|
]
|
|
@@ -275,15 +299,15 @@ class DatabaseManager:
|
|
|
275
299
|
if self.connection_pool:
|
|
276
300
|
async with self.connection_pool.acquire() as conn:
|
|
277
301
|
result = await conn.execute(
|
|
278
|
-
|
|
279
|
-
days_old
|
|
302
|
+
"DELETE FROM task_history WHERE timestamp < NOW() - INTERVAL %s DAY",
|
|
303
|
+
days_old,
|
|
280
304
|
)
|
|
281
305
|
else:
|
|
282
306
|
conn = await asyncpg.connect(**self.db_config)
|
|
283
307
|
try:
|
|
284
308
|
result = await conn.execute(
|
|
285
|
-
|
|
286
|
-
days_old
|
|
309
|
+
"DELETE FROM task_history WHERE timestamp < NOW() - INTERVAL %s DAY",
|
|
310
|
+
days_old,
|
|
287
311
|
)
|
|
288
312
|
finally:
|
|
289
313
|
await conn.close()
|