moai-adk 0.15.1__py3-none-any.whl → 0.32.8__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 moai-adk might be problematic. Click here for more details.

Files changed (699) hide show
  1. moai_adk/__init__.py +2 -6
  2. moai_adk/__main__.py +136 -21
  3. moai_adk/cli/__init__.py +6 -2
  4. moai_adk/cli/commands/__init__.py +1 -4
  5. moai_adk/cli/commands/analyze.py +116 -0
  6. moai_adk/cli/commands/doctor.py +17 -5
  7. moai_adk/cli/commands/init.py +105 -47
  8. moai_adk/cli/commands/language.py +248 -0
  9. moai_adk/cli/commands/status.py +8 -13
  10. moai_adk/cli/commands/update.py +1734 -65
  11. moai_adk/cli/main.py +3 -2
  12. moai_adk/cli/prompts/init_prompts.py +144 -91
  13. moai_adk/cli/spec_status.py +263 -0
  14. moai_adk/cli/ui/__init__.py +44 -0
  15. moai_adk/cli/ui/progress.py +422 -0
  16. moai_adk/cli/ui/prompts.py +389 -0
  17. moai_adk/cli/ui/theme.py +129 -0
  18. moai_adk/cli/worktree/__init__.py +27 -0
  19. moai_adk/cli/worktree/__main__.py +31 -0
  20. moai_adk/cli/worktree/cli.py +672 -0
  21. moai_adk/cli/worktree/exceptions.py +89 -0
  22. moai_adk/cli/worktree/manager.py +490 -0
  23. moai_adk/cli/worktree/models.py +65 -0
  24. moai_adk/cli/worktree/registry.py +128 -0
  25. moai_adk/core/PHASE2_OPTIMIZATIONS.md +467 -0
  26. moai_adk/core/__init__.py +0 -1
  27. moai_adk/core/analysis/__init__.py +9 -0
  28. moai_adk/core/analysis/session_analyzer.py +400 -0
  29. moai_adk/core/claude_integration.py +393 -0
  30. moai_adk/core/command_helpers.py +270 -0
  31. moai_adk/core/comprehensive_monitoring_system.py +1183 -0
  32. moai_adk/core/config/__init__.py +6 -0
  33. moai_adk/core/config/auto_spec_config.py +340 -0
  34. moai_adk/core/config/migration.py +147 -16
  35. moai_adk/core/config/unified.py +436 -0
  36. moai_adk/core/context_manager.py +273 -0
  37. moai_adk/core/diagnostics/slash_commands.py +0 -1
  38. moai_adk/core/enterprise_features.py +1404 -0
  39. moai_adk/core/error_recovery_system.py +1902 -0
  40. moai_adk/core/event_driven_hook_system.py +1371 -0
  41. moai_adk/core/git/__init__.py +8 -1
  42. moai_adk/core/git/branch.py +0 -1
  43. moai_adk/core/git/branch_manager.py +2 -10
  44. moai_adk/core/git/checkpoint.py +1 -7
  45. moai_adk/core/git/commit.py +0 -1
  46. moai_adk/core/git/conflict_detector.py +413 -0
  47. moai_adk/core/git/event_detector.py +3 -5
  48. moai_adk/core/git/manager.py +91 -2
  49. moai_adk/core/hooks/post_tool_auto_spec_completion.py +901 -0
  50. moai_adk/core/input_validation_middleware.py +1006 -0
  51. moai_adk/core/integration/__init__.py +22 -0
  52. moai_adk/core/integration/engine.py +157 -0
  53. moai_adk/core/integration/integration_tester.py +226 -0
  54. moai_adk/core/integration/models.py +88 -0
  55. moai_adk/core/integration/utils.py +211 -0
  56. moai_adk/core/issue_creator.py +20 -28
  57. moai_adk/core/jit_context_loader.py +956 -0
  58. moai_adk/core/jit_enhanced_hook_manager.py +1987 -0
  59. moai_adk/core/language_config.py +202 -0
  60. moai_adk/core/language_config_resolver.py +485 -0
  61. moai_adk/core/language_validator.py +543 -0
  62. moai_adk/core/mcp/setup.py +116 -0
  63. moai_adk/core/merge/__init__.py +9 -0
  64. moai_adk/core/merge/analyzer.py +481 -0
  65. moai_adk/core/migration/__init__.py +18 -0
  66. moai_adk/core/migration/alfred_to_moai_migrator.py +383 -0
  67. moai_adk/core/migration/backup_manager.py +277 -0
  68. moai_adk/core/migration/custom_element_scanner.py +358 -0
  69. moai_adk/core/migration/file_migrator.py +209 -0
  70. moai_adk/core/migration/interactive_checkbox_ui.py +488 -0
  71. moai_adk/core/migration/selective_restorer.py +470 -0
  72. moai_adk/core/migration/template_utils.py +74 -0
  73. moai_adk/core/migration/user_selection_ui.py +338 -0
  74. moai_adk/core/migration/version_detector.py +139 -0
  75. moai_adk/core/migration/version_migrator.py +228 -0
  76. moai_adk/core/performance/__init__.py +6 -0
  77. moai_adk/core/performance/cache_system.py +316 -0
  78. moai_adk/core/performance/parallel_processor.py +116 -0
  79. moai_adk/core/phase_optimized_hook_scheduler.py +879 -0
  80. moai_adk/core/project/__init__.py +0 -1
  81. moai_adk/core/project/backup_utils.py +2 -7
  82. moai_adk/core/project/checker.py +2 -4
  83. moai_adk/core/project/detector.py +17 -39
  84. moai_adk/core/project/initializer.py +170 -33
  85. moai_adk/core/project/phase_executor.py +398 -68
  86. moai_adk/core/project/validator.py +7 -32
  87. moai_adk/core/quality/__init__.py +1 -1
  88. moai_adk/core/quality/trust_checker.py +37 -101
  89. moai_adk/core/quality/validators/__init__.py +1 -1
  90. moai_adk/core/quality/validators/base_validator.py +1 -1
  91. moai_adk/core/realtime_monitoring_dashboard.py +1724 -0
  92. moai_adk/core/robust_json_parser.py +611 -0
  93. moai_adk/core/rollback_manager.py +918 -0
  94. moai_adk/core/session_manager.py +651 -0
  95. moai_adk/core/skill_loading_system.py +579 -0
  96. moai_adk/core/spec/confidence_scoring.py +680 -0
  97. moai_adk/core/spec/ears_template_engine.py +1247 -0
  98. moai_adk/core/spec/quality_validator.py +687 -0
  99. moai_adk/core/spec_status_manager.py +478 -0
  100. moai_adk/core/template/__init__.py +0 -1
  101. moai_adk/core/template/backup.py +82 -17
  102. moai_adk/core/template/config.py +112 -40
  103. moai_adk/core/template/languages.py +0 -1
  104. moai_adk/core/template/merger.py +75 -26
  105. moai_adk/core/template/processor.py +750 -72
  106. moai_adk/core/template_engine.py +90 -48
  107. moai_adk/core/template_variable_synchronizer.py +417 -0
  108. moai_adk/core/unified_permission_manager.py +745 -0
  109. moai_adk/core/user_behavior_analytics.py +851 -0
  110. moai_adk/core/version_sync.py +429 -0
  111. moai_adk/foundation/__init__.py +56 -0
  112. moai_adk/foundation/backend.py +1027 -0
  113. moai_adk/foundation/database.py +1115 -0
  114. moai_adk/foundation/devops.py +1585 -0
  115. moai_adk/foundation/ears.py +431 -0
  116. moai_adk/foundation/frontend.py +870 -0
  117. moai_adk/foundation/git/commit_templates.py +557 -0
  118. moai_adk/foundation/git.py +376 -0
  119. moai_adk/foundation/langs.py +484 -0
  120. moai_adk/foundation/ml_ops.py +1162 -0
  121. moai_adk/foundation/testing.py +1524 -0
  122. moai_adk/foundation/trust/trust_principles.py +676 -0
  123. moai_adk/foundation/trust/validation_checklist.py +1573 -0
  124. moai_adk/project/__init__.py +0 -0
  125. moai_adk/project/configuration.py +1084 -0
  126. moai_adk/project/documentation.py +566 -0
  127. moai_adk/project/schema.py +447 -0
  128. moai_adk/statusline/__init__.py +38 -0
  129. moai_adk/statusline/alfred_detector.py +105 -0
  130. moai_adk/statusline/config.py +373 -0
  131. moai_adk/statusline/enhanced_output_style_detector.py +372 -0
  132. moai_adk/statusline/git_collector.py +190 -0
  133. moai_adk/statusline/main.py +264 -0
  134. moai_adk/statusline/metrics_tracker.py +78 -0
  135. moai_adk/statusline/renderer.py +383 -0
  136. moai_adk/statusline/update_checker.py +129 -0
  137. moai_adk/statusline/version_reader.py +741 -0
  138. moai_adk/templates/.claude/agents/moai/ai-nano-banana.md +549 -0
  139. moai_adk/templates/.claude/agents/moai/builder-agent.md +445 -0
  140. moai_adk/templates/.claude/agents/moai/builder-command.md +1132 -0
  141. moai_adk/templates/.claude/agents/moai/builder-skill.md +601 -0
  142. moai_adk/templates/.claude/agents/moai/expert-backend.md +831 -0
  143. moai_adk/templates/.claude/agents/moai/expert-database.md +774 -0
  144. moai_adk/templates/.claude/agents/moai/expert-debug.md +396 -0
  145. moai_adk/templates/.claude/agents/moai/expert-devops.md +711 -0
  146. moai_adk/templates/.claude/agents/moai/expert-frontend.md +666 -0
  147. moai_adk/templates/.claude/agents/moai/expert-security.md +474 -0
  148. moai_adk/templates/.claude/agents/moai/expert-uiux.md +1038 -0
  149. moai_adk/templates/.claude/agents/moai/manager-claude-code.md +429 -0
  150. moai_adk/templates/.claude/agents/moai/manager-docs.md +570 -0
  151. moai_adk/templates/.claude/agents/moai/manager-git.md +937 -0
  152. moai_adk/templates/.claude/agents/moai/manager-project.md +891 -0
  153. moai_adk/templates/.claude/agents/moai/manager-quality.md +598 -0
  154. moai_adk/templates/.claude/agents/moai/manager-spec.md +713 -0
  155. moai_adk/templates/.claude/agents/moai/manager-strategy.md +600 -0
  156. moai_adk/templates/.claude/agents/moai/manager-tdd.md +603 -0
  157. moai_adk/templates/.claude/agents/moai/mcp-context7.md +369 -0
  158. moai_adk/templates/.claude/agents/moai/mcp-figma.md +1567 -0
  159. moai_adk/templates/.claude/agents/moai/mcp-notion.md +749 -0
  160. moai_adk/templates/.claude/agents/moai/mcp-playwright.md +427 -0
  161. moai_adk/templates/.claude/agents/moai/mcp-sequential-thinking.md +994 -0
  162. moai_adk/templates/.claude/commands/moai/0-project.md +1143 -0
  163. moai_adk/templates/.claude/commands/moai/1-plan.md +1435 -0
  164. moai_adk/templates/.claude/commands/moai/2-run.md +883 -0
  165. moai_adk/templates/.claude/commands/moai/3-sync.md +993 -0
  166. moai_adk/templates/.claude/commands/moai/9-feedback.md +314 -0
  167. moai_adk/templates/.claude/hooks/__init__.py +8 -0
  168. moai_adk/templates/.claude/hooks/moai/__init__.py +8 -0
  169. moai_adk/templates/.claude/hooks/moai/lib/__init__.py +85 -0
  170. moai_adk/templates/.claude/hooks/{alfred/shared/core → moai/lib}/checkpoint.py +9 -36
  171. moai_adk/templates/.claude/hooks/moai/lib/common.py +131 -0
  172. moai_adk/templates/.claude/hooks/moai/lib/config_manager.py +446 -0
  173. moai_adk/templates/.claude/hooks/moai/lib/config_validator.py +639 -0
  174. moai_adk/templates/.claude/hooks/moai/lib/example_config.json +104 -0
  175. moai_adk/templates/.claude/hooks/moai/lib/git_operations_manager.py +590 -0
  176. moai_adk/templates/.claude/hooks/moai/lib/language_validator.py +317 -0
  177. moai_adk/templates/.claude/hooks/moai/lib/models.py +102 -0
  178. moai_adk/templates/.claude/hooks/moai/lib/path_utils.py +28 -0
  179. moai_adk/templates/.claude/hooks/{alfred/shared/core → moai/lib}/project.py +63 -44
  180. moai_adk/templates/.claude/hooks/moai/lib/test_hooks_improvements.py +443 -0
  181. moai_adk/templates/.claude/hooks/{alfred/core → moai/lib}/timeout.py +40 -16
  182. moai_adk/templates/.claude/hooks/moai/lib/unified_timeout_manager.py +530 -0
  183. moai_adk/templates/.claude/hooks/moai/session_end__auto_cleanup.py +862 -0
  184. moai_adk/templates/.claude/hooks/moai/session_start__show_project_info.py +921 -0
  185. moai_adk/templates/.claude/output-styles/moai/r2d2.md +380 -0
  186. moai_adk/templates/.claude/output-styles/moai/yoda.md +338 -0
  187. moai_adk/templates/.claude/settings.json +78 -50
  188. moai_adk/templates/.claude/skills/moai-docs-generation/SKILL.md +247 -0
  189. moai_adk/templates/.claude/skills/moai-docs-generation/modules/README.md +44 -0
  190. moai_adk/templates/.claude/skills/moai-docs-generation/modules/api-documentation.md +130 -0
  191. moai_adk/templates/.claude/skills/moai-docs-generation/modules/code-documentation.md +152 -0
  192. moai_adk/templates/.claude/skills/moai-docs-generation/modules/multi-format-output.md +178 -0
  193. moai_adk/templates/.claude/skills/moai-docs-generation/modules/user-guides.md +147 -0
  194. moai_adk/templates/.claude/skills/moai-domain-backend/SKILL.md +312 -283
  195. moai_adk/templates/.claude/skills/moai-domain-database/SKILL.md +291 -94
  196. moai_adk/templates/.claude/skills/moai-domain-database/modules/README.md +53 -0
  197. moai_adk/templates/.claude/skills/moai-domain-database/modules/mongodb.md +231 -0
  198. moai_adk/templates/.claude/skills/moai-domain-database/modules/postgresql.md +169 -0
  199. moai_adk/templates/.claude/skills/moai-domain-database/modules/redis.md +262 -0
  200. moai_adk/templates/.claude/skills/moai-domain-frontend/SKILL.md +469 -101
  201. moai_adk/templates/.claude/skills/moai-domain-uiux/SKILL.md +453 -0
  202. moai_adk/templates/.claude/skills/moai-domain-uiux/examples.md +560 -0
  203. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/accessibility-wcag.md +260 -0
  204. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/component-architecture.md +228 -0
  205. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/design-system-tokens.md +405 -0
  206. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/icon-libraries.md +401 -0
  207. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/theming-system.md +373 -0
  208. moai_adk/templates/.claude/skills/moai-domain-uiux/reference.md +243 -0
  209. moai_adk/templates/.claude/skills/moai-formats-data/SKILL.md +491 -0
  210. moai_adk/templates/.claude/skills/moai-formats-data/modules/README.md +98 -0
  211. moai_adk/templates/.claude/skills/moai-formats-data/modules/SKILL-MODULARIZATION-TEMPLATE.md +278 -0
  212. moai_adk/templates/.claude/skills/moai-formats-data/modules/caching-performance.md +459 -0
  213. moai_adk/templates/.claude/skills/moai-formats-data/modules/data-validation.md +485 -0
  214. moai_adk/templates/.claude/skills/moai-formats-data/modules/json-optimization.md +374 -0
  215. moai_adk/templates/.claude/skills/moai-formats-data/modules/toon-encoding.md +308 -0
  216. moai_adk/templates/.claude/skills/moai-foundation-claude/SKILL.md +201 -0
  217. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/best-practices-checklist.md +616 -0
  218. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-custom-slash-commands-official.md +729 -0
  219. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-hooks-official.md +560 -0
  220. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-iam-official.md +635 -0
  221. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-memory-official.md +543 -0
  222. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-settings-official.md +663 -0
  223. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-skills-official.md +113 -0
  224. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-sub-agents-official.md +238 -0
  225. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/complete-configuration-guide.md +175 -0
  226. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/skill-examples.md +1674 -0
  227. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/skill-formatting-guide.md +729 -0
  228. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-examples.md +1513 -0
  229. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-formatting-guide.md +1086 -0
  230. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-integration-patterns.md +1100 -0
  231. moai_adk/templates/.claude/skills/moai-foundation-context/SKILL.md +438 -0
  232. moai_adk/templates/.claude/skills/moai-foundation-core/SKILL.md +515 -0
  233. moai_adk/templates/.claude/skills/moai-foundation-core/modules/README.md +296 -0
  234. moai_adk/templates/.claude/skills/moai-foundation-core/modules/agents-reference.md +346 -0
  235. moai_adk/templates/.claude/skills/moai-foundation-core/modules/commands-reference.md +432 -0
  236. moai_adk/templates/.claude/skills/moai-foundation-core/modules/delegation-patterns.md +757 -0
  237. moai_adk/templates/.claude/skills/moai-foundation-core/modules/execution-rules.md +687 -0
  238. moai_adk/templates/.claude/skills/moai-foundation-core/modules/modular-system.md +665 -0
  239. moai_adk/templates/.claude/skills/moai-foundation-core/modules/progressive-disclosure.md +649 -0
  240. moai_adk/templates/.claude/skills/moai-foundation-core/modules/spec-first-tdd.md +864 -0
  241. moai_adk/templates/.claude/skills/moai-foundation-core/modules/token-optimization.md +708 -0
  242. moai_adk/templates/.claude/skills/moai-foundation-core/modules/trust-5-framework.md +981 -0
  243. moai_adk/templates/.claude/skills/moai-foundation-quality/SKILL.md +362 -0
  244. moai_adk/templates/.claude/skills/moai-foundation-quality/examples.md +1232 -0
  245. moai_adk/templates/.claude/skills/moai-foundation-quality/modules/best-practices.md +261 -0
  246. moai_adk/templates/.claude/skills/moai-foundation-quality/modules/integration-patterns.md +194 -0
  247. moai_adk/templates/.claude/skills/moai-foundation-quality/modules/proactive-analysis.md +229 -0
  248. moai_adk/templates/.claude/skills/moai-foundation-quality/modules/trust5-validation.md +169 -0
  249. moai_adk/templates/.claude/skills/moai-foundation-quality/reference.md +1266 -0
  250. moai_adk/templates/.claude/skills/moai-foundation-quality/scripts/quality-gate.sh +668 -0
  251. moai_adk/templates/.claude/skills/moai-foundation-quality/templates/github-actions-quality.yml +481 -0
  252. moai_adk/templates/.claude/skills/moai-foundation-quality/templates/quality-config.yaml +519 -0
  253. moai_adk/templates/.claude/skills/moai-integration-mcp/SKILL.md +352 -0
  254. moai_adk/templates/.claude/skills/moai-integration-mcp/modules/README.md +52 -0
  255. moai_adk/templates/.claude/skills/moai-integration-mcp/modules/error-handling.md +334 -0
  256. moai_adk/templates/.claude/skills/moai-integration-mcp/modules/integration-patterns.md +310 -0
  257. moai_adk/templates/.claude/skills/moai-integration-mcp/modules/security-authentication.md +256 -0
  258. moai_adk/templates/.claude/skills/moai-integration-mcp/modules/server-architecture.md +253 -0
  259. moai_adk/templates/.claude/skills/moai-lang-unified/README.md +133 -0
  260. moai_adk/templates/.claude/skills/moai-lang-unified/SKILL.md +296 -0
  261. moai_adk/templates/.claude/skills/moai-lang-unified/examples.md +1269 -0
  262. moai_adk/templates/.claude/skills/moai-lang-unified/reference.md +331 -0
  263. moai_adk/templates/.claude/skills/moai-library-mermaid/SKILL.md +298 -0
  264. moai_adk/templates/.claude/skills/moai-library-mermaid/advanced-patterns.md +465 -0
  265. moai_adk/templates/.claude/skills/moai-library-mermaid/examples.md +270 -0
  266. moai_adk/templates/.claude/skills/moai-library-mermaid/optimization.md +440 -0
  267. moai_adk/templates/.claude/skills/moai-library-mermaid/reference.md +228 -0
  268. moai_adk/templates/.claude/skills/moai-library-nextra/SKILL.md +316 -0
  269. moai_adk/templates/.claude/skills/moai-library-nextra/advanced-patterns.md +336 -0
  270. moai_adk/templates/.claude/skills/moai-library-nextra/modules/advanced-deployment-patterns.md +182 -0
  271. moai_adk/templates/.claude/skills/moai-library-nextra/modules/advanced-patterns.md +17 -0
  272. moai_adk/templates/.claude/skills/moai-library-nextra/modules/configuration.md +57 -0
  273. moai_adk/templates/.claude/skills/moai-library-nextra/modules/content-architecture-optimization.md +162 -0
  274. moai_adk/templates/.claude/skills/moai-library-nextra/modules/deployment.md +52 -0
  275. moai_adk/templates/.claude/skills/moai-library-nextra/modules/framework-core-configuration.md +186 -0
  276. moai_adk/templates/.claude/skills/moai-library-nextra/modules/i18n-setup.md +55 -0
  277. moai_adk/templates/.claude/skills/moai-library-nextra/modules/mdx-components.md +52 -0
  278. moai_adk/templates/.claude/skills/moai-library-nextra/optimization.md +303 -0
  279. moai_adk/templates/.claude/skills/moai-library-shadcn/SKILL.md +370 -0
  280. moai_adk/templates/.claude/skills/moai-library-shadcn/examples.md +575 -0
  281. moai_adk/templates/.claude/skills/moai-library-shadcn/modules/advanced-patterns.md +394 -0
  282. moai_adk/templates/.claude/skills/moai-library-shadcn/modules/optimization.md +278 -0
  283. moai_adk/templates/.claude/skills/moai-library-shadcn/modules/shadcn-components.md +457 -0
  284. moai_adk/templates/.claude/skills/moai-library-shadcn/modules/shadcn-theming.md +373 -0
  285. moai_adk/templates/.claude/skills/moai-library-shadcn/reference.md +74 -0
  286. moai_adk/templates/.claude/skills/moai-platform-baas/README.md +186 -0
  287. moai_adk/templates/.claude/skills/moai-platform-baas/SKILL.md +290 -0
  288. moai_adk/templates/.claude/skills/moai-platform-baas/examples.md +1225 -0
  289. moai_adk/templates/.claude/skills/moai-platform-baas/reference.md +567 -0
  290. moai_adk/templates/.claude/skills/moai-platform-baas/scripts/provider-selector.py +323 -0
  291. moai_adk/templates/.claude/skills/moai-platform-baas/templates/stack-config.yaml +204 -0
  292. moai_adk/templates/.claude/skills/moai-workflow-jit-docs/SKILL.md +446 -0
  293. moai_adk/templates/.claude/skills/moai-workflow-jit-docs/advanced-patterns.md +379 -0
  294. moai_adk/templates/.claude/skills/moai-workflow-jit-docs/optimization.md +286 -0
  295. moai_adk/templates/.claude/skills/moai-workflow-project/README.md +190 -0
  296. moai_adk/templates/.claude/skills/moai-workflow-project/SKILL.md +387 -0
  297. moai_adk/templates/.claude/skills/moai-workflow-project/__init__.py +520 -0
  298. moai_adk/templates/.claude/skills/moai-workflow-project/complete_workflow_demo_fixed.py +574 -0
  299. moai_adk/templates/.claude/skills/moai-workflow-project/examples/complete_project_setup.py +317 -0
  300. moai_adk/templates/.claude/skills/moai-workflow-project/examples/complete_workflow_demo.py +663 -0
  301. moai_adk/templates/.claude/skills/moai-workflow-project/examples/config-migration-example.json +190 -0
  302. moai_adk/templates/.claude/skills/moai-workflow-project/examples/question-examples.json +135 -0
  303. moai_adk/templates/.claude/skills/moai-workflow-project/examples/quick_start.py +196 -0
  304. moai_adk/templates/.claude/skills/moai-workflow-project/modules/__init__.py +17 -0
  305. moai_adk/templates/.claude/skills/moai-workflow-project/modules/advanced-patterns.md +158 -0
  306. moai_adk/templates/.claude/skills/moai-workflow-project/modules/ask_user_integration.py +340 -0
  307. moai_adk/templates/.claude/skills/moai-workflow-project/modules/batch_questions.py +713 -0
  308. moai_adk/templates/.claude/skills/moai-workflow-project/modules/config_manager.py +538 -0
  309. moai_adk/templates/.claude/skills/moai-workflow-project/modules/documentation_manager.py +1336 -0
  310. moai_adk/templates/.claude/skills/moai-workflow-project/modules/language_initializer.py +730 -0
  311. moai_adk/templates/.claude/skills/moai-workflow-project/modules/migration_manager.py +608 -0
  312. moai_adk/templates/.claude/skills/moai-workflow-project/modules/template_optimizer.py +1005 -0
  313. moai_adk/templates/.claude/skills/moai-workflow-project/schemas/config-schema.json +316 -0
  314. moai_adk/templates/.claude/skills/moai-workflow-project/schemas/tab_schema.json +1362 -0
  315. moai_adk/templates/.claude/skills/moai-workflow-project/templates/config-template.json +71 -0
  316. moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/product-template.md +44 -0
  317. moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/structure-template.md +48 -0
  318. moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/tech-template.md +71 -0
  319. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/config-manager-setup.json +109 -0
  320. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/language-initializer.json +228 -0
  321. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/menu-project-config.json +130 -0
  322. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/project-batch-questions.json +97 -0
  323. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/spec-workflow-setup.json +150 -0
  324. moai_adk/templates/.claude/skills/moai-workflow-project/test_integration_simple.py +436 -0
  325. moai_adk/templates/.claude/skills/moai-workflow-templates/SKILL.md +374 -0
  326. moai_adk/templates/.claude/skills/moai-workflow-templates/modules/code-templates.md +124 -0
  327. moai_adk/templates/.claude/skills/moai-workflow-templates/modules/feedback-templates.md +100 -0
  328. moai_adk/templates/.claude/skills/moai-workflow-templates/modules/template-optimizer.md +138 -0
  329. moai_adk/templates/.claude/skills/moai-workflow-testing/LICENSE.txt +202 -0
  330. moai_adk/templates/.claude/skills/moai-workflow-testing/SKILL.md +453 -0
  331. moai_adk/templates/.claude/skills/moai-workflow-testing/advanced-patterns.md +576 -0
  332. moai_adk/templates/.claude/skills/moai-workflow-testing/examples/ai-powered-testing.py +294 -0
  333. moai_adk/templates/.claude/skills/moai-workflow-testing/examples/console_logging.py +35 -0
  334. moai_adk/templates/.claude/skills/moai-workflow-testing/examples/element_discovery.py +40 -0
  335. moai_adk/templates/.claude/skills/moai-workflow-testing/examples/static_html_automation.py +34 -0
  336. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/README.md +220 -0
  337. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/ai-debugging.md +845 -0
  338. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/automated-code-review.md +1416 -0
  339. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/performance-optimization.md +1234 -0
  340. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/smart-refactoring.md +1243 -0
  341. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/tdd-context7.md +1260 -0
  342. moai_adk/templates/.claude/skills/moai-workflow-testing/optimization.md +505 -0
  343. moai_adk/templates/.claude/skills/moai-workflow-testing/reference/playwright-best-practices.md +57 -0
  344. moai_adk/templates/.claude/skills/moai-workflow-testing/scripts/with_server.py +218 -0
  345. moai_adk/templates/.claude/skills/moai-workflow-testing/templates/alfred-integration.md +376 -0
  346. moai_adk/templates/.claude/skills/moai-workflow-testing/workflows/enterprise-testing-workflow.py +571 -0
  347. moai_adk/templates/.claude/skills/moai-worktree/SKILL.md +410 -0
  348. moai_adk/templates/.claude/skills/moai-worktree/examples.md +606 -0
  349. moai_adk/templates/.claude/skills/moai-worktree/modules/integration-patterns.md +982 -0
  350. moai_adk/templates/.claude/skills/moai-worktree/modules/parallel-development.md +778 -0
  351. moai_adk/templates/.claude/skills/moai-worktree/modules/worktree-commands.md +646 -0
  352. moai_adk/templates/.claude/skills/moai-worktree/modules/worktree-management.md +782 -0
  353. moai_adk/templates/.claude/skills/moai-worktree/reference.md +357 -0
  354. moai_adk/templates/.git-hooks/pre-commit +128 -0
  355. moai_adk/templates/.git-hooks/pre-push +220 -13
  356. moai_adk/templates/.github/workflows/ci-universal.yml +513 -0
  357. moai_adk/templates/.github/workflows/security-secrets-check.yml +179 -0
  358. moai_adk/templates/.github/workflows/spec-issue-sync.yml +0 -1
  359. moai_adk/templates/.gitignore +197 -13
  360. moai_adk/templates/.mcp.json +20 -0
  361. moai_adk/templates/.moai/cache/personalization.json +10 -0
  362. moai_adk/templates/.moai/config/config.yaml +344 -0
  363. moai_adk/templates/.moai/config/presets/manual.yaml +28 -0
  364. moai_adk/templates/.moai/config/presets/personal.yaml +30 -0
  365. moai_adk/templates/.moai/config/presets/team.yaml +33 -0
  366. moai_adk/templates/.moai/config/questions/_schema.yaml +79 -0
  367. moai_adk/templates/.moai/config/questions/tab1-user.yaml +108 -0
  368. moai_adk/templates/.moai/config/questions/tab2-project.yaml +122 -0
  369. moai_adk/templates/.moai/config/questions/tab3-git.yaml +542 -0
  370. moai_adk/templates/.moai/config/questions/tab4-quality.yaml +167 -0
  371. moai_adk/templates/.moai/config/questions/tab5-system.yaml +152 -0
  372. moai_adk/templates/.moai/config/sections/git-strategy.yaml +40 -0
  373. moai_adk/templates/.moai/config/sections/language.yaml +11 -0
  374. moai_adk/templates/.moai/config/sections/project.yaml +13 -0
  375. moai_adk/templates/.moai/config/sections/quality.yaml +15 -0
  376. moai_adk/templates/.moai/config/sections/system.yaml +14 -0
  377. moai_adk/templates/.moai/config/sections/user.yaml +5 -0
  378. moai_adk/templates/.moai/config/statusline-config.yaml +86 -0
  379. moai_adk/templates/.moai/scripts/setup-glm.py +136 -0
  380. moai_adk/templates/CLAUDE.md +310 -1050
  381. moai_adk/utils/__init__.py +24 -2
  382. moai_adk/utils/banner.py +7 -11
  383. moai_adk/utils/common.py +294 -0
  384. moai_adk/utils/link_validator.py +241 -0
  385. moai_adk/utils/logger.py +4 -9
  386. moai_adk/utils/safe_file_reader.py +206 -0
  387. moai_adk/{templates/.claude/hooks/alfred/utils → utils}/timeout.py +8 -9
  388. moai_adk/utils/toon_utils.py +256 -0
  389. moai_adk/version.py +22 -0
  390. moai_adk-0.32.8.dist-info/METADATA +2478 -0
  391. moai_adk-0.32.8.dist-info/RECORD +396 -0
  392. {moai_adk-0.15.1.dist-info → moai_adk-0.32.8.dist-info}/WHEEL +1 -1
  393. {moai_adk-0.15.1.dist-info → moai_adk-0.32.8.dist-info}/entry_points.txt +1 -0
  394. moai_adk/cli/commands/backup.py +0 -80
  395. moai_adk/core/tags/__init__.py +0 -86
  396. moai_adk/core/tags/ci_validator.py +0 -463
  397. moai_adk/core/tags/cli.py +0 -283
  398. moai_adk/core/tags/generator.py +0 -109
  399. moai_adk/core/tags/inserter.py +0 -99
  400. moai_adk/core/tags/mapper.py +0 -126
  401. moai_adk/core/tags/parser.py +0 -76
  402. moai_adk/core/tags/pre_commit_validator.py +0 -393
  403. moai_adk/core/tags/reporter.py +0 -956
  404. moai_adk/core/tags/tags.py +0 -149
  405. moai_adk/core/tags/validator.py +0 -897
  406. moai_adk/templates/.claude/agents/alfred/backend-expert.md +0 -319
  407. moai_adk/templates/.claude/agents/alfred/cc-manager.md +0 -316
  408. moai_adk/templates/.claude/agents/alfred/debug-helper.md +0 -208
  409. moai_adk/templates/.claude/agents/alfred/devops-expert.md +0 -464
  410. moai_adk/templates/.claude/agents/alfred/doc-syncer.md +0 -214
  411. moai_adk/templates/.claude/agents/alfred/frontend-expert.md +0 -357
  412. moai_adk/templates/.claude/agents/alfred/git-manager.md +0 -406
  413. moai_adk/templates/.claude/agents/alfred/implementation-planner.md +0 -423
  414. moai_adk/templates/.claude/agents/alfred/project-manager.md +0 -312
  415. moai_adk/templates/.claude/agents/alfred/quality-gate.md +0 -343
  416. moai_adk/templates/.claude/agents/alfred/skill-factory.md +0 -865
  417. moai_adk/templates/.claude/agents/alfred/spec-builder.md +0 -426
  418. moai_adk/templates/.claude/agents/alfred/tag-agent.md +0 -361
  419. moai_adk/templates/.claude/agents/alfred/tdd-implementer.md +0 -428
  420. moai_adk/templates/.claude/agents/alfred/trust-checker.md +0 -375
  421. moai_adk/templates/.claude/agents/alfred/ui-ux-expert.md +0 -571
  422. moai_adk/templates/.claude/commands/alfred/0-project.md +0 -1854
  423. moai_adk/templates/.claude/commands/alfred/1-plan.md +0 -880
  424. moai_adk/templates/.claude/commands/alfred/2-run.md +0 -793
  425. moai_adk/templates/.claude/commands/alfred/3-sync.md +0 -1084
  426. moai_adk/templates/.claude/commands/alfred/9-feedback.md +0 -149
  427. moai_adk/templates/.claude/hooks/alfred/core/project.py +0 -748
  428. moai_adk/templates/.claude/hooks/alfred/core/ttl_cache.py +0 -108
  429. moai_adk/templates/.claude/hooks/alfred/core/version_cache.py +0 -198
  430. moai_adk/templates/.claude/hooks/alfred/handlers/__init__.py +0 -29
  431. moai_adk/templates/.claude/hooks/alfred/post_tool__log_changes.py +0 -94
  432. moai_adk/templates/.claude/hooks/alfred/pre_tool__auto_checkpoint.py +0 -100
  433. moai_adk/templates/.claude/hooks/alfred/session_end__cleanup.py +0 -94
  434. moai_adk/templates/.claude/hooks/alfred/session_start__show_project_info.py +0 -94
  435. moai_adk/templates/.claude/hooks/alfred/shared/core/__init__.py +0 -170
  436. moai_adk/templates/.claude/hooks/alfred/shared/core/context.py +0 -67
  437. moai_adk/templates/.claude/hooks/alfred/shared/core/tags.py +0 -230
  438. moai_adk/templates/.claude/hooks/alfred/shared/core/version_cache.py +0 -198
  439. moai_adk/templates/.claude/hooks/alfred/shared/handlers/__init__.py +0 -21
  440. moai_adk/templates/.claude/hooks/alfred/shared/handlers/notification.py +0 -154
  441. moai_adk/templates/.claude/hooks/alfred/shared/handlers/session.py +0 -174
  442. moai_adk/templates/.claude/hooks/alfred/shared/handlers/tool.py +0 -87
  443. moai_adk/templates/.claude/hooks/alfred/shared/handlers/user.py +0 -61
  444. moai_adk/templates/.claude/hooks/alfred/user_prompt__jit_load_docs.py +0 -112
  445. moai_adk/templates/.claude/hooks/alfred/utils/__init__.py +0 -1
  446. moai_adk/templates/.claude/skills/moai-alfred-agent-guide/SKILL.md +0 -70
  447. moai_adk/templates/.claude/skills/moai-alfred-agent-guide/examples.md +0 -62
  448. moai_adk/templates/.claude/skills/moai-alfred-agent-guide/reference.md +0 -242
  449. moai_adk/templates/.claude/skills/moai-alfred-config-schema/SKILL.md +0 -56
  450. moai_adk/templates/.claude/skills/moai-alfred-config-schema/examples.md +0 -28
  451. moai_adk/templates/.claude/skills/moai-alfred-config-schema/reference.md +0 -444
  452. moai_adk/templates/.claude/skills/moai-alfred-context-budget/SKILL.md +0 -62
  453. moai_adk/templates/.claude/skills/moai-alfred-context-budget/examples.md +0 -28
  454. moai_adk/templates/.claude/skills/moai-alfred-context-budget/reference.md +0 -405
  455. moai_adk/templates/.claude/skills/moai-alfred-dev-guide/SKILL.md +0 -51
  456. moai_adk/templates/.claude/skills/moai-alfred-dev-guide/examples.md +0 -355
  457. moai_adk/templates/.claude/skills/moai-alfred-dev-guide/reference.md +0 -239
  458. moai_adk/templates/.claude/skills/moai-alfred-ears-authoring/SKILL.md +0 -113
  459. moai_adk/templates/.claude/skills/moai-alfred-ears-authoring/examples.md +0 -29
  460. moai_adk/templates/.claude/skills/moai-alfred-ears-authoring/reference.md +0 -28
  461. moai_adk/templates/.claude/skills/moai-alfred-expertise-detection/SKILL.md +0 -323
  462. moai_adk/templates/.claude/skills/moai-alfred-expertise-detection/examples.md +0 -286
  463. moai_adk/templates/.claude/skills/moai-alfred-expertise-detection/reference.md +0 -126
  464. moai_adk/templates/.claude/skills/moai-alfred-git-workflow/SKILL.md +0 -122
  465. moai_adk/templates/.claude/skills/moai-alfred-git-workflow/examples.md +0 -29
  466. moai_adk/templates/.claude/skills/moai-alfred-git-workflow/reference.md +0 -29
  467. moai_adk/templates/.claude/skills/moai-alfred-gitflow-policy/SKILL.md +0 -74
  468. moai_adk/templates/.claude/skills/moai-alfred-gitflow-policy/examples.md +0 -4
  469. moai_adk/templates/.claude/skills/moai-alfred-gitflow-policy/reference.md +0 -269
  470. moai_adk/templates/.claude/skills/moai-alfred-interactive-questions/SKILL.md +0 -237
  471. moai_adk/templates/.claude/skills/moai-alfred-interactive-questions/examples.md +0 -615
  472. moai_adk/templates/.claude/skills/moai-alfred-interactive-questions/reference.md +0 -653
  473. moai_adk/templates/.claude/skills/moai-alfred-issue-labels/SKILL.md +0 -19
  474. moai_adk/templates/.claude/skills/moai-alfred-issue-labels/examples.md +0 -4
  475. moai_adk/templates/.claude/skills/moai-alfred-issue-labels/reference.md +0 -150
  476. moai_adk/templates/.claude/skills/moai-alfred-language-detection/SKILL.md +0 -113
  477. moai_adk/templates/.claude/skills/moai-alfred-language-detection/examples.md +0 -29
  478. moai_adk/templates/.claude/skills/moai-alfred-language-detection/reference.md +0 -28
  479. moai_adk/templates/.claude/skills/moai-alfred-persona-roles/SKILL.md +0 -198
  480. moai_adk/templates/.claude/skills/moai-alfred-persona-roles/examples.md +0 -431
  481. moai_adk/templates/.claude/skills/moai-alfred-persona-roles/reference.md +0 -141
  482. moai_adk/templates/.claude/skills/moai-alfred-practices/SKILL.md +0 -89
  483. moai_adk/templates/.claude/skills/moai-alfred-practices/examples.md +0 -122
  484. moai_adk/templates/.claude/skills/moai-alfred-practices/reference.md +0 -369
  485. moai_adk/templates/.claude/skills/moai-alfred-proactive-suggestions/SKILL.md +0 -508
  486. moai_adk/templates/.claude/skills/moai-alfred-proactive-suggestions/examples.md +0 -481
  487. moai_adk/templates/.claude/skills/moai-alfred-proactive-suggestions/reference.md +0 -100
  488. moai_adk/templates/.claude/skills/moai-alfred-reporting/SKILL.md +0 -273
  489. moai_adk/templates/.claude/skills/moai-alfred-rules/SKILL.md +0 -77
  490. moai_adk/templates/.claude/skills/moai-alfred-rules/examples.md +0 -265
  491. moai_adk/templates/.claude/skills/moai-alfred-rules/reference.md +0 -539
  492. moai_adk/templates/.claude/skills/moai-alfred-session-state/SKILL.md +0 -19
  493. moai_adk/templates/.claude/skills/moai-alfred-session-state/examples.md +0 -4
  494. moai_adk/templates/.claude/skills/moai-alfred-session-state/reference.md +0 -84
  495. moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/README.md +0 -137
  496. moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/SKILL.md +0 -219
  497. moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/examples/validate-spec.sh +0 -161
  498. moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/examples.md +0 -541
  499. moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/reference.md +0 -622
  500. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-extended/SKILL.md +0 -115
  501. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-extended/examples.md +0 -4
  502. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-extended/reference.md +0 -348
  503. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-validation/SKILL.md +0 -113
  504. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-validation/examples.md +0 -29
  505. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-validation/reference.md +0 -28
  506. moai_adk/templates/.claude/skills/moai-alfred-tag-scanning/SKILL.md +0 -113
  507. moai_adk/templates/.claude/skills/moai-alfred-tag-scanning/examples.md +0 -29
  508. moai_adk/templates/.claude/skills/moai-alfred-tag-scanning/reference.md +0 -28
  509. moai_adk/templates/.claude/skills/moai-alfred-todowrite-pattern/SKILL.md +0 -19
  510. moai_adk/templates/.claude/skills/moai-alfred-todowrite-pattern/examples.md +0 -4
  511. moai_adk/templates/.claude/skills/moai-alfred-todowrite-pattern/reference.md +0 -211
  512. moai_adk/templates/.claude/skills/moai-alfred-trust-validation/SKILL.md +0 -113
  513. moai_adk/templates/.claude/skills/moai-alfred-trust-validation/examples.md +0 -29
  514. moai_adk/templates/.claude/skills/moai-alfred-trust-validation/reference.md +0 -28
  515. moai_adk/templates/.claude/skills/moai-alfred-workflow/SKILL.md +0 -288
  516. moai_adk/templates/.claude/skills/moai-cc-agents/SKILL.md +0 -269
  517. moai_adk/templates/.claude/skills/moai-cc-agents/templates/agent-template.md +0 -32
  518. moai_adk/templates/.claude/skills/moai-cc-claude-md/SKILL.md +0 -298
  519. moai_adk/templates/.claude/skills/moai-cc-claude-md/templates/CLAUDE-template.md +0 -26
  520. moai_adk/templates/.claude/skills/moai-cc-commands/SKILL.md +0 -307
  521. moai_adk/templates/.claude/skills/moai-cc-commands/templates/command-template.md +0 -21
  522. moai_adk/templates/.claude/skills/moai-cc-hooks/SKILL.md +0 -252
  523. moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/pre-bash-check.sh +0 -19
  524. moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/preserve-permissions.sh +0 -19
  525. moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/validate-bash-command.py +0 -24
  526. moai_adk/templates/.claude/skills/moai-cc-mcp-plugins/SKILL.md +0 -199
  527. moai_adk/templates/.claude/skills/moai-cc-mcp-plugins/templates/settings-mcp-template.json +0 -39
  528. moai_adk/templates/.claude/skills/moai-cc-memory/SKILL.md +0 -316
  529. moai_adk/templates/.claude/skills/moai-cc-memory/templates/session-summary-template.md +0 -18
  530. moai_adk/templates/.claude/skills/moai-cc-settings/SKILL.md +0 -263
  531. moai_adk/templates/.claude/skills/moai-cc-settings/templates/settings-complete-template.json +0 -30
  532. moai_adk/templates/.claude/skills/moai-cc-skill-descriptions/SKILL.md +0 -19
  533. moai_adk/templates/.claude/skills/moai-cc-skill-descriptions/examples.md +0 -4
  534. moai_adk/templates/.claude/skills/moai-cc-skill-descriptions/reference.md +0 -218
  535. moai_adk/templates/.claude/skills/moai-cc-skill-factory/CHECKLIST.md +0 -482
  536. moai_adk/templates/.claude/skills/moai-cc-skill-factory/EXAMPLES.md +0 -278
  537. moai_adk/templates/.claude/skills/moai-cc-skill-factory/INTERACTIVE-DISCOVERY.md +0 -524
  538. moai_adk/templates/.claude/skills/moai-cc-skill-factory/METADATA.md +0 -477
  539. moai_adk/templates/.claude/skills/moai-cc-skill-factory/PARALLEL-ANALYSIS-REPORT.md +0 -429
  540. moai_adk/templates/.claude/skills/moai-cc-skill-factory/PYTHON-VERSION-MATRIX.md +0 -391
  541. moai_adk/templates/.claude/skills/moai-cc-skill-factory/SKILL-FACTORY-WORKFLOW.md +0 -431
  542. moai_adk/templates/.claude/skills/moai-cc-skill-factory/SKILL-UPDATE-ADVISOR.md +0 -577
  543. moai_adk/templates/.claude/skills/moai-cc-skill-factory/SKILL.md +0 -271
  544. moai_adk/templates/.claude/skills/moai-cc-skill-factory/STEP-BY-STEP-GUIDE.md +0 -466
  545. moai_adk/templates/.claude/skills/moai-cc-skill-factory/STRUCTURE.md +0 -583
  546. moai_adk/templates/.claude/skills/moai-cc-skill-factory/WEB-RESEARCH.md +0 -526
  547. moai_adk/templates/.claude/skills/moai-cc-skill-factory/reference.md +0 -465
  548. moai_adk/templates/.claude/skills/moai-cc-skill-factory/scripts/generate-structure.sh +0 -328
  549. moai_adk/templates/.claude/skills/moai-cc-skill-factory/scripts/validate-skill.sh +0 -312
  550. moai_adk/templates/.claude/skills/moai-cc-skill-factory/templates/SKILL_TEMPLATE.md +0 -245
  551. moai_adk/templates/.claude/skills/moai-cc-skill-factory/templates/examples-template.md +0 -285
  552. moai_adk/templates/.claude/skills/moai-cc-skill-factory/templates/reference-template.md +0 -278
  553. moai_adk/templates/.claude/skills/moai-cc-skill-factory/templates/scripts-template.sh +0 -303
  554. moai_adk/templates/.claude/skills/moai-cc-skills/SKILL.md +0 -291
  555. moai_adk/templates/.claude/skills/moai-cc-skills/templates/SKILL-template.md +0 -15
  556. moai_adk/templates/.claude/skills/moai-design-systems/SKILL.md +0 -802
  557. moai_adk/templates/.claude/skills/moai-design-systems/examples.md +0 -1238
  558. moai_adk/templates/.claude/skills/moai-design-systems/reference.md +0 -673
  559. moai_adk/templates/.claude/skills/moai-domain-backend/examples.md +0 -1633
  560. moai_adk/templates/.claude/skills/moai-domain-backend/reference.md +0 -660
  561. moai_adk/templates/.claude/skills/moai-domain-cli-tool/SKILL.md +0 -123
  562. moai_adk/templates/.claude/skills/moai-domain-cli-tool/examples.md +0 -29
  563. moai_adk/templates/.claude/skills/moai-domain-cli-tool/reference.md +0 -30
  564. moai_adk/templates/.claude/skills/moai-domain-data-science/SKILL.md +0 -123
  565. moai_adk/templates/.claude/skills/moai-domain-data-science/examples.md +0 -29
  566. moai_adk/templates/.claude/skills/moai-domain-data-science/reference.md +0 -30
  567. moai_adk/templates/.claude/skills/moai-domain-database/examples.md +0 -29
  568. moai_adk/templates/.claude/skills/moai-domain-database/reference.md +0 -30
  569. moai_adk/templates/.claude/skills/moai-domain-devops/SKILL.md +0 -124
  570. moai_adk/templates/.claude/skills/moai-domain-devops/examples.md +0 -29
  571. moai_adk/templates/.claude/skills/moai-domain-devops/reference.md +0 -31
  572. moai_adk/templates/.claude/skills/moai-domain-frontend/examples.md +0 -29
  573. moai_adk/templates/.claude/skills/moai-domain-frontend/reference.md +0 -31
  574. moai_adk/templates/.claude/skills/moai-domain-ml/SKILL.md +0 -123
  575. moai_adk/templates/.claude/skills/moai-domain-ml/examples.md +0 -29
  576. moai_adk/templates/.claude/skills/moai-domain-ml/reference.md +0 -30
  577. moai_adk/templates/.claude/skills/moai-domain-mobile-app/SKILL.md +0 -123
  578. moai_adk/templates/.claude/skills/moai-domain-mobile-app/examples.md +0 -29
  579. moai_adk/templates/.claude/skills/moai-domain-mobile-app/reference.md +0 -30
  580. moai_adk/templates/.claude/skills/moai-domain-security/SKILL.md +0 -123
  581. moai_adk/templates/.claude/skills/moai-domain-security/examples.md +0 -29
  582. moai_adk/templates/.claude/skills/moai-domain-security/reference.md +0 -30
  583. moai_adk/templates/.claude/skills/moai-domain-web-api/SKILL.md +0 -123
  584. moai_adk/templates/.claude/skills/moai-domain-web-api/examples.md +0 -29
  585. moai_adk/templates/.claude/skills/moai-domain-web-api/reference.md +0 -30
  586. moai_adk/templates/.claude/skills/moai-essentials-debug/SKILL.md +0 -303
  587. moai_adk/templates/.claude/skills/moai-essentials-debug/examples.md +0 -1064
  588. moai_adk/templates/.claude/skills/moai-essentials-debug/reference.md +0 -1047
  589. moai_adk/templates/.claude/skills/moai-essentials-perf/SKILL.md +0 -113
  590. moai_adk/templates/.claude/skills/moai-essentials-perf/examples.md +0 -29
  591. moai_adk/templates/.claude/skills/moai-essentials-perf/reference.md +0 -28
  592. moai_adk/templates/.claude/skills/moai-essentials-refactor/SKILL.md +0 -113
  593. moai_adk/templates/.claude/skills/moai-essentials-refactor/examples.md +0 -29
  594. moai_adk/templates/.claude/skills/moai-essentials-refactor/reference.md +0 -28
  595. moai_adk/templates/.claude/skills/moai-essentials-review/SKILL.md +0 -113
  596. moai_adk/templates/.claude/skills/moai-essentials-review/examples.md +0 -29
  597. moai_adk/templates/.claude/skills/moai-essentials-review/reference.md +0 -28
  598. moai_adk/templates/.claude/skills/moai-foundation-ears/SKILL.md +0 -116
  599. moai_adk/templates/.claude/skills/moai-foundation-ears/examples.md +0 -29
  600. moai_adk/templates/.claude/skills/moai-foundation-ears/reference.md +0 -28
  601. moai_adk/templates/.claude/skills/moai-foundation-git/SKILL.md +0 -122
  602. moai_adk/templates/.claude/skills/moai-foundation-git/examples.md +0 -29
  603. moai_adk/templates/.claude/skills/moai-foundation-git/reference.md +0 -29
  604. moai_adk/templates/.claude/skills/moai-foundation-langs/SKILL.md +0 -113
  605. moai_adk/templates/.claude/skills/moai-foundation-langs/examples.md +0 -29
  606. moai_adk/templates/.claude/skills/moai-foundation-langs/reference.md +0 -28
  607. moai_adk/templates/.claude/skills/moai-foundation-specs/SKILL.md +0 -113
  608. moai_adk/templates/.claude/skills/moai-foundation-specs/examples.md +0 -29
  609. moai_adk/templates/.claude/skills/moai-foundation-specs/reference.md +0 -28
  610. moai_adk/templates/.claude/skills/moai-foundation-tags/SKILL.md +0 -113
  611. moai_adk/templates/.claude/skills/moai-foundation-tags/examples.md +0 -29
  612. moai_adk/templates/.claude/skills/moai-foundation-tags/reference.md +0 -28
  613. moai_adk/templates/.claude/skills/moai-foundation-trust/SKILL.md +0 -307
  614. moai_adk/templates/.claude/skills/moai-foundation-trust/examples.md +0 -0
  615. moai_adk/templates/.claude/skills/moai-foundation-trust/reference.md +0 -1099
  616. moai_adk/templates/.claude/skills/moai-lang-c/SKILL.md +0 -124
  617. moai_adk/templates/.claude/skills/moai-lang-c/examples.md +0 -29
  618. moai_adk/templates/.claude/skills/moai-lang-c/reference.md +0 -31
  619. moai_adk/templates/.claude/skills/moai-lang-cpp/SKILL.md +0 -124
  620. moai_adk/templates/.claude/skills/moai-lang-cpp/examples.md +0 -29
  621. moai_adk/templates/.claude/skills/moai-lang-cpp/reference.md +0 -31
  622. moai_adk/templates/.claude/skills/moai-lang-csharp/SKILL.md +0 -123
  623. moai_adk/templates/.claude/skills/moai-lang-csharp/examples.md +0 -29
  624. moai_adk/templates/.claude/skills/moai-lang-csharp/reference.md +0 -30
  625. moai_adk/templates/.claude/skills/moai-lang-dart/SKILL.md +0 -123
  626. moai_adk/templates/.claude/skills/moai-lang-dart/examples.md +0 -29
  627. moai_adk/templates/.claude/skills/moai-lang-dart/reference.md +0 -30
  628. moai_adk/templates/.claude/skills/moai-lang-go/SKILL.md +0 -127
  629. moai_adk/templates/.claude/skills/moai-lang-go/examples.md +0 -29
  630. moai_adk/templates/.claude/skills/moai-lang-go/reference.md +0 -31
  631. moai_adk/templates/.claude/skills/moai-lang-java/SKILL.md +0 -126
  632. moai_adk/templates/.claude/skills/moai-lang-java/examples.md +0 -29
  633. moai_adk/templates/.claude/skills/moai-lang-java/reference.md +0 -31
  634. moai_adk/templates/.claude/skills/moai-lang-javascript/SKILL.md +0 -125
  635. moai_adk/templates/.claude/skills/moai-lang-javascript/examples.md +0 -29
  636. moai_adk/templates/.claude/skills/moai-lang-javascript/reference.md +0 -32
  637. moai_adk/templates/.claude/skills/moai-lang-kotlin/SKILL.md +0 -124
  638. moai_adk/templates/.claude/skills/moai-lang-kotlin/examples.md +0 -29
  639. moai_adk/templates/.claude/skills/moai-lang-kotlin/reference.md +0 -31
  640. moai_adk/templates/.claude/skills/moai-lang-php/SKILL.md +0 -126
  641. moai_adk/templates/.claude/skills/moai-lang-php/examples.md +0 -29
  642. moai_adk/templates/.claude/skills/moai-lang-php/reference.md +0 -30
  643. moai_adk/templates/.claude/skills/moai-lang-python/SKILL.md +0 -433
  644. moai_adk/templates/.claude/skills/moai-lang-python/examples.md +0 -624
  645. moai_adk/templates/.claude/skills/moai-lang-python/reference.md +0 -316
  646. moai_adk/templates/.claude/skills/moai-lang-r/SKILL.md +0 -123
  647. moai_adk/templates/.claude/skills/moai-lang-r/examples.md +0 -29
  648. moai_adk/templates/.claude/skills/moai-lang-r/reference.md +0 -30
  649. moai_adk/templates/.claude/skills/moai-lang-ruby/SKILL.md +0 -124
  650. moai_adk/templates/.claude/skills/moai-lang-ruby/examples.md +0 -29
  651. moai_adk/templates/.claude/skills/moai-lang-ruby/reference.md +0 -31
  652. moai_adk/templates/.claude/skills/moai-lang-rust/SKILL.md +0 -127
  653. moai_adk/templates/.claude/skills/moai-lang-rust/examples.md +0 -29
  654. moai_adk/templates/.claude/skills/moai-lang-rust/reference.md +0 -31
  655. moai_adk/templates/.claude/skills/moai-lang-scala/SKILL.md +0 -125
  656. moai_adk/templates/.claude/skills/moai-lang-scala/examples.md +0 -29
  657. moai_adk/templates/.claude/skills/moai-lang-scala/reference.md +0 -30
  658. moai_adk/templates/.claude/skills/moai-lang-shell/SKILL.md +0 -123
  659. moai_adk/templates/.claude/skills/moai-lang-shell/examples.md +0 -29
  660. moai_adk/templates/.claude/skills/moai-lang-shell/reference.md +0 -30
  661. moai_adk/templates/.claude/skills/moai-lang-sql/SKILL.md +0 -124
  662. moai_adk/templates/.claude/skills/moai-lang-sql/examples.md +0 -29
  663. moai_adk/templates/.claude/skills/moai-lang-sql/reference.md +0 -31
  664. moai_adk/templates/.claude/skills/moai-lang-swift/SKILL.md +0 -123
  665. moai_adk/templates/.claude/skills/moai-lang-swift/examples.md +0 -29
  666. moai_adk/templates/.claude/skills/moai-lang-swift/reference.md +0 -30
  667. moai_adk/templates/.claude/skills/moai-lang-typescript/SKILL.md +0 -133
  668. moai_adk/templates/.claude/skills/moai-lang-typescript/examples.md +0 -29
  669. moai_adk/templates/.claude/skills/moai-lang-typescript/reference.md +0 -34
  670. moai_adk/templates/.claude/skills/moai-project-documentation.md +0 -622
  671. moai_adk/templates/.github/workflows/c-tag-validation.yml +0 -11
  672. moai_adk/templates/.github/workflows/cpp-tag-validation.yml +0 -11
  673. moai_adk/templates/.github/workflows/csharp-tag-validation.yml +0 -11
  674. moai_adk/templates/.github/workflows/dart-tag-validation.yml +0 -11
  675. moai_adk/templates/.github/workflows/go-tag-validation.yml +0 -130
  676. moai_adk/templates/.github/workflows/java-tag-validation.yml +0 -11
  677. moai_adk/templates/.github/workflows/javascript-tag-validation.yml +0 -135
  678. moai_adk/templates/.github/workflows/kotlin-tag-validation.yml +0 -11
  679. moai_adk/templates/.github/workflows/moai-gitflow.yml +0 -419
  680. moai_adk/templates/.github/workflows/moai-release-create.yml +0 -100
  681. moai_adk/templates/.github/workflows/moai-release-pipeline.yml +0 -188
  682. moai_adk/templates/.github/workflows/php-tag-validation.yml +0 -11
  683. moai_adk/templates/.github/workflows/python-tag-validation.yml +0 -118
  684. moai_adk/templates/.github/workflows/release.yml +0 -118
  685. moai_adk/templates/.github/workflows/ruby-tag-validation.yml +0 -11
  686. moai_adk/templates/.github/workflows/rust-tag-validation.yml +0 -11
  687. moai_adk/templates/.github/workflows/shell-tag-validation.yml +0 -11
  688. moai_adk/templates/.github/workflows/swift-tag-validation.yml +0 -11
  689. moai_adk/templates/.github/workflows/tag-report.yml +0 -269
  690. moai_adk/templates/.github/workflows/tag-validation.yml +0 -186
  691. moai_adk/templates/.github/workflows/typescript-tag-validation.yml +0 -154
  692. moai_adk/templates/.moai/config.json +0 -115
  693. moai_adk/templates/workflows/go-tag-validation.yml +0 -30
  694. moai_adk/templates/workflows/javascript-tag-validation.yml +0 -41
  695. moai_adk/templates/workflows/python-tag-validation.yml +0 -42
  696. moai_adk/templates/workflows/typescript-tag-validation.yml +0 -31
  697. moai_adk-0.15.1.dist-info/METADATA +0 -3094
  698. moai_adk-0.15.1.dist-info/RECORD +0 -365
  699. {moai_adk-0.15.1.dist-info → moai_adk-0.32.8.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,1724 @@
1
+ """
2
+ Real-time Monitoring Dashboard
3
+
4
+ Phase 3: Enterprise-grade real-time monitoring dashboard with alerting,
5
+ analytics, and visualization capabilities for the hook system.
6
+
7
+ Key Features:
8
+ - Real-time performance monitoring and visualization
9
+ - Automated alerting with configurable thresholds
10
+ - Integration with external monitoring systems (Prometheus, Grafana, DataDog)
11
+ - Visual analytics for system health and performance
12
+ - REST API for monitoring data access
13
+ - WebSocket support for real-time updates
14
+ - Historical data analysis and trend prediction
15
+ - Multi-tenant dashboard support
16
+ - Custom alert rule engine
17
+ - Performance bottleneck detection
18
+ """
19
+
20
+ import asyncio
21
+ import logging
22
+ import statistics
23
+ import threading
24
+ import time
25
+ import uuid
26
+ from collections import defaultdict, deque
27
+ from dataclasses import dataclass, field
28
+ from datetime import datetime, timedelta
29
+ from enum import Enum
30
+ from typing import Any, Callable, Dict, List, Optional, Set, Union
31
+
32
+ logger = logging.getLogger(__name__)
33
+
34
+
35
+ class MetricType(Enum):
36
+ """Types of metrics collected by the monitoring system"""
37
+
38
+ SYSTEM_PERFORMANCE = "system_performance"
39
+ HOOK_EXECUTION = "hook_execution"
40
+ ERROR_RATE = "error_rate"
41
+ RESPONSE_TIME = "response_time"
42
+ MEMORY_USAGE = "memory_usage"
43
+ CPU_USAGE = "cpu_usage"
44
+ NETWORK_IO = "network_io"
45
+ DISK_IO = "disk_io"
46
+ THROUGHPUT = "throughput"
47
+ AVAILABILITY = "availability"
48
+ CACHE_PERFORMANCE = "cache_performance"
49
+ DATABASE_PERFORMANCE = "database_performance"
50
+
51
+
52
+ class AlertSeverity(Enum):
53
+ """Alert severity levels"""
54
+
55
+ INFO = 1
56
+ WARNING = 2
57
+ ERROR = 3
58
+ CRITICAL = 4
59
+ EMERGENCY = 5
60
+
61
+
62
+ class DashboardType(Enum):
63
+ """Dashboard types"""
64
+
65
+ SYSTEM_OVERVIEW = "system_overview"
66
+ PERFORMANCE_ANALYTICS = "performance_analytics"
67
+ ERROR_MONITORING = "error_monitoring"
68
+ HOOK_ANALYSIS = "hook_analysis"
69
+ RESOURCE_USAGE = "resource_usage"
70
+ CUSTOM = "custom"
71
+
72
+
73
+ @dataclass
74
+ class MetricData:
75
+ """Single metric data point with enhanced metadata"""
76
+
77
+ timestamp: datetime
78
+ metric_type: MetricType
79
+ value: Union[int, float, str, bool]
80
+ tags: Dict[str, str] = field(default_factory=dict)
81
+ source: str = ""
82
+ metadata: Dict[str, Any] = field(default_factory=dict)
83
+ component: str = ""
84
+ environment: str = "production"
85
+ tenant_id: Optional[str] = None
86
+
87
+ def to_dict(self) -> Dict[str, Any]:
88
+ """Convert to dictionary for serialization"""
89
+ return {
90
+ "timestamp": self.timestamp.isoformat(),
91
+ "metric_type": self.metric_type.value,
92
+ "value": self.value,
93
+ "tags": self.tags,
94
+ "source": self.source,
95
+ "metadata": self.metadata,
96
+ "component": self.component,
97
+ "environment": self.environment,
98
+ "tenant_id": self.tenant_id,
99
+ }
100
+
101
+
102
+ @dataclass
103
+ class Alert:
104
+ """Enhanced alert definition with correlation and context"""
105
+
106
+ alert_id: str
107
+ severity: AlertSeverity
108
+ title: str
109
+ description: str
110
+ timestamp: datetime
111
+ metric_type: MetricType
112
+ threshold: float
113
+ current_value: float
114
+ source: str
115
+ component: str
116
+ tags: Dict[str, str] = field(default_factory=dict)
117
+ resolved: bool = False
118
+ resolved_at: Optional[datetime] = None
119
+ acknowledged: bool = False
120
+ acknowledged_at: Optional[datetime] = None
121
+ correlation_id: Optional[str] = None
122
+ context: Dict[str, Any] = field(default_factory=dict)
123
+ affected_services: List[str] = field(default_factory=list)
124
+ recovery_actions: List[str] = field(default_factory=list)
125
+ tenant_id: Optional[str] = None
126
+
127
+ def to_dict(self) -> Dict[str, Any]:
128
+ """Convert to dictionary for serialization"""
129
+ return {
130
+ "alert_id": self.alert_id,
131
+ "severity": self.severity.value,
132
+ "title": self.title,
133
+ "description": self.description,
134
+ "timestamp": self.timestamp.isoformat(),
135
+ "metric_type": self.metric_type.value,
136
+ "threshold": self.threshold,
137
+ "current_value": self.current_value,
138
+ "source": self.source,
139
+ "component": self.component,
140
+ "tags": self.tags,
141
+ "resolved": self.resolved,
142
+ "resolved_at": self.resolved_at.isoformat() if self.resolved_at else None,
143
+ "acknowledged": self.acknowledged,
144
+ "acknowledged_at": (self.acknowledged_at.isoformat() if self.acknowledged_at else None),
145
+ "correlation_id": self.correlation_id,
146
+ "context": self.context,
147
+ "affected_services": self.affected_services,
148
+ "recovery_actions": self.recovery_actions,
149
+ }
150
+
151
+
152
+ @dataclass
153
+ class DashboardWidget:
154
+ """Dashboard widget definition"""
155
+
156
+ widget_id: str
157
+ widget_type: str # "chart", "metric", "table", "alert", "heatmap"
158
+ title: str
159
+ position: Dict[str, Any] # {"x": 0, "y": 0, "width": 4, "height": 2}
160
+ config: Dict[str, Any] = field(default_factory=dict)
161
+ data_source: str = ""
162
+ refresh_interval_seconds: int = 30
163
+ metrics: List[str] = field(default_factory=list)
164
+ filters: Dict[str, Any] = field(default_factory=dict)
165
+
166
+
167
+ @dataclass
168
+ class Dashboard:
169
+ """Dashboard definition with widgets and layout"""
170
+
171
+ dashboard_id: str
172
+ name: str
173
+ description: str
174
+ dashboard_type: DashboardType
175
+ widgets: List[DashboardWidget] = field(default_factory=list)
176
+ layout: Dict[str, Any] = field(default_factory=dict)
177
+ filters: Dict[str, Any] = field(default_factory=dict)
178
+ owner: str = ""
179
+ tenant_id: Optional[str] = None
180
+ is_public: bool = False
181
+ created_at: datetime = field(default_factory=datetime.now)
182
+ updated_at: datetime = field(default_factory=datetime.now)
183
+
184
+ def to_dict(self) -> Dict[str, Any]:
185
+ """Convert to dictionary for serialization"""
186
+ return {
187
+ "dashboard_id": self.dashboard_id,
188
+ "name": self.name,
189
+ "description": self.description,
190
+ "dashboard_type": self.dashboard_type.value,
191
+ "widgets": [w.__dict__ for w in self.widgets],
192
+ "layout": self.layout,
193
+ "filters": self.filters,
194
+ "owner": self.owner,
195
+ "tenant_id": self.tenant_id,
196
+ "is_public": self.is_public,
197
+ "created_at": self.created_at.isoformat(),
198
+ "updated_at": self.updated_at.isoformat(),
199
+ }
200
+
201
+
202
+ class MetricsCollector:
203
+ """Advanced metrics collection with multi-tenant support"""
204
+
205
+ def __init__(self, buffer_size: int = 100000, retention_hours: int = 168): # 7 days
206
+ self.buffer_size = buffer_size
207
+ self.retention_hours = retention_hours
208
+ self.metrics_buffer: Dict[str, deque] = defaultdict(lambda: deque(maxlen=buffer_size))
209
+ self.aggregated_metrics: Dict[str, Dict[str, Any]] = defaultdict(dict)
210
+ self.tenant_metrics: Dict[str, Dict[str, deque]] = defaultdict(lambda: defaultdict(deque))
211
+ self._lock = threading.Lock()
212
+ self._last_cleanup = datetime.now()
213
+
214
+ def add_metric(self, metric: MetricData) -> None:
215
+ """Add a metric to the collection with tenant support"""
216
+ with self._lock:
217
+ # Global metrics buffer
218
+ key = f"{metric.metric_type.value}:{metric.component}"
219
+ self.metrics_buffer[key].append(metric)
220
+
221
+ # Tenant-specific metrics
222
+ if metric.tenant_id:
223
+ tenant_key = f"{metric.metric_type.value}:{metric.component}:{metric.tenant_id}"
224
+ self.tenant_metrics[metric.tenant_id][tenant_key].append(metric)
225
+
226
+ # Update aggregated statistics
227
+ self._update_aggregated_metrics(metric)
228
+ self._cleanup_old_metrics()
229
+
230
+ def _update_aggregated_metrics(self, metric: MetricData) -> None:
231
+ """Update aggregated statistics for a metric type"""
232
+ key = f"{metric.metric_type.value}:{metric.component}"
233
+
234
+ if key not in self.aggregated_metrics:
235
+ self.aggregated_metrics[key] = {
236
+ "count": 0,
237
+ "sum": 0,
238
+ "min": float("inf"),
239
+ "max": float("-inf"),
240
+ "values": [],
241
+ "last_updated": datetime.now(),
242
+ }
243
+
244
+ agg = self.aggregated_metrics[key]
245
+
246
+ if isinstance(metric.value, (int, float)):
247
+ agg["count"] += 1
248
+ agg["sum"] += metric.value
249
+ agg["min"] = min(agg["min"], metric.value)
250
+ agg["max"] = max(agg["max"], metric.value)
251
+ agg["values"].append(metric.value)
252
+ agg["last_updated"] = datetime.now()
253
+
254
+ # Keep only recent values for statistics
255
+ if len(agg["values"]) > 10000:
256
+ agg["values"] = agg["values"][-10000:]
257
+
258
+ def _cleanup_old_metrics(self) -> None:
259
+ """Remove metrics older than retention period"""
260
+ now = datetime.now()
261
+ if (now - self._last_cleanup).seconds < 300: # Cleanup every 5 minutes
262
+ return
263
+
264
+ cutoff_time = now - timedelta(hours=self.retention_hours)
265
+
266
+ # Cleanup global metrics
267
+ for key, buffer in self.metrics_buffer.items():
268
+ while buffer and buffer[0].timestamp < cutoff_time:
269
+ buffer.popleft()
270
+
271
+ # Cleanup tenant metrics
272
+ for tenant_id, tenant_buffers in self.tenant_metrics.items():
273
+ for key, buffer in tenant_buffers.items():
274
+ while buffer and buffer[0].timestamp < cutoff_time:
275
+ buffer.popleft()
276
+
277
+ self._last_cleanup = now
278
+
279
+ def get_metrics(
280
+ self,
281
+ metric_type: Optional[MetricType] = None,
282
+ component: Optional[str] = None,
283
+ tenant_id: Optional[str] = None,
284
+ start_time: Optional[datetime] = None,
285
+ end_time: Optional[datetime] = None,
286
+ limit: Optional[int] = None,
287
+ tags: Optional[Dict[str, str]] = None,
288
+ ) -> List[MetricData]:
289
+ """Get metrics with comprehensive filtering"""
290
+ with self._lock:
291
+ # Choose the right metrics source
292
+ source_metrics: List[MetricData] = []
293
+ if tenant_id:
294
+ for buffer in self.tenant_metrics.get(tenant_id, {}).values():
295
+ source_metrics.extend(buffer)
296
+ else:
297
+ for buffer in self.metrics_buffer.values():
298
+ source_metrics.extend(buffer)
299
+
300
+ # Apply filters
301
+ metrics = source_metrics
302
+
303
+ # Filter by metric type
304
+ if metric_type:
305
+ metrics = [m for m in metrics if m.metric_type == metric_type]
306
+
307
+ # Filter by component
308
+ if component:
309
+ metrics = [m for m in metrics if m.component == component]
310
+
311
+ # Filter by time range
312
+ if start_time:
313
+ metrics = [m for m in metrics if m.timestamp >= start_time]
314
+ if end_time:
315
+ metrics = [m for m in metrics if m.timestamp <= end_time]
316
+
317
+ # Filter by tags
318
+ if tags:
319
+ metrics = [m for m in metrics if all(m.tags.get(k) == v for k, v in tags.items())]
320
+
321
+ # Sort by timestamp (newest first)
322
+ metrics.sort(key=lambda m: m.timestamp, reverse=True)
323
+
324
+ # Apply limit
325
+ if limit:
326
+ metrics = metrics[:limit]
327
+
328
+ return metrics
329
+
330
+ def get_statistics(
331
+ self,
332
+ metric_type: MetricType,
333
+ component: Optional[str] = None,
334
+ minutes: int = 60,
335
+ tenant_id: Optional[str] = None,
336
+ ) -> Dict[str, Any]:
337
+ """Get statistical summary for a metric type"""
338
+ with self._lock:
339
+ key = f"{metric_type.value}:{component}" if component else metric_type.value
340
+
341
+ # Choose the right aggregated metrics
342
+ if tenant_id:
343
+ agg: Dict[str, Any] = {}
344
+ # Calculate tenant-specific stats
345
+ tenant_metrics = self.get_metrics(metric_type, component, tenant_id)
346
+ if tenant_metrics:
347
+ values: List[float] = [float(m.value) for m in tenant_metrics if isinstance(m.value, (int, float))]
348
+ if values:
349
+ agg = {
350
+ "count": len(values),
351
+ "average": statistics.mean(values),
352
+ "median": statistics.median(values),
353
+ "min": min(values),
354
+ "max": max(values),
355
+ "std_dev": (statistics.stdev(values) if len(values) > 1 else 0),
356
+ "p95": self._percentile(values, 95),
357
+ "p99": self._percentile(values, 99),
358
+ }
359
+ else:
360
+ agg = self.aggregated_metrics.get(key, {})
361
+
362
+ if not agg or agg.get("count", 0) == 0:
363
+ return {
364
+ "count": 0,
365
+ "average": None,
366
+ "min": None,
367
+ "max": None,
368
+ "median": None,
369
+ "std_dev": None,
370
+ }
371
+
372
+ agg_values_raw = agg.get("values", [])
373
+ values_list: List[float] = agg_values_raw if isinstance(agg_values_raw, list) else []
374
+ if not values_list:
375
+ return {
376
+ "count": agg.get("count", 0),
377
+ "average": agg.get("sum", 0) / max(agg.get("count", 1), 1),
378
+ "min": agg.get("min"),
379
+ "max": agg.get("max"),
380
+ "median": None,
381
+ "std_dev": 0,
382
+ "p95": agg.get("max"),
383
+ "p99": agg.get("max"),
384
+ }
385
+
386
+ try:
387
+ last_updated_raw = agg.get("last_updated", datetime.now())
388
+ if isinstance(last_updated_raw, datetime):
389
+ last_updated_str = last_updated_raw.isoformat()
390
+ else:
391
+ last_updated_str = datetime.now().isoformat()
392
+ return {
393
+ "count": len(values_list),
394
+ "average": statistics.mean(values_list),
395
+ "median": statistics.median(values_list),
396
+ "min": min(values_list),
397
+ "max": max(values_list),
398
+ "std_dev": (statistics.stdev(values_list) if len(values_list) > 1 else 0),
399
+ "p95": self._percentile(values_list, 95),
400
+ "p99": self._percentile(values_list, 99),
401
+ "last_updated": last_updated_str,
402
+ }
403
+ except (statistics.StatisticsError, IndexError):
404
+ return {
405
+ "count": len(values_list),
406
+ "average": statistics.mean(values_list),
407
+ "median": statistics.median(values_list),
408
+ "min": min(values_list),
409
+ "max": max(values_list),
410
+ "std_dev": 0,
411
+ "p95": max(values_list),
412
+ "p99": max(values_list),
413
+ "last_updated": datetime.now().isoformat(),
414
+ }
415
+
416
+ def _percentile(self, values: List[float], percentile: int) -> float:
417
+ """Calculate percentile value"""
418
+ if not values:
419
+ return 0.0
420
+ sorted_values = sorted(values)
421
+ index = (percentile / 100) * (len(sorted_values) - 1)
422
+ if index.is_integer():
423
+ return sorted_values[int(index)]
424
+ else:
425
+ lower = sorted_values[int(index)]
426
+ upper = sorted_values[int(index) + 1]
427
+ return lower + (upper - lower) * (index - int(index))
428
+
429
+
430
+ class AlertManager:
431
+ """Advanced alert management with correlation and multi-tenant support"""
432
+
433
+ def __init__(self, metrics_collector: MetricsCollector):
434
+ self.metrics_collector = metrics_collector
435
+ self.alert_rules: List[Dict[str, Any]] = []
436
+ self.active_alerts: Dict[str, Alert] = {}
437
+ self.alert_history: List[Alert] = []
438
+ self.alert_callbacks: List[Callable[[Alert], None]] = []
439
+ self.tenant_alerts: Dict[str, Dict[str, Alert]] = defaultdict(dict)
440
+ self._lock = threading.Lock()
441
+
442
+ def add_alert_rule(
443
+ self,
444
+ name: str,
445
+ metric_type: MetricType,
446
+ threshold: float,
447
+ operator: str = "gt", # gt, lt, eq, ne, gte, lte
448
+ severity: AlertSeverity = AlertSeverity.WARNING,
449
+ window_minutes: int = 5,
450
+ consecutive_violations: int = 1,
451
+ tags: Optional[Dict[str, str]] = None,
452
+ description: Optional[str] = None,
453
+ tenant_id: Optional[str] = None,
454
+ component: Optional[str] = None,
455
+ cooldown_minutes: int = 15,
456
+ ) -> None:
457
+ """Add an alert rule with enhanced configuration"""
458
+ rule = {
459
+ "name": name,
460
+ "metric_type": metric_type,
461
+ "threshold": threshold,
462
+ "operator": operator,
463
+ "severity": severity,
464
+ "window_minutes": window_minutes,
465
+ "consecutive_violations": consecutive_violations,
466
+ "tags": tags or {},
467
+ "description": description or f"Alert when {metric_type.value} {operator} {threshold}",
468
+ "violation_count": 0,
469
+ "last_check": None,
470
+ "last_triggered": None,
471
+ "enabled": True,
472
+ "tenant_id": tenant_id,
473
+ "component": component,
474
+ "cooldown_minutes": cooldown_minutes,
475
+ }
476
+
477
+ with self._lock:
478
+ self.alert_rules.append(rule)
479
+
480
+ def check_alerts(self) -> List[Alert]:
481
+ """Check all alert rules and generate alerts for violations"""
482
+ triggered_alerts = []
483
+
484
+ with self._lock:
485
+ for rule in self.alert_rules:
486
+ if not rule["enabled"]:
487
+ continue
488
+
489
+ # Check cooldown period
490
+ if rule["last_triggered"]:
491
+ time_since_last = datetime.now() - rule["last_triggered"]
492
+ if time_since_last.total_seconds() < rule["cooldown_minutes"] * 60:
493
+ continue
494
+
495
+ # Get recent metrics for this rule
496
+ recent_metrics = self.metrics_collector.get_metrics(
497
+ metric_type=rule["metric_type"],
498
+ component=rule.get("component"),
499
+ tenant_id=rule.get("tenant_id"),
500
+ start_time=datetime.now() - timedelta(minutes=rule["window_minutes"]),
501
+ tags=rule.get("tags"),
502
+ )
503
+
504
+ if not recent_metrics:
505
+ continue
506
+
507
+ # Check for violations
508
+ violations = 0
509
+ latest_value = None
510
+
511
+ for metric in recent_metrics:
512
+ if isinstance(metric.value, (int, float)):
513
+ if self._evaluate_condition(metric.value, rule["threshold"], rule["operator"]):
514
+ violations += 1
515
+ latest_value = metric.value
516
+
517
+ # Trigger alert if threshold exceeded
518
+ if violations >= rule["consecutive_violations"]:
519
+ alert_id = f"{rule['name']}_{int(time.time())}"
520
+
521
+ alert = Alert(
522
+ alert_id=alert_id,
523
+ severity=rule["severity"],
524
+ title=f"{rule['name']} Alert Triggered",
525
+ description=rule["description"],
526
+ timestamp=datetime.now(),
527
+ metric_type=rule["metric_type"],
528
+ threshold=rule["threshold"],
529
+ current_value=latest_value or 0,
530
+ source="monitoring_system",
531
+ component=rule.get("component", "unknown"),
532
+ tags=rule.get("tags", {}),
533
+ tenant_id=rule.get("tenant_id"),
534
+ )
535
+
536
+ # Store alert
537
+ self.active_alerts[alert_id] = alert
538
+ self.alert_history.append(alert)
539
+
540
+ if alert.tenant_id:
541
+ self.tenant_alerts[alert.tenant_id][alert_id] = alert
542
+
543
+ triggered_alerts.append(alert)
544
+
545
+ # Update rule state
546
+ rule["violation_count"] = violations
547
+ rule["last_check"] = datetime.now()
548
+ rule["last_triggered"] = datetime.now()
549
+
550
+ # Trigger callbacks
551
+ for callback in self.alert_callbacks:
552
+ try:
553
+ callback(alert)
554
+ except Exception as e:
555
+ logger.error(f"Error in alert callback: {e}")
556
+
557
+ rule["violation_count"] = violations
558
+ rule["last_check"] = datetime.now()
559
+
560
+ # Check for resolved alerts
561
+ self._check_resolved_alerts()
562
+
563
+ return triggered_alerts
564
+
565
+ def _check_resolved_alerts(self) -> None:
566
+ """Check if any active alerts have been resolved"""
567
+ for alert_id, alert in list(self.active_alerts.items()):
568
+ # Check if alert condition is no longer met
569
+ rule = next((r for r in self.alert_rules if r["name"] in alert_id), None)
570
+ if rule:
571
+ recent_metrics = self.metrics_collector.get_metrics(
572
+ metric_type=alert.metric_type,
573
+ component=alert.component,
574
+ tenant_id=alert.tenant_id,
575
+ start_time=datetime.now() - timedelta(minutes=1), # Check last minute
576
+ )
577
+
578
+ if recent_metrics:
579
+ latest_value = None
580
+ for metric in recent_metrics:
581
+ if isinstance(metric.value, (int, float)):
582
+ if not self._evaluate_condition(metric.value, alert.threshold, rule["operator"]):
583
+ latest_value = metric.value
584
+ break
585
+
586
+ if latest_value is not None:
587
+ # Alert is resolved
588
+ alert.resolved = True
589
+ alert.resolved_at = datetime.now()
590
+ self.alert_history.append(alert)
591
+ del self.active_alerts[alert_id]
592
+
593
+ if alert.tenant_id and alert_id in self.tenant_alerts.get(alert.tenant_id, {}):
594
+ del self.tenant_alerts[alert.tenant_id][alert_id]
595
+
596
+ def _evaluate_condition(self, value: float, threshold: float, operator: str) -> bool:
597
+ """Evaluate alert condition"""
598
+ if operator == "gt":
599
+ return value > threshold
600
+ elif operator == "lt":
601
+ return value < threshold
602
+ elif operator == "eq":
603
+ return value == threshold
604
+ elif operator == "ne":
605
+ return value != threshold
606
+ elif operator == "gte":
607
+ return value >= threshold
608
+ elif operator == "lte":
609
+ return value <= threshold
610
+ else:
611
+ return False
612
+
613
+ def add_alert_callback(self, callback: Callable[[Alert], None]) -> None:
614
+ """Add a callback function to be triggered when alerts fire"""
615
+ self.alert_callbacks.append(callback)
616
+
617
+ def acknowledge_alert(self, alert_id: str, tenant_id: Optional[str] = None) -> bool:
618
+ """Acknowledge an alert"""
619
+ with self._lock:
620
+ if tenant_id:
621
+ alerts = self.tenant_alerts.get(tenant_id, {})
622
+ if alert_id in alerts:
623
+ alerts[alert_id].acknowledged = True
624
+ alerts[alert_id].acknowledged_at = datetime.now()
625
+ return True
626
+ else:
627
+ if alert_id in self.active_alerts:
628
+ self.active_alerts[alert_id].acknowledged = True
629
+ self.active_alerts[alert_id].acknowledged_at = datetime.now()
630
+ return True
631
+ return False
632
+
633
+ def get_active_alerts(
634
+ self,
635
+ severity: Optional[AlertSeverity] = None,
636
+ tenant_id: Optional[str] = None,
637
+ component: Optional[str] = None,
638
+ ) -> List[Alert]:
639
+ """Get currently active alerts with filtering"""
640
+ with self._lock:
641
+ if tenant_id:
642
+ alerts = list(self.tenant_alerts.get(tenant_id, {}).values())
643
+ else:
644
+ alerts = list(self.active_alerts.values())
645
+
646
+ # Apply filters
647
+ if severity:
648
+ alerts = [a for a in alerts if a.severity == severity]
649
+ if component:
650
+ alerts = [a for a in alerts if a.component == component]
651
+
652
+ return sorted(alerts, key=lambda a: (a.severity.value, a.timestamp), reverse=True)
653
+
654
+ def get_alert_history(
655
+ self,
656
+ hours: int = 24,
657
+ tenant_id: Optional[str] = None,
658
+ ) -> List[Alert]:
659
+ """Get alert history"""
660
+ cutoff_time = datetime.now() - timedelta(hours=hours)
661
+
662
+ if tenant_id:
663
+ tenant_history = []
664
+ for alert in self.alert_history:
665
+ if alert.tenant_id == tenant_id and alert.timestamp >= cutoff_time:
666
+ tenant_history.append(alert)
667
+ return tenant_history
668
+ else:
669
+ return [a for a in self.alert_history if a.timestamp >= cutoff_time]
670
+
671
+ def get_alert_statistics(
672
+ self,
673
+ hours: int = 24,
674
+ tenant_id: Optional[str] = None,
675
+ ) -> Dict[str, Any]:
676
+ """Get alert statistics"""
677
+ alerts = self.get_alert_history(hours, tenant_id)
678
+
679
+ # Count by severity
680
+ by_severity: Dict[str, int] = defaultdict(int)
681
+ by_component: Dict[str, int] = defaultdict(int)
682
+ by_hour: Dict[str, int] = defaultdict(int)
683
+
684
+ for alert in alerts:
685
+ by_severity[str(alert.severity.value)] += 1
686
+ by_component[alert.component] += 1
687
+ hour_key = alert.timestamp.strftime("%Y-%m-%d %H:00")
688
+ by_hour[hour_key] += 1
689
+
690
+ return {
691
+ "total_alerts": len(alerts),
692
+ "by_severity": dict(by_severity),
693
+ "by_component": dict(by_component),
694
+ "by_hour": dict(by_hour),
695
+ "resolved_count": sum(1 for a in alerts if a.resolved),
696
+ "acknowledged_count": sum(1 for a in alerts if a.acknowledged),
697
+ "resolution_rate": sum(1 for a in alerts if a.resolved) / max(len(alerts), 1),
698
+ "period_hours": hours,
699
+ }
700
+
701
+
702
+ class DashboardManager:
703
+ """Dashboard management with multi-tenant support"""
704
+
705
+ def __init__(self):
706
+ self.dashboards: Dict[str, Dashboard] = {}
707
+ self.tenant_dashboards: Dict[str, Dict[str, Dashboard]] = defaultdict(dict)
708
+ self.default_dashboards: Dict[str, Dashboard] = {}
709
+ self._lock = threading.Lock()
710
+
711
+ # Create default dashboards
712
+ self._create_default_dashboards()
713
+
714
+ def create_dashboard(
715
+ self,
716
+ name: str,
717
+ description: str,
718
+ dashboard_type: DashboardType,
719
+ widgets: List[DashboardWidget],
720
+ owner: str = "",
721
+ tenant_id: Optional[str] = None,
722
+ is_public: bool = False,
723
+ layout: Optional[Dict[str, Any]] = None,
724
+ ) -> str:
725
+ """Create a new dashboard"""
726
+ dashboard_id = str(uuid.uuid4())
727
+
728
+ dashboard = Dashboard(
729
+ dashboard_id=dashboard_id,
730
+ name=name,
731
+ description=description,
732
+ dashboard_type=dashboard_type,
733
+ widgets=widgets,
734
+ layout=layout or {"grid": {"cols": 12, "rows": 8}},
735
+ owner=owner,
736
+ tenant_id=tenant_id,
737
+ is_public=is_public,
738
+ )
739
+
740
+ with self._lock:
741
+ if tenant_id:
742
+ self.tenant_dashboards[tenant_id][dashboard_id] = dashboard
743
+ else:
744
+ self.dashboards[dashboard_id] = dashboard
745
+
746
+ logger.info(f"Created dashboard: {name} ({dashboard_id})")
747
+ return dashboard_id
748
+
749
+ def get_dashboard(self, dashboard_id: str, tenant_id: Optional[str] = None) -> Optional[Dashboard]:
750
+ """Get a dashboard by ID"""
751
+ with self._lock:
752
+ if tenant_id:
753
+ return self.tenant_dashboards.get(tenant_id, {}).get(dashboard_id)
754
+ else:
755
+ return self.dashboards.get(dashboard_id) or self.default_dashboards.get(dashboard_id)
756
+
757
+ def list_dashboards(
758
+ self,
759
+ tenant_id: Optional[str] = None,
760
+ dashboard_type: Optional[DashboardType] = None,
761
+ owner: Optional[str] = None,
762
+ is_public: Optional[bool] = None,
763
+ ) -> List[Dashboard]:
764
+ """List dashboards with filtering"""
765
+ with self._lock:
766
+ dashboards: List[Dashboard] = []
767
+
768
+ # Collect dashboards
769
+ if tenant_id:
770
+ dashboards.extend(self.tenant_dashboards.get(tenant_id, {}).values())
771
+ else:
772
+ dashboards.extend(self.dashboards.values())
773
+
774
+ # Add public dashboards
775
+ dashboards.extend([d for d in self.dashboards.values() if d.is_public])
776
+
777
+ # Apply filters
778
+ if dashboard_type:
779
+ dashboards = [d for d in dashboards if d.dashboard_type == dashboard_type]
780
+ if owner:
781
+ dashboards = [d for d in dashboards if d.owner == owner]
782
+ if is_public is not None:
783
+ dashboards = [d for d in dashboards if d.is_public == is_public]
784
+
785
+ return dashboards
786
+
787
+ def update_dashboard(
788
+ self,
789
+ dashboard_id: str,
790
+ updates: Dict[str, Any],
791
+ tenant_id: Optional[str] = None,
792
+ ) -> bool:
793
+ """Update a dashboard"""
794
+ with self._lock:
795
+ if tenant_id:
796
+ dashboard = self.tenant_dashboards.get(tenant_id, {}).get(dashboard_id)
797
+ else:
798
+ dashboard = self.dashboards.get(dashboard_id)
799
+
800
+ if not dashboard:
801
+ return False
802
+
803
+ # Update fields
804
+ for key, value in updates.items():
805
+ if hasattr(dashboard, key):
806
+ setattr(dashboard, key, value)
807
+ elif key in dashboard.__dict__:
808
+ dashboard.__dict__[key] = value
809
+
810
+ dashboard.updated_at = datetime.now()
811
+ return True
812
+
813
+ def delete_dashboard(self, dashboard_id: str, tenant_id: Optional[str] = None) -> bool:
814
+ """Delete a dashboard"""
815
+ with self._lock:
816
+ if tenant_id:
817
+ if dashboard_id in self.tenant_dashboards.get(tenant_id, {}):
818
+ del self.tenant_dashboards[tenant_id][dashboard_id]
819
+ return True
820
+ else:
821
+ if dashboard_id in self.dashboards:
822
+ del self.dashboards[dashboard_id]
823
+ return True
824
+ if dashboard_id in self.default_dashboards:
825
+ # Don't delete default dashboards
826
+ return False
827
+ return False
828
+
829
+ def _create_default_dashboards(self):
830
+ """Create default dashboards"""
831
+ # System Overview Dashboard
832
+ system_overview_widgets = [
833
+ DashboardWidget(
834
+ widget_id="sys_health",
835
+ widget_type="metric",
836
+ title="System Health",
837
+ position={"x": 0, "y": 0, "width": 4, "height": 2},
838
+ config={"metric": "health_score", "format": "percentage"},
839
+ ),
840
+ DashboardWidget(
841
+ widget_id="active_alerts",
842
+ widget_type="metric",
843
+ title="Active Alerts",
844
+ position={"x": 4, "y": 0, "width": 4, "height": 2},
845
+ config={"metric": "active_alerts", "format": "number"},
846
+ ),
847
+ DashboardWidget(
848
+ widget_id="uptime",
849
+ widget_type="metric",
850
+ title="System Uptime",
851
+ position={"x": 8, "y": 0, "width": 4, "height": 2},
852
+ config={"metric": "uptime", "format": "duration"},
853
+ ),
854
+ DashboardWidget(
855
+ widget_id="cpu_chart",
856
+ widget_type="chart",
857
+ title="CPU Usage",
858
+ position={"x": 0, "y": 2, "width": 6, "height": 3},
859
+ config={"chart_type": "line", "time_range": "1h"},
860
+ metrics=["cpu_usage"],
861
+ ),
862
+ DashboardWidget(
863
+ widget_id="memory_chart",
864
+ widget_type="chart",
865
+ title="Memory Usage",
866
+ position={"x": 6, "y": 2, "width": 6, "height": 3},
867
+ config={"chart_type": "line", "time_range": "1h"},
868
+ metrics=["memory_usage"],
869
+ ),
870
+ DashboardWidget(
871
+ widget_id="alert_table",
872
+ widget_type="table",
873
+ title="Recent Alerts",
874
+ position={"x": 0, "y": 5, "width": 12, "height": 3},
875
+ config={"limit": 10, "sort": "timestamp"},
876
+ ),
877
+ ]
878
+
879
+ system_dashboard = Dashboard(
880
+ dashboard_id="system_overview",
881
+ name="System Overview",
882
+ description="Overview of system health and performance",
883
+ dashboard_type=DashboardType.SYSTEM_OVERVIEW,
884
+ widgets=system_overview_widgets,
885
+ owner="system",
886
+ is_public=True,
887
+ )
888
+
889
+ self.default_dashboards["system_overview"] = system_dashboard
890
+
891
+ # Hook Analysis Dashboard
892
+ hook_analysis_widgets = [
893
+ DashboardWidget(
894
+ widget_id="hook_execution_chart",
895
+ widget_type="chart",
896
+ title="Hook Execution Rate",
897
+ position={"x": 0, "y": 0, "width": 6, "height": 3},
898
+ config={"chart_type": "line", "time_range": "24h"},
899
+ metrics=["hook_execution_rate"],
900
+ ),
901
+ DashboardWidget(
902
+ widget_id="hook_success_rate",
903
+ widget_type="metric",
904
+ title="Hook Success Rate",
905
+ position={"x": 6, "y": 0, "width": 6, "height": 3},
906
+ config={"metric": "hook_success_rate", "format": "percentage"},
907
+ ),
908
+ DashboardWidget(
909
+ widget_id="slow_hooks",
910
+ widget_type="table",
911
+ title="Slowest Hooks",
912
+ position={"x": 0, "y": 3, "width": 12, "height": 4},
913
+ config={"limit": 15, "sort": "execution_time", "order": "desc"},
914
+ ),
915
+ DashboardWidget(
916
+ widget_id="error_by_hook",
917
+ widget_type="chart",
918
+ title="Error Rate by Hook",
919
+ position={"x": 0, "y": 7, "width": 12, "height": 3},
920
+ config={"chart_type": "bar", "time_range": "24h"},
921
+ ),
922
+ ]
923
+
924
+ hook_dashboard = Dashboard(
925
+ dashboard_id="hook_analysis",
926
+ name="Hook Analysis",
927
+ description="Detailed analysis of hook execution performance",
928
+ dashboard_type=DashboardType.HOOK_ANALYSIS,
929
+ widgets=hook_analysis_widgets,
930
+ owner="system",
931
+ is_public=True,
932
+ )
933
+
934
+ self.default_dashboards["hook_analysis"] = hook_dashboard
935
+
936
+ logger.info("Created default dashboards")
937
+
938
+
939
+ class RealtimeMonitoringDashboard:
940
+ """
941
+ Real-time Monitoring Dashboard System
942
+
943
+ Enterprise-grade real-time monitoring dashboard with alerting,
944
+ analytics, and visualization capabilities.
945
+ """
946
+
947
+ def __init__(
948
+ self,
949
+ metrics_buffer_size: int = 100000,
950
+ retention_hours: int = 168, # 7 days
951
+ alert_check_interval: int = 30, # seconds
952
+ enable_websocket: bool = True,
953
+ enable_external_integration: bool = True,
954
+ ):
955
+ """Initialize Real-time Monitoring Dashboard
956
+
957
+ Args:
958
+ metrics_buffer_size: Size of metrics buffer
959
+ retention_hours: Hours to retain metrics
960
+ alert_check_interval: Interval between alert checks
961
+ enable_websocket: Enable WebSocket support for real-time updates
962
+ enable_external_integration: Enable external monitoring system integration
963
+ """
964
+ self.metrics_buffer_size = metrics_buffer_size
965
+ self.retention_hours = retention_hours
966
+ self.alert_check_interval = alert_check_interval
967
+ self.enable_websocket = enable_websocket
968
+ self.enable_external_integration = enable_external_integration
969
+
970
+ # Initialize components
971
+ self.metrics_collector = MetricsCollector(metrics_buffer_size, retention_hours)
972
+ self.alert_manager = AlertManager(self.metrics_collector)
973
+ self.dashboard_manager = DashboardManager()
974
+
975
+ # System state
976
+ self._running = False
977
+ self._startup_time = datetime.now()
978
+
979
+ # WebSocket connections
980
+ self.websocket_connections: Set[Any] = set()
981
+ self.websocket_lock = threading.Lock()
982
+
983
+ # Background tasks
984
+ self._monitoring_thread: Optional[threading.Thread] = None
985
+ self._alert_thread: Optional[threading.Thread] = None
986
+
987
+ # External integrations
988
+ self.external_integrations: Dict[str, Any] = {}
989
+
990
+ # Setup default alerts
991
+ self._setup_default_alerts()
992
+
993
+ logger.info("Real-time Monitoring Dashboard initialized")
994
+
995
+ def _setup_default_alerts(self):
996
+ """Setup default alert rules"""
997
+ # CPU usage alert
998
+ self.alert_manager.add_alert_rule(
999
+ name="High CPU Usage",
1000
+ metric_type=MetricType.CPU_USAGE,
1001
+ threshold=80.0,
1002
+ operator="gt",
1003
+ severity=AlertSeverity.ERROR,
1004
+ window_minutes=5,
1005
+ consecutive_violations=2,
1006
+ tags={"component": "system"},
1007
+ description="CPU usage exceeds 80% for 5 minutes",
1008
+ )
1009
+
1010
+ # Memory usage alert
1011
+ self.alert_manager.add_alert_rule(
1012
+ name="High Memory Usage",
1013
+ metric_type=MetricType.MEMORY_USAGE,
1014
+ threshold=85.0,
1015
+ operator="gt",
1016
+ severity=AlertSeverity.ERROR,
1017
+ window_minutes=5,
1018
+ consecutive_violations=2,
1019
+ tags={"component": "system"},
1020
+ description="Memory usage exceeds 85% for 5 minutes",
1021
+ )
1022
+
1023
+ # Error rate alert
1024
+ self.alert_manager.add_alert_rule(
1025
+ name="High Error Rate",
1026
+ metric_type=MetricType.ERROR_RATE,
1027
+ threshold=5.0,
1028
+ operator="gt",
1029
+ severity=AlertSeverity.CRITICAL,
1030
+ window_minutes=2,
1031
+ consecutive_violations=1,
1032
+ tags={"component": "system"},
1033
+ description="Error rate exceeds 5% in 2 minutes",
1034
+ )
1035
+
1036
+ # Hook execution time alert
1037
+ self.alert_manager.add_alert_rule(
1038
+ name="Slow Hook Execution",
1039
+ metric_type=MetricType.RESPONSE_TIME,
1040
+ threshold=5000.0, # 5 seconds
1041
+ operator="gt",
1042
+ severity=AlertSeverity.WARNING,
1043
+ window_minutes=10,
1044
+ consecutive_violations=3,
1045
+ tags={"component": "hooks"},
1046
+ description="Hook execution time exceeds 5 seconds",
1047
+ )
1048
+
1049
+ logger.info("Default alert rules configured")
1050
+
1051
+ async def start(self) -> None:
1052
+ """Start the monitoring dashboard system"""
1053
+ if self._running:
1054
+ return
1055
+
1056
+ logger.info("Starting Real-time Monitoring Dashboard...")
1057
+
1058
+ try:
1059
+ # Start background monitoring
1060
+ self._start_background_monitoring()
1061
+
1062
+ # Start alert checking
1063
+ self._start_alert_monitoring()
1064
+
1065
+ # Start WebSocket server if enabled
1066
+ if self.enable_websocket:
1067
+ await self._start_websocket_server()
1068
+
1069
+ # Initialize external integrations
1070
+ if self.enable_external_integration:
1071
+ await self._initialize_external_integrations()
1072
+
1073
+ self._running = True
1074
+ logger.info("Real-time Monitoring Dashboard started successfully")
1075
+
1076
+ except Exception as e:
1077
+ logger.error(f"Error starting monitoring dashboard: {e}")
1078
+ raise
1079
+
1080
+ def stop(self) -> None:
1081
+ """Stop the monitoring dashboard system"""
1082
+ if not self._running:
1083
+ return
1084
+
1085
+ logger.info("Stopping Real-time Monitoring Dashboard...")
1086
+
1087
+ try:
1088
+ # Stop background threads
1089
+ self._running = False
1090
+ if self._monitoring_thread:
1091
+ self._monitoring_thread.join(timeout=5)
1092
+ if self._alert_thread:
1093
+ self._alert_thread.join(timeout=5)
1094
+
1095
+ # Close WebSocket connections
1096
+ with self.websocket_lock:
1097
+ for conn in self.websocket_connections:
1098
+ try:
1099
+ # Close connection
1100
+ pass # Implementation depends on WebSocket library
1101
+ except Exception:
1102
+ pass
1103
+ self.websocket_connections.clear()
1104
+
1105
+ logger.info("Real-time Monitoring Dashboard stopped")
1106
+
1107
+ except Exception as e:
1108
+ logger.error(f"Error stopping monitoring dashboard: {e}")
1109
+
1110
+ def _start_background_monitoring(self) -> None:
1111
+ """Start background metrics collection"""
1112
+
1113
+ def monitor_loop():
1114
+ while self._running:
1115
+ try:
1116
+ self._collect_system_metrics()
1117
+ time.sleep(30) # Collect metrics every 30 seconds
1118
+ except Exception as e:
1119
+ logger.error(f"Error in monitoring loop: {e}")
1120
+ time.sleep(30)
1121
+
1122
+ self._monitoring_thread = threading.Thread(target=monitor_loop, daemon=True)
1123
+ self._monitoring_thread.start()
1124
+
1125
+ def _start_alert_monitoring(self) -> None:
1126
+ """Start alert checking"""
1127
+
1128
+ def alert_loop():
1129
+ while self._running:
1130
+ try:
1131
+ alerts = self.alert_manager.check_alerts()
1132
+ if alerts:
1133
+ for alert in alerts:
1134
+ logger.warning(f"Alert triggered: {alert.title} - {alert.current_value}")
1135
+ # Broadcast to WebSocket clients
1136
+ self._broadcast_alert(alert)
1137
+
1138
+ time.sleep(self.alert_check_interval)
1139
+ except Exception as e:
1140
+ logger.error(f"Error in alert loop: {e}")
1141
+ time.sleep(self.alert_check_interval)
1142
+
1143
+ self._alert_thread = threading.Thread(target=alert_loop, daemon=True)
1144
+ self._alert_thread.start()
1145
+
1146
+ async def _start_websocket_server(self) -> None:
1147
+ """Start WebSocket server for real-time updates"""
1148
+ # Implementation depends on WebSocket library (websockets, FastAPI WebSocket, etc.)
1149
+ logger.info("WebSocket server support enabled")
1150
+ pass
1151
+
1152
+ async def _initialize_external_integrations(self) -> None:
1153
+ """Initialize external monitoring system integrations"""
1154
+ # Prometheus integration
1155
+ try:
1156
+ await self._setup_prometheus_integration()
1157
+ except Exception as e:
1158
+ logger.warning(f"Failed to setup Prometheus integration: {e}")
1159
+
1160
+ # DataDog integration
1161
+ try:
1162
+ await self._setup_datadog_integration()
1163
+ except Exception as e:
1164
+ logger.warning(f"Failed to setup DataDog integration: {e}")
1165
+
1166
+ logger.info("External integrations initialized")
1167
+
1168
+ async def _setup_prometheus_integration(self) -> None:
1169
+ """Setup Prometheus integration"""
1170
+ # Implementation would setup Prometheus metrics endpoint
1171
+ pass
1172
+
1173
+ async def _setup_datadog_integration(self) -> None:
1174
+ """Setup DataDog integration"""
1175
+ # Implementation would setup DataDog API client
1176
+ pass
1177
+
1178
+ def _collect_system_metrics(self) -> None:
1179
+ """Collect system performance metrics"""
1180
+ try:
1181
+ import psutil
1182
+
1183
+ # CPU Usage
1184
+ cpu_percent = psutil.cpu_percent(interval=1)
1185
+ self.add_metric(
1186
+ MetricType.CPU_USAGE,
1187
+ cpu_percent,
1188
+ tags={"component": "system"},
1189
+ source="psutil",
1190
+ )
1191
+
1192
+ # Memory Usage
1193
+ memory = psutil.virtual_memory()
1194
+ self.add_metric(
1195
+ MetricType.MEMORY_USAGE,
1196
+ memory.percent,
1197
+ tags={"component": "system"},
1198
+ source="psutil",
1199
+ )
1200
+
1201
+ # Python process memory
1202
+ process = psutil.Process()
1203
+ process_memory = process.memory_info()
1204
+ self.add_metric(
1205
+ MetricType.MEMORY_USAGE,
1206
+ process_memory.rss / (1024**2), # MB
1207
+ tags={"component": "python_process"},
1208
+ source="psutil",
1209
+ )
1210
+
1211
+ # System load
1212
+ try:
1213
+ load_avg = psutil.getloadavg()
1214
+ self.add_metric(
1215
+ MetricType.SYSTEM_PERFORMANCE,
1216
+ load_avg[0], # 1-minute load average
1217
+ tags={"component": "system", "metric": "load_1min"},
1218
+ source="psutil",
1219
+ )
1220
+ except (AttributeError, OSError):
1221
+ pass # Not available on all systems
1222
+
1223
+ except Exception as e:
1224
+ logger.error(f"Error collecting system metrics: {e}")
1225
+
1226
+ def add_metric(
1227
+ self,
1228
+ metric_type: MetricType,
1229
+ value: Union[int, float],
1230
+ tags: Optional[Dict[str, str]] = None,
1231
+ source: str = "custom",
1232
+ component: str = "",
1233
+ tenant_id: Optional[str] = None,
1234
+ metadata: Optional[Dict[str, Any]] = None,
1235
+ ) -> None:
1236
+ """Add a metric to the monitoring system"""
1237
+ metric = MetricData(
1238
+ timestamp=datetime.now(),
1239
+ metric_type=metric_type,
1240
+ value=value,
1241
+ tags=tags or {},
1242
+ source=source,
1243
+ component=component,
1244
+ tenant_id=tenant_id,
1245
+ metadata=metadata or {},
1246
+ )
1247
+
1248
+ self.metrics_collector.add_metric(metric)
1249
+
1250
+ def get_dashboard_data(
1251
+ self,
1252
+ dashboard_id: str,
1253
+ tenant_id: Optional[str] = None,
1254
+ time_range: Optional[str] = None, # "1h", "24h", "7d"
1255
+ filters: Optional[Dict[str, Any]] = None,
1256
+ ) -> Dict[str, Any]:
1257
+ """Get dashboard data for visualization"""
1258
+ try:
1259
+ # Get dashboard
1260
+ dashboard = self.dashboard_manager.get_dashboard(dashboard_id, tenant_id)
1261
+ if not dashboard:
1262
+ return {"error": "Dashboard not found"}
1263
+
1264
+ # Calculate time range
1265
+ end_time = datetime.now()
1266
+ if time_range:
1267
+ if time_range == "1h":
1268
+ start_time = end_time - timedelta(hours=1)
1269
+ elif time_range == "24h":
1270
+ start_time = end_time - timedelta(hours=24)
1271
+ elif time_range == "7d":
1272
+ start_time = end_time - timedelta(days=7)
1273
+ else:
1274
+ start_time = end_time - timedelta(hours=1) # Default
1275
+ else:
1276
+ start_time = end_time - timedelta(hours=1)
1277
+
1278
+ # Collect data for each widget
1279
+ widgets_data = {}
1280
+ for widget in dashboard.widgets:
1281
+ try:
1282
+ widget_data = self._get_widget_data(widget, start_time, end_time, tenant_id, filters)
1283
+ widgets_data[widget.widget_id] = widget_data
1284
+ except Exception as e:
1285
+ logger.error(f"Error getting data for widget {widget.widget_id}: {e}")
1286
+ widgets_data[widget.widget_id] = {"error": str(e)}
1287
+
1288
+ return {
1289
+ "dashboard": dashboard.to_dict(),
1290
+ "widgets_data": widgets_data,
1291
+ "time_range": time_range or "1h",
1292
+ "generated_at": datetime.now().isoformat(),
1293
+ }
1294
+
1295
+ except Exception as e:
1296
+ logger.error(f"Error getting dashboard data: {e}")
1297
+ return {"error": str(e), "generated_at": datetime.now().isoformat()}
1298
+
1299
+ def _get_widget_data(
1300
+ self,
1301
+ widget: DashboardWidget,
1302
+ start_time: datetime,
1303
+ end_time: datetime,
1304
+ tenant_id: Optional[str] = None,
1305
+ filters: Optional[Dict[str, Any]] = None,
1306
+ ) -> Dict[str, Any]:
1307
+ """Get data for a specific widget"""
1308
+ if widget.widget_type == "metric":
1309
+ return self._get_metric_widget_data(widget, tenant_id)
1310
+ elif widget.widget_type == "chart":
1311
+ return self._get_chart_widget_data(widget, start_time, end_time, tenant_id, filters)
1312
+ elif widget.widget_type == "table":
1313
+ return self._get_table_widget_data(widget, start_time, end_time, tenant_id, filters)
1314
+ elif widget.widget_type == "alert":
1315
+ return self._get_alert_widget_data(widget, tenant_id)
1316
+ else:
1317
+ return {"error": f"Unsupported widget type: {widget.widget_type}"}
1318
+
1319
+ def _get_metric_widget_data(self, widget: DashboardWidget, tenant_id: Optional[str] = None) -> Dict[str, Any]:
1320
+ """Get data for metric widget"""
1321
+ metric_name = widget.config.get("metric")
1322
+ if not metric_name:
1323
+ return {"error": "No metric specified"}
1324
+
1325
+ # Get latest metrics
1326
+ metric_type = None
1327
+ if metric_name == "cpu_usage":
1328
+ metric_type = MetricType.CPU_USAGE
1329
+ elif metric_name == "memory_usage":
1330
+ metric_type = MetricType.MEMORY_USAGE
1331
+ elif metric_name == "health_score":
1332
+ metric_type = MetricType.AVAILABILITY
1333
+ else:
1334
+ return {"error": f"Unknown metric: {metric_name}"}
1335
+
1336
+ recent_metrics = self.metrics_collector.get_metrics(metric_type=metric_type, tenant_id=tenant_id, limit=1)
1337
+
1338
+ if not recent_metrics:
1339
+ return {"value": 0, "status": "no_data"}
1340
+
1341
+ latest_metric = recent_metrics[0]
1342
+ format_type = widget.config.get("format", "number")
1343
+
1344
+ if format_type == "percentage":
1345
+ value = f"{latest_metric.value:.1f}%"
1346
+ elif format_type == "duration":
1347
+ value = f"{latest_metric.value:.0f}s"
1348
+ else:
1349
+ value = str(latest_metric.value)
1350
+
1351
+ return {
1352
+ "value": latest_metric.value,
1353
+ "formatted_value": value,
1354
+ "timestamp": latest_metric.timestamp.isoformat(),
1355
+ "format": format_type,
1356
+ }
1357
+
1358
+ def _get_chart_widget_data(
1359
+ self,
1360
+ widget: DashboardWidget,
1361
+ start_time: datetime,
1362
+ end_time: datetime,
1363
+ tenant_id: Optional[str] = None,
1364
+ filters: Optional[Dict[str, Any]] = None,
1365
+ ) -> Dict[str, Any]:
1366
+ """Get data for chart widget"""
1367
+ chart_type = widget.config.get("chart_type", "line")
1368
+ metrics = widget.metrics or []
1369
+
1370
+ chart_data = {
1371
+ "type": chart_type,
1372
+ "data": [],
1373
+ "labels": [],
1374
+ }
1375
+
1376
+ for metric_name in metrics:
1377
+ # Map metric names to MetricType
1378
+ metric_type = self._map_metric_name(metric_name)
1379
+ if metric_type:
1380
+ metric_data = self.metrics_collector.get_metrics(
1381
+ metric_type=metric_type,
1382
+ tenant_id=tenant_id,
1383
+ start_time=start_time,
1384
+ end_time=end_time,
1385
+ limit=100,
1386
+ )
1387
+
1388
+ series_data = []
1389
+ for metric in metric_data:
1390
+ series_data.append(
1391
+ {
1392
+ "timestamp": metric.timestamp.isoformat(),
1393
+ "value": metric.value,
1394
+ }
1395
+ )
1396
+
1397
+ chart_data["data"].append(
1398
+ {
1399
+ "name": metric_name,
1400
+ "series": series_data,
1401
+ }
1402
+ )
1403
+
1404
+ return chart_data
1405
+
1406
+ def _get_table_widget_data(
1407
+ self,
1408
+ widget: DashboardWidget,
1409
+ start_time: datetime,
1410
+ end_time: datetime,
1411
+ tenant_id: Optional[str] = None,
1412
+ filters: Optional[Dict[str, Any]] = None,
1413
+ ) -> Dict[str, Any]:
1414
+ """Get data for table widget"""
1415
+ if widget.widget_id == "alert_table":
1416
+ alerts = self.alert_manager.get_alert_history(hours=24, tenant_id=tenant_id)
1417
+
1418
+ table_data = []
1419
+ for alert in alerts:
1420
+ table_data.append(
1421
+ {
1422
+ "timestamp": alert.timestamp.isoformat(),
1423
+ "severity": alert.severity.value,
1424
+ "title": alert.title,
1425
+ "description": alert.description,
1426
+ "component": alert.component,
1427
+ "resolved": alert.resolved,
1428
+ }
1429
+ )
1430
+
1431
+ return {
1432
+ "columns": [
1433
+ "timestamp",
1434
+ "severity",
1435
+ "title",
1436
+ "description",
1437
+ "component",
1438
+ "resolved",
1439
+ ],
1440
+ "data": table_data,
1441
+ }
1442
+
1443
+ return {"error": "Unknown table type"}
1444
+
1445
+ def _get_alert_widget_data(self, widget: DashboardWidget, tenant_id: Optional[str] = None) -> Dict[str, Any]:
1446
+ """Get data for alert widget"""
1447
+ active_alerts = self.alert_manager.get_active_alerts(tenant_id=tenant_id)
1448
+
1449
+ return {
1450
+ "active_count": len(active_alerts),
1451
+ "severity_breakdown": {
1452
+ severity.value: len([a for a in active_alerts if a.severity == severity]) for severity in AlertSeverity
1453
+ },
1454
+ "recent_alerts": [
1455
+ {
1456
+ "id": alert.alert_id,
1457
+ "title": alert.title,
1458
+ "severity": alert.severity.value,
1459
+ "timestamp": alert.timestamp.isoformat(),
1460
+ }
1461
+ for alert in sorted(active_alerts, key=lambda a: a.timestamp, reverse=True)[:10]
1462
+ ],
1463
+ }
1464
+
1465
+ def _map_metric_name(self, metric_name: str) -> Optional[MetricType]:
1466
+ """Map metric name to MetricType enum"""
1467
+ mapping = {
1468
+ "cpu_usage": MetricType.CPU_USAGE,
1469
+ "memory_usage": MetricType.MEMORY_USAGE,
1470
+ "hook_execution_rate": MetricType.THROUGHPUT,
1471
+ "hook_success_rate": MetricType.AVAILABILITY,
1472
+ "response_time": MetricType.RESPONSE_TIME,
1473
+ "error_rate": MetricType.ERROR_RATE,
1474
+ "network_io": MetricType.NETWORK_IO,
1475
+ "disk_io": MetricType.DISK_IO,
1476
+ "cache_performance": MetricType.CACHE_PERFORMANCE,
1477
+ "database_performance": MetricType.DATABASE_PERFORMANCE,
1478
+ }
1479
+
1480
+ return mapping.get(metric_name)
1481
+
1482
+ def _broadcast_alert(self, alert: Alert) -> None:
1483
+ """Broadcast alert to WebSocket clients"""
1484
+ if not self.enable_websocket:
1485
+ return
1486
+
1487
+ {
1488
+ "type": "alert",
1489
+ "data": alert.to_dict(),
1490
+ "timestamp": datetime.now().isoformat(),
1491
+ }
1492
+
1493
+ # Implementation would send message to all connected WebSocket clients
1494
+ logger.info(f"Broadcasting alert: {alert.title}")
1495
+
1496
+ def get_system_status(self) -> Dict[str, Any]:
1497
+ """Get comprehensive system status"""
1498
+ return {
1499
+ "status": "running" if self._running else "stopped",
1500
+ "uptime_seconds": (datetime.now() - self._startup_time).total_seconds(),
1501
+ "metrics_collected": len(self.metrics_collector.metrics_buffer),
1502
+ "active_alerts": len(self.alert_manager.active_alerts),
1503
+ "total_dashboards": len(self.dashboard_manager.dashboards) + len(self.dashboard_manager.default_dashboards),
1504
+ "websocket_connections": len(self.websocket_connections),
1505
+ "external_integrations": list(self.external_integrations.keys()),
1506
+ "last_update": datetime.now().isoformat(),
1507
+ }
1508
+
1509
+ def create_custom_dashboard(
1510
+ self,
1511
+ name: str,
1512
+ description: str,
1513
+ widgets: List[Dict[str, Any]],
1514
+ owner: str = "",
1515
+ tenant_id: Optional[str] = None,
1516
+ is_public: bool = False,
1517
+ ) -> str:
1518
+ """Create a custom dashboard from widget definitions"""
1519
+ dashboard_widgets = []
1520
+
1521
+ for widget_def in widgets:
1522
+ widget = DashboardWidget(
1523
+ widget_id=widget_def.get("widget_id", str(uuid.uuid4())),
1524
+ widget_type=widget_def.get("widget_type", "metric"),
1525
+ title=widget_def.get("title", ""),
1526
+ position=widget_def.get("position", {"x": 0, "y": 0, "width": 4, "height": 2}),
1527
+ config=widget_def.get("config", {}),
1528
+ metrics=widget_def.get("metrics", []),
1529
+ )
1530
+ dashboard_widgets.append(widget)
1531
+
1532
+ return self.dashboard_manager.create_dashboard(
1533
+ name=name,
1534
+ description=description,
1535
+ dashboard_type=DashboardType.CUSTOM,
1536
+ widgets=dashboard_widgets,
1537
+ owner=owner,
1538
+ tenant_id=tenant_id,
1539
+ is_public=is_public,
1540
+ )
1541
+
1542
+
1543
+ # Global instance for easy access
1544
+ _monitoring_dashboard: Optional[RealtimeMonitoringDashboard] = None
1545
+
1546
+
1547
+ def get_monitoring_dashboard(
1548
+ metrics_buffer_size: int = 100000,
1549
+ retention_hours: int = 168,
1550
+ alert_check_interval: int = 30,
1551
+ enable_websocket: bool = True,
1552
+ enable_external_integration: bool = True,
1553
+ ) -> RealtimeMonitoringDashboard:
1554
+ """Get or create global monitoring dashboard instance"""
1555
+ global _monitoring_dashboard
1556
+ if _monitoring_dashboard is None:
1557
+ _monitoring_dashboard = RealtimeMonitoringDashboard(
1558
+ metrics_buffer_size=metrics_buffer_size,
1559
+ retention_hours=retention_hours,
1560
+ alert_check_interval=alert_check_interval,
1561
+ enable_websocket=enable_websocket,
1562
+ enable_external_integration=enable_external_integration,
1563
+ )
1564
+ return _monitoring_dashboard
1565
+
1566
+
1567
+ # Convenience functions
1568
+ async def start_monitoring() -> None:
1569
+ """Start the monitoring dashboard"""
1570
+ dashboard = get_monitoring_dashboard()
1571
+ await dashboard.start()
1572
+
1573
+
1574
+ def stop_monitoring() -> None:
1575
+ """Stop the monitoring dashboard"""
1576
+ dashboard = get_monitoring_dashboard()
1577
+ dashboard.stop()
1578
+
1579
+
1580
+ def add_system_metric(
1581
+ metric_type: MetricType,
1582
+ value: Union[int, float],
1583
+ component: str = "",
1584
+ tags: Optional[Dict[str, str]] = None,
1585
+ ) -> None:
1586
+ """Add a system metric"""
1587
+ dashboard = get_monitoring_dashboard()
1588
+ dashboard.add_metric(metric_type, value, tags, component=component)
1589
+
1590
+
1591
+ def add_hook_metric(
1592
+ hook_path: str,
1593
+ execution_time_ms: float,
1594
+ success: bool,
1595
+ tenant_id: Optional[str] = None,
1596
+ ) -> None:
1597
+ """Add hook execution metric"""
1598
+ dashboard = get_monitoring_dashboard()
1599
+
1600
+ # Add execution time metric
1601
+ dashboard.add_metric(
1602
+ MetricType.RESPONSE_TIME,
1603
+ execution_time_ms,
1604
+ tags={"hook_path": hook_path, "success": str(success)},
1605
+ component="hooks",
1606
+ tenant_id=tenant_id,
1607
+ )
1608
+
1609
+ # Add success rate metric
1610
+ dashboard.add_metric(
1611
+ MetricType.AVAILABILITY,
1612
+ 1.0 if success else 0.0,
1613
+ tags={"hook_path": hook_path},
1614
+ component="hooks",
1615
+ tenant_id=tenant_id,
1616
+ )
1617
+
1618
+
1619
+ if __name__ == "__main__":
1620
+ # Example usage
1621
+ async def main():
1622
+ print("šŸ“Š Starting Real-time Monitoring Dashboard...")
1623
+
1624
+ # Initialize monitoring dashboard
1625
+ dashboard = RealtimeMonitoringDashboard(
1626
+ metrics_buffer_size=10000,
1627
+ retention_hours=24,
1628
+ enable_websocket=False, # Disable for demo
1629
+ enable_external_integration=False,
1630
+ )
1631
+
1632
+ try:
1633
+ # Start the system
1634
+ await dashboard.start()
1635
+
1636
+ # Add some test metrics
1637
+ print("\nšŸ“ˆ Adding test metrics...")
1638
+ for i in range(20):
1639
+ dashboard.add_metric(
1640
+ MetricType.CPU_USAGE,
1641
+ 20 + (i % 80), # CPU usage from 20% to 100%
1642
+ tags={"component": "system", "instance": "demo"},
1643
+ source="demo",
1644
+ )
1645
+
1646
+ dashboard.add_metric(
1647
+ MetricType.MEMORY_USAGE,
1648
+ 30 + (i % 70), # Memory usage from 30% to 100%
1649
+ tags={"component": "system"},
1650
+ source="demo",
1651
+ )
1652
+
1653
+ dashboard.add_hook_metric(
1654
+ f"test_hook_{i % 5}.py",
1655
+ 100 + (i * 50), # Execution time from 100ms to 1000ms
1656
+ i % 4 != 0, # 75% success rate
1657
+ tenant_id="demo_tenant" if i % 2 == 0 else None,
1658
+ )
1659
+
1660
+ await asyncio.sleep(0.1)
1661
+
1662
+ # Let metrics process
1663
+ print("\nā³ Processing metrics and checking alerts...")
1664
+ await asyncio.sleep(5)
1665
+
1666
+ # Get system status
1667
+ status = dashboard.get_system_status()
1668
+ print("\nšŸ“Š System Status:")
1669
+ print(f" Status: {status['status']}")
1670
+ print(f" Uptime: {status['uptime_seconds']:.1f}s")
1671
+ print(f" Metrics collected: {status['metrics_collected']}")
1672
+ print(f" Active alerts: {status['active_alerts']}")
1673
+ print(f" Total dashboards: {status['total_dashboards']}")
1674
+
1675
+ # Get dashboard data
1676
+ dashboard_data = dashboard.get_dashboard_data("system_overview")
1677
+ print("\nšŸ“± Dashboard Data:")
1678
+ print(f" Dashboard: {dashboard_data['dashboard']['name']}")
1679
+ print(f" Widgets: {len(dashboard_data.get('widgets_data', {}))}")
1680
+ print(f" Generated at: {dashboard_data.get('generated_at')}")
1681
+
1682
+ # Get metrics statistics
1683
+ cpu_stats = dashboard.metrics_collector.get_statistics(MetricType.CPU_USAGE, minutes=10)
1684
+ memory_stats = dashboard.metrics_collector.get_statistics(MetricType.MEMORY_USAGE, minutes=10)
1685
+ print("\nšŸ“ˆ Metrics Statistics (last 10 minutes):")
1686
+ cpu_avg = cpu_stats.get("average", 0)
1687
+ cpu_max = cpu_stats.get("max", 0)
1688
+ cpu_count = cpu_stats.get("count", 0)
1689
+ print(f" CPU Usage - Avg: {cpu_avg:.1f}%, Max: {cpu_max:.1f}%, Count: {cpu_count}")
1690
+ mem_avg = memory_stats.get("average", 0)
1691
+ mem_max = memory_stats.get("max", 0)
1692
+ mem_count = memory_stats.get("count", 0)
1693
+ print(f" Memory Usage - Avg: {mem_avg:.1f}%, Max: {mem_max:.1f}%, Count: {mem_count}")
1694
+
1695
+ # Get alert statistics
1696
+ alert_stats = dashboard.alert_manager.get_alert_statistics(hours=1)
1697
+ print("\n🚨 Alert Statistics (last 1 hour):")
1698
+ print(f" Total alerts: {alert_stats['total_alerts']}")
1699
+ print(f" Resolved: {alert_stats['resolved_count']}")
1700
+ print(f" Resolution rate: {alert_stats['resolution_rate']:.1%}")
1701
+ print(f" By severity: {alert_stats['by_severity']}")
1702
+
1703
+ # List available dashboards
1704
+ dashboards = dashboard.dashboard_manager.list_dashboards()
1705
+ print("\nšŸ“‹ Available Dashboards:")
1706
+ for dashboard_info in dashboards:
1707
+ print(f" - {dashboard_info.name} ({dashboard_info.dashboard_type.value})")
1708
+
1709
+ print("\nāœ… Real-time Monitoring Dashboard demo completed successfully!")
1710
+
1711
+ except Exception as e:
1712
+ print(f"\nāŒ Demo failed: {str(e)}")
1713
+ import traceback
1714
+
1715
+ traceback.print_exc()
1716
+
1717
+ finally:
1718
+ # Stop the system
1719
+ print("\nšŸ›‘ Stopping monitoring dashboard...")
1720
+ dashboard.stop()
1721
+ print("āœ… System stopped")
1722
+
1723
+ # Run the demo
1724
+ asyncio.run(main())