aiecs 1.5.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (302) hide show
  1. aiecs/__init__.py +72 -0
  2. aiecs/__main__.py +41 -0
  3. aiecs/aiecs_client.py +469 -0
  4. aiecs/application/__init__.py +10 -0
  5. aiecs/application/executors/__init__.py +10 -0
  6. aiecs/application/executors/operation_executor.py +363 -0
  7. aiecs/application/knowledge_graph/__init__.py +7 -0
  8. aiecs/application/knowledge_graph/builder/__init__.py +37 -0
  9. aiecs/application/knowledge_graph/builder/document_builder.py +375 -0
  10. aiecs/application/knowledge_graph/builder/graph_builder.py +356 -0
  11. aiecs/application/knowledge_graph/builder/schema_mapping.py +531 -0
  12. aiecs/application/knowledge_graph/builder/structured_pipeline.py +443 -0
  13. aiecs/application/knowledge_graph/builder/text_chunker.py +319 -0
  14. aiecs/application/knowledge_graph/extractors/__init__.py +27 -0
  15. aiecs/application/knowledge_graph/extractors/base.py +100 -0
  16. aiecs/application/knowledge_graph/extractors/llm_entity_extractor.py +327 -0
  17. aiecs/application/knowledge_graph/extractors/llm_relation_extractor.py +349 -0
  18. aiecs/application/knowledge_graph/extractors/ner_entity_extractor.py +244 -0
  19. aiecs/application/knowledge_graph/fusion/__init__.py +23 -0
  20. aiecs/application/knowledge_graph/fusion/entity_deduplicator.py +387 -0
  21. aiecs/application/knowledge_graph/fusion/entity_linker.py +343 -0
  22. aiecs/application/knowledge_graph/fusion/knowledge_fusion.py +580 -0
  23. aiecs/application/knowledge_graph/fusion/relation_deduplicator.py +189 -0
  24. aiecs/application/knowledge_graph/pattern_matching/__init__.py +21 -0
  25. aiecs/application/knowledge_graph/pattern_matching/pattern_matcher.py +344 -0
  26. aiecs/application/knowledge_graph/pattern_matching/query_executor.py +378 -0
  27. aiecs/application/knowledge_graph/profiling/__init__.py +12 -0
  28. aiecs/application/knowledge_graph/profiling/query_plan_visualizer.py +199 -0
  29. aiecs/application/knowledge_graph/profiling/query_profiler.py +223 -0
  30. aiecs/application/knowledge_graph/reasoning/__init__.py +27 -0
  31. aiecs/application/knowledge_graph/reasoning/evidence_synthesis.py +347 -0
  32. aiecs/application/knowledge_graph/reasoning/inference_engine.py +504 -0
  33. aiecs/application/knowledge_graph/reasoning/logic_form_parser.py +167 -0
  34. aiecs/application/knowledge_graph/reasoning/logic_parser/__init__.py +79 -0
  35. aiecs/application/knowledge_graph/reasoning/logic_parser/ast_builder.py +513 -0
  36. aiecs/application/knowledge_graph/reasoning/logic_parser/ast_nodes.py +630 -0
  37. aiecs/application/knowledge_graph/reasoning/logic_parser/ast_validator.py +654 -0
  38. aiecs/application/knowledge_graph/reasoning/logic_parser/error_handler.py +477 -0
  39. aiecs/application/knowledge_graph/reasoning/logic_parser/parser.py +390 -0
  40. aiecs/application/knowledge_graph/reasoning/logic_parser/query_context.py +217 -0
  41. aiecs/application/knowledge_graph/reasoning/logic_query_integration.py +169 -0
  42. aiecs/application/knowledge_graph/reasoning/query_planner.py +872 -0
  43. aiecs/application/knowledge_graph/reasoning/reasoning_engine.py +554 -0
  44. aiecs/application/knowledge_graph/retrieval/__init__.py +19 -0
  45. aiecs/application/knowledge_graph/retrieval/retrieval_strategies.py +596 -0
  46. aiecs/application/knowledge_graph/search/__init__.py +59 -0
  47. aiecs/application/knowledge_graph/search/hybrid_search.py +423 -0
  48. aiecs/application/knowledge_graph/search/reranker.py +295 -0
  49. aiecs/application/knowledge_graph/search/reranker_strategies.py +553 -0
  50. aiecs/application/knowledge_graph/search/text_similarity.py +398 -0
  51. aiecs/application/knowledge_graph/traversal/__init__.py +15 -0
  52. aiecs/application/knowledge_graph/traversal/enhanced_traversal.py +329 -0
  53. aiecs/application/knowledge_graph/traversal/path_scorer.py +269 -0
  54. aiecs/application/knowledge_graph/validators/__init__.py +13 -0
  55. aiecs/application/knowledge_graph/validators/relation_validator.py +189 -0
  56. aiecs/application/knowledge_graph/visualization/__init__.py +11 -0
  57. aiecs/application/knowledge_graph/visualization/graph_visualizer.py +321 -0
  58. aiecs/common/__init__.py +9 -0
  59. aiecs/common/knowledge_graph/__init__.py +17 -0
  60. aiecs/common/knowledge_graph/runnable.py +484 -0
  61. aiecs/config/__init__.py +16 -0
  62. aiecs/config/config.py +498 -0
  63. aiecs/config/graph_config.py +137 -0
  64. aiecs/config/registry.py +23 -0
  65. aiecs/core/__init__.py +46 -0
  66. aiecs/core/interface/__init__.py +34 -0
  67. aiecs/core/interface/execution_interface.py +152 -0
  68. aiecs/core/interface/storage_interface.py +171 -0
  69. aiecs/domain/__init__.py +289 -0
  70. aiecs/domain/agent/__init__.py +189 -0
  71. aiecs/domain/agent/base_agent.py +697 -0
  72. aiecs/domain/agent/exceptions.py +103 -0
  73. aiecs/domain/agent/graph_aware_mixin.py +559 -0
  74. aiecs/domain/agent/hybrid_agent.py +490 -0
  75. aiecs/domain/agent/integration/__init__.py +26 -0
  76. aiecs/domain/agent/integration/context_compressor.py +222 -0
  77. aiecs/domain/agent/integration/context_engine_adapter.py +252 -0
  78. aiecs/domain/agent/integration/retry_policy.py +219 -0
  79. aiecs/domain/agent/integration/role_config.py +213 -0
  80. aiecs/domain/agent/knowledge_aware_agent.py +646 -0
  81. aiecs/domain/agent/lifecycle.py +296 -0
  82. aiecs/domain/agent/llm_agent.py +300 -0
  83. aiecs/domain/agent/memory/__init__.py +12 -0
  84. aiecs/domain/agent/memory/conversation.py +197 -0
  85. aiecs/domain/agent/migration/__init__.py +14 -0
  86. aiecs/domain/agent/migration/conversion.py +160 -0
  87. aiecs/domain/agent/migration/legacy_wrapper.py +90 -0
  88. aiecs/domain/agent/models.py +317 -0
  89. aiecs/domain/agent/observability.py +407 -0
  90. aiecs/domain/agent/persistence.py +289 -0
  91. aiecs/domain/agent/prompts/__init__.py +29 -0
  92. aiecs/domain/agent/prompts/builder.py +161 -0
  93. aiecs/domain/agent/prompts/formatters.py +189 -0
  94. aiecs/domain/agent/prompts/template.py +255 -0
  95. aiecs/domain/agent/registry.py +260 -0
  96. aiecs/domain/agent/tool_agent.py +257 -0
  97. aiecs/domain/agent/tools/__init__.py +12 -0
  98. aiecs/domain/agent/tools/schema_generator.py +221 -0
  99. aiecs/domain/community/__init__.py +155 -0
  100. aiecs/domain/community/agent_adapter.py +477 -0
  101. aiecs/domain/community/analytics.py +481 -0
  102. aiecs/domain/community/collaborative_workflow.py +642 -0
  103. aiecs/domain/community/communication_hub.py +645 -0
  104. aiecs/domain/community/community_builder.py +320 -0
  105. aiecs/domain/community/community_integration.py +800 -0
  106. aiecs/domain/community/community_manager.py +813 -0
  107. aiecs/domain/community/decision_engine.py +879 -0
  108. aiecs/domain/community/exceptions.py +225 -0
  109. aiecs/domain/community/models/__init__.py +33 -0
  110. aiecs/domain/community/models/community_models.py +268 -0
  111. aiecs/domain/community/resource_manager.py +457 -0
  112. aiecs/domain/community/shared_context_manager.py +603 -0
  113. aiecs/domain/context/__init__.py +58 -0
  114. aiecs/domain/context/context_engine.py +989 -0
  115. aiecs/domain/context/conversation_models.py +354 -0
  116. aiecs/domain/context/graph_memory.py +467 -0
  117. aiecs/domain/execution/__init__.py +12 -0
  118. aiecs/domain/execution/model.py +57 -0
  119. aiecs/domain/knowledge_graph/__init__.py +19 -0
  120. aiecs/domain/knowledge_graph/models/__init__.py +52 -0
  121. aiecs/domain/knowledge_graph/models/entity.py +130 -0
  122. aiecs/domain/knowledge_graph/models/evidence.py +194 -0
  123. aiecs/domain/knowledge_graph/models/inference_rule.py +186 -0
  124. aiecs/domain/knowledge_graph/models/path.py +179 -0
  125. aiecs/domain/knowledge_graph/models/path_pattern.py +173 -0
  126. aiecs/domain/knowledge_graph/models/query.py +272 -0
  127. aiecs/domain/knowledge_graph/models/query_plan.py +187 -0
  128. aiecs/domain/knowledge_graph/models/relation.py +136 -0
  129. aiecs/domain/knowledge_graph/schema/__init__.py +23 -0
  130. aiecs/domain/knowledge_graph/schema/entity_type.py +135 -0
  131. aiecs/domain/knowledge_graph/schema/graph_schema.py +271 -0
  132. aiecs/domain/knowledge_graph/schema/property_schema.py +155 -0
  133. aiecs/domain/knowledge_graph/schema/relation_type.py +171 -0
  134. aiecs/domain/knowledge_graph/schema/schema_manager.py +496 -0
  135. aiecs/domain/knowledge_graph/schema/type_enums.py +205 -0
  136. aiecs/domain/task/__init__.py +13 -0
  137. aiecs/domain/task/dsl_processor.py +613 -0
  138. aiecs/domain/task/model.py +62 -0
  139. aiecs/domain/task/task_context.py +268 -0
  140. aiecs/infrastructure/__init__.py +24 -0
  141. aiecs/infrastructure/graph_storage/__init__.py +11 -0
  142. aiecs/infrastructure/graph_storage/base.py +601 -0
  143. aiecs/infrastructure/graph_storage/batch_operations.py +449 -0
  144. aiecs/infrastructure/graph_storage/cache.py +429 -0
  145. aiecs/infrastructure/graph_storage/distributed.py +226 -0
  146. aiecs/infrastructure/graph_storage/error_handling.py +390 -0
  147. aiecs/infrastructure/graph_storage/graceful_degradation.py +306 -0
  148. aiecs/infrastructure/graph_storage/health_checks.py +378 -0
  149. aiecs/infrastructure/graph_storage/in_memory.py +514 -0
  150. aiecs/infrastructure/graph_storage/index_optimization.py +483 -0
  151. aiecs/infrastructure/graph_storage/lazy_loading.py +410 -0
  152. aiecs/infrastructure/graph_storage/metrics.py +357 -0
  153. aiecs/infrastructure/graph_storage/migration.py +413 -0
  154. aiecs/infrastructure/graph_storage/pagination.py +471 -0
  155. aiecs/infrastructure/graph_storage/performance_monitoring.py +466 -0
  156. aiecs/infrastructure/graph_storage/postgres.py +871 -0
  157. aiecs/infrastructure/graph_storage/query_optimizer.py +635 -0
  158. aiecs/infrastructure/graph_storage/schema_cache.py +290 -0
  159. aiecs/infrastructure/graph_storage/sqlite.py +623 -0
  160. aiecs/infrastructure/graph_storage/streaming.py +495 -0
  161. aiecs/infrastructure/messaging/__init__.py +13 -0
  162. aiecs/infrastructure/messaging/celery_task_manager.py +383 -0
  163. aiecs/infrastructure/messaging/websocket_manager.py +298 -0
  164. aiecs/infrastructure/monitoring/__init__.py +34 -0
  165. aiecs/infrastructure/monitoring/executor_metrics.py +174 -0
  166. aiecs/infrastructure/monitoring/global_metrics_manager.py +213 -0
  167. aiecs/infrastructure/monitoring/structured_logger.py +48 -0
  168. aiecs/infrastructure/monitoring/tracing_manager.py +410 -0
  169. aiecs/infrastructure/persistence/__init__.py +24 -0
  170. aiecs/infrastructure/persistence/context_engine_client.py +187 -0
  171. aiecs/infrastructure/persistence/database_manager.py +333 -0
  172. aiecs/infrastructure/persistence/file_storage.py +754 -0
  173. aiecs/infrastructure/persistence/redis_client.py +220 -0
  174. aiecs/llm/__init__.py +86 -0
  175. aiecs/llm/callbacks/__init__.py +11 -0
  176. aiecs/llm/callbacks/custom_callbacks.py +264 -0
  177. aiecs/llm/client_factory.py +420 -0
  178. aiecs/llm/clients/__init__.py +33 -0
  179. aiecs/llm/clients/base_client.py +193 -0
  180. aiecs/llm/clients/googleai_client.py +181 -0
  181. aiecs/llm/clients/openai_client.py +131 -0
  182. aiecs/llm/clients/vertex_client.py +437 -0
  183. aiecs/llm/clients/xai_client.py +184 -0
  184. aiecs/llm/config/__init__.py +51 -0
  185. aiecs/llm/config/config_loader.py +275 -0
  186. aiecs/llm/config/config_validator.py +236 -0
  187. aiecs/llm/config/model_config.py +151 -0
  188. aiecs/llm/utils/__init__.py +10 -0
  189. aiecs/llm/utils/validate_config.py +91 -0
  190. aiecs/main.py +363 -0
  191. aiecs/scripts/__init__.py +3 -0
  192. aiecs/scripts/aid/VERSION_MANAGEMENT.md +97 -0
  193. aiecs/scripts/aid/__init__.py +19 -0
  194. aiecs/scripts/aid/version_manager.py +215 -0
  195. aiecs/scripts/dependance_check/DEPENDENCY_SYSTEM_SUMMARY.md +242 -0
  196. aiecs/scripts/dependance_check/README_DEPENDENCY_CHECKER.md +310 -0
  197. aiecs/scripts/dependance_check/__init__.py +17 -0
  198. aiecs/scripts/dependance_check/dependency_checker.py +938 -0
  199. aiecs/scripts/dependance_check/dependency_fixer.py +391 -0
  200. aiecs/scripts/dependance_check/download_nlp_data.py +396 -0
  201. aiecs/scripts/dependance_check/quick_dependency_check.py +270 -0
  202. aiecs/scripts/dependance_check/setup_nlp_data.sh +217 -0
  203. aiecs/scripts/dependance_patch/__init__.py +7 -0
  204. aiecs/scripts/dependance_patch/fix_weasel/README_WEASEL_PATCH.md +126 -0
  205. aiecs/scripts/dependance_patch/fix_weasel/__init__.py +11 -0
  206. aiecs/scripts/dependance_patch/fix_weasel/fix_weasel_validator.py +128 -0
  207. aiecs/scripts/dependance_patch/fix_weasel/fix_weasel_validator.sh +82 -0
  208. aiecs/scripts/dependance_patch/fix_weasel/patch_weasel_library.sh +188 -0
  209. aiecs/scripts/dependance_patch/fix_weasel/run_weasel_patch.sh +41 -0
  210. aiecs/scripts/tools_develop/README.md +449 -0
  211. aiecs/scripts/tools_develop/TOOL_AUTO_DISCOVERY.md +234 -0
  212. aiecs/scripts/tools_develop/__init__.py +21 -0
  213. aiecs/scripts/tools_develop/check_type_annotations.py +259 -0
  214. aiecs/scripts/tools_develop/validate_tool_schemas.py +422 -0
  215. aiecs/scripts/tools_develop/verify_tools.py +356 -0
  216. aiecs/tasks/__init__.py +1 -0
  217. aiecs/tasks/worker.py +172 -0
  218. aiecs/tools/__init__.py +299 -0
  219. aiecs/tools/apisource/__init__.py +99 -0
  220. aiecs/tools/apisource/intelligence/__init__.py +19 -0
  221. aiecs/tools/apisource/intelligence/data_fusion.py +381 -0
  222. aiecs/tools/apisource/intelligence/query_analyzer.py +413 -0
  223. aiecs/tools/apisource/intelligence/search_enhancer.py +388 -0
  224. aiecs/tools/apisource/monitoring/__init__.py +9 -0
  225. aiecs/tools/apisource/monitoring/metrics.py +303 -0
  226. aiecs/tools/apisource/providers/__init__.py +115 -0
  227. aiecs/tools/apisource/providers/base.py +664 -0
  228. aiecs/tools/apisource/providers/census.py +401 -0
  229. aiecs/tools/apisource/providers/fred.py +564 -0
  230. aiecs/tools/apisource/providers/newsapi.py +412 -0
  231. aiecs/tools/apisource/providers/worldbank.py +357 -0
  232. aiecs/tools/apisource/reliability/__init__.py +12 -0
  233. aiecs/tools/apisource/reliability/error_handler.py +375 -0
  234. aiecs/tools/apisource/reliability/fallback_strategy.py +391 -0
  235. aiecs/tools/apisource/tool.py +850 -0
  236. aiecs/tools/apisource/utils/__init__.py +9 -0
  237. aiecs/tools/apisource/utils/validators.py +338 -0
  238. aiecs/tools/base_tool.py +201 -0
  239. aiecs/tools/docs/__init__.py +121 -0
  240. aiecs/tools/docs/ai_document_orchestrator.py +599 -0
  241. aiecs/tools/docs/ai_document_writer_orchestrator.py +2403 -0
  242. aiecs/tools/docs/content_insertion_tool.py +1333 -0
  243. aiecs/tools/docs/document_creator_tool.py +1317 -0
  244. aiecs/tools/docs/document_layout_tool.py +1166 -0
  245. aiecs/tools/docs/document_parser_tool.py +994 -0
  246. aiecs/tools/docs/document_writer_tool.py +1818 -0
  247. aiecs/tools/knowledge_graph/__init__.py +17 -0
  248. aiecs/tools/knowledge_graph/graph_reasoning_tool.py +734 -0
  249. aiecs/tools/knowledge_graph/graph_search_tool.py +923 -0
  250. aiecs/tools/knowledge_graph/kg_builder_tool.py +476 -0
  251. aiecs/tools/langchain_adapter.py +542 -0
  252. aiecs/tools/schema_generator.py +275 -0
  253. aiecs/tools/search_tool/__init__.py +100 -0
  254. aiecs/tools/search_tool/analyzers.py +589 -0
  255. aiecs/tools/search_tool/cache.py +260 -0
  256. aiecs/tools/search_tool/constants.py +128 -0
  257. aiecs/tools/search_tool/context.py +216 -0
  258. aiecs/tools/search_tool/core.py +749 -0
  259. aiecs/tools/search_tool/deduplicator.py +123 -0
  260. aiecs/tools/search_tool/error_handler.py +271 -0
  261. aiecs/tools/search_tool/metrics.py +371 -0
  262. aiecs/tools/search_tool/rate_limiter.py +178 -0
  263. aiecs/tools/search_tool/schemas.py +277 -0
  264. aiecs/tools/statistics/__init__.py +80 -0
  265. aiecs/tools/statistics/ai_data_analysis_orchestrator.py +643 -0
  266. aiecs/tools/statistics/ai_insight_generator_tool.py +505 -0
  267. aiecs/tools/statistics/ai_report_orchestrator_tool.py +694 -0
  268. aiecs/tools/statistics/data_loader_tool.py +564 -0
  269. aiecs/tools/statistics/data_profiler_tool.py +658 -0
  270. aiecs/tools/statistics/data_transformer_tool.py +573 -0
  271. aiecs/tools/statistics/data_visualizer_tool.py +495 -0
  272. aiecs/tools/statistics/model_trainer_tool.py +487 -0
  273. aiecs/tools/statistics/statistical_analyzer_tool.py +459 -0
  274. aiecs/tools/task_tools/__init__.py +86 -0
  275. aiecs/tools/task_tools/chart_tool.py +732 -0
  276. aiecs/tools/task_tools/classfire_tool.py +922 -0
  277. aiecs/tools/task_tools/image_tool.py +447 -0
  278. aiecs/tools/task_tools/office_tool.py +684 -0
  279. aiecs/tools/task_tools/pandas_tool.py +635 -0
  280. aiecs/tools/task_tools/report_tool.py +635 -0
  281. aiecs/tools/task_tools/research_tool.py +392 -0
  282. aiecs/tools/task_tools/scraper_tool.py +715 -0
  283. aiecs/tools/task_tools/stats_tool.py +688 -0
  284. aiecs/tools/temp_file_manager.py +130 -0
  285. aiecs/tools/tool_executor/__init__.py +37 -0
  286. aiecs/tools/tool_executor/tool_executor.py +881 -0
  287. aiecs/utils/LLM_output_structor.py +445 -0
  288. aiecs/utils/__init__.py +34 -0
  289. aiecs/utils/base_callback.py +47 -0
  290. aiecs/utils/cache_provider.py +695 -0
  291. aiecs/utils/execution_utils.py +184 -0
  292. aiecs/utils/logging.py +1 -0
  293. aiecs/utils/prompt_loader.py +14 -0
  294. aiecs/utils/token_usage_repository.py +323 -0
  295. aiecs/ws/__init__.py +0 -0
  296. aiecs/ws/socket_server.py +52 -0
  297. aiecs-1.5.1.dist-info/METADATA +608 -0
  298. aiecs-1.5.1.dist-info/RECORD +302 -0
  299. aiecs-1.5.1.dist-info/WHEEL +5 -0
  300. aiecs-1.5.1.dist-info/entry_points.txt +10 -0
  301. aiecs-1.5.1.dist-info/licenses/LICENSE +225 -0
  302. aiecs-1.5.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,481 @@
1
+ """
2
+ Community Analytics
3
+
4
+ Tracks decision patterns, member participation, community health metrics,
5
+ and collaboration effectiveness.
6
+ """
7
+
8
+ import logging
9
+ from datetime import datetime, timedelta
10
+ from typing import Dict, Any
11
+ from collections import defaultdict
12
+
13
+ from .models.community_models import DecisionStatus
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+
18
+ class CommunityAnalytics:
19
+ """
20
+ Analytics engine for tracking community health and effectiveness.
21
+ """
22
+
23
+ def __init__(self, community_manager=None):
24
+ """
25
+ Initialize community analytics.
26
+
27
+ Args:
28
+ community_manager: Reference to the community manager
29
+ """
30
+ self.community_manager = community_manager
31
+
32
+ # Analytics caches
33
+ self._decision_patterns_cache: Dict[str, Any] = {}
34
+ self._participation_cache: Dict[str, Any] = {}
35
+ self._health_metrics_cache: Dict[str, Any] = {}
36
+
37
+ logger.info("Community analytics initialized")
38
+
39
+ def get_decision_analytics(
40
+ self, community_id: str, time_range_days: int = 30
41
+ ) -> Dict[str, Any]:
42
+ """
43
+ Get decision analytics for a community.
44
+
45
+ Args:
46
+ community_id: ID of the community
47
+ time_range_days: Time range for analytics in days
48
+
49
+ Returns:
50
+ Decision analytics data
51
+ """
52
+ if not self.community_manager:
53
+ return {}
54
+
55
+ community = self.community_manager.communities.get(community_id)
56
+ if not community:
57
+ return {}
58
+
59
+ cutoff_date = datetime.utcnow() - timedelta(days=time_range_days)
60
+
61
+ # Collect decisions within time range
62
+ decisions = []
63
+ for decision in self.community_manager.decisions.values():
64
+ if decision.created_at >= cutoff_date:
65
+ # Check if decision belongs to this community
66
+ if decision.proposer_id in community.members:
67
+ decisions.append(decision)
68
+
69
+ # Calculate decision metrics
70
+ total_decisions = len(decisions)
71
+ approved = sum(1 for d in decisions if d.status == DecisionStatus.APPROVED)
72
+ rejected = sum(1 for d in decisions if d.status == DecisionStatus.REJECTED)
73
+ pending = sum(
74
+ 1 for d in decisions if d.status in [DecisionStatus.PROPOSED, DecisionStatus.VOTING]
75
+ )
76
+
77
+ # Calculate average time to decision
78
+ decision_times = []
79
+ for decision in decisions:
80
+ if decision.status in [
81
+ DecisionStatus.APPROVED,
82
+ DecisionStatus.REJECTED,
83
+ ]:
84
+ if decision.implemented_at or decision.created_at:
85
+ end_time = decision.implemented_at or datetime.utcnow()
86
+ duration = (end_time - decision.created_at).total_seconds() / 3600 # hours
87
+ decision_times.append(duration)
88
+
89
+ avg_decision_time = sum(decision_times) / len(decision_times) if decision_times else 0
90
+
91
+ # Decision types distribution
92
+ decision_types = defaultdict(int)
93
+ for decision in decisions:
94
+ decision_types[decision.decision_type] += 1
95
+
96
+ # Approval rate by type
97
+ approval_by_type = {}
98
+ for dtype in decision_types.keys():
99
+ type_decisions = [d for d in decisions if d.decision_type == dtype]
100
+ type_approved = sum(1 for d in type_decisions if d.status == DecisionStatus.APPROVED)
101
+ approval_by_type[dtype] = type_approved / len(type_decisions) if type_decisions else 0
102
+
103
+ analytics = {
104
+ "community_id": community_id,
105
+ "time_range_days": time_range_days,
106
+ "total_decisions": total_decisions,
107
+ "approved": approved,
108
+ "rejected": rejected,
109
+ "pending": pending,
110
+ "approval_rate": (approved / total_decisions if total_decisions > 0 else 0),
111
+ "rejection_rate": (rejected / total_decisions if total_decisions > 0 else 0),
112
+ "average_decision_time_hours": avg_decision_time,
113
+ "decision_types": dict(decision_types),
114
+ "approval_rate_by_type": approval_by_type,
115
+ "decision_velocity": (total_decisions / time_range_days if time_range_days > 0 else 0),
116
+ }
117
+
118
+ return analytics
119
+
120
+ def get_member_participation_analytics(
121
+ self, community_id: str, time_range_days: int = 30
122
+ ) -> Dict[str, Any]:
123
+ """
124
+ Get member participation analytics.
125
+
126
+ Args:
127
+ community_id: ID of the community
128
+ time_range_days: Time range for analytics in days
129
+
130
+ Returns:
131
+ Participation analytics data
132
+ """
133
+ if not self.community_manager:
134
+ return {}
135
+
136
+ community = self.community_manager.communities.get(community_id)
137
+ if not community:
138
+ return {}
139
+
140
+ cutoff_date = datetime.utcnow() - timedelta(days=time_range_days)
141
+
142
+ # Member participation metrics
143
+ member_metrics = {}
144
+ for member_id in community.members:
145
+ member = self.community_manager.members.get(member_id)
146
+ if not member:
147
+ continue
148
+
149
+ # Count votes
150
+ votes_cast = 0
151
+ proposals_made = 0
152
+
153
+ for decision in self.community_manager.decisions.values():
154
+ if decision.created_at >= cutoff_date:
155
+ if (
156
+ member_id in decision.votes_for
157
+ or member_id in decision.votes_against
158
+ or member_id in decision.abstentions
159
+ ):
160
+ votes_cast += 1
161
+ if decision.proposer_id == member_id:
162
+ proposals_made += 1
163
+
164
+ # Count resources contributed
165
+ resources_created = sum(
166
+ 1
167
+ for resource in self.community_manager.resources.values()
168
+ if resource.owner_id == member_id and resource.created_at >= cutoff_date
169
+ )
170
+
171
+ member_metrics[member_id] = {
172
+ "agent_id": member.agent_id,
173
+ "community_role": member.community_role.value,
174
+ "votes_cast": votes_cast,
175
+ "proposals_made": proposals_made,
176
+ "resources_created": resources_created,
177
+ "contribution_score": member.contribution_score,
178
+ "reputation": member.reputation,
179
+ "is_active": member.is_active,
180
+ "participation_level": member.participation_level,
181
+ }
182
+
183
+ # Calculate aggregate metrics
184
+ total_members = len(member_metrics)
185
+ active_members = sum(1 for m in member_metrics.values() if m["is_active"])
186
+ total_votes = sum(m["votes_cast"] for m in member_metrics.values())
187
+ total_proposals = sum(m["proposals_made"] for m in member_metrics.values())
188
+ total_resources = sum(m["resources_created"] for m in member_metrics.values())
189
+
190
+ # Identify top contributors
191
+ top_voters = sorted(
192
+ member_metrics.items(),
193
+ key=lambda x: x[1]["votes_cast"],
194
+ reverse=True,
195
+ )[:5]
196
+
197
+ top_proposers = sorted(
198
+ member_metrics.items(),
199
+ key=lambda x: x[1]["proposals_made"],
200
+ reverse=True,
201
+ )[:5]
202
+
203
+ top_contributors = sorted(
204
+ member_metrics.items(),
205
+ key=lambda x: x[1]["contribution_score"],
206
+ reverse=True,
207
+ )[:5]
208
+
209
+ analytics = {
210
+ "community_id": community_id,
211
+ "time_range_days": time_range_days,
212
+ "total_members": total_members,
213
+ "active_members": active_members,
214
+ "activity_rate": (active_members / total_members if total_members > 0 else 0),
215
+ "total_votes_cast": total_votes,
216
+ "total_proposals_made": total_proposals,
217
+ "total_resources_created": total_resources,
218
+ "average_votes_per_member": (total_votes / total_members if total_members > 0 else 0),
219
+ "average_proposals_per_member": (
220
+ total_proposals / total_members if total_members > 0 else 0
221
+ ),
222
+ "member_metrics": member_metrics,
223
+ "top_voters": [{"member_id": mid, **metrics} for mid, metrics in top_voters],
224
+ "top_proposers": [{"member_id": mid, **metrics} for mid, metrics in top_proposers],
225
+ "top_contributors": [
226
+ {"member_id": mid, **metrics} for mid, metrics in top_contributors
227
+ ],
228
+ }
229
+
230
+ return analytics
231
+
232
+ def get_community_health_metrics(self, community_id: str) -> Dict[str, Any]:
233
+ """
234
+ Get comprehensive community health metrics.
235
+
236
+ Args:
237
+ community_id: ID of the community
238
+
239
+ Returns:
240
+ Health metrics data
241
+ """
242
+ if not self.community_manager:
243
+ return {}
244
+
245
+ community = self.community_manager.communities.get(community_id)
246
+ if not community:
247
+ return {}
248
+
249
+ # Member health
250
+ total_members = len(community.members)
251
+ active_members = sum(
252
+ 1
253
+ for mid in community.members
254
+ if self.community_manager.members.get(mid)
255
+ and self.community_manager.members[mid].is_active
256
+ )
257
+
258
+ # Leadership health
259
+ has_leaders = len(community.leaders) > 0
260
+ has_coordinators = len(community.coordinators) > 0
261
+ (
262
+ (len(community.leaders) + len(community.coordinators)) / total_members
263
+ if total_members > 0
264
+ else 0
265
+ )
266
+
267
+ # Activity health
268
+ recent_activity_days = 7
269
+ recent_cutoff = datetime.utcnow() - timedelta(days=recent_activity_days)
270
+
271
+ recent_decisions = sum(
272
+ 1
273
+ for d in self.community_manager.decisions.values()
274
+ if d.created_at >= recent_cutoff and d.proposer_id in community.members
275
+ )
276
+
277
+ recent_resources = sum(
278
+ 1
279
+ for rid in community.shared_resources
280
+ if self.community_manager.resources.get(rid)
281
+ and self.community_manager.resources[rid].created_at >= recent_cutoff
282
+ )
283
+
284
+ # Diversity metrics
285
+ role_distribution = defaultdict(int)
286
+ for member_id in community.members:
287
+ member = self.community_manager.members.get(member_id)
288
+ if member:
289
+ role_distribution[member.community_role.value] += 1
290
+
291
+ role_diversity = len(role_distribution) / 5 # Max 5 role types
292
+
293
+ # Collaboration score (from community model)
294
+ collaboration_score = community.collaboration_score
295
+
296
+ # Calculate overall health score (0-100)
297
+ health_components = {
298
+ "member_activity": ((active_members / total_members * 100) if total_members > 0 else 0),
299
+ "leadership": (
300
+ 100
301
+ if has_leaders and has_coordinators
302
+ else 50 if has_leaders or has_coordinators else 0
303
+ ),
304
+ "recent_activity": min((recent_decisions + recent_resources) * 10, 100),
305
+ "role_diversity": role_diversity * 100,
306
+ "collaboration": collaboration_score * 100,
307
+ }
308
+
309
+ overall_health = sum(health_components.values()) / len(health_components)
310
+
311
+ # Determine health status
312
+ if overall_health >= 80:
313
+ health_status = "excellent"
314
+ elif overall_health >= 60:
315
+ health_status = "good"
316
+ elif overall_health >= 40:
317
+ health_status = "fair"
318
+ elif overall_health >= 20:
319
+ health_status = "poor"
320
+ else:
321
+ health_status = "critical"
322
+
323
+ # Recommendations
324
+ recommendations = []
325
+ if total_members == 0:
326
+ recommendations.append("Add members to the community to begin collaboration")
327
+ elif active_members / total_members < 0.5:
328
+ recommendations.append("Increase member engagement through targeted activities")
329
+ if not has_leaders:
330
+ recommendations.append("Assign community leaders for better coordination")
331
+ if recent_decisions + recent_resources < 3:
332
+ recommendations.append("Encourage more community activity and collaboration")
333
+ if role_diversity < 0.6:
334
+ recommendations.append("Improve role diversity by adding members with different roles")
335
+
336
+ metrics = {
337
+ "community_id": community_id,
338
+ "community_name": community.name,
339
+ "overall_health_score": round(overall_health, 2),
340
+ "health_status": health_status,
341
+ "health_components": health_components,
342
+ "member_statistics": {
343
+ "total": total_members,
344
+ "active": active_members,
345
+ "inactive": total_members - active_members,
346
+ "leaders": len(community.leaders),
347
+ "coordinators": len(community.coordinators),
348
+ },
349
+ "activity_statistics": {
350
+ "recent_decisions": recent_decisions,
351
+ "recent_resources": recent_resources,
352
+ "total_decisions": community.decision_count,
353
+ "total_resources": community.resource_count,
354
+ },
355
+ "diversity_metrics": {
356
+ "role_distribution": dict(role_distribution),
357
+ "role_diversity_score": round(role_diversity, 2),
358
+ },
359
+ "collaboration_score": collaboration_score,
360
+ "recommendations": recommendations,
361
+ "timestamp": datetime.utcnow().isoformat(),
362
+ }
363
+
364
+ return metrics
365
+
366
+ def get_collaboration_effectiveness(
367
+ self, community_id: str, time_range_days: int = 30
368
+ ) -> Dict[str, Any]:
369
+ """
370
+ Get collaboration effectiveness metrics.
371
+
372
+ Args:
373
+ community_id: ID of the community
374
+ time_range_days: Time range for analytics in days
375
+
376
+ Returns:
377
+ Collaboration effectiveness data
378
+ """
379
+ if not self.community_manager:
380
+ return {}
381
+
382
+ # Get decision and participation analytics
383
+ decision_analytics = self.get_decision_analytics(community_id, time_range_days)
384
+ participation_analytics = self.get_member_participation_analytics(
385
+ community_id, time_range_days
386
+ )
387
+
388
+ # Calculate effectiveness metrics
389
+ decision_efficiency = decision_analytics.get("decision_velocity", 0) * 10
390
+ approval_effectiveness = decision_analytics.get("approval_rate", 0) * 100
391
+ participation_rate = participation_analytics.get("activity_rate", 0) * 100
392
+
393
+ # Combined effectiveness score
394
+ effectiveness_score = (
395
+ decision_efficiency * 0.3 + approval_effectiveness * 0.4 + participation_rate * 0.3
396
+ )
397
+
398
+ # Determine effectiveness level
399
+ if effectiveness_score >= 80:
400
+ effectiveness_level = "highly_effective"
401
+ elif effectiveness_score >= 60:
402
+ effectiveness_level = "effective"
403
+ elif effectiveness_score >= 40:
404
+ effectiveness_level = "moderately_effective"
405
+ else:
406
+ effectiveness_level = "needs_improvement"
407
+
408
+ # Identify strengths and weaknesses
409
+ strengths = []
410
+ weaknesses = []
411
+
412
+ if decision_efficiency >= 8:
413
+ strengths.append("High decision velocity")
414
+ else:
415
+ weaknesses.append("Low decision-making speed")
416
+
417
+ if approval_effectiveness >= 70:
418
+ strengths.append("High approval rate")
419
+ else:
420
+ weaknesses.append("Low approval rate - may indicate alignment issues")
421
+
422
+ if participation_rate >= 70:
423
+ strengths.append("Strong member participation")
424
+ else:
425
+ weaknesses.append("Low member participation")
426
+
427
+ metrics = {
428
+ "community_id": community_id,
429
+ "time_range_days": time_range_days,
430
+ "effectiveness_score": round(effectiveness_score, 2),
431
+ "effectiveness_level": effectiveness_level,
432
+ "component_scores": {
433
+ "decision_efficiency": round(decision_efficiency, 2),
434
+ "approval_effectiveness": round(approval_effectiveness, 2),
435
+ "participation_rate": round(participation_rate, 2),
436
+ },
437
+ "strengths": strengths,
438
+ "weaknesses": weaknesses,
439
+ "decision_summary": {
440
+ "velocity": decision_analytics.get("decision_velocity", 0),
441
+ "approval_rate": decision_analytics.get("approval_rate", 0),
442
+ "avg_time_hours": decision_analytics.get("average_decision_time_hours", 0),
443
+ },
444
+ "participation_summary": {
445
+ "active_members": participation_analytics.get("active_members", 0),
446
+ "total_members": participation_analytics.get("total_members", 0),
447
+ "avg_votes_per_member": participation_analytics.get("average_votes_per_member", 0),
448
+ },
449
+ "timestamp": datetime.utcnow().isoformat(),
450
+ }
451
+
452
+ return metrics
453
+
454
+ def get_comprehensive_report(
455
+ self, community_id: str, time_range_days: int = 30
456
+ ) -> Dict[str, Any]:
457
+ """
458
+ Get comprehensive analytics report for a community.
459
+
460
+ Args:
461
+ community_id: ID of the community
462
+ time_range_days: Time range for analytics in days
463
+
464
+ Returns:
465
+ Comprehensive analytics report
466
+ """
467
+ report = {
468
+ "community_id": community_id,
469
+ "report_date": datetime.utcnow().isoformat(),
470
+ "time_range_days": time_range_days,
471
+ "decision_analytics": self.get_decision_analytics(community_id, time_range_days),
472
+ "participation_analytics": self.get_member_participation_analytics(
473
+ community_id, time_range_days
474
+ ),
475
+ "health_metrics": self.get_community_health_metrics(community_id),
476
+ "collaboration_effectiveness": self.get_collaboration_effectiveness(
477
+ community_id, time_range_days
478
+ ),
479
+ }
480
+
481
+ return report