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.
Files changed (302) hide show
  1. aiecs/__init__.py +72 -0
  2. aiecs/__main__.py +41 -0
  3. aiecs/aiecs_client.py +469 -0
  4. aiecs/application/__init__.py +10 -0
  5. aiecs/application/executors/__init__.py +10 -0
  6. aiecs/application/executors/operation_executor.py +363 -0
  7. aiecs/application/knowledge_graph/__init__.py +7 -0
  8. aiecs/application/knowledge_graph/builder/__init__.py +37 -0
  9. aiecs/application/knowledge_graph/builder/document_builder.py +375 -0
  10. aiecs/application/knowledge_graph/builder/graph_builder.py +356 -0
  11. aiecs/application/knowledge_graph/builder/schema_mapping.py +531 -0
  12. aiecs/application/knowledge_graph/builder/structured_pipeline.py +443 -0
  13. aiecs/application/knowledge_graph/builder/text_chunker.py +319 -0
  14. aiecs/application/knowledge_graph/extractors/__init__.py +27 -0
  15. aiecs/application/knowledge_graph/extractors/base.py +100 -0
  16. aiecs/application/knowledge_graph/extractors/llm_entity_extractor.py +327 -0
  17. aiecs/application/knowledge_graph/extractors/llm_relation_extractor.py +349 -0
  18. aiecs/application/knowledge_graph/extractors/ner_entity_extractor.py +244 -0
  19. aiecs/application/knowledge_graph/fusion/__init__.py +23 -0
  20. aiecs/application/knowledge_graph/fusion/entity_deduplicator.py +387 -0
  21. aiecs/application/knowledge_graph/fusion/entity_linker.py +343 -0
  22. aiecs/application/knowledge_graph/fusion/knowledge_fusion.py +580 -0
  23. aiecs/application/knowledge_graph/fusion/relation_deduplicator.py +189 -0
  24. aiecs/application/knowledge_graph/pattern_matching/__init__.py +21 -0
  25. aiecs/application/knowledge_graph/pattern_matching/pattern_matcher.py +344 -0
  26. aiecs/application/knowledge_graph/pattern_matching/query_executor.py +378 -0
  27. aiecs/application/knowledge_graph/profiling/__init__.py +12 -0
  28. aiecs/application/knowledge_graph/profiling/query_plan_visualizer.py +199 -0
  29. aiecs/application/knowledge_graph/profiling/query_profiler.py +223 -0
  30. aiecs/application/knowledge_graph/reasoning/__init__.py +27 -0
  31. aiecs/application/knowledge_graph/reasoning/evidence_synthesis.py +347 -0
  32. aiecs/application/knowledge_graph/reasoning/inference_engine.py +504 -0
  33. aiecs/application/knowledge_graph/reasoning/logic_form_parser.py +167 -0
  34. aiecs/application/knowledge_graph/reasoning/logic_parser/__init__.py +79 -0
  35. aiecs/application/knowledge_graph/reasoning/logic_parser/ast_builder.py +513 -0
  36. aiecs/application/knowledge_graph/reasoning/logic_parser/ast_nodes.py +630 -0
  37. aiecs/application/knowledge_graph/reasoning/logic_parser/ast_validator.py +654 -0
  38. aiecs/application/knowledge_graph/reasoning/logic_parser/error_handler.py +477 -0
  39. aiecs/application/knowledge_graph/reasoning/logic_parser/parser.py +390 -0
  40. aiecs/application/knowledge_graph/reasoning/logic_parser/query_context.py +217 -0
  41. aiecs/application/knowledge_graph/reasoning/logic_query_integration.py +169 -0
  42. aiecs/application/knowledge_graph/reasoning/query_planner.py +872 -0
  43. aiecs/application/knowledge_graph/reasoning/reasoning_engine.py +554 -0
  44. aiecs/application/knowledge_graph/retrieval/__init__.py +19 -0
  45. aiecs/application/knowledge_graph/retrieval/retrieval_strategies.py +596 -0
  46. aiecs/application/knowledge_graph/search/__init__.py +59 -0
  47. aiecs/application/knowledge_graph/search/hybrid_search.py +423 -0
  48. aiecs/application/knowledge_graph/search/reranker.py +295 -0
  49. aiecs/application/knowledge_graph/search/reranker_strategies.py +553 -0
  50. aiecs/application/knowledge_graph/search/text_similarity.py +398 -0
  51. aiecs/application/knowledge_graph/traversal/__init__.py +15 -0
  52. aiecs/application/knowledge_graph/traversal/enhanced_traversal.py +329 -0
  53. aiecs/application/knowledge_graph/traversal/path_scorer.py +269 -0
  54. aiecs/application/knowledge_graph/validators/__init__.py +13 -0
  55. aiecs/application/knowledge_graph/validators/relation_validator.py +189 -0
  56. aiecs/application/knowledge_graph/visualization/__init__.py +11 -0
  57. aiecs/application/knowledge_graph/visualization/graph_visualizer.py +321 -0
  58. aiecs/common/__init__.py +9 -0
  59. aiecs/common/knowledge_graph/__init__.py +17 -0
  60. aiecs/common/knowledge_graph/runnable.py +484 -0
  61. aiecs/config/__init__.py +16 -0
  62. aiecs/config/config.py +498 -0
  63. aiecs/config/graph_config.py +137 -0
  64. aiecs/config/registry.py +23 -0
  65. aiecs/core/__init__.py +46 -0
  66. aiecs/core/interface/__init__.py +34 -0
  67. aiecs/core/interface/execution_interface.py +152 -0
  68. aiecs/core/interface/storage_interface.py +171 -0
  69. aiecs/domain/__init__.py +289 -0
  70. aiecs/domain/agent/__init__.py +189 -0
  71. aiecs/domain/agent/base_agent.py +697 -0
  72. aiecs/domain/agent/exceptions.py +103 -0
  73. aiecs/domain/agent/graph_aware_mixin.py +559 -0
  74. aiecs/domain/agent/hybrid_agent.py +490 -0
  75. aiecs/domain/agent/integration/__init__.py +26 -0
  76. aiecs/domain/agent/integration/context_compressor.py +222 -0
  77. aiecs/domain/agent/integration/context_engine_adapter.py +252 -0
  78. aiecs/domain/agent/integration/retry_policy.py +219 -0
  79. aiecs/domain/agent/integration/role_config.py +213 -0
  80. aiecs/domain/agent/knowledge_aware_agent.py +646 -0
  81. aiecs/domain/agent/lifecycle.py +296 -0
  82. aiecs/domain/agent/llm_agent.py +300 -0
  83. aiecs/domain/agent/memory/__init__.py +12 -0
  84. aiecs/domain/agent/memory/conversation.py +197 -0
  85. aiecs/domain/agent/migration/__init__.py +14 -0
  86. aiecs/domain/agent/migration/conversion.py +160 -0
  87. aiecs/domain/agent/migration/legacy_wrapper.py +90 -0
  88. aiecs/domain/agent/models.py +317 -0
  89. aiecs/domain/agent/observability.py +407 -0
  90. aiecs/domain/agent/persistence.py +289 -0
  91. aiecs/domain/agent/prompts/__init__.py +29 -0
  92. aiecs/domain/agent/prompts/builder.py +161 -0
  93. aiecs/domain/agent/prompts/formatters.py +189 -0
  94. aiecs/domain/agent/prompts/template.py +255 -0
  95. aiecs/domain/agent/registry.py +260 -0
  96. aiecs/domain/agent/tool_agent.py +257 -0
  97. aiecs/domain/agent/tools/__init__.py +12 -0
  98. aiecs/domain/agent/tools/schema_generator.py +221 -0
  99. aiecs/domain/community/__init__.py +155 -0
  100. aiecs/domain/community/agent_adapter.py +477 -0
  101. aiecs/domain/community/analytics.py +481 -0
  102. aiecs/domain/community/collaborative_workflow.py +642 -0
  103. aiecs/domain/community/communication_hub.py +645 -0
  104. aiecs/domain/community/community_builder.py +320 -0
  105. aiecs/domain/community/community_integration.py +800 -0
  106. aiecs/domain/community/community_manager.py +813 -0
  107. aiecs/domain/community/decision_engine.py +879 -0
  108. aiecs/domain/community/exceptions.py +225 -0
  109. aiecs/domain/community/models/__init__.py +33 -0
  110. aiecs/domain/community/models/community_models.py +268 -0
  111. aiecs/domain/community/resource_manager.py +457 -0
  112. aiecs/domain/community/shared_context_manager.py +603 -0
  113. aiecs/domain/context/__init__.py +58 -0
  114. aiecs/domain/context/context_engine.py +989 -0
  115. aiecs/domain/context/conversation_models.py +354 -0
  116. aiecs/domain/context/graph_memory.py +467 -0
  117. aiecs/domain/execution/__init__.py +12 -0
  118. aiecs/domain/execution/model.py +57 -0
  119. aiecs/domain/knowledge_graph/__init__.py +19 -0
  120. aiecs/domain/knowledge_graph/models/__init__.py +52 -0
  121. aiecs/domain/knowledge_graph/models/entity.py +130 -0
  122. aiecs/domain/knowledge_graph/models/evidence.py +194 -0
  123. aiecs/domain/knowledge_graph/models/inference_rule.py +186 -0
  124. aiecs/domain/knowledge_graph/models/path.py +179 -0
  125. aiecs/domain/knowledge_graph/models/path_pattern.py +173 -0
  126. aiecs/domain/knowledge_graph/models/query.py +272 -0
  127. aiecs/domain/knowledge_graph/models/query_plan.py +187 -0
  128. aiecs/domain/knowledge_graph/models/relation.py +136 -0
  129. aiecs/domain/knowledge_graph/schema/__init__.py +23 -0
  130. aiecs/domain/knowledge_graph/schema/entity_type.py +135 -0
  131. aiecs/domain/knowledge_graph/schema/graph_schema.py +271 -0
  132. aiecs/domain/knowledge_graph/schema/property_schema.py +155 -0
  133. aiecs/domain/knowledge_graph/schema/relation_type.py +171 -0
  134. aiecs/domain/knowledge_graph/schema/schema_manager.py +496 -0
  135. aiecs/domain/knowledge_graph/schema/type_enums.py +205 -0
  136. aiecs/domain/task/__init__.py +13 -0
  137. aiecs/domain/task/dsl_processor.py +613 -0
  138. aiecs/domain/task/model.py +62 -0
  139. aiecs/domain/task/task_context.py +268 -0
  140. aiecs/infrastructure/__init__.py +24 -0
  141. aiecs/infrastructure/graph_storage/__init__.py +11 -0
  142. aiecs/infrastructure/graph_storage/base.py +601 -0
  143. aiecs/infrastructure/graph_storage/batch_operations.py +449 -0
  144. aiecs/infrastructure/graph_storage/cache.py +429 -0
  145. aiecs/infrastructure/graph_storage/distributed.py +226 -0
  146. aiecs/infrastructure/graph_storage/error_handling.py +390 -0
  147. aiecs/infrastructure/graph_storage/graceful_degradation.py +306 -0
  148. aiecs/infrastructure/graph_storage/health_checks.py +378 -0
  149. aiecs/infrastructure/graph_storage/in_memory.py +514 -0
  150. aiecs/infrastructure/graph_storage/index_optimization.py +483 -0
  151. aiecs/infrastructure/graph_storage/lazy_loading.py +410 -0
  152. aiecs/infrastructure/graph_storage/metrics.py +357 -0
  153. aiecs/infrastructure/graph_storage/migration.py +413 -0
  154. aiecs/infrastructure/graph_storage/pagination.py +471 -0
  155. aiecs/infrastructure/graph_storage/performance_monitoring.py +466 -0
  156. aiecs/infrastructure/graph_storage/postgres.py +871 -0
  157. aiecs/infrastructure/graph_storage/query_optimizer.py +635 -0
  158. aiecs/infrastructure/graph_storage/schema_cache.py +290 -0
  159. aiecs/infrastructure/graph_storage/sqlite.py +623 -0
  160. aiecs/infrastructure/graph_storage/streaming.py +495 -0
  161. aiecs/infrastructure/messaging/__init__.py +13 -0
  162. aiecs/infrastructure/messaging/celery_task_manager.py +383 -0
  163. aiecs/infrastructure/messaging/websocket_manager.py +298 -0
  164. aiecs/infrastructure/monitoring/__init__.py +34 -0
  165. aiecs/infrastructure/monitoring/executor_metrics.py +174 -0
  166. aiecs/infrastructure/monitoring/global_metrics_manager.py +213 -0
  167. aiecs/infrastructure/monitoring/structured_logger.py +48 -0
  168. aiecs/infrastructure/monitoring/tracing_manager.py +410 -0
  169. aiecs/infrastructure/persistence/__init__.py +24 -0
  170. aiecs/infrastructure/persistence/context_engine_client.py +187 -0
  171. aiecs/infrastructure/persistence/database_manager.py +333 -0
  172. aiecs/infrastructure/persistence/file_storage.py +754 -0
  173. aiecs/infrastructure/persistence/redis_client.py +220 -0
  174. aiecs/llm/__init__.py +86 -0
  175. aiecs/llm/callbacks/__init__.py +11 -0
  176. aiecs/llm/callbacks/custom_callbacks.py +264 -0
  177. aiecs/llm/client_factory.py +420 -0
  178. aiecs/llm/clients/__init__.py +33 -0
  179. aiecs/llm/clients/base_client.py +193 -0
  180. aiecs/llm/clients/googleai_client.py +181 -0
  181. aiecs/llm/clients/openai_client.py +131 -0
  182. aiecs/llm/clients/vertex_client.py +437 -0
  183. aiecs/llm/clients/xai_client.py +184 -0
  184. aiecs/llm/config/__init__.py +51 -0
  185. aiecs/llm/config/config_loader.py +275 -0
  186. aiecs/llm/config/config_validator.py +236 -0
  187. aiecs/llm/config/model_config.py +151 -0
  188. aiecs/llm/utils/__init__.py +10 -0
  189. aiecs/llm/utils/validate_config.py +91 -0
  190. aiecs/main.py +363 -0
  191. aiecs/scripts/__init__.py +3 -0
  192. aiecs/scripts/aid/VERSION_MANAGEMENT.md +97 -0
  193. aiecs/scripts/aid/__init__.py +19 -0
  194. aiecs/scripts/aid/version_manager.py +215 -0
  195. aiecs/scripts/dependance_check/DEPENDENCY_SYSTEM_SUMMARY.md +242 -0
  196. aiecs/scripts/dependance_check/README_DEPENDENCY_CHECKER.md +310 -0
  197. aiecs/scripts/dependance_check/__init__.py +17 -0
  198. aiecs/scripts/dependance_check/dependency_checker.py +938 -0
  199. aiecs/scripts/dependance_check/dependency_fixer.py +391 -0
  200. aiecs/scripts/dependance_check/download_nlp_data.py +396 -0
  201. aiecs/scripts/dependance_check/quick_dependency_check.py +270 -0
  202. aiecs/scripts/dependance_check/setup_nlp_data.sh +217 -0
  203. aiecs/scripts/dependance_patch/__init__.py +7 -0
  204. aiecs/scripts/dependance_patch/fix_weasel/README_WEASEL_PATCH.md +126 -0
  205. aiecs/scripts/dependance_patch/fix_weasel/__init__.py +11 -0
  206. aiecs/scripts/dependance_patch/fix_weasel/fix_weasel_validator.py +128 -0
  207. aiecs/scripts/dependance_patch/fix_weasel/fix_weasel_validator.sh +82 -0
  208. aiecs/scripts/dependance_patch/fix_weasel/patch_weasel_library.sh +188 -0
  209. aiecs/scripts/dependance_patch/fix_weasel/run_weasel_patch.sh +41 -0
  210. aiecs/scripts/tools_develop/README.md +449 -0
  211. aiecs/scripts/tools_develop/TOOL_AUTO_DISCOVERY.md +234 -0
  212. aiecs/scripts/tools_develop/__init__.py +21 -0
  213. aiecs/scripts/tools_develop/check_type_annotations.py +259 -0
  214. aiecs/scripts/tools_develop/validate_tool_schemas.py +422 -0
  215. aiecs/scripts/tools_develop/verify_tools.py +356 -0
  216. aiecs/tasks/__init__.py +1 -0
  217. aiecs/tasks/worker.py +172 -0
  218. aiecs/tools/__init__.py +299 -0
  219. aiecs/tools/apisource/__init__.py +99 -0
  220. aiecs/tools/apisource/intelligence/__init__.py +19 -0
  221. aiecs/tools/apisource/intelligence/data_fusion.py +381 -0
  222. aiecs/tools/apisource/intelligence/query_analyzer.py +413 -0
  223. aiecs/tools/apisource/intelligence/search_enhancer.py +388 -0
  224. aiecs/tools/apisource/monitoring/__init__.py +9 -0
  225. aiecs/tools/apisource/monitoring/metrics.py +303 -0
  226. aiecs/tools/apisource/providers/__init__.py +115 -0
  227. aiecs/tools/apisource/providers/base.py +664 -0
  228. aiecs/tools/apisource/providers/census.py +401 -0
  229. aiecs/tools/apisource/providers/fred.py +564 -0
  230. aiecs/tools/apisource/providers/newsapi.py +412 -0
  231. aiecs/tools/apisource/providers/worldbank.py +357 -0
  232. aiecs/tools/apisource/reliability/__init__.py +12 -0
  233. aiecs/tools/apisource/reliability/error_handler.py +375 -0
  234. aiecs/tools/apisource/reliability/fallback_strategy.py +391 -0
  235. aiecs/tools/apisource/tool.py +850 -0
  236. aiecs/tools/apisource/utils/__init__.py +9 -0
  237. aiecs/tools/apisource/utils/validators.py +338 -0
  238. aiecs/tools/base_tool.py +201 -0
  239. aiecs/tools/docs/__init__.py +121 -0
  240. aiecs/tools/docs/ai_document_orchestrator.py +599 -0
  241. aiecs/tools/docs/ai_document_writer_orchestrator.py +2403 -0
  242. aiecs/tools/docs/content_insertion_tool.py +1333 -0
  243. aiecs/tools/docs/document_creator_tool.py +1317 -0
  244. aiecs/tools/docs/document_layout_tool.py +1166 -0
  245. aiecs/tools/docs/document_parser_tool.py +994 -0
  246. aiecs/tools/docs/document_writer_tool.py +1818 -0
  247. aiecs/tools/knowledge_graph/__init__.py +17 -0
  248. aiecs/tools/knowledge_graph/graph_reasoning_tool.py +734 -0
  249. aiecs/tools/knowledge_graph/graph_search_tool.py +923 -0
  250. aiecs/tools/knowledge_graph/kg_builder_tool.py +476 -0
  251. aiecs/tools/langchain_adapter.py +542 -0
  252. aiecs/tools/schema_generator.py +275 -0
  253. aiecs/tools/search_tool/__init__.py +100 -0
  254. aiecs/tools/search_tool/analyzers.py +589 -0
  255. aiecs/tools/search_tool/cache.py +260 -0
  256. aiecs/tools/search_tool/constants.py +128 -0
  257. aiecs/tools/search_tool/context.py +216 -0
  258. aiecs/tools/search_tool/core.py +749 -0
  259. aiecs/tools/search_tool/deduplicator.py +123 -0
  260. aiecs/tools/search_tool/error_handler.py +271 -0
  261. aiecs/tools/search_tool/metrics.py +371 -0
  262. aiecs/tools/search_tool/rate_limiter.py +178 -0
  263. aiecs/tools/search_tool/schemas.py +277 -0
  264. aiecs/tools/statistics/__init__.py +80 -0
  265. aiecs/tools/statistics/ai_data_analysis_orchestrator.py +643 -0
  266. aiecs/tools/statistics/ai_insight_generator_tool.py +505 -0
  267. aiecs/tools/statistics/ai_report_orchestrator_tool.py +694 -0
  268. aiecs/tools/statistics/data_loader_tool.py +564 -0
  269. aiecs/tools/statistics/data_profiler_tool.py +658 -0
  270. aiecs/tools/statistics/data_transformer_tool.py +573 -0
  271. aiecs/tools/statistics/data_visualizer_tool.py +495 -0
  272. aiecs/tools/statistics/model_trainer_tool.py +487 -0
  273. aiecs/tools/statistics/statistical_analyzer_tool.py +459 -0
  274. aiecs/tools/task_tools/__init__.py +86 -0
  275. aiecs/tools/task_tools/chart_tool.py +732 -0
  276. aiecs/tools/task_tools/classfire_tool.py +922 -0
  277. aiecs/tools/task_tools/image_tool.py +447 -0
  278. aiecs/tools/task_tools/office_tool.py +684 -0
  279. aiecs/tools/task_tools/pandas_tool.py +635 -0
  280. aiecs/tools/task_tools/report_tool.py +635 -0
  281. aiecs/tools/task_tools/research_tool.py +392 -0
  282. aiecs/tools/task_tools/scraper_tool.py +715 -0
  283. aiecs/tools/task_tools/stats_tool.py +688 -0
  284. aiecs/tools/temp_file_manager.py +130 -0
  285. aiecs/tools/tool_executor/__init__.py +37 -0
  286. aiecs/tools/tool_executor/tool_executor.py +881 -0
  287. aiecs/utils/LLM_output_structor.py +445 -0
  288. aiecs/utils/__init__.py +34 -0
  289. aiecs/utils/base_callback.py +47 -0
  290. aiecs/utils/cache_provider.py +695 -0
  291. aiecs/utils/execution_utils.py +184 -0
  292. aiecs/utils/logging.py +1 -0
  293. aiecs/utils/prompt_loader.py +14 -0
  294. aiecs/utils/token_usage_repository.py +323 -0
  295. aiecs/ws/__init__.py +0 -0
  296. aiecs/ws/socket_server.py +52 -0
  297. aiecs-1.5.1.dist-info/METADATA +608 -0
  298. aiecs-1.5.1.dist-info/RECORD +302 -0
  299. aiecs-1.5.1.dist-info/WHEEL +5 -0
  300. aiecs-1.5.1.dist-info/entry_points.txt +10 -0
  301. aiecs-1.5.1.dist-info/licenses/LICENSE +225 -0
  302. aiecs-1.5.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,410 @@
1
+ import functools
2
+ import logging
3
+ import os
4
+ from typing import Dict, Any, Optional
5
+ import jaeger_client
6
+ import jaeger_client.config
7
+ from opentracing import Span
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+
12
+ class TracingManager:
13
+ """
14
+ Specialized handler for distributed tracing and link tracking
15
+ """
16
+
17
+ def __init__(
18
+ self,
19
+ service_name: str = "service_executor",
20
+ jaeger_host: Optional[str] = None,
21
+ jaeger_port: Optional[int] = None,
22
+ enable_tracing: Optional[bool] = None,
23
+ ):
24
+ self.service_name = service_name
25
+ # Get configuration from environment variables, use defaults if not
26
+ # available
27
+ self.jaeger_host = jaeger_host or os.getenv("JAEGER_AGENT_HOST", "jaeger")
28
+ self.jaeger_port = jaeger_port or int(os.getenv("JAEGER_AGENT_PORT", "6831"))
29
+ self.enable_tracing = (
30
+ enable_tracing
31
+ if enable_tracing is not None
32
+ else os.getenv("JAEGER_ENABLE_TRACING", "true").lower() == "true"
33
+ )
34
+ self.tracer = None
35
+
36
+ if self.enable_tracing:
37
+ self._init_tracer()
38
+
39
+ def _init_tracer(self):
40
+ """Initialize Jaeger tracer"""
41
+ try:
42
+ config = jaeger_client.config.Config(
43
+ config={
44
+ "sampler": {
45
+ "type": "const",
46
+ "param": 1,
47
+ },
48
+ "local_agent": {
49
+ "reporting_host": self.jaeger_host,
50
+ "reporting_port": self.jaeger_port,
51
+ },
52
+ "logging": True,
53
+ },
54
+ service_name=self.service_name,
55
+ validate=True,
56
+ )
57
+ self.tracer = config.initialize_tracer()
58
+ logger.info(
59
+ f"Jaeger tracer initialized for service '{self.service_name}' at {self.jaeger_host}:{self.jaeger_port}"
60
+ )
61
+ except Exception as e:
62
+ logger.warning(f"Failed to initialize Jaeger tracer: {e}")
63
+ self.tracer = None
64
+ self.enable_tracing = False
65
+
66
+ def start_span(
67
+ self,
68
+ operation_name: str,
69
+ parent_span: Optional[Span] = None,
70
+ tags: Optional[Dict[str, Any]] = None,
71
+ ) -> Optional[Span]:
72
+ """
73
+ Start a tracing span
74
+
75
+ Args:
76
+ operation_name: Operation name
77
+ parent_span: Parent span
78
+ tags: Initial tags
79
+
80
+ Returns:
81
+ Span object or None (if tracing is not enabled)
82
+ """
83
+ if not self.enable_tracing or not self.tracer:
84
+ return None
85
+
86
+ try:
87
+ span = self.tracer.start_span(operation_name=operation_name, child_of=parent_span)
88
+
89
+ # Set initial tags
90
+ if tags:
91
+ for key, value in tags.items():
92
+ span.set_tag(key, value)
93
+
94
+ # Set service information
95
+ span.set_tag("service.name", self.service_name)
96
+ span.set_tag("span.kind", "server")
97
+
98
+ return span
99
+ except Exception as e:
100
+ logger.error(f"Error starting span '{operation_name}': {e}")
101
+ return None
102
+
103
+ def finish_span(
104
+ self,
105
+ span: Optional[Span],
106
+ tags: Optional[Dict[str, Any]] = None,
107
+ logs: Optional[Dict[str, Any]] = None,
108
+ error: Optional[Exception] = None,
109
+ ):
110
+ """
111
+ Finish tracing span
112
+
113
+ Args:
114
+ span: Span to finish
115
+ tags: Additional tags
116
+ logs: Log information
117
+ error: Error information
118
+ """
119
+ if not span or not self.enable_tracing:
120
+ return
121
+
122
+ try:
123
+ # Add additional tags
124
+ if tags:
125
+ for key, value in tags.items():
126
+ span.set_tag(key, value)
127
+
128
+ # Record error
129
+ if error:
130
+ span.set_tag("error", True)
131
+ span.set_tag("error.kind", type(error).__name__)
132
+ span.set_tag("error.message", str(error))
133
+ span.log_kv({"event": "error", "error.object": error})
134
+
135
+ # Add logs
136
+ if logs:
137
+ span.log_kv(logs)
138
+
139
+ span.finish()
140
+ except Exception as e:
141
+ logger.error(f"Error finishing span: {e}")
142
+
143
+ def with_tracing(self, operation_name: str, tags: Optional[Dict[str, Any]] = None):
144
+ """
145
+ Tracing decorator
146
+
147
+ Args:
148
+ operation_name: Operation name
149
+ tags: Initial tags
150
+ """
151
+
152
+ def decorator(func):
153
+ @functools.wraps(func)
154
+ async def async_wrapper(*args, **kwargs):
155
+ if not self.enable_tracing or not self.tracer:
156
+ return await func(*args, **kwargs)
157
+
158
+ span = self.start_span(operation_name, tags=tags)
159
+
160
+ try:
161
+ # Add function arguments as tags
162
+ self._add_function_args_to_span(span, args, kwargs)
163
+
164
+ result = await func(*args, **kwargs)
165
+
166
+ # Record success
167
+ if span:
168
+ span.set_tag("success", True)
169
+
170
+ return result
171
+ except Exception as e:
172
+ self.finish_span(span, error=e)
173
+ raise
174
+ finally:
175
+ if span and not span.finished:
176
+ self.finish_span(span)
177
+
178
+ @functools.wraps(func)
179
+ def sync_wrapper(*args, **kwargs):
180
+ if not self.enable_tracing or not self.tracer:
181
+ return func(*args, **kwargs)
182
+
183
+ span = self.start_span(operation_name, tags=tags)
184
+
185
+ try:
186
+ # Add function arguments as tags
187
+ self._add_function_args_to_span(span, args, kwargs)
188
+
189
+ result = func(*args, **kwargs)
190
+
191
+ # Record success
192
+ if span:
193
+ span.set_tag("success", True)
194
+
195
+ return result
196
+ except Exception as e:
197
+ self.finish_span(span, error=e)
198
+ raise
199
+ finally:
200
+ if span and not span.finished:
201
+ self.finish_span(span)
202
+
203
+ # Return appropriate wrapper based on function type
204
+ import asyncio
205
+
206
+ if asyncio.iscoroutinefunction(func):
207
+ return async_wrapper
208
+ else:
209
+ return sync_wrapper
210
+
211
+ return decorator
212
+
213
+ def _add_function_args_to_span(self, span: Optional[Span], args: tuple, kwargs: Dict[str, Any]):
214
+ """Add function arguments to span tags"""
215
+ if not span:
216
+ return
217
+
218
+ try:
219
+ # Add positional arguments
220
+ for i, arg in enumerate(args):
221
+ if isinstance(arg, (str, int, float, bool)):
222
+ span.set_tag(f"arg_{i}", arg)
223
+ elif hasattr(arg, "__class__"):
224
+ span.set_tag(f"arg_{i}_type", arg.__class__.__name__)
225
+
226
+ # Add keyword arguments
227
+ for key, value in kwargs.items():
228
+ if isinstance(value, (str, int, float, bool)):
229
+ span.set_tag(key, value)
230
+ # Avoid overly large dictionaries
231
+ elif isinstance(value, dict) and len(str(value)) < 1000:
232
+ span.set_tag(f"{key}_json", str(value))
233
+ elif hasattr(value, "__class__"):
234
+ span.set_tag(f"{key}_type", value.__class__.__name__)
235
+ except Exception as e:
236
+ logger.debug(f"Error adding function args to span: {e}")
237
+
238
+ def trace_database_operation(self, operation: str, table: str = None, query: str = None):
239
+ """Database operation tracing decorator"""
240
+
241
+ def decorator(func):
242
+ @functools.wraps(func)
243
+ async def wrapper(*args, **kwargs):
244
+ tags = {
245
+ "component": "database",
246
+ "db.type": "postgresql",
247
+ "db.statement.type": operation,
248
+ }
249
+
250
+ if table:
251
+ tags["db.table"] = table
252
+ if query:
253
+ tags["db.statement"] = query[:500] # Limit query length
254
+
255
+ span = self.start_span(f"db.{operation}", tags=tags)
256
+
257
+ try:
258
+ result = await func(*args, **kwargs)
259
+ if span:
260
+ span.set_tag(
261
+ "db.rows_affected",
262
+ len(result) if isinstance(result, list) else 1,
263
+ )
264
+ return result
265
+ except Exception as e:
266
+ self.finish_span(span, error=e)
267
+ raise
268
+ finally:
269
+ if span and not span.finished:
270
+ self.finish_span(span)
271
+
272
+ return wrapper
273
+
274
+ return decorator
275
+
276
+ def trace_external_call(self, service_name: str, endpoint: str = None):
277
+ """External service call tracing decorator"""
278
+
279
+ def decorator(func):
280
+ @functools.wraps(func)
281
+ async def wrapper(*args, **kwargs):
282
+ tags = {
283
+ "component": "http",
284
+ "span.kind": "client",
285
+ "peer.service": service_name,
286
+ }
287
+
288
+ if endpoint:
289
+ tags["http.url"] = endpoint
290
+
291
+ span = self.start_span(f"http.{service_name}", tags=tags)
292
+
293
+ try:
294
+ result = await func(*args, **kwargs)
295
+ if span:
296
+ span.set_tag("http.status_code", 200)
297
+ return result
298
+ except Exception as e:
299
+ if span:
300
+ span.set_tag("http.status_code", 500)
301
+ self.finish_span(span, error=e)
302
+ raise
303
+ finally:
304
+ if span and not span.finished:
305
+ self.finish_span(span)
306
+
307
+ return wrapper
308
+
309
+ return decorator
310
+
311
+ def trace_tool_execution(self, tool_name: str, operation: str):
312
+ """Tool execution tracing decorator"""
313
+
314
+ def decorator(func):
315
+ @functools.wraps(func)
316
+ async def wrapper(*args, **kwargs):
317
+ tags = {
318
+ "component": "tool",
319
+ "tool.name": tool_name,
320
+ "tool.operation": operation,
321
+ }
322
+
323
+ span = self.start_span(f"tool.{tool_name}.{operation}", tags=tags)
324
+
325
+ try:
326
+ result = await func(*args, **kwargs)
327
+ if span:
328
+ span.set_tag("tool.success", True)
329
+ if hasattr(result, "__len__"):
330
+ span.set_tag("tool.result_size", len(result))
331
+ return result
332
+ except Exception as e:
333
+ if span:
334
+ span.set_tag("tool.success", False)
335
+ self.finish_span(span, error=e)
336
+ raise
337
+ finally:
338
+ if span and not span.finished:
339
+ self.finish_span(span)
340
+
341
+ return wrapper
342
+
343
+ return decorator
344
+
345
+ def create_child_span(
346
+ self,
347
+ parent_span: Optional[Span],
348
+ operation_name: str,
349
+ tags: Optional[Dict[str, Any]] = None,
350
+ ) -> Optional[Span]:
351
+ """Create child span"""
352
+ if not self.enable_tracing or not parent_span:
353
+ return None
354
+
355
+ return self.start_span(operation_name, parent_span=parent_span, tags=tags)
356
+
357
+ def inject_span_context(self, span: Optional[Span], carrier: Dict[str, str]):
358
+ """Inject span context into carrier (for cross-service propagation)"""
359
+ if not self.enable_tracing or not span or not self.tracer:
360
+ return
361
+
362
+ try:
363
+ from opentracing.propagation import Format
364
+
365
+ self.tracer.inject(span.context, Format.TEXT_MAP, carrier)
366
+ except Exception as e:
367
+ logger.error(f"Error injecting span context: {e}")
368
+
369
+ def extract_span_context(self, carrier: Dict[str, str]) -> Optional[Any]:
370
+ """Extract span context from carrier"""
371
+ if not self.enable_tracing or not self.tracer:
372
+ return None
373
+
374
+ try:
375
+ from opentracing.propagation import Format
376
+
377
+ return self.tracer.extract(Format.TEXT_MAP, carrier)
378
+ except Exception as e:
379
+ logger.error(f"Error extracting span context: {e}")
380
+ return None
381
+
382
+ def get_active_span(self) -> Optional[Span]:
383
+ """Get current active span"""
384
+ if not self.enable_tracing or not self.tracer:
385
+ return None
386
+
387
+ try:
388
+ return self.tracer.active_span
389
+ except Exception as e:
390
+ logger.error(f"Error getting active span: {e}")
391
+ return None
392
+
393
+ def close_tracer(self):
394
+ """Close tracer"""
395
+ if self.tracer:
396
+ try:
397
+ self.tracer.close()
398
+ logger.info("Tracer closed successfully")
399
+ except Exception as e:
400
+ logger.error(f"Error closing tracer: {e}")
401
+
402
+ def get_tracer_info(self) -> Dict[str, Any]:
403
+ """Get tracer information"""
404
+ return {
405
+ "enabled": self.enable_tracing,
406
+ "service_name": self.service_name,
407
+ "jaeger_host": self.jaeger_host,
408
+ "jaeger_port": self.jaeger_port,
409
+ "tracer_initialized": self.tracer is not None,
410
+ }
@@ -0,0 +1,24 @@
1
+ """Infrastructure persistence module
2
+
3
+ Contains data persistence and storage infrastructure.
4
+ """
5
+
6
+ from .database_manager import DatabaseManager
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
+ )
15
+
16
+ __all__ = [
17
+ "DatabaseManager",
18
+ "RedisClient",
19
+ "initialize_context_engine",
20
+ "get_context_engine",
21
+ "close_context_engine",
22
+ "is_context_engine_initialized",
23
+ "reset_context_engine",
24
+ ]
@@ -0,0 +1,187 @@
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(
119
+ "ContextEngine not initialized. Call initialize_context_engine() "
120
+ "during application startup."
121
+ )
122
+ return _global_context_engine
123
+
124
+
125
+ async def close_context_engine() -> None:
126
+ """
127
+ Close and cleanup the global ContextEngine instance.
128
+
129
+ This should be called during application shutdown (in main.py lifespan).
130
+
131
+ Example:
132
+ @asynccontextmanager
133
+ async def lifespan(app: FastAPI):
134
+ # Startup
135
+ await initialize_context_engine()
136
+ yield
137
+ # Shutdown
138
+ await close_context_engine()
139
+ """
140
+ global _global_context_engine, _initialized
141
+
142
+ async with _initialization_lock:
143
+ if _global_context_engine:
144
+ try:
145
+ logger.info("Closing global ContextEngine...")
146
+ # ContextEngine cleanup if needed
147
+ if hasattr(_global_context_engine, "close"):
148
+ await _global_context_engine.close()
149
+ logger.info("✅ Global ContextEngine closed successfully")
150
+ except Exception as e:
151
+ logger.error(f"Error closing ContextEngine: {e}")
152
+ finally:
153
+ _global_context_engine = None
154
+ _initialized = False
155
+
156
+
157
+ def is_context_engine_initialized() -> bool:
158
+ """
159
+ Check if the global ContextEngine is initialized.
160
+
161
+ Returns:
162
+ True if ContextEngine is initialized and available, False otherwise
163
+ """
164
+ return _initialized and _global_context_engine is not None
165
+
166
+
167
+ # Convenience function for testing
168
+ async def reset_context_engine() -> None:
169
+ """
170
+ Reset the global ContextEngine instance.
171
+
172
+ This is primarily for testing purposes to allow re-initialization.
173
+ Should NOT be used in production code.
174
+ """
175
+ global _global_context_engine, _initialized
176
+
177
+ async with _initialization_lock:
178
+ if _global_context_engine:
179
+ try:
180
+ if hasattr(_global_context_engine, "close"):
181
+ await _global_context_engine.close()
182
+ except Exception as e:
183
+ logger.warning(f"Error during ContextEngine reset: {e}")
184
+
185
+ _global_context_engine = None
186
+ _initialized = False
187
+ logger.info("ContextEngine reset completed")