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,803 @@
1
+ """
2
+ Community Manager
3
+
4
+ Core component for managing agent communities, including governance,
5
+ resource sharing, and collaborative decision-making.
6
+ """
7
+
8
+ import logging
9
+ from datetime import datetime, timedelta
10
+ from typing import Dict, List, Any, Optional, Set, Protocol, TYPE_CHECKING
11
+
12
+ if TYPE_CHECKING:
13
+ from aiecs.domain.context.context_engine import ContextEngine
14
+ import uuid
15
+
16
+ from .models.community_models import (
17
+ AgentCommunity,
18
+ CommunityMember,
19
+ CommunityResource,
20
+ CommunityDecision,
21
+ CollaborationSession,
22
+ CommunityRole,
23
+ GovernanceType,
24
+ DecisionStatus,
25
+ ResourceType,
26
+ )
27
+ from .exceptions import CommunityValidationError as TaskValidationError
28
+
29
+ logger = logging.getLogger(__name__)
30
+
31
+
32
+ class MemberLifecycleHooks(Protocol):
33
+ """
34
+ Protocol defining lifecycle hooks for community member events.
35
+ Implement this protocol to receive notifications about member lifecycle events.
36
+ """
37
+
38
+ async def on_member_join(self, community_id: str, member_id: str, member: CommunityMember) -> None:
39
+ """Called when a member joins a community."""
40
+ ...
41
+
42
+ async def on_member_exit(
43
+ self,
44
+ community_id: str,
45
+ member_id: str,
46
+ member: CommunityMember,
47
+ reason: Optional[str] = None,
48
+ ) -> None:
49
+ """Called when a member exits/is removed from a community."""
50
+ ...
51
+
52
+ async def on_member_update(
53
+ self,
54
+ community_id: str,
55
+ member_id: str,
56
+ member: CommunityMember,
57
+ changes: Dict[str, Any],
58
+ ) -> None:
59
+ """Called when a member's properties are updated."""
60
+ ...
61
+
62
+ async def on_member_inactive(
63
+ self,
64
+ community_id: str,
65
+ member_id: str,
66
+ member: CommunityMember,
67
+ reason: Optional[str] = None,
68
+ ) -> None:
69
+ """Called when a member becomes inactive."""
70
+ ...
71
+
72
+
73
+ class CommunityManager:
74
+ """
75
+ Manager for agent communities, handling governance, collaboration, and resource sharing.
76
+ """
77
+
78
+ def __init__(self, context_engine: Optional["ContextEngine"] = None) -> None:
79
+ """
80
+ Initialize the community manager.
81
+
82
+ Args:
83
+ context_engine: Optional context engine for persistent storage
84
+ """
85
+ self.context_engine = context_engine
86
+
87
+ # In-memory storage (should be replaced with persistent storage)
88
+ self.communities: Dict[str, AgentCommunity] = {}
89
+ self.members: Dict[str, CommunityMember] = {}
90
+ self.resources: Dict[str, CommunityResource] = {}
91
+ self.decisions: Dict[str, CommunityDecision] = {}
92
+ self.sessions: Dict[str, CollaborationSession] = {}
93
+
94
+ # Community relationships
95
+ # member_id -> set of community_ids
96
+ self.member_communities: Dict[str, Set[str]] = {}
97
+ # community_id -> set of member_ids
98
+ self.community_members: Dict[str, Set[str]] = {}
99
+
100
+ # Lifecycle hooks
101
+ self.lifecycle_hooks: List[MemberLifecycleHooks] = []
102
+
103
+ self._initialized = False
104
+ logger.info("Community manager initialized")
105
+
106
+ async def initialize(self) -> None:
107
+ """Initialize the community manager."""
108
+ if self._initialized:
109
+ return
110
+
111
+ # Load existing communities and members from persistent storage if
112
+ # available
113
+ if self.context_engine:
114
+ await self._load_from_storage()
115
+
116
+ self._initialized = True
117
+ logger.info("Community manager initialization completed")
118
+
119
+ async def create_community(
120
+ self,
121
+ name: str,
122
+ description: Optional[str] = None,
123
+ governance_type: GovernanceType = GovernanceType.DEMOCRATIC,
124
+ governance_rules: Optional[Dict[str, Any]] = None,
125
+ creator_agent_id: Optional[str] = None,
126
+ ) -> str:
127
+ """
128
+ Create a new agent community.
129
+
130
+ Args:
131
+ name: Name of the community
132
+ description: Optional description
133
+ governance_type: Type of governance
134
+ governance_rules: Governance rules and policies
135
+ creator_agent_id: ID of the agent creating the community
136
+
137
+ Returns:
138
+ Community ID
139
+ """
140
+ community = AgentCommunity(
141
+ name=name,
142
+ description=description,
143
+ governance_type=governance_type,
144
+ governance_rules=governance_rules or {},
145
+ max_members=None,
146
+ updated_at=None,
147
+ )
148
+
149
+ self.communities[community.community_id] = community
150
+ self.community_members[community.community_id] = set()
151
+
152
+ # Add creator as the first leader if provided
153
+ if creator_agent_id:
154
+ await self.add_member_to_community(
155
+ community.community_id,
156
+ creator_agent_id,
157
+ community_role=CommunityRole.LEADER,
158
+ )
159
+
160
+ # Auto-save to storage
161
+ await self._save_to_storage()
162
+
163
+ logger.info(f"Created community: {name} ({community.community_id})")
164
+ return community.community_id
165
+
166
+ async def add_member_to_community(
167
+ self,
168
+ community_id: str,
169
+ agent_id: str,
170
+ agent_role: str = "general",
171
+ community_role: CommunityRole = CommunityRole.CONTRIBUTOR,
172
+ specializations: Optional[List[str]] = None,
173
+ ) -> str:
174
+ """
175
+ Add a member to a community.
176
+
177
+ Args:
178
+ community_id: ID of the community
179
+ agent_id: ID of the agent to add
180
+ agent_role: Functional role of the agent
181
+ community_role: Role within the community
182
+ specializations: Areas of specialization
183
+
184
+ Returns:
185
+ Member ID
186
+ """
187
+ if community_id not in self.communities:
188
+ raise TaskValidationError(f"Community not found: {community_id}")
189
+
190
+ # Check if agent is already a member
191
+ existing_member = self._find_member_by_agent_id(community_id, agent_id)
192
+ if existing_member:
193
+ logger.warning(f"Agent {agent_id} is already a member of community {community_id}")
194
+ return existing_member.member_id
195
+
196
+ member = CommunityMember(
197
+ member_id=str(uuid.uuid4()),
198
+ agent_id=agent_id,
199
+ agent_role=agent_role,
200
+ community_role=community_role,
201
+ specializations=specializations or [],
202
+ last_active_at=None,
203
+ )
204
+
205
+ self.members[member.member_id] = member
206
+
207
+ # Update relationships
208
+ if agent_id not in self.member_communities:
209
+ self.member_communities[agent_id] = set()
210
+ self.member_communities[agent_id].add(community_id)
211
+ self.community_members[community_id].add(member.member_id)
212
+
213
+ # Update community
214
+ community = self.communities[community_id]
215
+ community.members.append(member.member_id)
216
+
217
+ if community_role == CommunityRole.LEADER:
218
+ community.leaders.append(member.member_id)
219
+ elif community_role == CommunityRole.COORDINATOR:
220
+ community.coordinators.append(member.member_id)
221
+
222
+ # Auto-save to storage
223
+ await self._save_to_storage()
224
+
225
+ # Execute lifecycle hooks
226
+ await self._execute_hook("on_member_join", community_id, member.member_id, member)
227
+
228
+ logger.info(f"Added member {agent_id} to community {community_id} as {community_role}")
229
+ return member.member_id
230
+
231
+ async def create_community_resource(
232
+ self,
233
+ community_id: str,
234
+ owner_member_id: str,
235
+ name: str,
236
+ resource_type: ResourceType,
237
+ content: Dict[str, Any],
238
+ description: Optional[str] = None,
239
+ access_level: str = "public",
240
+ tags: Optional[List[str]] = None,
241
+ ) -> str:
242
+ """
243
+ Create a shared community resource.
244
+
245
+ Args:
246
+ community_id: ID of the community
247
+ owner_member_id: ID of the member creating the resource
248
+ name: Name of the resource
249
+ resource_type: Type of resource
250
+ content: Resource content/data
251
+ description: Optional description
252
+ access_level: Access level (public, restricted, private)
253
+ tags: Tags for categorization
254
+
255
+ Returns:
256
+ Resource ID
257
+ """
258
+ if community_id not in self.communities:
259
+ raise TaskValidationError(f"Community not found: {community_id}")
260
+
261
+ if owner_member_id not in self.members:
262
+ raise TaskValidationError(f"Member not found: {owner_member_id}")
263
+
264
+ resource = CommunityResource(
265
+ name=name,
266
+ resource_type=resource_type,
267
+ description=description,
268
+ owner_id=owner_member_id,
269
+ updated_at=None,
270
+ access_level=access_level,
271
+ content=content,
272
+ tags=tags or [],
273
+ )
274
+
275
+ self.resources[resource.resource_id] = resource
276
+
277
+ # Update community
278
+ community = self.communities[community_id]
279
+ community.shared_resources.append(resource.resource_id)
280
+ community.resource_count += 1
281
+
282
+ # Auto-save to storage
283
+ await self._save_to_storage()
284
+
285
+ logger.info(f"Created resource {name} in community {community_id}")
286
+ return resource.resource_id
287
+
288
+ async def propose_decision(
289
+ self,
290
+ community_id: str,
291
+ proposer_member_id: str,
292
+ title: str,
293
+ description: str,
294
+ decision_type: str,
295
+ implementation_plan: Optional[str] = None,
296
+ deadline: Optional[datetime] = None,
297
+ ) -> str:
298
+ """
299
+ Propose a decision for community consideration.
300
+
301
+ Args:
302
+ community_id: ID of the community
303
+ proposer_member_id: ID of the member proposing
304
+ title: Title of the proposal
305
+ description: Detailed description
306
+ decision_type: Type of decision
307
+ implementation_plan: Plan for implementation
308
+ deadline: Implementation deadline
309
+
310
+ Returns:
311
+ Decision ID
312
+ """
313
+ if community_id not in self.communities:
314
+ raise TaskValidationError(f"Community not found: {community_id}")
315
+
316
+ if proposer_member_id not in self.members:
317
+ raise TaskValidationError(f"Member not found: {proposer_member_id}")
318
+
319
+ decision = CommunityDecision(
320
+ title=title,
321
+ description=description,
322
+ proposer_id=proposer_member_id,
323
+ decision_type=decision_type,
324
+ implementation_plan=implementation_plan,
325
+ deadline=deadline,
326
+ voting_ends_at=datetime.utcnow() + timedelta(days=3), # Default 3-day voting period
327
+ implemented_at=None,
328
+ )
329
+
330
+ self.decisions[decision.decision_id] = decision
331
+
332
+ # Update community
333
+ community = self.communities[community_id]
334
+ community.decision_count += 1
335
+
336
+ # Auto-save to storage
337
+ await self._save_to_storage()
338
+
339
+ logger.info(f"Proposed decision '{title}' in community {community_id}")
340
+ return decision.decision_id
341
+
342
+ async def vote_on_decision(
343
+ self,
344
+ decision_id: str,
345
+ member_id: str,
346
+ vote: str, # "for", "against", "abstain"
347
+ ) -> bool:
348
+ """
349
+ Cast a vote on a community decision.
350
+
351
+ Args:
352
+ decision_id: ID of the decision
353
+ member_id: ID of the voting member
354
+ vote: Vote choice ("for", "against", "abstain")
355
+
356
+ Returns:
357
+ True if vote was cast successfully
358
+ """
359
+ if decision_id not in self.decisions:
360
+ raise TaskValidationError(f"Decision not found: {decision_id}")
361
+
362
+ if member_id not in self.members:
363
+ raise TaskValidationError(f"Member not found: {member_id}")
364
+
365
+ decision = self.decisions[decision_id]
366
+
367
+ # Check if voting is still open
368
+ if decision.status != DecisionStatus.VOTING and decision.status != DecisionStatus.PROPOSED:
369
+ raise TaskValidationError(f"Voting is closed for decision {decision_id}")
370
+
371
+ if decision.voting_ends_at and datetime.utcnow() > decision.voting_ends_at:
372
+ raise TaskValidationError(f"Voting period has ended for decision {decision_id}")
373
+
374
+ # Remove previous vote if exists
375
+ if member_id in decision.votes_for:
376
+ decision.votes_for.remove(member_id)
377
+ if member_id in decision.votes_against:
378
+ decision.votes_against.remove(member_id)
379
+ if member_id in decision.abstentions:
380
+ decision.abstentions.remove(member_id)
381
+
382
+ # Cast new vote
383
+ if vote.lower() == "for":
384
+ decision.votes_for.append(member_id)
385
+ elif vote.lower() == "against":
386
+ decision.votes_against.append(member_id)
387
+ elif vote.lower() == "abstain":
388
+ decision.abstentions.append(member_id)
389
+ else:
390
+ raise TaskValidationError(f"Invalid vote choice: {vote}")
391
+
392
+ # Update decision status
393
+ if decision.status == DecisionStatus.PROPOSED:
394
+ decision.status = DecisionStatus.VOTING
395
+
396
+ # Auto-save to storage
397
+ await self._save_to_storage()
398
+
399
+ logger.info(f"Member {member_id} voted '{vote}' on decision {decision_id}")
400
+ return True
401
+
402
+ async def remove_member_from_community(
403
+ self,
404
+ community_id: str,
405
+ member_id: str,
406
+ transfer_resources: bool = True,
407
+ new_owner_id: Optional[str] = None,
408
+ ) -> bool:
409
+ """
410
+ Remove a member from a community with graceful cleanup.
411
+
412
+ Args:
413
+ community_id: ID of the community
414
+ member_id: ID of the member to remove
415
+ transfer_resources: Whether to transfer member's resources
416
+ new_owner_id: Optional new owner for transferred resources
417
+
418
+ Returns:
419
+ True if member was removed successfully
420
+ """
421
+ if community_id not in self.communities:
422
+ raise TaskValidationError(f"Community not found: {community_id}")
423
+
424
+ if member_id not in self.members:
425
+ raise TaskValidationError(f"Member not found: {member_id}")
426
+
427
+ member = self.members[member_id]
428
+ community = self.communities[community_id]
429
+
430
+ # Transfer or orphan resources
431
+ if transfer_resources:
432
+ await self.transfer_member_resources(
433
+ member_id=member_id,
434
+ new_owner_id=(new_owner_id or community.leaders[0] if community.leaders else None),
435
+ community_id=community_id,
436
+ )
437
+
438
+ # Remove from community member list
439
+ if member_id in community.members:
440
+ community.members.remove(member_id)
441
+
442
+ # Remove from leadership positions
443
+ if member_id in community.leaders:
444
+ community.leaders.remove(member_id)
445
+
446
+ if member_id in community.coordinators:
447
+ community.coordinators.remove(member_id)
448
+
449
+ # Update relationships
450
+ if community_id in self.community_members:
451
+ self.community_members[community_id].discard(member_id)
452
+
453
+ if member.agent_id in self.member_communities:
454
+ self.member_communities[member.agent_id].discard(community_id)
455
+
456
+ # Mark member as inactive
457
+ member.is_active = False
458
+ member.last_active_at = datetime.utcnow()
459
+
460
+ # Auto-save to storage
461
+ await self._save_to_storage()
462
+
463
+ # Execute lifecycle hooks
464
+ await self._execute_hook("on_member_exit", community_id, member_id, member, reason="removed")
465
+
466
+ logger.info(f"Removed member {member_id} from community {community_id}")
467
+ return True
468
+
469
+ async def transfer_member_resources(self, member_id: str, new_owner_id: Optional[str], community_id: str) -> List[str]:
470
+ """
471
+ Transfer ownership of member's resources to another member.
472
+
473
+ Args:
474
+ member_id: ID of the member whose resources to transfer
475
+ new_owner_id: ID of the new owner (None = make resources orphaned/community-owned)
476
+ community_id: ID of the community
477
+
478
+ Returns:
479
+ List of transferred resource IDs
480
+ """
481
+ if member_id not in self.members:
482
+ raise TaskValidationError(f"Member not found: {member_id}")
483
+
484
+ transferred_resources = []
485
+
486
+ # Find all resources owned by this member
487
+ for resource_id, resource in self.resources.items():
488
+ if resource.owner_id == member_id:
489
+ if new_owner_id:
490
+ # Transfer to new owner
491
+ resource.owner_id = new_owner_id
492
+ resource.metadata["transferred_from"] = member_id
493
+ resource.metadata["transferred_at"] = datetime.utcnow().isoformat()
494
+ resource.updated_at = datetime.utcnow()
495
+ else:
496
+ # Make community-owned (orphaned)
497
+ resource.owner_id = "community"
498
+ resource.metadata["orphaned_from"] = member_id
499
+ resource.metadata["orphaned_at"] = datetime.utcnow().isoformat()
500
+ resource.access_level = "public" # Make public for community access
501
+
502
+ transferred_resources.append(resource_id)
503
+
504
+ # Auto-save to storage
505
+ if transferred_resources:
506
+ await self._save_to_storage()
507
+
508
+ logger.info(f"Transferred {len(transferred_resources)} resources from member {member_id}")
509
+ return transferred_resources
510
+
511
+ async def deactivate_member(self, member_id: str, reason: Optional[str] = None) -> bool:
512
+ """
513
+ Soft deactivation of a member (doesn't remove, just marks inactive).
514
+
515
+ Args:
516
+ member_id: ID of the member to deactivate
517
+ reason: Optional reason for deactivation
518
+
519
+ Returns:
520
+ True if member was deactivated successfully
521
+ """
522
+ if member_id not in self.members:
523
+ raise TaskValidationError(f"Member not found: {member_id}")
524
+
525
+ member = self.members[member_id]
526
+ member.is_active = False
527
+ member.last_active_at = datetime.utcnow()
528
+ member.participation_level = "inactive"
529
+
530
+ if reason:
531
+ member.metadata["deactivation_reason"] = reason
532
+ member.metadata["deactivated_at"] = datetime.utcnow().isoformat()
533
+
534
+ # Auto-save to storage
535
+ await self._save_to_storage()
536
+
537
+ # Execute lifecycle hooks
538
+ await self._execute_hook("on_member_inactive", None, member_id, member, reason=reason)
539
+
540
+ logger.info(f"Deactivated member {member_id}")
541
+ return True
542
+
543
+ async def reactivate_member(self, member_id: str, restore_roles: bool = True) -> bool:
544
+ """
545
+ Reactivate a previously deactivated member.
546
+
547
+ Args:
548
+ member_id: ID of the member to reactivate
549
+ restore_roles: Whether to restore previous roles
550
+
551
+ Returns:
552
+ True if member was reactivated successfully
553
+ """
554
+ if member_id not in self.members:
555
+ raise TaskValidationError(f"Member not found: {member_id}")
556
+
557
+ member = self.members[member_id]
558
+ member.is_active = True
559
+ member.last_active_at = datetime.utcnow()
560
+ member.participation_level = "active"
561
+
562
+ # Clear deactivation metadata
563
+ if "deactivation_reason" in member.metadata:
564
+ del member.metadata["deactivation_reason"]
565
+ if "deactivated_at" in member.metadata:
566
+ member.metadata["previous_deactivation"] = member.metadata["deactivated_at"]
567
+ del member.metadata["deactivated_at"]
568
+
569
+ member.metadata["reactivated_at"] = datetime.utcnow().isoformat()
570
+
571
+ # Auto-save to storage
572
+ await self._save_to_storage()
573
+
574
+ logger.info(f"Reactivated member {member_id}")
575
+ return True
576
+
577
+ def _find_member_by_agent_id(self, community_id: str, agent_id: str) -> Optional[CommunityMember]:
578
+ """Find a community member by agent ID."""
579
+ if community_id not in self.community_members:
580
+ return None
581
+
582
+ for member_id in self.community_members[community_id]:
583
+ member = self.members.get(member_id)
584
+ if member and member.agent_id == agent_id:
585
+ return member
586
+
587
+ return None
588
+
589
+ def register_lifecycle_hook(self, hook: MemberLifecycleHooks) -> None:
590
+ """
591
+ Register a lifecycle hook handler.
592
+
593
+ Args:
594
+ hook: Hook handler implementing MemberLifecycleHooks protocol
595
+ """
596
+ self.lifecycle_hooks.append(hook)
597
+ logger.info(f"Registered lifecycle hook: {hook.__class__.__name__}")
598
+
599
+ def unregister_lifecycle_hook(self, hook: MemberLifecycleHooks) -> bool:
600
+ """
601
+ Unregister a lifecycle hook handler.
602
+
603
+ Args:
604
+ hook: Hook handler to remove
605
+
606
+ Returns:
607
+ True if hook was removed
608
+ """
609
+ if hook in self.lifecycle_hooks:
610
+ self.lifecycle_hooks.remove(hook)
611
+ logger.info(f"Unregistered lifecycle hook: {hook.__class__.__name__}")
612
+ return True
613
+ return False
614
+
615
+ async def _execute_hook(
616
+ self,
617
+ hook_name: str,
618
+ community_id: Optional[str],
619
+ member_id: str,
620
+ member: CommunityMember,
621
+ **kwargs,
622
+ ) -> None:
623
+ """
624
+ Execute all registered hooks for a specific event.
625
+
626
+ Args:
627
+ hook_name: Name of the hook method to call
628
+ community_id: ID of the community (optional for some hooks)
629
+ member_id: ID of the member
630
+ member: Member object
631
+ **kwargs: Additional arguments to pass to the hook
632
+ """
633
+ for hook in self.lifecycle_hooks:
634
+ try:
635
+ hook_method = getattr(hook, hook_name, None)
636
+ if hook_method:
637
+ if community_id:
638
+ await hook_method(community_id, member_id, member, **kwargs)
639
+ else:
640
+ await hook_method(member_id, member, **kwargs)
641
+ except Exception as e:
642
+ logger.error(f"Error executing lifecycle hook {hook_name}: {e}")
643
+
644
+ async def _load_from_storage(self) -> None:
645
+ """
646
+ Load communities and members from persistent storage.
647
+
648
+ Loads:
649
+ - Communities
650
+ - Members
651
+ - Resources
652
+ - Decisions
653
+ - Sessions
654
+ - Relationships
655
+ """
656
+ if not self.context_engine:
657
+ logger.warning("No context engine available for loading")
658
+ return
659
+
660
+ try:
661
+ # Load communities
662
+ communities_data = await self._load_data_by_key("communities")
663
+ if communities_data:
664
+ for community_id, community_dict in communities_data.items():
665
+ try:
666
+ community = AgentCommunity(**community_dict)
667
+ self.communities[community_id] = community
668
+ self.community_members[community_id] = set(community.members)
669
+ except Exception as e:
670
+ logger.error(f"Failed to load community {community_id}: {e}")
671
+
672
+ # Load members
673
+ members_data = await self._load_data_by_key("community_members")
674
+ if members_data:
675
+ for member_id, member_dict in members_data.items():
676
+ try:
677
+ member = CommunityMember(**member_dict)
678
+ self.members[member_id] = member
679
+ except Exception as e:
680
+ logger.error(f"Failed to load member {member_id}: {e}")
681
+
682
+ # Load resources
683
+ resources_data = await self._load_data_by_key("community_resources")
684
+ if resources_data:
685
+ for resource_id, resource_dict in resources_data.items():
686
+ try:
687
+ resource = CommunityResource(**resource_dict)
688
+ self.resources[resource_id] = resource
689
+ except Exception as e:
690
+ logger.error(f"Failed to load resource {resource_id}: {e}")
691
+
692
+ # Load decisions
693
+ decisions_data = await self._load_data_by_key("community_decisions")
694
+ if decisions_data:
695
+ for decision_id, decision_dict in decisions_data.items():
696
+ try:
697
+ decision = CommunityDecision(**decision_dict)
698
+ self.decisions[decision_id] = decision
699
+ except Exception as e:
700
+ logger.error(f"Failed to load decision {decision_id}: {e}")
701
+
702
+ # Load sessions
703
+ sessions_data = await self._load_data_by_key("community_sessions")
704
+ if sessions_data:
705
+ for session_id, session_dict in sessions_data.items():
706
+ try:
707
+ session = CollaborationSession(**session_dict)
708
+ self.sessions[session_id] = session
709
+ except Exception as e:
710
+ logger.error(f"Failed to load session {session_id}: {e}")
711
+
712
+ # Rebuild member_communities relationships
713
+ for member_id, member in self.members.items():
714
+ for community_id, community in self.communities.items():
715
+ if member_id in community.members:
716
+ if member.agent_id not in self.member_communities:
717
+ self.member_communities[member.agent_id] = set()
718
+ self.member_communities[member.agent_id].add(community_id)
719
+
720
+ logger.info(f"Loaded {len(self.communities)} communities, {len(self.members)} members from storage")
721
+
722
+ except Exception as e:
723
+ logger.error(f"Error loading from storage: {e}")
724
+
725
+ async def _load_data_by_key(self, key: str) -> Optional[Dict[str, Any]]:
726
+ """Load data from context engine by key."""
727
+ if not self.context_engine:
728
+ return None
729
+
730
+ try:
731
+ # Try to get data from context engine
732
+ # The exact method depends on the context engine implementation
733
+ if hasattr(self.context_engine, "get_context"):
734
+ data = await self.context_engine.get_context(key)
735
+ return data
736
+ elif hasattr(self.context_engine, "get"):
737
+ data = await self.context_engine.get(key)
738
+ return data
739
+ else:
740
+ logger.warning("Context engine does not support get operations")
741
+ return None
742
+ except Exception as e:
743
+ logger.debug(f"No data found for key {key}: {e}")
744
+ return None
745
+
746
+ async def _save_to_storage(self) -> None:
747
+ """
748
+ Save all communities and members to persistent storage.
749
+
750
+ Saves:
751
+ - Communities
752
+ - Members
753
+ - Resources
754
+ - Decisions
755
+ - Sessions
756
+ """
757
+ if not self.context_engine:
758
+ logger.debug("No context engine available for saving")
759
+ return
760
+
761
+ try:
762
+ # Save communities
763
+ communities_data = {cid: community.model_dump() for cid, community in self.communities.items()}
764
+ await self._save_data_by_key("communities", communities_data)
765
+
766
+ # Save members
767
+ members_data = {mid: member.model_dump() for mid, member in self.members.items()}
768
+ await self._save_data_by_key("community_members", members_data)
769
+
770
+ # Save resources
771
+ resources_data = {rid: resource.model_dump() for rid, resource in self.resources.items()}
772
+ await self._save_data_by_key("community_resources", resources_data)
773
+
774
+ # Save decisions
775
+ decisions_data = {did: decision.model_dump() for did, decision in self.decisions.items()}
776
+ await self._save_data_by_key("community_decisions", decisions_data)
777
+
778
+ # Save sessions
779
+ sessions_data = {sid: session.model_dump() for sid, session in self.sessions.items()}
780
+ await self._save_data_by_key("community_sessions", sessions_data)
781
+
782
+ logger.debug(f"Saved {len(self.communities)} communities, {len(self.members)} members to storage")
783
+
784
+ except Exception as e:
785
+ logger.error(f"Error saving to storage: {e}")
786
+
787
+ async def _save_data_by_key(self, key: str, data: Dict[str, Any]) -> None:
788
+ """Save data to context engine by key."""
789
+ if not self.context_engine:
790
+ return
791
+
792
+ try:
793
+ # The exact method depends on the context engine implementation
794
+ if hasattr(self.context_engine, "set_context"):
795
+ await self.context_engine.set_context(key, data)
796
+ elif hasattr(self.context_engine, "set"):
797
+ await self.context_engine.set(key, data)
798
+ elif hasattr(self.context_engine, "save"):
799
+ await self.context_engine.save(key, data)
800
+ else:
801
+ logger.warning("Context engine does not support set/save operations")
802
+ except Exception as e:
803
+ logger.error(f"Failed to save data for key {key}: {e}")