aiecs 1.0.1__py3-none-any.whl → 1.7.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of aiecs might be problematic. Click here for more details.

Files changed (340) hide show
  1. aiecs/__init__.py +13 -16
  2. aiecs/__main__.py +7 -7
  3. aiecs/aiecs_client.py +269 -75
  4. aiecs/application/executors/operation_executor.py +79 -54
  5. aiecs/application/knowledge_graph/__init__.py +7 -0
  6. aiecs/application/knowledge_graph/builder/__init__.py +37 -0
  7. aiecs/application/knowledge_graph/builder/data_quality.py +302 -0
  8. aiecs/application/knowledge_graph/builder/data_reshaping.py +293 -0
  9. aiecs/application/knowledge_graph/builder/document_builder.py +369 -0
  10. aiecs/application/knowledge_graph/builder/graph_builder.py +490 -0
  11. aiecs/application/knowledge_graph/builder/import_optimizer.py +396 -0
  12. aiecs/application/knowledge_graph/builder/schema_inference.py +462 -0
  13. aiecs/application/knowledge_graph/builder/schema_mapping.py +563 -0
  14. aiecs/application/knowledge_graph/builder/structured_pipeline.py +1384 -0
  15. aiecs/application/knowledge_graph/builder/text_chunker.py +317 -0
  16. aiecs/application/knowledge_graph/extractors/__init__.py +27 -0
  17. aiecs/application/knowledge_graph/extractors/base.py +98 -0
  18. aiecs/application/knowledge_graph/extractors/llm_entity_extractor.py +422 -0
  19. aiecs/application/knowledge_graph/extractors/llm_relation_extractor.py +347 -0
  20. aiecs/application/knowledge_graph/extractors/ner_entity_extractor.py +241 -0
  21. aiecs/application/knowledge_graph/fusion/__init__.py +78 -0
  22. aiecs/application/knowledge_graph/fusion/ab_testing.py +395 -0
  23. aiecs/application/knowledge_graph/fusion/abbreviation_expander.py +327 -0
  24. aiecs/application/knowledge_graph/fusion/alias_index.py +597 -0
  25. aiecs/application/knowledge_graph/fusion/alias_matcher.py +384 -0
  26. aiecs/application/knowledge_graph/fusion/cache_coordinator.py +343 -0
  27. aiecs/application/knowledge_graph/fusion/entity_deduplicator.py +433 -0
  28. aiecs/application/knowledge_graph/fusion/entity_linker.py +511 -0
  29. aiecs/application/knowledge_graph/fusion/evaluation_dataset.py +240 -0
  30. aiecs/application/knowledge_graph/fusion/knowledge_fusion.py +632 -0
  31. aiecs/application/knowledge_graph/fusion/matching_config.py +489 -0
  32. aiecs/application/knowledge_graph/fusion/name_normalizer.py +352 -0
  33. aiecs/application/knowledge_graph/fusion/relation_deduplicator.py +183 -0
  34. aiecs/application/knowledge_graph/fusion/semantic_name_matcher.py +464 -0
  35. aiecs/application/knowledge_graph/fusion/similarity_pipeline.py +534 -0
  36. aiecs/application/knowledge_graph/pattern_matching/__init__.py +21 -0
  37. aiecs/application/knowledge_graph/pattern_matching/pattern_matcher.py +342 -0
  38. aiecs/application/knowledge_graph/pattern_matching/query_executor.py +366 -0
  39. aiecs/application/knowledge_graph/profiling/__init__.py +12 -0
  40. aiecs/application/knowledge_graph/profiling/query_plan_visualizer.py +195 -0
  41. aiecs/application/knowledge_graph/profiling/query_profiler.py +223 -0
  42. aiecs/application/knowledge_graph/reasoning/__init__.py +27 -0
  43. aiecs/application/knowledge_graph/reasoning/evidence_synthesis.py +341 -0
  44. aiecs/application/knowledge_graph/reasoning/inference_engine.py +500 -0
  45. aiecs/application/knowledge_graph/reasoning/logic_form_parser.py +163 -0
  46. aiecs/application/knowledge_graph/reasoning/logic_parser/__init__.py +79 -0
  47. aiecs/application/knowledge_graph/reasoning/logic_parser/ast_builder.py +513 -0
  48. aiecs/application/knowledge_graph/reasoning/logic_parser/ast_nodes.py +913 -0
  49. aiecs/application/knowledge_graph/reasoning/logic_parser/ast_validator.py +866 -0
  50. aiecs/application/knowledge_graph/reasoning/logic_parser/error_handler.py +475 -0
  51. aiecs/application/knowledge_graph/reasoning/logic_parser/parser.py +396 -0
  52. aiecs/application/knowledge_graph/reasoning/logic_parser/query_context.py +208 -0
  53. aiecs/application/knowledge_graph/reasoning/logic_query_integration.py +170 -0
  54. aiecs/application/knowledge_graph/reasoning/query_planner.py +855 -0
  55. aiecs/application/knowledge_graph/reasoning/reasoning_engine.py +518 -0
  56. aiecs/application/knowledge_graph/retrieval/__init__.py +27 -0
  57. aiecs/application/knowledge_graph/retrieval/query_intent_classifier.py +211 -0
  58. aiecs/application/knowledge_graph/retrieval/retrieval_strategies.py +592 -0
  59. aiecs/application/knowledge_graph/retrieval/strategy_types.py +23 -0
  60. aiecs/application/knowledge_graph/search/__init__.py +59 -0
  61. aiecs/application/knowledge_graph/search/hybrid_search.py +457 -0
  62. aiecs/application/knowledge_graph/search/reranker.py +293 -0
  63. aiecs/application/knowledge_graph/search/reranker_strategies.py +535 -0
  64. aiecs/application/knowledge_graph/search/text_similarity.py +392 -0
  65. aiecs/application/knowledge_graph/traversal/__init__.py +15 -0
  66. aiecs/application/knowledge_graph/traversal/enhanced_traversal.py +305 -0
  67. aiecs/application/knowledge_graph/traversal/path_scorer.py +271 -0
  68. aiecs/application/knowledge_graph/validators/__init__.py +13 -0
  69. aiecs/application/knowledge_graph/validators/relation_validator.py +239 -0
  70. aiecs/application/knowledge_graph/visualization/__init__.py +11 -0
  71. aiecs/application/knowledge_graph/visualization/graph_visualizer.py +313 -0
  72. aiecs/common/__init__.py +9 -0
  73. aiecs/common/knowledge_graph/__init__.py +17 -0
  74. aiecs/common/knowledge_graph/runnable.py +471 -0
  75. aiecs/config/__init__.py +20 -5
  76. aiecs/config/config.py +762 -31
  77. aiecs/config/graph_config.py +131 -0
  78. aiecs/config/tool_config.py +399 -0
  79. aiecs/core/__init__.py +29 -13
  80. aiecs/core/interface/__init__.py +2 -2
  81. aiecs/core/interface/execution_interface.py +22 -22
  82. aiecs/core/interface/storage_interface.py +37 -88
  83. aiecs/core/registry/__init__.py +31 -0
  84. aiecs/core/registry/service_registry.py +92 -0
  85. aiecs/domain/__init__.py +270 -1
  86. aiecs/domain/agent/__init__.py +191 -0
  87. aiecs/domain/agent/base_agent.py +3870 -0
  88. aiecs/domain/agent/exceptions.py +99 -0
  89. aiecs/domain/agent/graph_aware_mixin.py +569 -0
  90. aiecs/domain/agent/hybrid_agent.py +1435 -0
  91. aiecs/domain/agent/integration/__init__.py +29 -0
  92. aiecs/domain/agent/integration/context_compressor.py +216 -0
  93. aiecs/domain/agent/integration/context_engine_adapter.py +587 -0
  94. aiecs/domain/agent/integration/protocols.py +281 -0
  95. aiecs/domain/agent/integration/retry_policy.py +218 -0
  96. aiecs/domain/agent/integration/role_config.py +213 -0
  97. aiecs/domain/agent/knowledge_aware_agent.py +1892 -0
  98. aiecs/domain/agent/lifecycle.py +291 -0
  99. aiecs/domain/agent/llm_agent.py +692 -0
  100. aiecs/domain/agent/memory/__init__.py +12 -0
  101. aiecs/domain/agent/memory/conversation.py +1124 -0
  102. aiecs/domain/agent/migration/__init__.py +14 -0
  103. aiecs/domain/agent/migration/conversion.py +163 -0
  104. aiecs/domain/agent/migration/legacy_wrapper.py +86 -0
  105. aiecs/domain/agent/models.py +884 -0
  106. aiecs/domain/agent/observability.py +479 -0
  107. aiecs/domain/agent/persistence.py +449 -0
  108. aiecs/domain/agent/prompts/__init__.py +29 -0
  109. aiecs/domain/agent/prompts/builder.py +159 -0
  110. aiecs/domain/agent/prompts/formatters.py +187 -0
  111. aiecs/domain/agent/prompts/template.py +255 -0
  112. aiecs/domain/agent/registry.py +253 -0
  113. aiecs/domain/agent/tool_agent.py +444 -0
  114. aiecs/domain/agent/tools/__init__.py +15 -0
  115. aiecs/domain/agent/tools/schema_generator.py +364 -0
  116. aiecs/domain/community/__init__.py +155 -0
  117. aiecs/domain/community/agent_adapter.py +469 -0
  118. aiecs/domain/community/analytics.py +432 -0
  119. aiecs/domain/community/collaborative_workflow.py +648 -0
  120. aiecs/domain/community/communication_hub.py +634 -0
  121. aiecs/domain/community/community_builder.py +320 -0
  122. aiecs/domain/community/community_integration.py +796 -0
  123. aiecs/domain/community/community_manager.py +803 -0
  124. aiecs/domain/community/decision_engine.py +849 -0
  125. aiecs/domain/community/exceptions.py +231 -0
  126. aiecs/domain/community/models/__init__.py +33 -0
  127. aiecs/domain/community/models/community_models.py +234 -0
  128. aiecs/domain/community/resource_manager.py +461 -0
  129. aiecs/domain/community/shared_context_manager.py +589 -0
  130. aiecs/domain/context/__init__.py +40 -10
  131. aiecs/domain/context/context_engine.py +1910 -0
  132. aiecs/domain/context/conversation_models.py +87 -53
  133. aiecs/domain/context/graph_memory.py +582 -0
  134. aiecs/domain/execution/model.py +12 -4
  135. aiecs/domain/knowledge_graph/__init__.py +19 -0
  136. aiecs/domain/knowledge_graph/models/__init__.py +52 -0
  137. aiecs/domain/knowledge_graph/models/entity.py +148 -0
  138. aiecs/domain/knowledge_graph/models/evidence.py +178 -0
  139. aiecs/domain/knowledge_graph/models/inference_rule.py +184 -0
  140. aiecs/domain/knowledge_graph/models/path.py +171 -0
  141. aiecs/domain/knowledge_graph/models/path_pattern.py +171 -0
  142. aiecs/domain/knowledge_graph/models/query.py +261 -0
  143. aiecs/domain/knowledge_graph/models/query_plan.py +181 -0
  144. aiecs/domain/knowledge_graph/models/relation.py +202 -0
  145. aiecs/domain/knowledge_graph/schema/__init__.py +23 -0
  146. aiecs/domain/knowledge_graph/schema/entity_type.py +131 -0
  147. aiecs/domain/knowledge_graph/schema/graph_schema.py +253 -0
  148. aiecs/domain/knowledge_graph/schema/property_schema.py +143 -0
  149. aiecs/domain/knowledge_graph/schema/relation_type.py +163 -0
  150. aiecs/domain/knowledge_graph/schema/schema_manager.py +691 -0
  151. aiecs/domain/knowledge_graph/schema/type_enums.py +209 -0
  152. aiecs/domain/task/dsl_processor.py +172 -56
  153. aiecs/domain/task/model.py +20 -8
  154. aiecs/domain/task/task_context.py +27 -24
  155. aiecs/infrastructure/__init__.py +0 -2
  156. aiecs/infrastructure/graph_storage/__init__.py +11 -0
  157. aiecs/infrastructure/graph_storage/base.py +837 -0
  158. aiecs/infrastructure/graph_storage/batch_operations.py +458 -0
  159. aiecs/infrastructure/graph_storage/cache.py +424 -0
  160. aiecs/infrastructure/graph_storage/distributed.py +223 -0
  161. aiecs/infrastructure/graph_storage/error_handling.py +380 -0
  162. aiecs/infrastructure/graph_storage/graceful_degradation.py +294 -0
  163. aiecs/infrastructure/graph_storage/health_checks.py +378 -0
  164. aiecs/infrastructure/graph_storage/in_memory.py +1197 -0
  165. aiecs/infrastructure/graph_storage/index_optimization.py +446 -0
  166. aiecs/infrastructure/graph_storage/lazy_loading.py +431 -0
  167. aiecs/infrastructure/graph_storage/metrics.py +344 -0
  168. aiecs/infrastructure/graph_storage/migration.py +400 -0
  169. aiecs/infrastructure/graph_storage/pagination.py +483 -0
  170. aiecs/infrastructure/graph_storage/performance_monitoring.py +456 -0
  171. aiecs/infrastructure/graph_storage/postgres.py +1563 -0
  172. aiecs/infrastructure/graph_storage/property_storage.py +353 -0
  173. aiecs/infrastructure/graph_storage/protocols.py +76 -0
  174. aiecs/infrastructure/graph_storage/query_optimizer.py +642 -0
  175. aiecs/infrastructure/graph_storage/schema_cache.py +290 -0
  176. aiecs/infrastructure/graph_storage/sqlite.py +1373 -0
  177. aiecs/infrastructure/graph_storage/streaming.py +487 -0
  178. aiecs/infrastructure/graph_storage/tenant.py +412 -0
  179. aiecs/infrastructure/messaging/celery_task_manager.py +92 -54
  180. aiecs/infrastructure/messaging/websocket_manager.py +51 -35
  181. aiecs/infrastructure/monitoring/__init__.py +22 -0
  182. aiecs/infrastructure/monitoring/executor_metrics.py +45 -11
  183. aiecs/infrastructure/monitoring/global_metrics_manager.py +212 -0
  184. aiecs/infrastructure/monitoring/structured_logger.py +3 -7
  185. aiecs/infrastructure/monitoring/tracing_manager.py +63 -35
  186. aiecs/infrastructure/persistence/__init__.py +14 -1
  187. aiecs/infrastructure/persistence/context_engine_client.py +184 -0
  188. aiecs/infrastructure/persistence/database_manager.py +67 -43
  189. aiecs/infrastructure/persistence/file_storage.py +180 -103
  190. aiecs/infrastructure/persistence/redis_client.py +74 -21
  191. aiecs/llm/__init__.py +73 -25
  192. aiecs/llm/callbacks/__init__.py +11 -0
  193. aiecs/llm/{custom_callbacks.py → callbacks/custom_callbacks.py} +26 -19
  194. aiecs/llm/client_factory.py +224 -36
  195. aiecs/llm/client_resolver.py +155 -0
  196. aiecs/llm/clients/__init__.py +38 -0
  197. aiecs/llm/clients/base_client.py +324 -0
  198. aiecs/llm/clients/google_function_calling_mixin.py +457 -0
  199. aiecs/llm/clients/googleai_client.py +241 -0
  200. aiecs/llm/clients/openai_client.py +158 -0
  201. aiecs/llm/clients/openai_compatible_mixin.py +367 -0
  202. aiecs/llm/clients/vertex_client.py +897 -0
  203. aiecs/llm/clients/xai_client.py +201 -0
  204. aiecs/llm/config/__init__.py +51 -0
  205. aiecs/llm/config/config_loader.py +272 -0
  206. aiecs/llm/config/config_validator.py +206 -0
  207. aiecs/llm/config/model_config.py +143 -0
  208. aiecs/llm/protocols.py +149 -0
  209. aiecs/llm/utils/__init__.py +10 -0
  210. aiecs/llm/utils/validate_config.py +89 -0
  211. aiecs/main.py +140 -121
  212. aiecs/scripts/aid/VERSION_MANAGEMENT.md +138 -0
  213. aiecs/scripts/aid/__init__.py +19 -0
  214. aiecs/scripts/aid/module_checker.py +499 -0
  215. aiecs/scripts/aid/version_manager.py +235 -0
  216. aiecs/scripts/{DEPENDENCY_SYSTEM_SUMMARY.md → dependance_check/DEPENDENCY_SYSTEM_SUMMARY.md} +1 -0
  217. aiecs/scripts/{README_DEPENDENCY_CHECKER.md → dependance_check/README_DEPENDENCY_CHECKER.md} +1 -0
  218. aiecs/scripts/dependance_check/__init__.py +15 -0
  219. aiecs/scripts/dependance_check/dependency_checker.py +1835 -0
  220. aiecs/scripts/{dependency_fixer.py → dependance_check/dependency_fixer.py} +192 -90
  221. aiecs/scripts/{download_nlp_data.py → dependance_check/download_nlp_data.py} +203 -71
  222. aiecs/scripts/dependance_patch/__init__.py +7 -0
  223. aiecs/scripts/dependance_patch/fix_weasel/__init__.py +11 -0
  224. aiecs/scripts/{fix_weasel_validator.py → dependance_patch/fix_weasel/fix_weasel_validator.py} +21 -14
  225. aiecs/scripts/{patch_weasel_library.sh → dependance_patch/fix_weasel/patch_weasel_library.sh} +1 -1
  226. aiecs/scripts/knowledge_graph/__init__.py +3 -0
  227. aiecs/scripts/knowledge_graph/run_threshold_experiments.py +212 -0
  228. aiecs/scripts/migrations/multi_tenancy/README.md +142 -0
  229. aiecs/scripts/tools_develop/README.md +671 -0
  230. aiecs/scripts/tools_develop/README_CONFIG_CHECKER.md +273 -0
  231. aiecs/scripts/tools_develop/TOOLS_CONFIG_GUIDE.md +1287 -0
  232. aiecs/scripts/tools_develop/TOOL_AUTO_DISCOVERY.md +234 -0
  233. aiecs/scripts/tools_develop/__init__.py +21 -0
  234. aiecs/scripts/tools_develop/check_all_tools_config.py +548 -0
  235. aiecs/scripts/tools_develop/check_type_annotations.py +257 -0
  236. aiecs/scripts/tools_develop/pre-commit-schema-coverage.sh +66 -0
  237. aiecs/scripts/tools_develop/schema_coverage.py +511 -0
  238. aiecs/scripts/tools_develop/validate_tool_schemas.py +475 -0
  239. aiecs/scripts/tools_develop/verify_executor_config_fix.py +98 -0
  240. aiecs/scripts/tools_develop/verify_tools.py +352 -0
  241. aiecs/tasks/__init__.py +0 -1
  242. aiecs/tasks/worker.py +115 -47
  243. aiecs/tools/__init__.py +194 -72
  244. aiecs/tools/apisource/__init__.py +99 -0
  245. aiecs/tools/apisource/intelligence/__init__.py +19 -0
  246. aiecs/tools/apisource/intelligence/data_fusion.py +632 -0
  247. aiecs/tools/apisource/intelligence/query_analyzer.py +417 -0
  248. aiecs/tools/apisource/intelligence/search_enhancer.py +385 -0
  249. aiecs/tools/apisource/monitoring/__init__.py +9 -0
  250. aiecs/tools/apisource/monitoring/metrics.py +330 -0
  251. aiecs/tools/apisource/providers/__init__.py +112 -0
  252. aiecs/tools/apisource/providers/base.py +671 -0
  253. aiecs/tools/apisource/providers/census.py +397 -0
  254. aiecs/tools/apisource/providers/fred.py +535 -0
  255. aiecs/tools/apisource/providers/newsapi.py +409 -0
  256. aiecs/tools/apisource/providers/worldbank.py +352 -0
  257. aiecs/tools/apisource/reliability/__init__.py +12 -0
  258. aiecs/tools/apisource/reliability/error_handler.py +363 -0
  259. aiecs/tools/apisource/reliability/fallback_strategy.py +376 -0
  260. aiecs/tools/apisource/tool.py +832 -0
  261. aiecs/tools/apisource/utils/__init__.py +9 -0
  262. aiecs/tools/apisource/utils/validators.py +334 -0
  263. aiecs/tools/base_tool.py +415 -21
  264. aiecs/tools/docs/__init__.py +121 -0
  265. aiecs/tools/docs/ai_document_orchestrator.py +607 -0
  266. aiecs/tools/docs/ai_document_writer_orchestrator.py +2350 -0
  267. aiecs/tools/docs/content_insertion_tool.py +1320 -0
  268. aiecs/tools/docs/document_creator_tool.py +1323 -0
  269. aiecs/tools/docs/document_layout_tool.py +1160 -0
  270. aiecs/tools/docs/document_parser_tool.py +1011 -0
  271. aiecs/tools/docs/document_writer_tool.py +1829 -0
  272. aiecs/tools/knowledge_graph/__init__.py +17 -0
  273. aiecs/tools/knowledge_graph/graph_reasoning_tool.py +807 -0
  274. aiecs/tools/knowledge_graph/graph_search_tool.py +944 -0
  275. aiecs/tools/knowledge_graph/kg_builder_tool.py +524 -0
  276. aiecs/tools/langchain_adapter.py +300 -138
  277. aiecs/tools/schema_generator.py +455 -0
  278. aiecs/tools/search_tool/__init__.py +100 -0
  279. aiecs/tools/search_tool/analyzers.py +581 -0
  280. aiecs/tools/search_tool/cache.py +264 -0
  281. aiecs/tools/search_tool/constants.py +128 -0
  282. aiecs/tools/search_tool/context.py +224 -0
  283. aiecs/tools/search_tool/core.py +778 -0
  284. aiecs/tools/search_tool/deduplicator.py +119 -0
  285. aiecs/tools/search_tool/error_handler.py +242 -0
  286. aiecs/tools/search_tool/metrics.py +343 -0
  287. aiecs/tools/search_tool/rate_limiter.py +172 -0
  288. aiecs/tools/search_tool/schemas.py +275 -0
  289. aiecs/tools/statistics/__init__.py +80 -0
  290. aiecs/tools/statistics/ai_data_analysis_orchestrator.py +646 -0
  291. aiecs/tools/statistics/ai_insight_generator_tool.py +508 -0
  292. aiecs/tools/statistics/ai_report_orchestrator_tool.py +684 -0
  293. aiecs/tools/statistics/data_loader_tool.py +555 -0
  294. aiecs/tools/statistics/data_profiler_tool.py +638 -0
  295. aiecs/tools/statistics/data_transformer_tool.py +580 -0
  296. aiecs/tools/statistics/data_visualizer_tool.py +498 -0
  297. aiecs/tools/statistics/model_trainer_tool.py +507 -0
  298. aiecs/tools/statistics/statistical_analyzer_tool.py +472 -0
  299. aiecs/tools/task_tools/__init__.py +49 -36
  300. aiecs/tools/task_tools/chart_tool.py +200 -184
  301. aiecs/tools/task_tools/classfire_tool.py +268 -267
  302. aiecs/tools/task_tools/image_tool.py +175 -131
  303. aiecs/tools/task_tools/office_tool.py +226 -146
  304. aiecs/tools/task_tools/pandas_tool.py +477 -121
  305. aiecs/tools/task_tools/report_tool.py +390 -142
  306. aiecs/tools/task_tools/research_tool.py +149 -79
  307. aiecs/tools/task_tools/scraper_tool.py +339 -145
  308. aiecs/tools/task_tools/stats_tool.py +448 -209
  309. aiecs/tools/temp_file_manager.py +26 -24
  310. aiecs/tools/tool_executor/__init__.py +18 -16
  311. aiecs/tools/tool_executor/tool_executor.py +364 -52
  312. aiecs/utils/LLM_output_structor.py +74 -48
  313. aiecs/utils/__init__.py +14 -3
  314. aiecs/utils/base_callback.py +0 -3
  315. aiecs/utils/cache_provider.py +696 -0
  316. aiecs/utils/execution_utils.py +50 -31
  317. aiecs/utils/prompt_loader.py +1 -0
  318. aiecs/utils/token_usage_repository.py +37 -11
  319. aiecs/ws/socket_server.py +14 -4
  320. {aiecs-1.0.1.dist-info → aiecs-1.7.6.dist-info}/METADATA +52 -15
  321. aiecs-1.7.6.dist-info/RECORD +337 -0
  322. aiecs-1.7.6.dist-info/entry_points.txt +13 -0
  323. aiecs/config/registry.py +0 -19
  324. aiecs/domain/context/content_engine.py +0 -982
  325. aiecs/llm/base_client.py +0 -99
  326. aiecs/llm/openai_client.py +0 -125
  327. aiecs/llm/vertex_client.py +0 -186
  328. aiecs/llm/xai_client.py +0 -184
  329. aiecs/scripts/dependency_checker.py +0 -857
  330. aiecs/scripts/quick_dependency_check.py +0 -269
  331. aiecs/tools/task_tools/search_api.py +0 -7
  332. aiecs-1.0.1.dist-info/RECORD +0 -90
  333. aiecs-1.0.1.dist-info/entry_points.txt +0 -7
  334. /aiecs/scripts/{setup_nlp_data.sh → dependance_check/setup_nlp_data.sh} +0 -0
  335. /aiecs/scripts/{README_WEASEL_PATCH.md → dependance_patch/fix_weasel/README_WEASEL_PATCH.md} +0 -0
  336. /aiecs/scripts/{fix_weasel_validator.sh → dependance_patch/fix_weasel/fix_weasel_validator.sh} +0 -0
  337. /aiecs/scripts/{run_weasel_patch.sh → dependance_patch/fix_weasel/run_weasel_patch.sh} +0 -0
  338. {aiecs-1.0.1.dist-info → aiecs-1.7.6.dist-info}/WHEEL +0 -0
  339. {aiecs-1.0.1.dist-info → aiecs-1.7.6.dist-info}/licenses/LICENSE +0 -0
  340. {aiecs-1.0.1.dist-info → aiecs-1.7.6.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,691 @@
1
+ """
2
+ Schema Manager
3
+
4
+ Service for managing knowledge graph schemas with CRUD operations.
5
+ Supports multi-tenancy with tenant-scoped schemas and global fallback.
6
+ """
7
+
8
+ from typing import Optional, List, Dict, Any, Type
9
+ from enum import Enum
10
+ import json
11
+ from pathlib import Path
12
+ from aiecs.domain.knowledge_graph.schema.graph_schema import GraphSchema
13
+ from aiecs.domain.knowledge_graph.schema.entity_type import EntityType
14
+ from aiecs.domain.knowledge_graph.schema.relation_type import RelationType
15
+ from aiecs.domain.knowledge_graph.schema.property_schema import PropertySchema
16
+ from aiecs.domain.knowledge_graph.schema.type_enums import TypeEnumGenerator
17
+ from aiecs.infrastructure.graph_storage.schema_cache import LRUCache
18
+ from aiecs.infrastructure.graph_storage.tenant import TenantContext
19
+
20
+
21
+ class SchemaManager:
22
+ """
23
+ Schema Manager Service
24
+
25
+ Manages knowledge graph schemas with support for:
26
+ - Creating, reading, updating, deleting entity and relation types
27
+ - Schema persistence (save/load from JSON)
28
+ - Schema validation
29
+ - Transaction-like operations (commit/rollback)
30
+ - LRU caching with TTL for performance optimization
31
+
32
+ Example:
33
+ ```python
34
+ manager = SchemaManager(cache_size=1000, ttl_seconds=3600)
35
+
36
+ # Add entity type
37
+ person_type = EntityType(name="Person", ...)
38
+ manager.create_entity_type(person_type)
39
+
40
+ # Get entity type (cached)
41
+ person = manager.get_entity_type("Person")
42
+
43
+ # Check cache stats
44
+ stats = manager.get_cache_stats()
45
+ print(f"Cache hit rate: {stats['hit_rate']:.2%}")
46
+
47
+ # Save schema
48
+ manager.save("./schema.json")
49
+ ```
50
+ """
51
+
52
+ def __init__(
53
+ self,
54
+ schema: Optional[GraphSchema] = None,
55
+ cache_size: int = 1000,
56
+ ttl_seconds: Optional[int] = 3600,
57
+ enable_cache: bool = True,
58
+ ):
59
+ """
60
+ Initialize schema manager with multi-tenancy support
61
+
62
+ Args:
63
+ schema: Initial global schema (default: empty schema)
64
+ cache_size: Maximum cache size (default: 1000)
65
+ ttl_seconds: Cache TTL in seconds (default: 3600, None = no expiration)
66
+ enable_cache: Whether to enable caching (default: True)
67
+ """
68
+ # Global schema (tenant_id=None)
69
+ self.schema = schema if schema is not None else GraphSchema()
70
+ self._transaction_schema: Optional[GraphSchema] = None
71
+
72
+ # Tenant-scoped schemas: tenant_id -> GraphSchema
73
+ self._tenant_schemas: Dict[str, GraphSchema] = {}
74
+
75
+ # Initialize caches
76
+ self._enable_cache = enable_cache
77
+ # Declare cache variables as Optional before if/else to avoid type conflicts
78
+ self._entity_type_cache: Optional[LRUCache[EntityType]]
79
+ self._relation_type_cache: Optional[LRUCache[RelationType]]
80
+ self._property_cache: Optional[LRUCache[PropertySchema]]
81
+ if enable_cache:
82
+ self._entity_type_cache = LRUCache(max_size=cache_size, ttl_seconds=ttl_seconds)
83
+ self._relation_type_cache = LRUCache(max_size=cache_size, ttl_seconds=ttl_seconds)
84
+ self._property_cache = LRUCache(max_size=cache_size, ttl_seconds=ttl_seconds)
85
+ else:
86
+ self._entity_type_cache = None
87
+ self._relation_type_cache = None
88
+ self._property_cache = None
89
+
90
+ def _get_schema(self, tenant_id: Optional[str] = None) -> GraphSchema:
91
+ """
92
+ Get schema for a specific tenant (with fallback to global)
93
+
94
+ Args:
95
+ tenant_id: Tenant ID (None = global schema)
96
+
97
+ Returns:
98
+ GraphSchema for the tenant (or global if tenant schema doesn't exist)
99
+ """
100
+ if tenant_id is None:
101
+ return self.schema
102
+
103
+ # Return tenant-specific schema if it exists, otherwise use global
104
+ return self._tenant_schemas.get(tenant_id, self.schema)
105
+
106
+ def _ensure_tenant_schema(self, tenant_id: str) -> GraphSchema:
107
+ """
108
+ Ensure a tenant-specific schema exists (creates if needed)
109
+
110
+ Args:
111
+ tenant_id: Tenant ID
112
+
113
+ Returns:
114
+ Tenant-specific GraphSchema
115
+
116
+ Note:
117
+ Creates an empty schema for the tenant. Global types are accessible
118
+ via fallback mechanism in get_entity_type/get_relation_type methods.
119
+ """
120
+ if tenant_id not in self._tenant_schemas:
121
+ # Create new empty schema for tenant
122
+ # Fallback to global schema happens in get methods
123
+ self._tenant_schemas[tenant_id] = GraphSchema()
124
+
125
+ return self._tenant_schemas[tenant_id]
126
+
127
+ def _make_cache_key(self, type_name: str, tenant_id: Optional[str] = None) -> str:
128
+ """
129
+ Create cache key with tenant scope
130
+
131
+ Args:
132
+ type_name: Type name
133
+ tenant_id: Tenant ID (None = global)
134
+
135
+ Returns:
136
+ Cache key string
137
+ """
138
+ if tenant_id is None:
139
+ return type_name
140
+ return f"{tenant_id}:{type_name}"
141
+
142
+ # Entity Type Operations
143
+
144
+ def create_entity_type(self, entity_type: EntityType, tenant_id: Optional[str] = None) -> None:
145
+ """
146
+ Create a new entity type (tenant-scoped or global)
147
+
148
+ Args:
149
+ entity_type: Entity type to create
150
+ tenant_id: Tenant ID for tenant-scoped schema (None = global)
151
+
152
+ Raises:
153
+ ValueError: If entity type already exists
154
+
155
+ Note:
156
+ Tenant schemas are independent from global schema. The same type name
157
+ can exist in both global and tenant schemas with different definitions.
158
+ """
159
+ schema = self._ensure_tenant_schema(tenant_id) if tenant_id else self.schema
160
+
161
+ # Safety check: ensure tenant schema is not the global schema
162
+ if tenant_id is not None and schema is self.schema:
163
+ raise RuntimeError(f"Internal error: tenant schema for '{tenant_id}' is referencing global schema")
164
+
165
+ schema.add_entity_type(entity_type)
166
+
167
+ # Cache the new entity type with tenant-scoped key
168
+ if self._enable_cache and self._entity_type_cache:
169
+ cache_key = self._make_cache_key(entity_type.name, tenant_id)
170
+ self._entity_type_cache.set(cache_key, entity_type)
171
+
172
+ def register_entity_type(self, entity_type: EntityType, tenant_id: Optional[str] = None) -> None:
173
+ """
174
+ Register a new entity type (alias for create_entity_type)
175
+
176
+ Args:
177
+ entity_type: Entity type to register
178
+ tenant_id: Tenant ID for tenant-scoped schema (None = global)
179
+
180
+ Raises:
181
+ ValueError: If entity type already exists
182
+ """
183
+ self.create_entity_type(entity_type, tenant_id=tenant_id)
184
+
185
+ def update_entity_type(self, entity_type: EntityType, tenant_id: Optional[str] = None) -> None:
186
+ """
187
+ Update an existing entity type (tenant-scoped or global)
188
+
189
+ Args:
190
+ entity_type: Updated entity type
191
+ tenant_id: Tenant ID for tenant-scoped schema (None = global)
192
+
193
+ Raises:
194
+ ValueError: If entity type doesn't exist
195
+ """
196
+ schema = self._get_schema(tenant_id)
197
+ schema.update_entity_type(entity_type)
198
+
199
+ # Invalidate cache for this entity type
200
+ if self._enable_cache and self._entity_type_cache:
201
+ cache_key = self._make_cache_key(entity_type.name, tenant_id)
202
+ self._entity_type_cache.delete(cache_key)
203
+
204
+ def delete_entity_type(self, type_name: str, tenant_id: Optional[str] = None) -> None:
205
+ """
206
+ Delete an entity type (tenant-scoped or global)
207
+
208
+ Args:
209
+ type_name: Name of entity type to delete
210
+ tenant_id: Tenant ID for tenant-scoped schema (None = global)
211
+
212
+ Raises:
213
+ ValueError: If entity type doesn't exist or is in use
214
+ """
215
+ schema = self._get_schema(tenant_id)
216
+ schema.delete_entity_type(type_name)
217
+
218
+ # Invalidate cache for this entity type
219
+ if self._enable_cache and self._entity_type_cache:
220
+ cache_key = self._make_cache_key(type_name, tenant_id)
221
+ self._entity_type_cache.delete(cache_key)
222
+
223
+ def get_entity_type(self, type_name: str, tenant_id: Optional[str] = None) -> Optional[EntityType]:
224
+ """
225
+ Get an entity type by name (with caching and tenant-scoped fallback)
226
+
227
+ Args:
228
+ type_name: Name of entity type
229
+ tenant_id: Tenant ID for tenant-scoped schema (None = global)
230
+
231
+ Returns:
232
+ Entity type or None if not found
233
+
234
+ Note:
235
+ Falls back to global schema if tenant schema doesn't have the type
236
+ """
237
+ cache_key = self._make_cache_key(type_name, tenant_id)
238
+
239
+ # Try cache first
240
+ if self._enable_cache and self._entity_type_cache:
241
+ cached = self._entity_type_cache.get(cache_key)
242
+ if cached is not None:
243
+ return cached
244
+
245
+ # Load from tenant schema first
246
+ if tenant_id is not None:
247
+ tenant_schema = self._tenant_schemas.get(tenant_id)
248
+ if tenant_schema is not None:
249
+ entity_type = tenant_schema.get_entity_type(type_name)
250
+ if entity_type is not None:
251
+ # Cache the tenant-specific result
252
+ if self._enable_cache and self._entity_type_cache:
253
+ self._entity_type_cache.set(cache_key, entity_type)
254
+ return entity_type
255
+
256
+ # Fall back to global schema
257
+ entity_type = self.schema.get_entity_type(type_name)
258
+
259
+ # Cache the result if found
260
+ if entity_type is not None and self._enable_cache and self._entity_type_cache:
261
+ self._entity_type_cache.set(cache_key, entity_type)
262
+
263
+ return entity_type
264
+
265
+ def list_entity_types(self, tenant_id: Optional[str] = None) -> List[str]:
266
+ """
267
+ List all entity type names (tenant-scoped or global)
268
+
269
+ Args:
270
+ tenant_id: Tenant ID for tenant-scoped schema (None = global)
271
+
272
+ Returns:
273
+ List of entity type names (includes tenant-specific + global if tenant_id provided)
274
+
275
+ Note:
276
+ When tenant_id is provided, returns union of tenant-specific and global types
277
+ """
278
+ schema = self._get_schema(tenant_id)
279
+ tenant_types = set(schema.get_entity_type_names())
280
+
281
+ # If querying tenant schema, also include global types (fallback)
282
+ if tenant_id is not None and tenant_id in self._tenant_schemas:
283
+ global_types = set(self.schema.get_entity_type_names())
284
+ tenant_types.update(global_types)
285
+
286
+ return sorted(list(tenant_types))
287
+
288
+ # Relation Type Operations
289
+
290
+ def create_relation_type(self, relation_type: RelationType, tenant_id: Optional[str] = None) -> None:
291
+ """
292
+ Create a new relation type (tenant-scoped or global)
293
+
294
+ Args:
295
+ relation_type: Relation type to create
296
+ tenant_id: Tenant ID for tenant-scoped schema (None = global)
297
+
298
+ Raises:
299
+ ValueError: If relation type already exists
300
+ """
301
+ schema = self._ensure_tenant_schema(tenant_id) if tenant_id else self.schema
302
+ schema.add_relation_type(relation_type)
303
+
304
+ # Cache the new relation type with tenant-scoped key
305
+ if self._enable_cache and self._relation_type_cache:
306
+ cache_key = self._make_cache_key(relation_type.name, tenant_id)
307
+ self._relation_type_cache.set(cache_key, relation_type)
308
+
309
+ def update_relation_type(self, relation_type: RelationType, tenant_id: Optional[str] = None) -> None:
310
+ """
311
+ Update an existing relation type (tenant-scoped or global)
312
+
313
+ Args:
314
+ relation_type: Updated relation type
315
+ tenant_id: Tenant ID for tenant-scoped schema (None = global)
316
+
317
+ Raises:
318
+ ValueError: If relation type doesn't exist
319
+ """
320
+ schema = self._get_schema(tenant_id)
321
+ schema.update_relation_type(relation_type)
322
+
323
+ # Invalidate cache for this relation type
324
+ if self._enable_cache and self._relation_type_cache:
325
+ cache_key = self._make_cache_key(relation_type.name, tenant_id)
326
+ self._relation_type_cache.delete(cache_key)
327
+
328
+ def delete_relation_type(self, type_name: str, tenant_id: Optional[str] = None) -> None:
329
+ """
330
+ Delete a relation type (tenant-scoped or global)
331
+
332
+ Args:
333
+ type_name: Name of relation type to delete
334
+ tenant_id: Tenant ID for tenant-scoped schema (None = global)
335
+
336
+ Raises:
337
+ ValueError: If relation type doesn't exist
338
+ """
339
+ schema = self._get_schema(tenant_id)
340
+ schema.delete_relation_type(type_name)
341
+
342
+ # Invalidate cache for this relation type
343
+ if self._enable_cache and self._relation_type_cache:
344
+ cache_key = self._make_cache_key(type_name, tenant_id)
345
+ self._relation_type_cache.delete(cache_key)
346
+
347
+ def get_relation_type(self, type_name: str, tenant_id: Optional[str] = None) -> Optional[RelationType]:
348
+ """
349
+ Get a relation type by name (with caching and tenant-scoped fallback)
350
+
351
+ Args:
352
+ type_name: Name of relation type
353
+ tenant_id: Tenant ID for tenant-scoped schema (None = global)
354
+
355
+ Returns:
356
+ Relation type or None if not found
357
+
358
+ Note:
359
+ Falls back to global schema if tenant schema doesn't have the type
360
+ """
361
+ cache_key = self._make_cache_key(type_name, tenant_id)
362
+
363
+ # Try cache first
364
+ if self._enable_cache and self._relation_type_cache:
365
+ cached = self._relation_type_cache.get(cache_key)
366
+ if cached is not None:
367
+ return cached
368
+
369
+ # Load from tenant schema first
370
+ if tenant_id is not None:
371
+ tenant_schema = self._tenant_schemas.get(tenant_id)
372
+ if tenant_schema is not None:
373
+ relation_type = tenant_schema.get_relation_type(type_name)
374
+ if relation_type is not None:
375
+ # Cache the tenant-specific result
376
+ if self._enable_cache and self._relation_type_cache:
377
+ self._relation_type_cache.set(cache_key, relation_type)
378
+ return relation_type
379
+
380
+ # Fall back to global schema
381
+ relation_type = self.schema.get_relation_type(type_name)
382
+
383
+ # Cache the result if found
384
+ if relation_type is not None and self._enable_cache and self._relation_type_cache:
385
+ self._relation_type_cache.set(cache_key, relation_type)
386
+
387
+ return relation_type
388
+
389
+ def list_relation_types(self, tenant_id: Optional[str] = None) -> List[str]:
390
+ """
391
+ List all relation type names (tenant-scoped or global)
392
+
393
+ Args:
394
+ tenant_id: Tenant ID for tenant-scoped schema (None = global)
395
+
396
+ Returns:
397
+ List of relation type names (includes tenant-specific + global if tenant_id provided)
398
+
399
+ Note:
400
+ When tenant_id is provided, returns union of tenant-specific and global types
401
+ """
402
+ schema = self._get_schema(tenant_id)
403
+ tenant_types = set(schema.get_relation_type_names())
404
+
405
+ # If querying tenant schema, also include global types (fallback)
406
+ if tenant_id is not None and tenant_id in self._tenant_schemas:
407
+ global_types = set(self.schema.get_relation_type_names())
408
+ tenant_types.update(global_types)
409
+
410
+ return sorted(list(tenant_types))
411
+
412
+ # Schema Validation
413
+
414
+ def validate_entity(self, entity_type_name: str, properties: dict) -> bool:
415
+ """
416
+ Validate entity properties against schema
417
+
418
+ Args:
419
+ entity_type_name: Name of entity type
420
+ properties: Dictionary of properties to validate
421
+
422
+ Returns:
423
+ True if validation passes
424
+
425
+ Raises:
426
+ ValueError: If validation fails
427
+ """
428
+ entity_type = self.get_entity_type(entity_type_name)
429
+ if entity_type is None:
430
+ raise ValueError(f"Entity type '{entity_type_name}' not found in schema")
431
+
432
+ return entity_type.validate_properties(properties)
433
+
434
+ def validate_relation(
435
+ self,
436
+ relation_type_name: str,
437
+ source_entity_type: str,
438
+ target_entity_type: str,
439
+ properties: dict,
440
+ ) -> bool:
441
+ """
442
+ Validate relation against schema
443
+
444
+ Args:
445
+ relation_type_name: Name of relation type
446
+ source_entity_type: Source entity type name
447
+ target_entity_type: Target entity type name
448
+ properties: Dictionary of properties to validate
449
+
450
+ Returns:
451
+ True if validation passes
452
+
453
+ Raises:
454
+ ValueError: If validation fails
455
+ """
456
+ relation_type = self.get_relation_type(relation_type_name)
457
+ if relation_type is None:
458
+ raise ValueError(f"Relation type '{relation_type_name}' not found in schema")
459
+
460
+ # Validate entity types
461
+ relation_type.validate_entity_types(source_entity_type, target_entity_type)
462
+
463
+ # Validate properties
464
+ return relation_type.validate_properties(properties)
465
+
466
+ # Schema Persistence
467
+
468
+ def save(self, file_path: str) -> None:
469
+ """
470
+ Save schema to JSON file
471
+
472
+ Args:
473
+ file_path: Path to save schema
474
+ """
475
+ schema_dict = self.schema.model_dump(mode="json")
476
+
477
+ path = Path(file_path)
478
+ path.parent.mkdir(parents=True, exist_ok=True)
479
+
480
+ with open(path, "w", encoding="utf-8") as f:
481
+ json.dump(schema_dict, f, indent=2, ensure_ascii=False)
482
+
483
+ @classmethod
484
+ def load(cls, file_path: str) -> "SchemaManager":
485
+ """
486
+ Load schema from JSON file
487
+
488
+ Args:
489
+ file_path: Path to load schema from
490
+
491
+ Returns:
492
+ New SchemaManager instance with loaded schema
493
+ """
494
+ with open(file_path, "r", encoding="utf-8") as f:
495
+ schema_dict = json.load(f)
496
+
497
+ schema = GraphSchema(**schema_dict)
498
+ return cls(schema=schema)
499
+
500
+ # Transaction Support (Simple)
501
+
502
+ def begin_transaction(self) -> None:
503
+ """Begin a schema transaction"""
504
+ # Create a deep copy of the current schema
505
+ schema_json = self.schema.model_dump_json()
506
+ self._transaction_schema = GraphSchema(**json.loads(schema_json))
507
+
508
+ def commit(self) -> None:
509
+ """Commit the current transaction"""
510
+ self._transaction_schema = None
511
+
512
+ def rollback(self) -> None:
513
+ """
514
+ Rollback to the state at transaction start
515
+
516
+ Raises:
517
+ RuntimeError: If no transaction is active
518
+ """
519
+ if self._transaction_schema is None:
520
+ raise RuntimeError("No active transaction to rollback")
521
+
522
+ self.schema = self._transaction_schema
523
+ self._transaction_schema = None
524
+
525
+ @property
526
+ def is_in_transaction(self) -> bool:
527
+ """Check if a transaction is active"""
528
+ return self._transaction_schema is not None
529
+
530
+ # Cache Management
531
+
532
+ def invalidate_cache(self, type_name: Optional[str] = None, tenant_id: Optional[str] = None) -> None:
533
+ """
534
+ Invalidate cache entries (tenant-scoped or global)
535
+
536
+ Args:
537
+ type_name: Specific type to invalidate (None = invalidate all)
538
+ tenant_id: Tenant ID for tenant-scoped invalidation (None = global, "*" = all tenants)
539
+ """
540
+ if not self._enable_cache:
541
+ return
542
+
543
+ if type_name is None:
544
+ if tenant_id == "*":
545
+ # Clear all caches (all tenants)
546
+ if self._entity_type_cache:
547
+ self._entity_type_cache.clear()
548
+ if self._relation_type_cache:
549
+ self._relation_type_cache.clear()
550
+ if self._property_cache:
551
+ self._property_cache.clear()
552
+ elif tenant_id is not None:
553
+ # Clear only entries for specific tenant
554
+ self._invalidate_tenant_cache(tenant_id)
555
+ else:
556
+ # Clear global cache entries only
557
+ if self._entity_type_cache:
558
+ # Clear only non-tenant keys (no ":" in key)
559
+ for key in list(self._entity_type_cache._cache.keys()):
560
+ if ":" not in key:
561
+ self._entity_type_cache.delete(key)
562
+ if self._relation_type_cache:
563
+ for key in list(self._relation_type_cache._cache.keys()):
564
+ if ":" not in key:
565
+ self._relation_type_cache.delete(key)
566
+ else:
567
+ # Invalidate specific type with tenant scope
568
+ cache_key = self._make_cache_key(type_name, tenant_id)
569
+ if self._entity_type_cache:
570
+ self._entity_type_cache.delete(cache_key)
571
+ if self._relation_type_cache:
572
+ self._relation_type_cache.delete(cache_key)
573
+
574
+ def _invalidate_tenant_cache(self, tenant_id: str) -> None:
575
+ """
576
+ Invalidate all cache entries for a specific tenant
577
+
578
+ Args:
579
+ tenant_id: Tenant ID to invalidate
580
+ """
581
+ if not self._enable_cache:
582
+ return
583
+
584
+ tenant_prefix = f"{tenant_id}:"
585
+
586
+ # Remove all cache entries with this tenant prefix
587
+ if self._entity_type_cache:
588
+ for key in list(self._entity_type_cache._cache.keys()):
589
+ if key.startswith(tenant_prefix):
590
+ self._entity_type_cache.delete(key)
591
+
592
+ if self._relation_type_cache:
593
+ for key in list(self._relation_type_cache._cache.keys()):
594
+ if key.startswith(tenant_prefix):
595
+ self._relation_type_cache.delete(key)
596
+
597
+ if self._property_cache:
598
+ for key in list(self._property_cache._cache.keys()):
599
+ if key.startswith(tenant_prefix):
600
+ self._property_cache.delete(key)
601
+
602
+ def cleanup_expired_cache(self) -> Dict[str, int]:
603
+ """
604
+ Remove expired cache entries
605
+
606
+ Returns:
607
+ Dictionary with number of entries removed per cache
608
+ """
609
+ if not self._enable_cache:
610
+ return {"entity_types": 0, "relation_types": 0, "properties": 0}
611
+
612
+ return {
613
+ "entity_types": (self._entity_type_cache.cleanup_expired() if self._entity_type_cache else 0),
614
+ "relation_types": (self._relation_type_cache.cleanup_expired() if self._relation_type_cache else 0),
615
+ "properties": (self._property_cache.cleanup_expired() if self._property_cache else 0),
616
+ }
617
+
618
+ def get_cache_stats(self) -> Dict[str, Any]:
619
+ """
620
+ Get cache statistics
621
+
622
+ Returns:
623
+ Dictionary with cache statistics for all caches
624
+ """
625
+ if not self._enable_cache:
626
+ return {
627
+ "enabled": False,
628
+ "entity_types": {},
629
+ "relation_types": {},
630
+ "properties": {},
631
+ }
632
+
633
+ return {
634
+ "enabled": True,
635
+ "entity_types": (self._entity_type_cache.get_stats() if self._entity_type_cache else {}),
636
+ "relation_types": (self._relation_type_cache.get_stats() if self._relation_type_cache else {}),
637
+ "properties": (self._property_cache.get_stats() if self._property_cache else {}),
638
+ }
639
+
640
+ def reset_cache_metrics(self) -> None:
641
+ """Reset cache metrics (hits, misses, etc.)"""
642
+ if not self._enable_cache:
643
+ return
644
+
645
+ if self._entity_type_cache:
646
+ self._entity_type_cache.reset_metrics()
647
+ if self._relation_type_cache:
648
+ self._relation_type_cache.reset_metrics()
649
+ if self._property_cache:
650
+ self._property_cache.reset_metrics()
651
+
652
+ # Type Enum Generation (Task 3.4)
653
+
654
+ def generate_enums(self) -> Dict[str, Dict[str, Type[Enum]]]:
655
+ """
656
+ Generate type enums from schema
657
+
658
+ Creates Python Enum classes for all entity types and relation types
659
+ defined in the schema. The generated enums are string-based for
660
+ backward compatibility with existing code.
661
+
662
+ Returns:
663
+ Dictionary with "entity_types" and "relation_types" keys,
664
+ each containing a dictionary mapping type names to enum classes
665
+
666
+ Example:
667
+ >>> enums = schema_manager.generate_enums()
668
+ >>> PersonEnum = enums["entity_types"]["Person"]
669
+ >>> PersonEnum.PERSON # "Person"
670
+ >>>
671
+ >>> WorksForEnum = enums["relation_types"]["WORKS_FOR"]
672
+ >>> WorksForEnum.WORKS_FOR # "WORKS_FOR"
673
+
674
+ Note:
675
+ The generated enums are backward compatible with string literals:
676
+ >>> str(PersonEnum.PERSON) == "Person" # True
677
+ >>> PersonEnum.PERSON == "Person" # True
678
+ """
679
+ generator = TypeEnumGenerator(self.schema)
680
+ return generator.generate_all_enums()
681
+
682
+ def __str__(self) -> str:
683
+ cache_info = ""
684
+ if self._enable_cache and self._entity_type_cache:
685
+ stats = self.get_cache_stats()
686
+ entity_hit_rate = stats["entity_types"].get("hit_rate", 0)
687
+ cache_info = f", cache_hit_rate={entity_hit_rate:.2%}"
688
+ return f"SchemaManager({self.schema}{cache_info})"
689
+
690
+ def __repr__(self) -> str:
691
+ return self.__str__()