moai-adk 0.8.0__py3-none-any.whl ā 0.34.0__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.
- moai_adk/__init__.py +2 -6
- moai_adk/__main__.py +136 -21
- moai_adk/cli/__init__.py +6 -2
- moai_adk/cli/commands/__init__.py +1 -4
- moai_adk/cli/commands/analyze.py +116 -0
- moai_adk/cli/commands/doctor.py +17 -5
- moai_adk/cli/commands/init.py +118 -48
- moai_adk/cli/commands/language.py +248 -0
- moai_adk/cli/commands/status.py +8 -13
- moai_adk/cli/commands/update.py +1978 -149
- moai_adk/cli/main.py +3 -2
- moai_adk/cli/prompts/init_prompts.py +144 -91
- moai_adk/cli/spec_status.py +263 -0
- moai_adk/cli/ui/__init__.py +44 -0
- moai_adk/cli/ui/progress.py +422 -0
- moai_adk/cli/ui/prompts.py +389 -0
- moai_adk/cli/ui/theme.py +129 -0
- moai_adk/cli/worktree/__init__.py +27 -0
- moai_adk/cli/worktree/__main__.py +31 -0
- moai_adk/cli/worktree/cli.py +683 -0
- moai_adk/cli/worktree/exceptions.py +89 -0
- moai_adk/cli/worktree/manager.py +493 -0
- moai_adk/cli/worktree/models.py +65 -0
- moai_adk/cli/worktree/registry.py +422 -0
- moai_adk/core/PHASE2_OPTIMIZATIONS.md +467 -0
- moai_adk/core/__init__.py +0 -1
- moai_adk/core/analysis/__init__.py +9 -0
- moai_adk/core/analysis/session_analyzer.py +400 -0
- moai_adk/core/claude_integration.py +393 -0
- moai_adk/core/command_helpers.py +270 -0
- moai_adk/core/comprehensive_monitoring_system.py +1183 -0
- moai_adk/core/config/__init__.py +6 -0
- moai_adk/core/config/auto_spec_config.py +340 -0
- moai_adk/core/config/migration.py +148 -17
- moai_adk/core/config/unified.py +436 -0
- moai_adk/core/context_manager.py +273 -0
- moai_adk/core/diagnostics/slash_commands.py +0 -1
- moai_adk/core/enterprise_features.py +1404 -0
- moai_adk/core/error_recovery_system.py +1902 -0
- moai_adk/core/event_driven_hook_system.py +1371 -0
- moai_adk/core/git/__init__.py +8 -1
- moai_adk/core/git/branch.py +0 -1
- moai_adk/core/git/branch_manager.py +2 -10
- moai_adk/core/git/checkpoint.py +1 -7
- moai_adk/core/git/commit.py +0 -1
- moai_adk/core/git/conflict_detector.py +413 -0
- moai_adk/core/git/event_detector.py +3 -5
- moai_adk/core/git/manager.py +91 -2
- moai_adk/core/hooks/post_tool_auto_spec_completion.py +901 -0
- moai_adk/core/input_validation_middleware.py +1006 -0
- moai_adk/core/integration/__init__.py +22 -0
- moai_adk/core/integration/engine.py +157 -0
- moai_adk/core/integration/integration_tester.py +226 -0
- moai_adk/core/integration/models.py +88 -0
- moai_adk/core/integration/utils.py +211 -0
- moai_adk/core/issue_creator.py +305 -0
- moai_adk/core/jit_context_loader.py +956 -0
- moai_adk/core/jit_enhanced_hook_manager.py +1987 -0
- moai_adk/core/language_config.py +202 -0
- moai_adk/core/language_config_resolver.py +572 -0
- moai_adk/core/language_validator.py +543 -0
- moai_adk/core/mcp/setup.py +116 -0
- moai_adk/core/merge/__init__.py +9 -0
- moai_adk/core/merge/analyzer.py +481 -0
- moai_adk/core/migration/__init__.py +18 -0
- moai_adk/core/migration/alfred_to_moai_migrator.py +383 -0
- moai_adk/core/migration/backup_manager.py +277 -0
- moai_adk/core/migration/custom_element_scanner.py +358 -0
- moai_adk/core/migration/file_migrator.py +209 -0
- moai_adk/core/migration/interactive_checkbox_ui.py +488 -0
- moai_adk/core/migration/selective_restorer.py +470 -0
- moai_adk/core/migration/template_utils.py +74 -0
- moai_adk/core/migration/user_selection_ui.py +338 -0
- moai_adk/core/migration/version_detector.py +139 -0
- moai_adk/core/migration/version_migrator.py +228 -0
- moai_adk/core/performance/__init__.py +6 -0
- moai_adk/core/performance/cache_system.py +316 -0
- moai_adk/core/performance/parallel_processor.py +116 -0
- moai_adk/core/phase_optimized_hook_scheduler.py +879 -0
- moai_adk/core/project/__init__.py +0 -1
- moai_adk/core/project/backup_utils.py +2 -7
- moai_adk/core/project/checker.py +2 -4
- moai_adk/core/project/detector.py +189 -22
- moai_adk/core/project/initializer.py +218 -27
- moai_adk/core/project/phase_executor.py +416 -44
- moai_adk/core/project/validator.py +7 -32
- moai_adk/core/quality/__init__.py +1 -1
- moai_adk/core/quality/trust_checker.py +37 -101
- moai_adk/core/quality/validators/__init__.py +1 -1
- moai_adk/core/quality/validators/base_validator.py +1 -1
- moai_adk/core/realtime_monitoring_dashboard.py +1724 -0
- moai_adk/core/robust_json_parser.py +611 -0
- moai_adk/core/rollback_manager.py +918 -0
- moai_adk/core/session_manager.py +651 -0
- moai_adk/core/skill_loading_system.py +579 -0
- moai_adk/core/spec/confidence_scoring.py +680 -0
- moai_adk/core/spec/ears_template_engine.py +1247 -0
- moai_adk/core/spec/quality_validator.py +687 -0
- moai_adk/core/spec_status_manager.py +478 -0
- moai_adk/core/template/__init__.py +0 -1
- moai_adk/core/template/backup.py +82 -17
- moai_adk/core/template/config.py +112 -40
- moai_adk/core/template/languages.py +0 -1
- moai_adk/core/template/merger.py +75 -26
- moai_adk/core/template/processor.py +750 -72
- moai_adk/core/template_engine.py +310 -0
- moai_adk/core/template_variable_synchronizer.py +417 -0
- moai_adk/core/unified_permission_manager.py +745 -0
- moai_adk/core/user_behavior_analytics.py +851 -0
- moai_adk/core/version_sync.py +429 -0
- moai_adk/foundation/__init__.py +56 -0
- moai_adk/foundation/backend.py +1027 -0
- moai_adk/foundation/database.py +1115 -0
- moai_adk/foundation/devops.py +1585 -0
- moai_adk/foundation/ears.py +431 -0
- moai_adk/foundation/frontend.py +870 -0
- moai_adk/foundation/git/commit_templates.py +557 -0
- moai_adk/foundation/git.py +376 -0
- moai_adk/foundation/langs.py +484 -0
- moai_adk/foundation/ml_ops.py +1162 -0
- moai_adk/foundation/testing.py +1524 -0
- moai_adk/foundation/trust/trust_principles.py +676 -0
- moai_adk/foundation/trust/validation_checklist.py +1573 -0
- moai_adk/project/__init__.py +0 -0
- moai_adk/project/configuration.py +1084 -0
- moai_adk/project/documentation.py +566 -0
- moai_adk/project/schema.py +447 -0
- moai_adk/statusline/__init__.py +38 -0
- moai_adk/statusline/alfred_detector.py +105 -0
- moai_adk/statusline/config.py +376 -0
- moai_adk/statusline/enhanced_output_style_detector.py +372 -0
- moai_adk/statusline/git_collector.py +190 -0
- moai_adk/statusline/main.py +322 -0
- moai_adk/statusline/metrics_tracker.py +78 -0
- moai_adk/statusline/renderer.py +343 -0
- moai_adk/statusline/update_checker.py +129 -0
- moai_adk/statusline/version_reader.py +741 -0
- moai_adk/templates/.claude/agents/moai/ai-nano-banana.md +670 -0
- moai_adk/templates/.claude/agents/moai/builder-agent.md +474 -0
- moai_adk/templates/.claude/agents/moai/builder-command.md +1172 -0
- moai_adk/templates/.claude/agents/moai/builder-skill.md +666 -0
- moai_adk/templates/.claude/agents/moai/expert-backend.md +899 -0
- moai_adk/templates/.claude/agents/moai/expert-database.md +777 -0
- moai_adk/templates/.claude/agents/moai/expert-debug.md +401 -0
- moai_adk/templates/.claude/agents/moai/expert-devops.md +720 -0
- moai_adk/templates/.claude/agents/moai/expert-frontend.md +734 -0
- moai_adk/templates/.claude/agents/moai/expert-performance.md +657 -0
- moai_adk/templates/.claude/agents/moai/expert-security.md +509 -0
- moai_adk/templates/.claude/agents/moai/expert-testing.md +733 -0
- moai_adk/templates/.claude/agents/moai/expert-uiux.md +1041 -0
- moai_adk/templates/.claude/agents/moai/manager-claude-code.md +432 -0
- moai_adk/templates/.claude/agents/moai/manager-docs.md +573 -0
- moai_adk/templates/.claude/agents/moai/manager-git.md +1020 -0
- moai_adk/templates/.claude/agents/moai/manager-project.md +891 -0
- moai_adk/templates/.claude/agents/moai/manager-quality.md +624 -0
- moai_adk/templates/.claude/agents/moai/manager-spec.md +809 -0
- moai_adk/templates/.claude/agents/moai/manager-strategy.md +780 -0
- moai_adk/templates/.claude/agents/moai/manager-tdd.md +784 -0
- moai_adk/templates/.claude/agents/moai/mcp-context7.md +458 -0
- moai_adk/templates/.claude/agents/moai/mcp-figma.md +1607 -0
- moai_adk/templates/.claude/agents/moai/mcp-notion.md +789 -0
- moai_adk/templates/.claude/agents/moai/mcp-playwright.md +469 -0
- moai_adk/templates/.claude/agents/moai/mcp-sequential-thinking.md +1032 -0
- moai_adk/templates/.claude/commands/moai/0-project.md +1384 -0
- moai_adk/templates/.claude/commands/moai/1-plan.md +1427 -0
- moai_adk/templates/.claude/commands/moai/2-run.md +943 -0
- moai_adk/templates/.claude/commands/moai/3-sync.md +1324 -0
- moai_adk/templates/.claude/commands/moai/9-feedback.md +314 -0
- moai_adk/templates/.claude/hooks/__init__.py +8 -0
- moai_adk/templates/.claude/hooks/moai/__init__.py +8 -0
- moai_adk/templates/.claude/hooks/moai/lib/__init__.py +85 -0
- moai_adk/templates/.claude/hooks/{alfred/core ā moai/lib}/checkpoint.py +10 -37
- moai_adk/templates/.claude/hooks/moai/lib/common.py +131 -0
- moai_adk/templates/.claude/hooks/moai/lib/config_manager.py +446 -0
- moai_adk/templates/.claude/hooks/moai/lib/config_validator.py +639 -0
- moai_adk/templates/.claude/hooks/moai/lib/example_config.json +104 -0
- moai_adk/templates/.claude/hooks/moai/lib/git_operations_manager.py +590 -0
- moai_adk/templates/.claude/hooks/moai/lib/language_validator.py +317 -0
- moai_adk/templates/.claude/hooks/moai/lib/models.py +102 -0
- moai_adk/templates/.claude/hooks/moai/lib/path_utils.py +28 -0
- moai_adk/templates/.claude/hooks/moai/lib/project.py +768 -0
- moai_adk/templates/.claude/hooks/moai/lib/test_hooks_improvements.py +443 -0
- moai_adk/templates/.claude/hooks/moai/lib/timeout.py +160 -0
- moai_adk/templates/.claude/hooks/moai/lib/unified_timeout_manager.py +530 -0
- moai_adk/templates/.claude/hooks/moai/session_end__auto_cleanup.py +862 -0
- moai_adk/templates/.claude/hooks/moai/session_start__show_project_info.py +1075 -0
- moai_adk/templates/.claude/output-styles/moai/r2d2.md +560 -0
- moai_adk/templates/.claude/output-styles/moai/yoda.md +359 -0
- moai_adk/templates/.claude/settings.json +78 -50
- moai_adk/templates/.claude/skills/moai-ai-nano-banana/SKILL.md +438 -0
- moai_adk/templates/.claude/skills/moai-ai-nano-banana/examples.md +431 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/SKILL.md +249 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/examples.md +406 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/modules/README.md +44 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/modules/api-documentation.md +130 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/modules/code-documentation.md +152 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/modules/multi-format-output.md +178 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/modules/user-guides.md +147 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/reference.md +328 -0
- moai_adk/templates/.claude/skills/moai-domain-backend/SKILL.md +313 -283
- moai_adk/templates/.claude/skills/moai-domain-backend/examples.md +610 -1525
- moai_adk/templates/.claude/skills/moai-domain-backend/reference.md +423 -619
- moai_adk/templates/.claude/skills/moai-domain-database/SKILL.md +295 -95
- moai_adk/templates/.claude/skills/moai-domain-database/examples.md +817 -16
- moai_adk/templates/.claude/skills/moai-domain-database/modules/README.md +53 -0
- moai_adk/templates/.claude/skills/moai-domain-database/modules/mongodb.md +231 -0
- moai_adk/templates/.claude/skills/moai-domain-database/modules/postgresql.md +169 -0
- moai_adk/templates/.claude/skills/moai-domain-database/modules/redis.md +262 -0
- moai_adk/templates/.claude/skills/moai-domain-database/reference.md +532 -17
- moai_adk/templates/.claude/skills/moai-domain-frontend/SKILL.md +470 -97
- moai_adk/templates/.claude/skills/moai-domain-frontend/examples.md +955 -16
- moai_adk/templates/.claude/skills/moai-domain-frontend/reference.md +651 -18
- moai_adk/templates/.claude/skills/moai-domain-uiux/SKILL.md +455 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/examples.md +560 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/modules/accessibility-wcag.md +260 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/modules/component-architecture.md +228 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/modules/design-system-tokens.md +405 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/modules/icon-libraries.md +401 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/modules/theming-system.md +373 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/reference.md +243 -0
- moai_adk/templates/.claude/skills/moai-formats-data/SKILL.md +492 -0
- moai_adk/templates/.claude/skills/moai-formats-data/examples.md +804 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/README.md +98 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/SKILL-MODULARIZATION-TEMPLATE.md +278 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/caching-performance.md +459 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/data-validation.md +485 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/json-optimization.md +374 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/toon-encoding.md +308 -0
- moai_adk/templates/.claude/skills/moai-formats-data/reference.md +585 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/SKILL.md +202 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/examples.md +732 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/best-practices-checklist.md +616 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-custom-slash-commands-official.md +729 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-hooks-official.md +560 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-iam-official.md +635 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-memory-official.md +543 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-settings-official.md +663 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-skills-official.md +113 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-sub-agents-official.md +238 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/complete-configuration-guide.md +175 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/skill-examples.md +1674 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/skill-formatting-guide.md +729 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-examples.md +1513 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-formatting-guide.md +1086 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-integration-patterns.md +1100 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference.md +209 -0
- moai_adk/templates/.claude/skills/moai-foundation-context/SKILL.md +441 -0
- moai_adk/templates/.claude/skills/moai-foundation-context/examples.md +1048 -0
- moai_adk/templates/.claude/skills/moai-foundation-context/reference.md +246 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/SKILL.md +420 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/examples.md +358 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/README.md +296 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/agents-reference.md +359 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/commands-reference.md +432 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/delegation-patterns.md +757 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/execution-rules.md +687 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/modular-system.md +665 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/progressive-disclosure.md +649 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/spec-first-tdd.md +864 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/token-optimization.md +708 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/trust-5-framework.md +981 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/reference.md +478 -0
- moai_adk/templates/.claude/skills/moai-foundation-philosopher/SKILL.md +315 -0
- moai_adk/templates/.claude/skills/moai-foundation-philosopher/examples.md +228 -0
- moai_adk/templates/.claude/skills/moai-foundation-philosopher/modules/assumption-matrix.md +80 -0
- moai_adk/templates/.claude/skills/moai-foundation-philosopher/modules/cognitive-bias.md +199 -0
- moai_adk/templates/.claude/skills/moai-foundation-philosopher/modules/first-principles.md +140 -0
- moai_adk/templates/.claude/skills/moai-foundation-philosopher/modules/trade-off-analysis.md +154 -0
- moai_adk/templates/.claude/skills/moai-foundation-philosopher/reference.md +157 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/SKILL.md +364 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/examples.md +1232 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/modules/best-practices.md +261 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/modules/integration-patterns.md +194 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/modules/proactive-analysis.md +229 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/modules/trust5-validation.md +169 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/reference.md +1266 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/scripts/quality-gate.sh +668 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/templates/github-actions-quality.yml +481 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/templates/quality-config.yaml +519 -0
- moai_adk/templates/.claude/skills/moai-lang-cpp/SKILL.md +618 -93
- moai_adk/templates/.claude/skills/moai-lang-csharp/SKILL.md +446 -91
- moai_adk/templates/.claude/skills/moai-lang-elixir/SKILL.md +612 -0
- moai_adk/templates/.claude/skills/moai-lang-flutter/SKILL.md +477 -0
- moai_adk/templates/.claude/skills/moai-lang-flutter/examples.md +1090 -0
- moai_adk/templates/.claude/skills/moai-lang-flutter/reference.md +686 -0
- moai_adk/templates/.claude/skills/moai-lang-go/SKILL.md +346 -94
- moai_adk/templates/.claude/skills/moai-lang-go/examples.md +906 -16
- moai_adk/templates/.claude/skills/moai-lang-go/reference.md +721 -15
- moai_adk/templates/.claude/skills/moai-lang-java/SKILL.md +352 -91
- moai_adk/templates/.claude/skills/moai-lang-java/examples.md +851 -16
- moai_adk/templates/.claude/skills/moai-lang-java/reference.md +278 -18
- moai_adk/templates/.claude/skills/moai-lang-kotlin/SKILL.md +344 -86
- moai_adk/templates/.claude/skills/moai-lang-kotlin/examples.md +993 -16
- moai_adk/templates/.claude/skills/moai-lang-kotlin/reference.md +549 -18
- moai_adk/templates/.claude/skills/moai-lang-php/SKILL.md +617 -96
- moai_adk/templates/.claude/skills/moai-lang-python/SKILL.md +364 -314
- moai_adk/templates/.claude/skills/moai-lang-python/examples.md +849 -496
- moai_adk/templates/.claude/skills/moai-lang-python/reference.md +731 -243
- moai_adk/templates/.claude/skills/moai-lang-r/SKILL.md +545 -89
- moai_adk/templates/.claude/skills/moai-lang-ruby/SKILL.md +650 -87
- moai_adk/templates/.claude/skills/moai-lang-rust/SKILL.md +341 -93
- moai_adk/templates/.claude/skills/moai-lang-rust/examples.md +646 -16
- moai_adk/templates/.claude/skills/moai-lang-rust/reference.md +491 -18
- moai_adk/templates/.claude/skills/moai-lang-scala/SKILL.md +463 -89
- moai_adk/templates/.claude/skills/moai-lang-scala/examples.md +620 -16
- moai_adk/templates/.claude/skills/moai-lang-scala/reference.md +410 -17
- moai_adk/templates/.claude/skills/moai-lang-swift/SKILL.md +486 -112
- moai_adk/templates/.claude/skills/moai-lang-swift/examples.md +905 -16
- moai_adk/templates/.claude/skills/moai-lang-swift/reference.md +659 -17
- moai_adk/templates/.claude/skills/moai-lang-typescript/SKILL.md +333 -92
- moai_adk/templates/.claude/skills/moai-lang-typescript/examples.md +1076 -16
- moai_adk/templates/.claude/skills/moai-lang-typescript/reference.md +718 -21
- moai_adk/templates/.claude/skills/moai-library-mermaid/SKILL.md +300 -0
- moai_adk/templates/.claude/skills/moai-library-mermaid/advanced-patterns.md +465 -0
- moai_adk/templates/.claude/skills/moai-library-mermaid/examples.md +270 -0
- moai_adk/templates/.claude/skills/moai-library-mermaid/optimization.md +440 -0
- moai_adk/templates/.claude/skills/moai-library-mermaid/reference.md +228 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/SKILL.md +319 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/advanced-patterns.md +336 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/examples.md +592 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/advanced-deployment-patterns.md +182 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/advanced-patterns.md +17 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/configuration.md +57 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/content-architecture-optimization.md +162 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/deployment.md +52 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/framework-core-configuration.md +186 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/i18n-setup.md +55 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/mdx-components.md +52 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/optimization.md +303 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/reference.md +379 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/SKILL.md +372 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/examples.md +575 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/modules/advanced-patterns.md +394 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/modules/optimization.md +278 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/modules/shadcn-components.md +457 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/modules/shadcn-theming.md +373 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/reference.md +74 -0
- moai_adk/templates/.claude/skills/moai-mcp-figma/SKILL.md +402 -0
- moai_adk/templates/.claude/skills/moai-mcp-figma/advanced-patterns.md +607 -0
- moai_adk/templates/.claude/skills/moai-mcp-notion/SKILL.md +300 -0
- moai_adk/templates/.claude/skills/moai-mcp-notion/advanced-patterns.md +537 -0
- moai_adk/templates/.claude/skills/moai-platform-auth0/SKILL.md +290 -0
- moai_adk/templates/.claude/skills/moai-platform-clerk/SKILL.md +390 -0
- moai_adk/templates/.claude/skills/moai-platform-convex/SKILL.md +398 -0
- moai_adk/templates/.claude/skills/moai-platform-firebase-auth/SKILL.md +379 -0
- moai_adk/templates/.claude/skills/moai-platform-firestore/SKILL.md +358 -0
- moai_adk/templates/.claude/skills/moai-platform-neon/SKILL.md +467 -0
- moai_adk/templates/.claude/skills/moai-platform-railway/SKILL.md +377 -0
- moai_adk/templates/.claude/skills/moai-platform-supabase/SKILL.md +466 -0
- moai_adk/templates/.claude/skills/moai-platform-vercel/SKILL.md +482 -0
- moai_adk/templates/.claude/skills/moai-workflow-jit-docs/SKILL.md +449 -0
- moai_adk/templates/.claude/skills/moai-workflow-jit-docs/advanced-patterns.md +379 -0
- moai_adk/templates/.claude/skills/moai-workflow-jit-docs/examples.md +544 -0
- moai_adk/templates/.claude/skills/moai-workflow-jit-docs/optimization.md +286 -0
- moai_adk/templates/.claude/skills/moai-workflow-jit-docs/reference.md +307 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/README.md +190 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/SKILL.md +390 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/__init__.py +520 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/complete_workflow_demo_fixed.py +574 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples/complete_project_setup.py +317 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples/complete_workflow_demo.py +663 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples/config-migration-example.json +190 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples/question-examples.json +175 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples/quick_start.py +196 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples.md +547 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/__init__.py +17 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/advanced-patterns.md +158 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/ask_user_integration.py +340 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/batch_questions.py +713 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/config_manager.py +538 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/documentation_manager.py +1336 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/language_initializer.py +730 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/migration_manager.py +608 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/template_optimizer.py +1005 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/reference.md +275 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/schemas/config-schema.json +316 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/schemas/tab_schema.json +1462 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/config-template.json +71 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/product-template.md +44 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/structure-template.md +48 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/tech-template.md +92 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/config-manager-setup.json +109 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/language-initializer.json +228 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/menu-project-config.json +130 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/project-batch-questions.json +97 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/spec-workflow-setup.json +150 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/test_integration_simple.py +436 -0
- moai_adk/templates/.claude/skills/moai-workflow-spec/SKILL.md +534 -0
- moai_adk/templates/.claude/skills/moai-workflow-spec/examples.md +900 -0
- moai_adk/templates/.claude/skills/moai-workflow-spec/reference.md +704 -0
- moai_adk/templates/.claude/skills/moai-workflow-templates/SKILL.md +377 -0
- moai_adk/templates/.claude/skills/moai-workflow-templates/examples.md +552 -0
- moai_adk/templates/.claude/skills/moai-workflow-templates/modules/code-templates.md +124 -0
- moai_adk/templates/.claude/skills/moai-workflow-templates/modules/feedback-templates.md +100 -0
- moai_adk/templates/.claude/skills/moai-workflow-templates/modules/template-optimizer.md +138 -0
- moai_adk/templates/.claude/skills/moai-workflow-templates/reference.md +346 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/LICENSE.txt +202 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/SKILL.md +456 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/advanced-patterns.md +576 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/examples/ai-powered-testing.py +294 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/examples/console_logging.py +35 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/examples/element_discovery.py +40 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/examples/static_html_automation.py +34 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/examples.md +672 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/README.md +220 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/ai-debugging.md +845 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/automated-code-review.md +1416 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/performance-optimization.md +1234 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/smart-refactoring.md +1243 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/tdd-context7.md +1260 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/optimization.md +505 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/reference/playwright-best-practices.md +57 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/reference.md +440 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/scripts/with_server.py +218 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/templates/alfred-integration.md +376 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/workflows/enterprise-testing-workflow.py +571 -0
- moai_adk/templates/.claude/skills/moai-worktree/SKILL.md +411 -0
- moai_adk/templates/.claude/skills/moai-worktree/examples.md +606 -0
- moai_adk/templates/.claude/skills/moai-worktree/modules/integration-patterns.md +982 -0
- moai_adk/templates/.claude/skills/moai-worktree/modules/parallel-development.md +778 -0
- moai_adk/templates/.claude/skills/moai-worktree/modules/worktree-commands.md +646 -0
- moai_adk/templates/.claude/skills/moai-worktree/modules/worktree-management.md +782 -0
- moai_adk/templates/.claude/skills/moai-worktree/reference.md +357 -0
- moai_adk/templates/.git-hooks/pre-commit +128 -0
- moai_adk/templates/.git-hooks/pre-push +365 -0
- moai_adk/templates/.github/workflows/ci-universal.yml +513 -0
- moai_adk/templates/.github/workflows/security-secrets-check.yml +179 -0
- moai_adk/templates/.github/workflows/spec-issue-sync.yml +206 -36
- moai_adk/templates/.gitignore +194 -13
- moai_adk/templates/.mcp.json +31 -0
- moai_adk/templates/.moai/config/config.yaml +58 -0
- moai_adk/templates/.moai/config/questions/_schema.yaml +151 -0
- moai_adk/templates/.moai/config/questions/tab0-init.yaml +251 -0
- moai_adk/templates/.moai/config/questions/tab1-user.yaml +108 -0
- moai_adk/templates/.moai/config/questions/tab2-project.yaml +81 -0
- moai_adk/templates/.moai/config/questions/tab3-git.yaml +634 -0
- moai_adk/templates/.moai/config/questions/tab4-quality.yaml +170 -0
- moai_adk/templates/.moai/config/questions/tab5-system.yaml +87 -0
- moai_adk/templates/.moai/config/sections/git-strategy.yaml +116 -0
- moai_adk/templates/.moai/config/sections/language.yaml +11 -0
- moai_adk/templates/.moai/config/sections/project.yaml +13 -0
- moai_adk/templates/.moai/config/sections/quality.yaml +17 -0
- moai_adk/templates/.moai/config/sections/system.yaml +14 -0
- moai_adk/templates/.moai/config/sections/user.yaml +5 -0
- moai_adk/templates/.moai/config/statusline-config.yaml +92 -0
- moai_adk/templates/.moai/scripts/setup-glm.py +136 -0
- moai_adk/templates/CLAUDE.md +571 -244
- moai_adk/utils/__init__.py +24 -2
- moai_adk/utils/banner.py +9 -13
- moai_adk/utils/common.py +294 -0
- moai_adk/utils/link_validator.py +241 -0
- moai_adk/utils/logger.py +4 -9
- moai_adk/utils/safe_file_reader.py +206 -0
- moai_adk/utils/timeout.py +160 -0
- moai_adk/utils/toon_utils.py +256 -0
- moai_adk/version.py +22 -0
- moai_adk-0.34.0.dist-info/METADATA +2999 -0
- moai_adk-0.34.0.dist-info/RECORD +463 -0
- {moai_adk-0.8.0.dist-info ā moai_adk-0.34.0.dist-info}/WHEEL +1 -1
- {moai_adk-0.8.0.dist-info ā moai_adk-0.34.0.dist-info}/entry_points.txt +1 -0
- moai_adk/cli/commands/backup.py +0 -80
- moai_adk/templates/.claude/agents/alfred/cc-manager.md +0 -293
- moai_adk/templates/.claude/agents/alfred/debug-helper.md +0 -196
- moai_adk/templates/.claude/agents/alfred/doc-syncer.md +0 -207
- moai_adk/templates/.claude/agents/alfred/git-manager.md +0 -375
- moai_adk/templates/.claude/agents/alfred/implementation-planner.md +0 -343
- moai_adk/templates/.claude/agents/alfred/project-manager.md +0 -246
- moai_adk/templates/.claude/agents/alfred/quality-gate.md +0 -320
- moai_adk/templates/.claude/agents/alfred/skill-factory.md +0 -837
- moai_adk/templates/.claude/agents/alfred/spec-builder.md +0 -272
- moai_adk/templates/.claude/agents/alfred/tag-agent.md +0 -265
- moai_adk/templates/.claude/agents/alfred/tdd-implementer.md +0 -311
- moai_adk/templates/.claude/agents/alfred/trust-checker.md +0 -352
- moai_adk/templates/.claude/commands/alfred/0-project.md +0 -1184
- moai_adk/templates/.claude/commands/alfred/1-plan.md +0 -665
- moai_adk/templates/.claude/commands/alfred/2-run.md +0 -488
- moai_adk/templates/.claude/commands/alfred/3-sync.md +0 -623
- moai_adk/templates/.claude/hooks/alfred/HOOK_SCHEMA_VALIDATION.md +0 -313
- moai_adk/templates/.claude/hooks/alfred/README.md +0 -230
- moai_adk/templates/.claude/hooks/alfred/alfred_hooks.py +0 -174
- moai_adk/templates/.claude/hooks/alfred/core/__init__.py +0 -170
- moai_adk/templates/.claude/hooks/alfred/core/context.py +0 -67
- moai_adk/templates/.claude/hooks/alfred/core/project.py +0 -416
- moai_adk/templates/.claude/hooks/alfred/core/tags.py +0 -198
- moai_adk/templates/.claude/hooks/alfred/handlers/__init__.py +0 -21
- moai_adk/templates/.claude/hooks/alfred/handlers/notification.py +0 -25
- moai_adk/templates/.claude/hooks/alfred/handlers/session.py +0 -161
- moai_adk/templates/.claude/hooks/alfred/handlers/tool.py +0 -90
- moai_adk/templates/.claude/hooks/alfred/handlers/user.py +0 -42
- moai_adk/templates/.claude/hooks/alfred/test_hook_output.py +0 -175
- moai_adk/templates/.claude/output-styles/alfred/agentic-coding.md +0 -640
- moai_adk/templates/.claude/output-styles/alfred/moai-adk-learning.md +0 -696
- moai_adk/templates/.claude/output-styles/alfred/study-with-alfred.md +0 -474
- moai_adk/templates/.claude/skills/moai-alfred-ears-authoring/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-alfred-ears-authoring/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-alfred-ears-authoring/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-alfred-git-workflow/SKILL.md +0 -122
- moai_adk/templates/.claude/skills/moai-alfred-git-workflow/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-alfred-git-workflow/reference.md +0 -29
- moai_adk/templates/.claude/skills/moai-alfred-interactive-questions/SKILL.md +0 -237
- moai_adk/templates/.claude/skills/moai-alfred-interactive-questions/examples.md +0 -615
- moai_adk/templates/.claude/skills/moai-alfred-interactive-questions/reference.md +0 -653
- moai_adk/templates/.claude/skills/moai-alfred-language-detection/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-alfred-language-detection/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-alfred-language-detection/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-validation/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-validation/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-validation/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-alfred-tag-scanning/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-alfred-tag-scanning/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-alfred-tag-scanning/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-alfred-trust-validation/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-alfred-trust-validation/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-alfred-trust-validation/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-cc-agents/SKILL.md +0 -269
- moai_adk/templates/.claude/skills/moai-cc-agents/templates/agent-template.md +0 -32
- moai_adk/templates/.claude/skills/moai-cc-claude-md/SKILL.md +0 -298
- moai_adk/templates/.claude/skills/moai-cc-claude-md/templates/CLAUDE-template.md +0 -26
- moai_adk/templates/.claude/skills/moai-cc-commands/SKILL.md +0 -307
- moai_adk/templates/.claude/skills/moai-cc-commands/templates/command-template.md +0 -21
- moai_adk/templates/.claude/skills/moai-cc-hooks/SKILL.md +0 -252
- moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/pre-bash-check.sh +0 -19
- moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/preserve-permissions.sh +0 -19
- moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/validate-bash-command.py +0 -24
- moai_adk/templates/.claude/skills/moai-cc-mcp-plugins/SKILL.md +0 -199
- moai_adk/templates/.claude/skills/moai-cc-mcp-plugins/templates/settings-mcp-template.json +0 -39
- moai_adk/templates/.claude/skills/moai-cc-memory/SKILL.md +0 -316
- moai_adk/templates/.claude/skills/moai-cc-memory/templates/session-summary-template.md +0 -18
- moai_adk/templates/.claude/skills/moai-cc-settings/SKILL.md +0 -263
- moai_adk/templates/.claude/skills/moai-cc-settings/templates/settings-complete-template.json +0 -30
- moai_adk/templates/.claude/skills/moai-cc-skills/SKILL.md +0 -291
- moai_adk/templates/.claude/skills/moai-cc-skills/templates/SKILL-template.md +0 -15
- moai_adk/templates/.claude/skills/moai-domain-cli-tool/SKILL.md +0 -123
- moai_adk/templates/.claude/skills/moai-domain-cli-tool/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-domain-cli-tool/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-domain-data-science/SKILL.md +0 -123
- moai_adk/templates/.claude/skills/moai-domain-data-science/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-domain-data-science/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-domain-devops/SKILL.md +0 -124
- moai_adk/templates/.claude/skills/moai-domain-devops/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-domain-devops/reference.md +0 -31
- moai_adk/templates/.claude/skills/moai-domain-ml/SKILL.md +0 -123
- moai_adk/templates/.claude/skills/moai-domain-ml/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-domain-ml/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-domain-mobile-app/SKILL.md +0 -123
- moai_adk/templates/.claude/skills/moai-domain-mobile-app/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-domain-mobile-app/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-domain-security/SKILL.md +0 -123
- moai_adk/templates/.claude/skills/moai-domain-security/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-domain-security/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-domain-web-api/SKILL.md +0 -123
- moai_adk/templates/.claude/skills/moai-domain-web-api/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-domain-web-api/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-essentials-debug/SKILL.md +0 -303
- moai_adk/templates/.claude/skills/moai-essentials-debug/examples.md +0 -1064
- moai_adk/templates/.claude/skills/moai-essentials-debug/reference.md +0 -1047
- moai_adk/templates/.claude/skills/moai-essentials-perf/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-essentials-perf/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-essentials-perf/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-essentials-refactor/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-essentials-refactor/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-essentials-refactor/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-essentials-review/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-essentials-review/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-essentials-review/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-foundation-ears/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-foundation-ears/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-foundation-ears/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-foundation-git/SKILL.md +0 -122
- moai_adk/templates/.claude/skills/moai-foundation-git/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-foundation-git/reference.md +0 -29
- moai_adk/templates/.claude/skills/moai-foundation-langs/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-foundation-langs/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-foundation-langs/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-foundation-specs/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-foundation-specs/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-foundation-specs/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-foundation-tags/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-foundation-tags/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-foundation-tags/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-foundation-trust/SKILL.md +0 -307
- moai_adk/templates/.claude/skills/moai-foundation-trust/examples.md +0 -0
- moai_adk/templates/.claude/skills/moai-foundation-trust/reference.md +0 -1099
- moai_adk/templates/.claude/skills/moai-lang-c/SKILL.md +0 -124
- moai_adk/templates/.claude/skills/moai-lang-c/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-c/reference.md +0 -31
- moai_adk/templates/.claude/skills/moai-lang-cpp/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-cpp/reference.md +0 -31
- moai_adk/templates/.claude/skills/moai-lang-csharp/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-csharp/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-lang-dart/SKILL.md +0 -123
- moai_adk/templates/.claude/skills/moai-lang-dart/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-dart/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-lang-javascript/SKILL.md +0 -125
- moai_adk/templates/.claude/skills/moai-lang-javascript/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-javascript/reference.md +0 -32
- moai_adk/templates/.claude/skills/moai-lang-php/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-php/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-lang-r/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-r/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-lang-ruby/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-ruby/reference.md +0 -31
- moai_adk/templates/.claude/skills/moai-lang-shell/SKILL.md +0 -123
- moai_adk/templates/.claude/skills/moai-lang-shell/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-shell/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-lang-sql/SKILL.md +0 -124
- moai_adk/templates/.claude/skills/moai-lang-sql/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-sql/reference.md +0 -31
- moai_adk/templates/.claude/skills/moai-skill-factory/CHECKLIST.md +0 -482
- moai_adk/templates/.claude/skills/moai-skill-factory/EXAMPLES.md +0 -278
- moai_adk/templates/.claude/skills/moai-skill-factory/INTERACTIVE-DISCOVERY.md +0 -524
- moai_adk/templates/.claude/skills/moai-skill-factory/METADATA.md +0 -477
- moai_adk/templates/.claude/skills/moai-skill-factory/PARALLEL-ANALYSIS-REPORT.md +0 -429
- moai_adk/templates/.claude/skills/moai-skill-factory/PYTHON-VERSION-MATRIX.md +0 -391
- moai_adk/templates/.claude/skills/moai-skill-factory/SKILL-FACTORY-WORKFLOW.md +0 -431
- moai_adk/templates/.claude/skills/moai-skill-factory/SKILL-UPDATE-ADVISOR.md +0 -577
- moai_adk/templates/.claude/skills/moai-skill-factory/SKILL.md +0 -271
- moai_adk/templates/.claude/skills/moai-skill-factory/STEP-BY-STEP-GUIDE.md +0 -466
- moai_adk/templates/.claude/skills/moai-skill-factory/STRUCTURE.md +0 -583
- moai_adk/templates/.claude/skills/moai-skill-factory/WEB-RESEARCH.md +0 -526
- moai_adk/templates/.claude/skills/moai-skill-factory/reference.md +0 -465
- moai_adk/templates/.claude/skills/moai-skill-factory/scripts/generate-structure.sh +0 -328
- moai_adk/templates/.claude/skills/moai-skill-factory/scripts/validate-skill.sh +0 -312
- moai_adk/templates/.claude/skills/moai-skill-factory/templates/SKILL_TEMPLATE.md +0 -245
- moai_adk/templates/.claude/skills/moai-skill-factory/templates/examples-template.md +0 -285
- moai_adk/templates/.claude/skills/moai-skill-factory/templates/reference-template.md +0 -278
- moai_adk/templates/.claude/skills/moai-skill-factory/templates/scripts-template.sh +0 -303
- moai_adk/templates/.claude/skills/moai-spec-authoring/README.md +0 -137
- moai_adk/templates/.claude/skills/moai-spec-authoring/SKILL.md +0 -218
- moai_adk/templates/.claude/skills/moai-spec-authoring/examples/validate-spec.sh +0 -161
- moai_adk/templates/.claude/skills/moai-spec-authoring/examples.md +0 -541
- moai_adk/templates/.claude/skills/moai-spec-authoring/reference.md +0 -622
- moai_adk/templates/.github/ISSUE_TEMPLATE/spec.yml +0 -176
- moai_adk/templates/.github/PULL_REQUEST_TEMPLATE.md +0 -69
- moai_adk/templates/.github/workflows/moai-gitflow.yml +0 -256
- moai_adk/templates/.moai/config.json +0 -96
- moai_adk/templates/.moai/memory/CLAUDE-AGENTS-GUIDE.md +0 -208
- moai_adk/templates/.moai/memory/CLAUDE-PRACTICES.md +0 -369
- moai_adk/templates/.moai/memory/CLAUDE-RULES.md +0 -539
- moai_adk/templates/.moai/memory/CONFIG-SCHEMA.md +0 -444
- moai_adk/templates/.moai/memory/DEVELOPMENT-GUIDE.md +0 -344
- moai_adk/templates/.moai/memory/GITFLOW-PROTECTION-POLICY.md +0 -220
- moai_adk/templates/.moai/memory/SKILLS-DESCRIPTION-POLICY.md +0 -218
- moai_adk/templates/.moai/memory/SPEC-METADATA.md +0 -356
- moai_adk/templates/.moai/memory/config-schema.md +0 -444
- moai_adk/templates/.moai/memory/gitflow-protection-policy.md +0 -220
- moai_adk/templates/.moai/memory/spec-metadata.md +0 -356
- moai_adk/templates/.moai/project/product.md +0 -161
- moai_adk/templates/.moai/project/structure.md +0 -156
- moai_adk/templates/.moai/project/tech.md +0 -227
- moai_adk/templates/__init__.py +0 -2
- moai_adk-0.8.0.dist-info/METADATA +0 -1722
- moai_adk-0.8.0.dist-info/RECORD +0 -282
- {moai_adk-0.8.0.dist-info ā moai_adk-0.34.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,1371 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Event-Driven Hook System Architecture
|
|
3
|
+
|
|
4
|
+
Phase 3: Enterprise-grade event-driven architecture for hook management with
|
|
5
|
+
message queuing, resource isolation, and asynchronous event processing.
|
|
6
|
+
|
|
7
|
+
Key Features:
|
|
8
|
+
- Event-driven architecture with message queuing
|
|
9
|
+
- Resource isolation between hook types
|
|
10
|
+
- Asynchronous event processing capabilities
|
|
11
|
+
- Scalable message broker integration
|
|
12
|
+
- Event persistence and recovery
|
|
13
|
+
- Hook workflow orchestration
|
|
14
|
+
- Enterprise-grade reliability and performance
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import asyncio
|
|
18
|
+
import json
|
|
19
|
+
import logging
|
|
20
|
+
import time
|
|
21
|
+
import uuid
|
|
22
|
+
from abc import ABC, abstractmethod
|
|
23
|
+
from collections import defaultdict, deque
|
|
24
|
+
from dataclasses import dataclass, field
|
|
25
|
+
from datetime import datetime, timedelta
|
|
26
|
+
from enum import Enum
|
|
27
|
+
from pathlib import Path
|
|
28
|
+
from typing import Any, Callable, Dict, List, Optional, Set
|
|
29
|
+
|
|
30
|
+
# Import existing systems
|
|
31
|
+
from .jit_enhanced_hook_manager import (
|
|
32
|
+
HookEvent,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
logger = logging.getLogger(__name__)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class EventType(Enum):
|
|
39
|
+
"""Event types in the event-driven system"""
|
|
40
|
+
|
|
41
|
+
HOOK_EXECUTION_REQUEST = "hook_execution_request"
|
|
42
|
+
HOOK_EXECUTION_COMPLETED = "hook_execution_completed"
|
|
43
|
+
HOOK_EXECUTION_FAILED = "hook_execution_failed"
|
|
44
|
+
SYSTEM_ALERT = "system_alert"
|
|
45
|
+
RESOURCE_STATUS_CHANGE = "resource_status_change"
|
|
46
|
+
HEALTH_CHECK = "health_check"
|
|
47
|
+
PERFORMANCE_UPDATE = "performance_update"
|
|
48
|
+
BATCH_EXECUTION_REQUEST = "batch_execution_request"
|
|
49
|
+
WORKFLOW_ORCHESTRATION = "workflow_orchestration"
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class EventPriority(Enum):
|
|
53
|
+
"""Event priority levels for message queuing"""
|
|
54
|
+
|
|
55
|
+
CRITICAL = 1 # System-critical events (security, failures)
|
|
56
|
+
HIGH = 2 # High-impact events (performance, alerts)
|
|
57
|
+
NORMAL = 3 # Standard events (hook execution)
|
|
58
|
+
LOW = 4 # Background events (analytics, metrics)
|
|
59
|
+
BULK = 5 # Bulk processing (batch operations)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class ResourceIsolationLevel(Enum):
|
|
63
|
+
"""Resource isolation levels for hook execution"""
|
|
64
|
+
|
|
65
|
+
SHARED = "shared" # Share resources across all hooks
|
|
66
|
+
TYPE_ISOLATED = "type" # Isolate by hook type (event type)
|
|
67
|
+
PRIORITY_ISOLATED = "priority" # Isolate by priority level
|
|
68
|
+
FULL_ISOLATION = "full" # Complete isolation for each hook
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class MessageBrokerType(Enum):
|
|
72
|
+
"""Supported message broker types"""
|
|
73
|
+
|
|
74
|
+
MEMORY = "memory" # In-memory message broker
|
|
75
|
+
REDIS = "redis" # Redis message broker
|
|
76
|
+
RABBITMQ = "rabbitmq" # RabbitMQ message broker
|
|
77
|
+
KAFKA = "kafka" # Apache Kafka
|
|
78
|
+
AWS_SQS = "aws_sqs" # AWS SQS
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@dataclass
|
|
82
|
+
class Event:
|
|
83
|
+
"""Base event class for the event-driven system"""
|
|
84
|
+
|
|
85
|
+
event_id: str
|
|
86
|
+
event_type: EventType
|
|
87
|
+
priority: EventPriority
|
|
88
|
+
timestamp: datetime
|
|
89
|
+
payload: Dict[str, Any]
|
|
90
|
+
source: str = ""
|
|
91
|
+
correlation_id: Optional[str] = None
|
|
92
|
+
causation_id: Optional[str] = None # Event that caused this event
|
|
93
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
94
|
+
retry_count: int = 0
|
|
95
|
+
max_retries: int = 3
|
|
96
|
+
timeout_seconds: float = 60.0
|
|
97
|
+
tags: Dict[str, str] = field(default_factory=dict)
|
|
98
|
+
|
|
99
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
100
|
+
"""Convert event to dictionary for serialization"""
|
|
101
|
+
return {
|
|
102
|
+
"event_id": self.event_id,
|
|
103
|
+
"event_type": self.event_type.value,
|
|
104
|
+
"priority": self.priority.value,
|
|
105
|
+
"timestamp": self.timestamp.isoformat(),
|
|
106
|
+
"payload": self.payload,
|
|
107
|
+
"source": self.source,
|
|
108
|
+
"correlation_id": self.correlation_id,
|
|
109
|
+
"causation_id": self.causation_id,
|
|
110
|
+
"metadata": self.metadata,
|
|
111
|
+
"retry_count": self.retry_count,
|
|
112
|
+
"max_retries": self.max_retries,
|
|
113
|
+
"timeout_seconds": self.timeout_seconds,
|
|
114
|
+
"tags": self.tags,
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
@classmethod
|
|
118
|
+
def from_dict(cls, data: Dict[str, Any]) -> "Event":
|
|
119
|
+
"""Create event from dictionary"""
|
|
120
|
+
return cls(
|
|
121
|
+
event_id=data["event_id"],
|
|
122
|
+
event_type=EventType(data["event_type"]),
|
|
123
|
+
priority=EventPriority(data["priority"]),
|
|
124
|
+
timestamp=datetime.fromisoformat(data["timestamp"]),
|
|
125
|
+
payload=data["payload"],
|
|
126
|
+
source=data.get("source", ""),
|
|
127
|
+
correlation_id=data.get("correlation_id"),
|
|
128
|
+
causation_id=data.get("causation_id"),
|
|
129
|
+
metadata=data.get("metadata", {}),
|
|
130
|
+
retry_count=data.get("retry_count", 0),
|
|
131
|
+
max_retries=data.get("max_retries", 3),
|
|
132
|
+
timeout_seconds=data.get("timeout_seconds", 60.0),
|
|
133
|
+
tags=data.get("tags", {}),
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
@dataclass
|
|
138
|
+
class HookExecutionEvent(Event):
|
|
139
|
+
"""Specialized event for hook execution"""
|
|
140
|
+
|
|
141
|
+
hook_path: str = ""
|
|
142
|
+
hook_event_type: Optional[HookEvent] = None
|
|
143
|
+
execution_context: Dict[str, Any] = field(default_factory=dict)
|
|
144
|
+
isolation_level: ResourceIsolationLevel = ResourceIsolationLevel.SHARED
|
|
145
|
+
|
|
146
|
+
def __post_init__(self) -> None:
|
|
147
|
+
"""Post-initialization setup"""
|
|
148
|
+
if self.event_type == EventType.HOOK_EXECUTION_REQUEST and not self.hook_path:
|
|
149
|
+
raise ValueError("hook_path is required for hook execution requests")
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
@dataclass
|
|
153
|
+
class WorkflowEvent(Event):
|
|
154
|
+
"""Specialized event for workflow orchestration"""
|
|
155
|
+
|
|
156
|
+
workflow_id: str = ""
|
|
157
|
+
step_id: str = ""
|
|
158
|
+
workflow_definition: Dict[str, Any] = field(default_factory=dict)
|
|
159
|
+
execution_state: Dict[str, Any] = field(default_factory=dict)
|
|
160
|
+
|
|
161
|
+
def __post_init__(self) -> None:
|
|
162
|
+
"""Post-initialization setup"""
|
|
163
|
+
if self.event_type == EventType.WORKFLOW_ORCHESTRATION and not self.workflow_id:
|
|
164
|
+
raise ValueError("workflow_id is required for workflow events")
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
class MessageBroker(ABC):
|
|
168
|
+
"""Abstract base class for message brokers"""
|
|
169
|
+
|
|
170
|
+
@abstractmethod
|
|
171
|
+
async def publish(self, topic: str, event: Event) -> bool:
|
|
172
|
+
"""Publish event to topic"""
|
|
173
|
+
pass
|
|
174
|
+
|
|
175
|
+
@abstractmethod
|
|
176
|
+
async def subscribe(self, topic: str, callback: Callable[[Event], None]) -> str:
|
|
177
|
+
"""Subscribe to topic with callback"""
|
|
178
|
+
pass
|
|
179
|
+
|
|
180
|
+
@abstractmethod
|
|
181
|
+
async def unsubscribe(self, subscription_id: str) -> bool:
|
|
182
|
+
"""Unsubscribe from topic"""
|
|
183
|
+
pass
|
|
184
|
+
|
|
185
|
+
@abstractmethod
|
|
186
|
+
async def create_queue(self, queue_name: str, config: Dict[str, Any]) -> bool:
|
|
187
|
+
"""Create message queue with configuration"""
|
|
188
|
+
pass
|
|
189
|
+
|
|
190
|
+
@abstractmethod
|
|
191
|
+
async def delete_queue(self, queue_name: str) -> bool:
|
|
192
|
+
"""Delete message queue"""
|
|
193
|
+
pass
|
|
194
|
+
|
|
195
|
+
@abstractmethod
|
|
196
|
+
def get_stats(self) -> Dict[str, Any]:
|
|
197
|
+
"""Get message broker statistics"""
|
|
198
|
+
pass
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
class InMemoryMessageBroker(MessageBroker):
|
|
202
|
+
"""In-memory message broker for development and testing"""
|
|
203
|
+
|
|
204
|
+
def __init__(self, max_queue_size: int = 10000):
|
|
205
|
+
self.max_queue_size = max_queue_size
|
|
206
|
+
self.queues: Dict[str, deque] = defaultdict(lambda: deque(maxlen=max_queue_size))
|
|
207
|
+
self.subscribers: Dict[str, List[tuple[str, Callable[[Event], None]]]] = defaultdict(list)
|
|
208
|
+
self._lock = asyncio.Lock()
|
|
209
|
+
self._stats = {
|
|
210
|
+
"messages_published": 0,
|
|
211
|
+
"messages_delivered": 0,
|
|
212
|
+
"queues_created": 0,
|
|
213
|
+
"active_subscriptions": 0,
|
|
214
|
+
"failed_publishes": 0,
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
async def publish(self, topic: str, event: Event) -> bool:
|
|
218
|
+
"""Publish event to topic"""
|
|
219
|
+
try:
|
|
220
|
+
async with self._lock:
|
|
221
|
+
if len(self.queues[topic]) >= self.max_queue_size:
|
|
222
|
+
# Remove oldest message if queue is full
|
|
223
|
+
self.queues[topic].popleft()
|
|
224
|
+
|
|
225
|
+
self.queues[topic].append(event)
|
|
226
|
+
self._stats["messages_published"] += 1
|
|
227
|
+
|
|
228
|
+
# Notify subscribers
|
|
229
|
+
for sub_id, callback in self.subscribers[topic]:
|
|
230
|
+
try:
|
|
231
|
+
# Create task for async callback
|
|
232
|
+
asyncio.create_task(self._safe_callback(callback, event))
|
|
233
|
+
self._stats["messages_delivered"] += 1
|
|
234
|
+
except Exception as e:
|
|
235
|
+
logger.error(f"Error in subscriber callback: {e}")
|
|
236
|
+
|
|
237
|
+
return True
|
|
238
|
+
except Exception as e:
|
|
239
|
+
logger.error(f"Error publishing event to {topic}: {e}")
|
|
240
|
+
self._stats["failed_publishes"] += 1
|
|
241
|
+
return False
|
|
242
|
+
|
|
243
|
+
async def _safe_callback(self, callback: Callable[[Event], None], event: Event) -> None:
|
|
244
|
+
"""Safely execute callback with error handling"""
|
|
245
|
+
try:
|
|
246
|
+
if asyncio.iscoroutinefunction(callback):
|
|
247
|
+
result = callback(event) # type: ignore[func-returns-value]
|
|
248
|
+
if result is not None:
|
|
249
|
+
await result
|
|
250
|
+
else:
|
|
251
|
+
callback(event)
|
|
252
|
+
except Exception as e:
|
|
253
|
+
logger.error(f"Error in event callback: {e}")
|
|
254
|
+
|
|
255
|
+
async def subscribe(self, topic: str, callback: Callable[[Event], None]) -> str:
|
|
256
|
+
"""Subscribe to topic with callback"""
|
|
257
|
+
subscription_id = str(uuid.uuid4())
|
|
258
|
+
async with self._lock:
|
|
259
|
+
self.subscribers[topic].append((subscription_id, callback))
|
|
260
|
+
self._stats["active_subscriptions"] += 1
|
|
261
|
+
return subscription_id
|
|
262
|
+
|
|
263
|
+
async def unsubscribe(self, subscription_id: str) -> bool:
|
|
264
|
+
"""Unsubscribe from topic"""
|
|
265
|
+
async with self._lock:
|
|
266
|
+
for topic in list(self.subscribers.keys()):
|
|
267
|
+
subscribers = self.subscribers[topic]
|
|
268
|
+
original_len = len(subscribers)
|
|
269
|
+
self.subscribers[topic] = [
|
|
270
|
+
(sub_id, callback) for sub_id, callback in subscribers if sub_id != subscription_id
|
|
271
|
+
]
|
|
272
|
+
if len(self.subscribers[topic]) < original_len:
|
|
273
|
+
self._stats["active_subscriptions"] -= 1
|
|
274
|
+
return True
|
|
275
|
+
return False
|
|
276
|
+
|
|
277
|
+
async def create_queue(self, queue_name: str, config: Dict[str, Any]) -> bool:
|
|
278
|
+
"""Create message queue with configuration"""
|
|
279
|
+
async with self._lock:
|
|
280
|
+
# Queue is created automatically on first use
|
|
281
|
+
self.queues[queue_name] = deque(maxlen=config.get("max_size", self.max_queue_size))
|
|
282
|
+
self._stats["queues_created"] += 1
|
|
283
|
+
return True
|
|
284
|
+
|
|
285
|
+
async def delete_queue(self, queue_name: str) -> bool:
|
|
286
|
+
"""Delete message queue"""
|
|
287
|
+
async with self._lock:
|
|
288
|
+
if queue_name in self.queues:
|
|
289
|
+
del self.queues[queue_name]
|
|
290
|
+
if queue_name in self.subscribers:
|
|
291
|
+
del self.subscribers[queue_name]
|
|
292
|
+
return True
|
|
293
|
+
|
|
294
|
+
def get_stats(self) -> Dict[str, Any]:
|
|
295
|
+
"""Get message broker statistics"""
|
|
296
|
+
return {
|
|
297
|
+
**self._stats,
|
|
298
|
+
"queue_count": len(self.queues),
|
|
299
|
+
"total_queued_messages": sum(len(queue) for queue in self.queues.values()),
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
class RedisMessageBroker(MessageBroker):
|
|
304
|
+
"""Redis-based message broker for production use"""
|
|
305
|
+
|
|
306
|
+
def __init__(self, redis_url: str = "redis://localhost:6379/0"):
|
|
307
|
+
self.redis_url = redis_url
|
|
308
|
+
self._redis = None
|
|
309
|
+
self._pubsub = None
|
|
310
|
+
self._subscribers: Dict[str, List[tuple[str, Callable[[Event], None]]]] = defaultdict(list)
|
|
311
|
+
self._stats = {
|
|
312
|
+
"messages_published": 0,
|
|
313
|
+
"messages_delivered": 0,
|
|
314
|
+
"queues_created": 0,
|
|
315
|
+
"active_subscriptions": 0,
|
|
316
|
+
"failed_publishes": 0,
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
async def _connect(self) -> None:
|
|
320
|
+
"""Connect to Redis"""
|
|
321
|
+
if self._redis is None:
|
|
322
|
+
try:
|
|
323
|
+
import redis.asyncio as redis_module
|
|
324
|
+
|
|
325
|
+
redis_client = redis_module.from_url(self.redis_url)
|
|
326
|
+
self._redis = redis_client
|
|
327
|
+
self._pubsub = redis_client.pubsub() # type: ignore[union-attr]
|
|
328
|
+
except ImportError:
|
|
329
|
+
raise ImportError("redis package is required for RedisMessageBroker")
|
|
330
|
+
except Exception as e:
|
|
331
|
+
raise ConnectionError(f"Failed to connect to Redis: {e}")
|
|
332
|
+
|
|
333
|
+
async def publish(self, topic: str, event: Event) -> bool:
|
|
334
|
+
"""Publish event to Redis topic"""
|
|
335
|
+
try:
|
|
336
|
+
await self._connect()
|
|
337
|
+
if self._redis is None:
|
|
338
|
+
raise ConnectionError("Redis connection not established")
|
|
339
|
+
message = json.dumps(event.to_dict())
|
|
340
|
+
await self._redis.publish(topic, message)
|
|
341
|
+
self._stats["messages_published"] += 1
|
|
342
|
+
return True
|
|
343
|
+
except Exception as e:
|
|
344
|
+
logger.error(f"Error publishing event to Redis topic {topic}: {e}")
|
|
345
|
+
self._stats["failed_publishes"] += 1
|
|
346
|
+
return False
|
|
347
|
+
|
|
348
|
+
async def subscribe(self, topic: str, callback: Callable[[Event], None]) -> str:
|
|
349
|
+
"""Subscribe to Redis topic"""
|
|
350
|
+
try:
|
|
351
|
+
await self._connect()
|
|
352
|
+
if self._pubsub is None:
|
|
353
|
+
raise ConnectionError("Redis pubsub not established")
|
|
354
|
+
subscription_id = str(uuid.uuid4())
|
|
355
|
+
|
|
356
|
+
# Add to local subscribers
|
|
357
|
+
self._subscribers[topic].append((subscription_id, callback))
|
|
358
|
+
|
|
359
|
+
# Subscribe to Redis pubsub
|
|
360
|
+
await self._pubsub.subscribe(topic)
|
|
361
|
+
|
|
362
|
+
# Start listener task
|
|
363
|
+
asyncio.create_task(self._listen_to_topic(topic))
|
|
364
|
+
|
|
365
|
+
self._stats["active_subscriptions"] += 1
|
|
366
|
+
return subscription_id
|
|
367
|
+
except Exception as e:
|
|
368
|
+
logger.error(f"Error subscribing to Redis topic {topic}: {e}")
|
|
369
|
+
return ""
|
|
370
|
+
|
|
371
|
+
async def _listen_to_topic(self, topic: str) -> None:
|
|
372
|
+
"""Listen to Redis topic and call callbacks"""
|
|
373
|
+
if self._pubsub is None:
|
|
374
|
+
return
|
|
375
|
+
try:
|
|
376
|
+
async for message in self._pubsub.listen():
|
|
377
|
+
if message["type"] == "message":
|
|
378
|
+
try:
|
|
379
|
+
event_data = json.loads(message["data"])
|
|
380
|
+
event = Event.from_dict(event_data)
|
|
381
|
+
|
|
382
|
+
# Call all subscribers for this topic
|
|
383
|
+
for subscription_id, callback in self._subscribers[topic]:
|
|
384
|
+
try:
|
|
385
|
+
if asyncio.iscoroutinefunction(callback):
|
|
386
|
+
await callback(event)
|
|
387
|
+
else:
|
|
388
|
+
callback(event)
|
|
389
|
+
self._stats["messages_delivered"] += 1
|
|
390
|
+
except Exception as e:
|
|
391
|
+
logger.error(f"Error in subscriber callback: {e}")
|
|
392
|
+
except Exception as e:
|
|
393
|
+
logger.error(f"Error processing Redis message: {e}")
|
|
394
|
+
except Exception as e:
|
|
395
|
+
logger.error(f"Error in Redis listener for topic {topic}: {e}")
|
|
396
|
+
|
|
397
|
+
async def unsubscribe(self, subscription_id: str) -> bool:
|
|
398
|
+
"""Unsubscribe from Redis topic"""
|
|
399
|
+
try:
|
|
400
|
+
# Remove from local subscribers
|
|
401
|
+
for topic, subscribers in self._subscribers.items():
|
|
402
|
+
self._subscribers[topic] = [
|
|
403
|
+
(sub_id, callback) for sub_id, callback in subscribers if sub_id != subscription_id
|
|
404
|
+
]
|
|
405
|
+
|
|
406
|
+
self._stats["active_subscriptions"] -= 1
|
|
407
|
+
return True
|
|
408
|
+
except Exception as e:
|
|
409
|
+
logger.error(f"Error unsubscribing from Redis: {e}")
|
|
410
|
+
return False
|
|
411
|
+
|
|
412
|
+
async def create_queue(self, queue_name: str, config: Dict[str, Any]) -> bool:
|
|
413
|
+
"""Create Redis queue"""
|
|
414
|
+
try:
|
|
415
|
+
await self._connect()
|
|
416
|
+
# Use Redis list as queue
|
|
417
|
+
self._stats["queues_created"] += 1
|
|
418
|
+
return True
|
|
419
|
+
except Exception as e:
|
|
420
|
+
logger.error(f"Error creating Redis queue {queue_name}: {e}")
|
|
421
|
+
return False
|
|
422
|
+
|
|
423
|
+
async def delete_queue(self, queue_name: str) -> bool:
|
|
424
|
+
"""Delete Redis queue"""
|
|
425
|
+
try:
|
|
426
|
+
await self._connect()
|
|
427
|
+
if self._redis is None:
|
|
428
|
+
raise ConnectionError("Redis connection not established")
|
|
429
|
+
await self._redis.delete(queue_name)
|
|
430
|
+
return True
|
|
431
|
+
except Exception as e:
|
|
432
|
+
logger.error(f"Error deleting Redis queue {queue_name}: {e}")
|
|
433
|
+
return False
|
|
434
|
+
|
|
435
|
+
def get_stats(self) -> Dict[str, Any]:
|
|
436
|
+
"""Get Redis message broker statistics"""
|
|
437
|
+
return self._stats
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
class ResourcePool:
|
|
441
|
+
"""Resource pool for hook execution with isolation"""
|
|
442
|
+
|
|
443
|
+
def __init__(self, isolation_level: ResourceIsolationLevel, max_concurrent: int = 10):
|
|
444
|
+
self.isolation_level = isolation_level
|
|
445
|
+
self.max_concurrent = max_concurrent
|
|
446
|
+
self._pools: Dict[str, asyncio.Semaphore] = {}
|
|
447
|
+
self._active_executions: Dict[str, Set[str]] = defaultdict(set)
|
|
448
|
+
self._lock = asyncio.Lock()
|
|
449
|
+
self._stats: Dict[str, Any] = {
|
|
450
|
+
"total_executions": 0,
|
|
451
|
+
"active_executions": 0,
|
|
452
|
+
"pool_utilization": {},
|
|
453
|
+
"isolation_violations": 0,
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
async def get_semaphore(self, hook_path: str, event_type: HookEvent) -> asyncio.Semaphore:
|
|
457
|
+
"""Get semaphore for hook based on isolation level"""
|
|
458
|
+
pool_key = self._get_pool_key(hook_path, event_type)
|
|
459
|
+
|
|
460
|
+
async with self._lock:
|
|
461
|
+
if pool_key not in self._pools:
|
|
462
|
+
self._pools[pool_key] = asyncio.Semaphore(self.max_concurrent)
|
|
463
|
+
return self._pools[pool_key]
|
|
464
|
+
|
|
465
|
+
def _get_pool_key(self, hook_path: str, event_type: HookEvent) -> str:
|
|
466
|
+
"""Generate pool key based on isolation level"""
|
|
467
|
+
if self.isolation_level == ResourceIsolationLevel.SHARED:
|
|
468
|
+
return "shared"
|
|
469
|
+
elif self.isolation_level == ResourceIsolationLevel.TYPE_ISOLATED:
|
|
470
|
+
return event_type.value
|
|
471
|
+
elif self.isolation_level == ResourceIsolationLevel.PRIORITY_ISOLATED:
|
|
472
|
+
# Extract priority from hook path or use default
|
|
473
|
+
if "security" in hook_path or "validation" in hook_path:
|
|
474
|
+
return "critical"
|
|
475
|
+
elif "performance" in hook_path:
|
|
476
|
+
return "high"
|
|
477
|
+
else:
|
|
478
|
+
return "normal"
|
|
479
|
+
elif self.isolation_level == ResourceIsolationLevel.FULL_ISOLATION:
|
|
480
|
+
return hook_path
|
|
481
|
+
else:
|
|
482
|
+
return "shared"
|
|
483
|
+
|
|
484
|
+
async def acquire_execution_slot(self, hook_path: str, event_type: HookEvent) -> bool:
|
|
485
|
+
"""Acquire execution slot in appropriate pool"""
|
|
486
|
+
pool_key = self._get_pool_key(hook_path, event_type)
|
|
487
|
+
semaphore = await self.get_semaphore(hook_path, event_type)
|
|
488
|
+
|
|
489
|
+
try:
|
|
490
|
+
await semaphore.acquire()
|
|
491
|
+
async with self._lock:
|
|
492
|
+
self._active_executions[pool_key].add(hook_path)
|
|
493
|
+
self._stats["active_executions"] += 1
|
|
494
|
+
self._stats["total_executions"] += 1
|
|
495
|
+
|
|
496
|
+
# Update pool utilization
|
|
497
|
+
available = semaphore._value
|
|
498
|
+
total = self.max_concurrent
|
|
499
|
+
utilization = ((total - available) / total) * 100
|
|
500
|
+
self._stats["pool_utilization"][pool_key] = utilization
|
|
501
|
+
|
|
502
|
+
return True
|
|
503
|
+
except Exception as e:
|
|
504
|
+
logger.error(f"Error acquiring execution slot for {hook_path}: {e}")
|
|
505
|
+
return False
|
|
506
|
+
|
|
507
|
+
async def release_execution_slot(self, hook_path: str, event_type: HookEvent) -> None:
|
|
508
|
+
"""Release execution slot"""
|
|
509
|
+
pool_key = self._get_pool_key(hook_path, event_type)
|
|
510
|
+
semaphore = await self.get_semaphore(hook_path, event_type)
|
|
511
|
+
|
|
512
|
+
async with self._lock:
|
|
513
|
+
self._active_executions[pool_key].discard(hook_path)
|
|
514
|
+
self._stats["active_executions"] = max(0, self._stats["active_executions"] - 1)
|
|
515
|
+
|
|
516
|
+
# Update pool utilization
|
|
517
|
+
available = semaphore._value
|
|
518
|
+
total = self.max_concurrent
|
|
519
|
+
utilization = ((total - available) / total) * 100
|
|
520
|
+
self._stats["pool_utilization"][pool_key] = utilization
|
|
521
|
+
|
|
522
|
+
semaphore.release()
|
|
523
|
+
|
|
524
|
+
def get_stats(self) -> Dict[str, Any]:
|
|
525
|
+
"""Get resource pool statistics"""
|
|
526
|
+
|
|
527
|
+
async def get_async_stats():
|
|
528
|
+
async with self._lock:
|
|
529
|
+
return {
|
|
530
|
+
**self._stats,
|
|
531
|
+
"pool_count": len(self._pools),
|
|
532
|
+
"active_pools": [
|
|
533
|
+
{
|
|
534
|
+
"pool_key": key,
|
|
535
|
+
"active_executions": len(executions),
|
|
536
|
+
"executions": list(executions),
|
|
537
|
+
}
|
|
538
|
+
for key, executions in self._active_executions.items()
|
|
539
|
+
],
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
# Return synchronous version for compatibility
|
|
543
|
+
try:
|
|
544
|
+
loop = asyncio.get_event_loop()
|
|
545
|
+
if loop.is_running():
|
|
546
|
+
return self._stats
|
|
547
|
+
else:
|
|
548
|
+
return loop.run_until_complete(get_async_stats())
|
|
549
|
+
except Exception:
|
|
550
|
+
return self._stats
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
class EventProcessor:
|
|
554
|
+
"""Event processor for handling hook execution events"""
|
|
555
|
+
|
|
556
|
+
def __init__(self, resource_pool: ResourcePool):
|
|
557
|
+
self.resource_pool = resource_pool
|
|
558
|
+
self._handlers: Dict[EventType, List[Callable]] = defaultdict(list)
|
|
559
|
+
self._processing_stats: Dict[str, Any] = {
|
|
560
|
+
"events_processed": 0,
|
|
561
|
+
"events_failed": 0,
|
|
562
|
+
"average_processing_time_ms": 0.0,
|
|
563
|
+
"by_event_type": defaultdict(int),
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
def register_handler(self, event_type: EventType, handler: Callable) -> None:
|
|
567
|
+
"""Register event handler for event type"""
|
|
568
|
+
self._handlers[event_type].append(handler)
|
|
569
|
+
|
|
570
|
+
async def process_event(self, event: Event) -> bool:
|
|
571
|
+
"""Process event with appropriate handlers"""
|
|
572
|
+
start_time = time.time()
|
|
573
|
+
success = False
|
|
574
|
+
|
|
575
|
+
try:
|
|
576
|
+
handlers = self._handlers.get(event.event_type, [])
|
|
577
|
+
if not handlers:
|
|
578
|
+
logger.warning(f"No handlers registered for event type: {event.event_type}")
|
|
579
|
+
return True
|
|
580
|
+
|
|
581
|
+
# Process event with all registered handlers
|
|
582
|
+
for handler in handlers:
|
|
583
|
+
try:
|
|
584
|
+
if asyncio.iscoroutinefunction(handler):
|
|
585
|
+
await handler(event)
|
|
586
|
+
else:
|
|
587
|
+
handler(event)
|
|
588
|
+
success = True
|
|
589
|
+
except Exception as e:
|
|
590
|
+
logger.error(f"Error in event handler for {event.event_type}: {e}")
|
|
591
|
+
success = False
|
|
592
|
+
|
|
593
|
+
# Update statistics
|
|
594
|
+
processing_time_ms = (time.time() - start_time) * 1000
|
|
595
|
+
self._update_stats(event.event_type, processing_time_ms, success)
|
|
596
|
+
|
|
597
|
+
return success
|
|
598
|
+
|
|
599
|
+
except Exception as e:
|
|
600
|
+
logger.error(f"Error processing event {event.event_id}: {e}")
|
|
601
|
+
processing_time_ms = (time.time() - start_time) * 1000
|
|
602
|
+
self._update_stats(event.event_type, processing_time_ms, False)
|
|
603
|
+
return False
|
|
604
|
+
|
|
605
|
+
def _update_stats(self, event_type: EventType, processing_time_ms: float, success: bool) -> None:
|
|
606
|
+
"""Update processing statistics"""
|
|
607
|
+
events_processed: int = self._processing_stats["events_processed"]
|
|
608
|
+
events_processed += 1
|
|
609
|
+
self._processing_stats["events_processed"] = events_processed
|
|
610
|
+
by_event_type: Dict[str, int] = self._processing_stats["by_event_type"]
|
|
611
|
+
by_event_type[event_type.value] = by_event_type.get(event_type.value, 0) + 1
|
|
612
|
+
|
|
613
|
+
if not success:
|
|
614
|
+
events_failed: int = self._processing_stats["events_failed"]
|
|
615
|
+
self._processing_stats["events_failed"] = events_failed + 1
|
|
616
|
+
|
|
617
|
+
# Update average processing time
|
|
618
|
+
total_events = events_processed
|
|
619
|
+
current_avg: float = self._processing_stats["average_processing_time_ms"]
|
|
620
|
+
self._processing_stats["average_processing_time_ms"] = (
|
|
621
|
+
current_avg * (total_events - 1) + processing_time_ms
|
|
622
|
+
) / total_events
|
|
623
|
+
|
|
624
|
+
def get_stats(self) -> Dict[str, Any]:
|
|
625
|
+
"""Get event processing statistics"""
|
|
626
|
+
events_processed: int = self._processing_stats["events_processed"]
|
|
627
|
+
events_failed: int = self._processing_stats["events_failed"]
|
|
628
|
+
return {
|
|
629
|
+
**self._processing_stats,
|
|
630
|
+
"success_rate": ((events_processed - events_failed) / max(events_processed, 1)) * 100,
|
|
631
|
+
"handlers_registered": {event_type.value: len(handlers) for event_type, handlers in self._handlers.items()},
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
|
|
635
|
+
class EventDrivenHookSystem:
|
|
636
|
+
"""
|
|
637
|
+
Event-Driven Hook System Architecture
|
|
638
|
+
|
|
639
|
+
Enterprise-grade event-driven system for hook management with message queuing,
|
|
640
|
+
resource isolation, and asynchronous event processing capabilities.
|
|
641
|
+
"""
|
|
642
|
+
|
|
643
|
+
def __init__(
|
|
644
|
+
self,
|
|
645
|
+
message_broker_type: MessageBrokerType = MessageBrokerType.MEMORY,
|
|
646
|
+
isolation_level: ResourceIsolationLevel = ResourceIsolationLevel.TYPE_ISOLATED,
|
|
647
|
+
max_concurrent_hooks: int = 10,
|
|
648
|
+
enable_persistence: bool = True,
|
|
649
|
+
persistence_path: Optional[Path] = None,
|
|
650
|
+
redis_url: str = "redis://localhost:6379/0",
|
|
651
|
+
):
|
|
652
|
+
"""Initialize Event-Driven Hook System
|
|
653
|
+
|
|
654
|
+
Args:
|
|
655
|
+
message_broker_type: Type of message broker to use
|
|
656
|
+
isolation_level: Resource isolation level for hook execution
|
|
657
|
+
max_concurrent_hooks: Maximum concurrent hook executions per pool
|
|
658
|
+
enable_persistence: Enable event persistence for recovery
|
|
659
|
+
persistence_path: Path for event persistence storage
|
|
660
|
+
redis_url: Redis URL for Redis message broker
|
|
661
|
+
"""
|
|
662
|
+
self.message_broker_type = message_broker_type
|
|
663
|
+
self.isolation_level = isolation_level
|
|
664
|
+
self.max_concurrent_hooks = max_concurrent_hooks
|
|
665
|
+
self.enable_persistence = enable_persistence
|
|
666
|
+
self.persistence_path = persistence_path or Path.cwd() / ".moai" / "cache" / "event_system"
|
|
667
|
+
self.redis_url = redis_url
|
|
668
|
+
|
|
669
|
+
# Initialize message broker
|
|
670
|
+
self.message_broker = self._create_message_broker()
|
|
671
|
+
|
|
672
|
+
# Initialize resource pool
|
|
673
|
+
self.resource_pool = ResourcePool(isolation_level, max_concurrent_hooks)
|
|
674
|
+
|
|
675
|
+
# Initialize event processor
|
|
676
|
+
self.event_processor = EventProcessor(self.resource_pool)
|
|
677
|
+
|
|
678
|
+
# System state
|
|
679
|
+
self._running = False
|
|
680
|
+
self._startup_time = datetime.now()
|
|
681
|
+
self._event_loops: List[asyncio.Task] = []
|
|
682
|
+
|
|
683
|
+
# Event persistence
|
|
684
|
+
self._pending_events: Dict[str, Event] = {}
|
|
685
|
+
self._processed_events: Set[str] = set()
|
|
686
|
+
|
|
687
|
+
# System metrics
|
|
688
|
+
self._system_metrics = {
|
|
689
|
+
"events_published": 0,
|
|
690
|
+
"events_processed": 0,
|
|
691
|
+
"events_failed": 0,
|
|
692
|
+
"hook_executions": 0,
|
|
693
|
+
"system_uptime_seconds": 0,
|
|
694
|
+
"average_event_latency_ms": 0.0,
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
# Setup persistence directory
|
|
698
|
+
if self.enable_persistence:
|
|
699
|
+
self.persistence_path.mkdir(parents=True, exist_ok=True)
|
|
700
|
+
|
|
701
|
+
def _create_message_broker(self) -> MessageBroker:
|
|
702
|
+
"""Create message broker based on type"""
|
|
703
|
+
if self.message_broker_type == MessageBrokerType.MEMORY:
|
|
704
|
+
return InMemoryMessageBroker()
|
|
705
|
+
elif self.message_broker_type == MessageBrokerType.REDIS:
|
|
706
|
+
return RedisMessageBroker(self.redis_url)
|
|
707
|
+
else:
|
|
708
|
+
logger.warning(f"Message broker {self.message_broker_type} not implemented, using in-memory")
|
|
709
|
+
return InMemoryMessageBroker()
|
|
710
|
+
|
|
711
|
+
async def start(self) -> None:
|
|
712
|
+
"""Start the event-driven hook system"""
|
|
713
|
+
if self._running:
|
|
714
|
+
return
|
|
715
|
+
|
|
716
|
+
logger.info("Starting Event-Driven Hook System...")
|
|
717
|
+
|
|
718
|
+
try:
|
|
719
|
+
# Load persisted events if enabled
|
|
720
|
+
if self.enable_persistence:
|
|
721
|
+
await self._load_persisted_events()
|
|
722
|
+
|
|
723
|
+
# Register event handlers
|
|
724
|
+
self._register_event_handlers()
|
|
725
|
+
|
|
726
|
+
# Create message queues for different event types
|
|
727
|
+
await self._setup_message_queues()
|
|
728
|
+
|
|
729
|
+
# Start event processing loops
|
|
730
|
+
await self._start_event_loops()
|
|
731
|
+
|
|
732
|
+
self._running = True
|
|
733
|
+
logger.info("Event-Driven Hook System started successfully")
|
|
734
|
+
|
|
735
|
+
except Exception as e:
|
|
736
|
+
logger.error(f"Error starting Event-Driven Hook System: {e}")
|
|
737
|
+
raise
|
|
738
|
+
|
|
739
|
+
async def stop(self) -> None:
|
|
740
|
+
"""Stop the event-driven hook system"""
|
|
741
|
+
if not self._running:
|
|
742
|
+
return
|
|
743
|
+
|
|
744
|
+
logger.info("Stopping Event-Driven Hook System...")
|
|
745
|
+
|
|
746
|
+
try:
|
|
747
|
+
# Cancel event loops
|
|
748
|
+
for loop_task in self._event_loops:
|
|
749
|
+
loop_task.cancel()
|
|
750
|
+
|
|
751
|
+
# Wait for loops to finish
|
|
752
|
+
if self._event_loops:
|
|
753
|
+
await asyncio.gather(*self._event_loops, return_exceptions=True)
|
|
754
|
+
|
|
755
|
+
# Persist pending events if enabled
|
|
756
|
+
if self.enable_persistence:
|
|
757
|
+
await self._persist_events()
|
|
758
|
+
|
|
759
|
+
self._running = False
|
|
760
|
+
logger.info("Event-Driven Hook System stopped")
|
|
761
|
+
|
|
762
|
+
except Exception as e:
|
|
763
|
+
logger.error(f"Error stopping Event-Driven Hook System: {e}")
|
|
764
|
+
|
|
765
|
+
def _register_event_handlers(self) -> None:
|
|
766
|
+
"""Register event handlers for different event types"""
|
|
767
|
+
# Hook execution request handler
|
|
768
|
+
self.event_processor.register_handler(EventType.HOOK_EXECUTION_REQUEST, self._handle_hook_execution_request)
|
|
769
|
+
|
|
770
|
+
# Hook execution completion handler
|
|
771
|
+
self.event_processor.register_handler(EventType.HOOK_EXECUTION_COMPLETED, self._handle_hook_execution_completed)
|
|
772
|
+
|
|
773
|
+
# Hook execution failure handler
|
|
774
|
+
self.event_processor.register_handler(EventType.HOOK_EXECUTION_FAILED, self._handle_hook_execution_failed)
|
|
775
|
+
|
|
776
|
+
# System alert handler
|
|
777
|
+
self.event_processor.register_handler(EventType.SYSTEM_ALERT, self._handle_system_alert)
|
|
778
|
+
|
|
779
|
+
# Health check handler
|
|
780
|
+
self.event_processor.register_handler(EventType.HEALTH_CHECK, self._handle_health_check)
|
|
781
|
+
|
|
782
|
+
# Batch execution handler
|
|
783
|
+
self.event_processor.register_handler(EventType.BATCH_EXECUTION_REQUEST, self._handle_batch_execution_request)
|
|
784
|
+
|
|
785
|
+
# Workflow orchestration handler
|
|
786
|
+
self.event_processor.register_handler(EventType.WORKFLOW_ORCHESTRATION, self._handle_workflow_orchestration)
|
|
787
|
+
|
|
788
|
+
async def _setup_message_queues(self) -> None:
|
|
789
|
+
"""Setup message queues for different event types"""
|
|
790
|
+
queue_configs = {
|
|
791
|
+
"hook_execution_high": {
|
|
792
|
+
"max_size": 1000,
|
|
793
|
+
"priority": EventPriority.HIGH.value,
|
|
794
|
+
},
|
|
795
|
+
"hook_execution_normal": {
|
|
796
|
+
"max_size": 5000,
|
|
797
|
+
"priority": EventPriority.NORMAL.value,
|
|
798
|
+
},
|
|
799
|
+
"hook_execution_low": {
|
|
800
|
+
"max_size": 10000,
|
|
801
|
+
"priority": EventPriority.LOW.value,
|
|
802
|
+
},
|
|
803
|
+
"system_events": {
|
|
804
|
+
"max_size": 1000,
|
|
805
|
+
"priority": EventPriority.CRITICAL.value,
|
|
806
|
+
},
|
|
807
|
+
"analytics": {"max_size": 20000, "priority": EventPriority.BULK.value},
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
for queue_name, config in queue_configs.items():
|
|
811
|
+
await self.message_broker.create_queue(queue_name, config)
|
|
812
|
+
|
|
813
|
+
async def _start_event_loops(self) -> None:
|
|
814
|
+
"""Start event processing loops"""
|
|
815
|
+
# Start main event processing loop
|
|
816
|
+
event_loop = asyncio.create_task(self._event_processing_loop())
|
|
817
|
+
self._event_loops.append(event_loop)
|
|
818
|
+
|
|
819
|
+
# Start metrics collection loop
|
|
820
|
+
metrics_loop = asyncio.create_task(self._metrics_collection_loop())
|
|
821
|
+
self._event_loops.append(metrics_loop)
|
|
822
|
+
|
|
823
|
+
# Start cleanup loop
|
|
824
|
+
cleanup_loop = asyncio.create_task(self._cleanup_loop())
|
|
825
|
+
self._event_loops.append(cleanup_loop)
|
|
826
|
+
|
|
827
|
+
# Start persistence loop if enabled
|
|
828
|
+
if self.enable_persistence:
|
|
829
|
+
persistence_loop = asyncio.create_task(self._persistence_loop())
|
|
830
|
+
self._event_loops.append(persistence_loop)
|
|
831
|
+
|
|
832
|
+
async def _event_processing_loop(self) -> None:
|
|
833
|
+
"""Main event processing loop"""
|
|
834
|
+
logger.info("Starting event processing loop")
|
|
835
|
+
|
|
836
|
+
while self._running:
|
|
837
|
+
try:
|
|
838
|
+
# Process events from different queues based on priority
|
|
839
|
+
await self._process_events_by_priority()
|
|
840
|
+
await asyncio.sleep(0.1) # Prevent busy waiting
|
|
841
|
+
except Exception as e:
|
|
842
|
+
logger.error(f"Error in event processing loop: {e}")
|
|
843
|
+
await asyncio.sleep(1)
|
|
844
|
+
|
|
845
|
+
async def _process_events_by_priority(self) -> None:
|
|
846
|
+
"""Process events by priority order"""
|
|
847
|
+
# Process critical system events first
|
|
848
|
+
await self._process_queue_events("system_events", EventPriority.CRITICAL)
|
|
849
|
+
|
|
850
|
+
# Then process high priority hook executions
|
|
851
|
+
await self._process_queue_events("hook_execution_high", EventPriority.HIGH)
|
|
852
|
+
|
|
853
|
+
# Then normal priority
|
|
854
|
+
await self._process_queue_events("hook_execution_normal", EventPriority.NORMAL)
|
|
855
|
+
|
|
856
|
+
# Then low priority
|
|
857
|
+
await self._process_queue_events("hook_execution_low", EventPriority.LOW)
|
|
858
|
+
|
|
859
|
+
# Finally bulk analytics events
|
|
860
|
+
await self._process_queue_events("analytics", EventPriority.BULK)
|
|
861
|
+
|
|
862
|
+
async def _process_queue_events(self, queue_name: str, priority: EventPriority) -> None:
|
|
863
|
+
"""Process events from a specific queue"""
|
|
864
|
+
# This is a simplified implementation
|
|
865
|
+
# In a real implementation, you would poll the message broker
|
|
866
|
+
pass
|
|
867
|
+
|
|
868
|
+
async def _metrics_collection_loop(self) -> None:
|
|
869
|
+
"""Collect system metrics"""
|
|
870
|
+
logger.info("Starting metrics collection loop")
|
|
871
|
+
|
|
872
|
+
while self._running:
|
|
873
|
+
try:
|
|
874
|
+
# Update system metrics
|
|
875
|
+
self._update_system_metrics()
|
|
876
|
+
|
|
877
|
+
# Publish performance update event
|
|
878
|
+
await self._publish_performance_update()
|
|
879
|
+
|
|
880
|
+
await asyncio.sleep(30) # Collect metrics every 30 seconds
|
|
881
|
+
except Exception as e:
|
|
882
|
+
logger.error(f"Error in metrics collection loop: {e}")
|
|
883
|
+
await asyncio.sleep(30)
|
|
884
|
+
|
|
885
|
+
async def _cleanup_loop(self) -> None:
|
|
886
|
+
"""Cleanup old events and resources"""
|
|
887
|
+
logger.info("Starting cleanup loop")
|
|
888
|
+
|
|
889
|
+
while self._running:
|
|
890
|
+
try:
|
|
891
|
+
# Clean up old processed events
|
|
892
|
+
await self._cleanup_old_events()
|
|
893
|
+
|
|
894
|
+
# Clean up completed workflow executions
|
|
895
|
+
await self._cleanup_completed_workflows()
|
|
896
|
+
|
|
897
|
+
await asyncio.sleep(300) # Cleanup every 5 minutes
|
|
898
|
+
except Exception as e:
|
|
899
|
+
logger.error(f"Error in cleanup loop: {e}")
|
|
900
|
+
await asyncio.sleep(300)
|
|
901
|
+
|
|
902
|
+
async def _persistence_loop(self) -> None:
|
|
903
|
+
"""Persist events for recovery"""
|
|
904
|
+
logger.info("Starting persistence loop")
|
|
905
|
+
|
|
906
|
+
while self._running:
|
|
907
|
+
try:
|
|
908
|
+
await self._persist_events()
|
|
909
|
+
await asyncio.sleep(60) # Persist every minute
|
|
910
|
+
except Exception as e:
|
|
911
|
+
logger.error(f"Error in persistence loop: {e}")
|
|
912
|
+
await asyncio.sleep(60)
|
|
913
|
+
|
|
914
|
+
async def _handle_hook_execution_request(self, event: HookExecutionEvent) -> None:
|
|
915
|
+
"""Handle hook execution request event"""
|
|
916
|
+
try:
|
|
917
|
+
# Acquire execution slot from resource pool
|
|
918
|
+
acquired = await self.resource_pool.acquire_execution_slot(
|
|
919
|
+
event.hook_path, event.hook_event_type or HookEvent.SESSION_START
|
|
920
|
+
)
|
|
921
|
+
|
|
922
|
+
if not acquired:
|
|
923
|
+
# Publish failed event
|
|
924
|
+
failure_event = Event(
|
|
925
|
+
event_id=str(uuid.uuid4()),
|
|
926
|
+
event_type=EventType.HOOK_EXECUTION_FAILED,
|
|
927
|
+
priority=EventPriority.HIGH,
|
|
928
|
+
timestamp=datetime.now(),
|
|
929
|
+
payload={
|
|
930
|
+
"hook_path": event.hook_path,
|
|
931
|
+
"reason": "Resource pool full",
|
|
932
|
+
"original_event_id": event.event_id,
|
|
933
|
+
},
|
|
934
|
+
correlation_id=event.correlation_id,
|
|
935
|
+
causation_id=event.event_id,
|
|
936
|
+
)
|
|
937
|
+
await self.message_broker.publish("system_events", failure_event)
|
|
938
|
+
return
|
|
939
|
+
|
|
940
|
+
try:
|
|
941
|
+
# Execute hook (this would integrate with existing hook manager)
|
|
942
|
+
await self._execute_hook_event(event)
|
|
943
|
+
|
|
944
|
+
# Publish completion event
|
|
945
|
+
completion_event = Event(
|
|
946
|
+
event_id=str(uuid.uuid4()),
|
|
947
|
+
event_type=EventType.HOOK_EXECUTION_COMPLETED,
|
|
948
|
+
priority=EventPriority.NORMAL,
|
|
949
|
+
timestamp=datetime.now(),
|
|
950
|
+
payload={
|
|
951
|
+
"hook_path": event.hook_path,
|
|
952
|
+
"execution_time": 0.0, # Would be filled by actual execution
|
|
953
|
+
"success": True,
|
|
954
|
+
"original_event_id": event.event_id,
|
|
955
|
+
},
|
|
956
|
+
correlation_id=event.correlation_id,
|
|
957
|
+
causation_id=event.event_id,
|
|
958
|
+
)
|
|
959
|
+
await self.message_broker.publish("hook_execution_normal", completion_event)
|
|
960
|
+
|
|
961
|
+
self._system_metrics["hook_executions"] += 1
|
|
962
|
+
|
|
963
|
+
finally:
|
|
964
|
+
# Always release the execution slot
|
|
965
|
+
await self.resource_pool.release_execution_slot(
|
|
966
|
+
event.hook_path, event.hook_event_type or HookEvent.SESSION_START
|
|
967
|
+
)
|
|
968
|
+
|
|
969
|
+
except Exception as e:
|
|
970
|
+
logger.error(f"Error handling hook execution request: {e}")
|
|
971
|
+
|
|
972
|
+
# Publish failure event
|
|
973
|
+
failure_event = Event(
|
|
974
|
+
event_id=str(uuid.uuid4()),
|
|
975
|
+
event_type=EventType.HOOK_EXECUTION_FAILED,
|
|
976
|
+
priority=EventPriority.HIGH,
|
|
977
|
+
timestamp=datetime.now(),
|
|
978
|
+
payload={
|
|
979
|
+
"hook_path": event.hook_path,
|
|
980
|
+
"reason": str(e),
|
|
981
|
+
"original_event_id": event.event_id,
|
|
982
|
+
},
|
|
983
|
+
correlation_id=event.correlation_id,
|
|
984
|
+
causation_id=event.event_id,
|
|
985
|
+
)
|
|
986
|
+
await self.message_broker.publish("system_events", failure_event)
|
|
987
|
+
|
|
988
|
+
async def _execute_hook_event(self, event: HookExecutionEvent) -> None:
|
|
989
|
+
"""Execute hook event (integration point with existing hook system)"""
|
|
990
|
+
# This is where you would integrate with the existing JITEnhancedHookManager
|
|
991
|
+
# For now, we'll simulate execution
|
|
992
|
+
logger.info(f"Executing hook: {event.hook_path} with isolation: {event.isolation_level}")
|
|
993
|
+
|
|
994
|
+
# Simulate execution time
|
|
995
|
+
await asyncio.sleep(0.1)
|
|
996
|
+
|
|
997
|
+
# In real implementation, you would call:
|
|
998
|
+
# result = await self.hook_manager._execute_single_hook(event.hook_path, event.execution_context)
|
|
999
|
+
|
|
1000
|
+
async def _handle_hook_execution_completed(self, event: Event) -> None:
|
|
1001
|
+
"""Handle hook execution completion event"""
|
|
1002
|
+
logger.debug(f"Hook execution completed: {event.payload}")
|
|
1003
|
+
self._system_metrics["events_processed"] += 1
|
|
1004
|
+
|
|
1005
|
+
async def _handle_hook_execution_failed(self, event: Event) -> None:
|
|
1006
|
+
"""Handle hook execution failure event"""
|
|
1007
|
+
logger.warning(f"Hook execution failed: {event.payload}")
|
|
1008
|
+
self._system_metrics["events_failed"] += 1
|
|
1009
|
+
|
|
1010
|
+
async def _handle_system_alert(self, event: Event) -> None:
|
|
1011
|
+
"""Handle system alert event"""
|
|
1012
|
+
logger.warning(f"System alert: {event.payload}")
|
|
1013
|
+
# Here you could trigger additional alerting mechanisms
|
|
1014
|
+
|
|
1015
|
+
async def _handle_health_check(self, event: Event) -> None:
|
|
1016
|
+
"""Handle health check event"""
|
|
1017
|
+
logger.debug(f"Health check: {event.payload}")
|
|
1018
|
+
# Respond with health status
|
|
1019
|
+
|
|
1020
|
+
async def _handle_batch_execution_request(self, event: Event) -> None:
|
|
1021
|
+
"""Handle batch execution request event"""
|
|
1022
|
+
logger.info(f"Batch execution request: {event.payload}")
|
|
1023
|
+
# Process multiple hooks in batch
|
|
1024
|
+
|
|
1025
|
+
async def _handle_workflow_orchestration(self, event: WorkflowEvent) -> None:
|
|
1026
|
+
"""Handle workflow orchestration event"""
|
|
1027
|
+
logger.info(f"Workflow orchestration: {event.workflow_id}")
|
|
1028
|
+
# Execute workflow steps
|
|
1029
|
+
|
|
1030
|
+
async def _publish_performance_update(self) -> None:
|
|
1031
|
+
"""Publish performance update event"""
|
|
1032
|
+
performance_event = Event(
|
|
1033
|
+
event_id=str(uuid.uuid4()),
|
|
1034
|
+
event_type=EventType.PERFORMANCE_UPDATE,
|
|
1035
|
+
priority=EventPriority.LOW,
|
|
1036
|
+
timestamp=datetime.now(),
|
|
1037
|
+
payload=self._system_metrics,
|
|
1038
|
+
source="event_system",
|
|
1039
|
+
)
|
|
1040
|
+
await self.message_broker.publish("analytics", performance_event)
|
|
1041
|
+
|
|
1042
|
+
def _update_system_metrics(self) -> None:
|
|
1043
|
+
"""Update system metrics"""
|
|
1044
|
+
self._system_metrics["system_uptime_seconds"] = (datetime.now() - self._startup_time).total_seconds()
|
|
1045
|
+
|
|
1046
|
+
async def _cleanup_old_events(self) -> None:
|
|
1047
|
+
"""Clean up old processed events"""
|
|
1048
|
+
cutoff_time = datetime.now() - timedelta(hours=24)
|
|
1049
|
+
|
|
1050
|
+
# Remove old processed events
|
|
1051
|
+
old_events = [
|
|
1052
|
+
event_id
|
|
1053
|
+
for event_id in self._processed_events
|
|
1054
|
+
if event_id in self._pending_events and self._pending_events[event_id].timestamp < cutoff_time
|
|
1055
|
+
]
|
|
1056
|
+
|
|
1057
|
+
for event_id in old_events:
|
|
1058
|
+
self._processed_events.discard(event_id)
|
|
1059
|
+
if event_id in self._pending_events:
|
|
1060
|
+
del self._pending_events[event_id]
|
|
1061
|
+
|
|
1062
|
+
async def _cleanup_completed_workflows(self) -> None:
|
|
1063
|
+
"""Clean up completed workflow executions"""
|
|
1064
|
+
# Implementation would clean up completed workflow state
|
|
1065
|
+
pass
|
|
1066
|
+
|
|
1067
|
+
async def _persist_events(self) -> None:
|
|
1068
|
+
"""Persist events to disk for recovery"""
|
|
1069
|
+
if not self.enable_persistence:
|
|
1070
|
+
return
|
|
1071
|
+
|
|
1072
|
+
try:
|
|
1073
|
+
# Persist pending events
|
|
1074
|
+
pending_file = self.persistence_path / "pending_events.json"
|
|
1075
|
+
pending_data = {event_id: event.to_dict() for event_id, event in self._pending_events.items()}
|
|
1076
|
+
|
|
1077
|
+
with open(pending_file, "w") as f:
|
|
1078
|
+
json.dump(pending_data, f, indent=2)
|
|
1079
|
+
|
|
1080
|
+
# Persist processed events
|
|
1081
|
+
processed_file = self.persistence_path / "processed_events.json"
|
|
1082
|
+
with open(processed_file, "w") as f:
|
|
1083
|
+
json.dump(list(self._processed_events), f, indent=2)
|
|
1084
|
+
|
|
1085
|
+
# Persist system metrics
|
|
1086
|
+
metrics_file = self.persistence_path / "system_metrics.json"
|
|
1087
|
+
with open(metrics_file, "w") as f:
|
|
1088
|
+
json.dump(self._system_metrics, f, indent=2)
|
|
1089
|
+
|
|
1090
|
+
except Exception as e:
|
|
1091
|
+
logger.error(f"Error persisting events: {e}")
|
|
1092
|
+
|
|
1093
|
+
async def _load_persisted_events(self) -> None:
|
|
1094
|
+
"""Load persisted events for recovery"""
|
|
1095
|
+
if not self.enable_persistence:
|
|
1096
|
+
return
|
|
1097
|
+
|
|
1098
|
+
try:
|
|
1099
|
+
# Load pending events
|
|
1100
|
+
pending_file = self.persistence_path / "pending_events.json"
|
|
1101
|
+
if pending_file.exists():
|
|
1102
|
+
with open(pending_file, "r") as f:
|
|
1103
|
+
pending_data = json.load(f)
|
|
1104
|
+
|
|
1105
|
+
self._pending_events = {
|
|
1106
|
+
event_id: Event.from_dict(event_data) for event_id, event_data in pending_data.items()
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
# Load processed events
|
|
1110
|
+
processed_file = self.persistence_path / "processed_events.json"
|
|
1111
|
+
if processed_file.exists():
|
|
1112
|
+
with open(processed_file, "r") as f:
|
|
1113
|
+
processed_data = json.load(f)
|
|
1114
|
+
self._processed_events = set(processed_data)
|
|
1115
|
+
|
|
1116
|
+
# Load system metrics
|
|
1117
|
+
metrics_file = self.persistence_path / "system_metrics.json"
|
|
1118
|
+
if metrics_file.exists():
|
|
1119
|
+
with open(metrics_file, "r") as f:
|
|
1120
|
+
self._system_metrics = json.load(f)
|
|
1121
|
+
|
|
1122
|
+
except Exception as e:
|
|
1123
|
+
logger.error(f"Error loading persisted events: {e}")
|
|
1124
|
+
|
|
1125
|
+
async def publish_hook_execution_event(
|
|
1126
|
+
self,
|
|
1127
|
+
hook_path: str,
|
|
1128
|
+
event_type: HookEvent,
|
|
1129
|
+
execution_context: Dict[str, Any],
|
|
1130
|
+
isolation_level: Optional[ResourceIsolationLevel] = None,
|
|
1131
|
+
priority: EventPriority = EventPriority.NORMAL,
|
|
1132
|
+
correlation_id: Optional[str] = None,
|
|
1133
|
+
) -> str:
|
|
1134
|
+
"""Publish hook execution event"""
|
|
1135
|
+
|
|
1136
|
+
event = HookExecutionEvent(
|
|
1137
|
+
event_id=str(uuid.uuid4()),
|
|
1138
|
+
event_type=EventType.HOOK_EXECUTION_REQUEST,
|
|
1139
|
+
priority=priority,
|
|
1140
|
+
timestamp=datetime.now(),
|
|
1141
|
+
payload={
|
|
1142
|
+
"hook_path": hook_path,
|
|
1143
|
+
"event_type": event_type.value,
|
|
1144
|
+
"execution_context": execution_context,
|
|
1145
|
+
},
|
|
1146
|
+
source="event_system",
|
|
1147
|
+
correlation_id=correlation_id or str(uuid.uuid4()),
|
|
1148
|
+
hook_path=hook_path,
|
|
1149
|
+
hook_event_type=event_type,
|
|
1150
|
+
execution_context=execution_context,
|
|
1151
|
+
isolation_level=isolation_level or self.isolation_level,
|
|
1152
|
+
)
|
|
1153
|
+
|
|
1154
|
+
# Determine queue based on priority
|
|
1155
|
+
queue_name = self._get_queue_name_by_priority(priority)
|
|
1156
|
+
|
|
1157
|
+
# Publish event
|
|
1158
|
+
success = await self.message_broker.publish(queue_name, event)
|
|
1159
|
+
|
|
1160
|
+
if success:
|
|
1161
|
+
self._system_metrics["events_published"] += 1
|
|
1162
|
+
if self.enable_persistence:
|
|
1163
|
+
self._pending_events[event.event_id] = event
|
|
1164
|
+
|
|
1165
|
+
return event.event_id
|
|
1166
|
+
|
|
1167
|
+
def _get_queue_name_by_priority(self, priority: EventPriority) -> str:
|
|
1168
|
+
"""Get queue name based on event priority"""
|
|
1169
|
+
if priority == EventPriority.CRITICAL:
|
|
1170
|
+
return "system_events"
|
|
1171
|
+
elif priority == EventPriority.HIGH:
|
|
1172
|
+
return "hook_execution_high"
|
|
1173
|
+
elif priority == EventPriority.NORMAL:
|
|
1174
|
+
return "hook_execution_normal"
|
|
1175
|
+
elif priority == EventPriority.LOW:
|
|
1176
|
+
return "hook_execution_low"
|
|
1177
|
+
else:
|
|
1178
|
+
return "analytics"
|
|
1179
|
+
|
|
1180
|
+
async def publish_system_alert(
|
|
1181
|
+
self,
|
|
1182
|
+
alert_type: str,
|
|
1183
|
+
message: str,
|
|
1184
|
+
severity: EventPriority = EventPriority.HIGH,
|
|
1185
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
1186
|
+
) -> str:
|
|
1187
|
+
"""Publish system alert event"""
|
|
1188
|
+
|
|
1189
|
+
alert_event = Event(
|
|
1190
|
+
event_id=str(uuid.uuid4()),
|
|
1191
|
+
event_type=EventType.SYSTEM_ALERT,
|
|
1192
|
+
priority=severity,
|
|
1193
|
+
timestamp=datetime.now(),
|
|
1194
|
+
payload={
|
|
1195
|
+
"alert_type": alert_type,
|
|
1196
|
+
"message": message,
|
|
1197
|
+
"metadata": metadata or {},
|
|
1198
|
+
},
|
|
1199
|
+
source="event_system",
|
|
1200
|
+
)
|
|
1201
|
+
|
|
1202
|
+
await self.message_broker.publish("system_events", alert_event)
|
|
1203
|
+
self._system_metrics["events_published"] += 1
|
|
1204
|
+
|
|
1205
|
+
return alert_event.event_id
|
|
1206
|
+
|
|
1207
|
+
async def get_system_status(self) -> Dict[str, Any]:
|
|
1208
|
+
"""Get comprehensive system status"""
|
|
1209
|
+
return {
|
|
1210
|
+
"status": "running" if self._running else "stopped",
|
|
1211
|
+
"uptime_seconds": self._system_metrics["system_uptime_seconds"],
|
|
1212
|
+
"message_broker_type": self.message_broker_type.value,
|
|
1213
|
+
"isolation_level": self.isolation_level.value,
|
|
1214
|
+
"max_concurrent_hooks": self.max_concurrent_hooks,
|
|
1215
|
+
"persistence_enabled": self.enable_persistence,
|
|
1216
|
+
"system_metrics": self._system_metrics,
|
|
1217
|
+
"message_broker_stats": self.message_broker.get_stats(),
|
|
1218
|
+
"resource_pool_stats": self.resource_pool.get_stats(),
|
|
1219
|
+
"event_processor_stats": self.event_processor.get_stats(),
|
|
1220
|
+
"pending_events_count": len(self._pending_events),
|
|
1221
|
+
"processed_events_count": len(self._processed_events),
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
def get_event_flow_diagram(self) -> Dict[str, Any]:
|
|
1225
|
+
"""Get event flow diagram for visualization"""
|
|
1226
|
+
return {
|
|
1227
|
+
"event_types": [event_type.value for event_type in EventType],
|
|
1228
|
+
"priorities": [priority.value for priority in EventPriority],
|
|
1229
|
+
"isolation_levels": [level.value for level in ResourceIsolationLevel],
|
|
1230
|
+
"message_broker_type": self.message_broker_type.value,
|
|
1231
|
+
"flow_pattern": {
|
|
1232
|
+
"hook_execution": [
|
|
1233
|
+
"HOOK_EXECUTION_REQUEST -> Resource Pool -> Hook Execution -> HOOK_EXECUTION_COMPLETED"
|
|
1234
|
+
],
|
|
1235
|
+
"system_alerts": ["SYSTEM_ALERT -> Alert Handlers -> Notification"],
|
|
1236
|
+
"batch_processing": ["BATCH_EXECUTION_REQUEST -> Batch Queue -> Parallel Execution -> Results"],
|
|
1237
|
+
"workflow_orchestration": [
|
|
1238
|
+
"WORKFLOW_ORCHESTRATION -> Workflow Engine -> Step Execution -> State Update"
|
|
1239
|
+
],
|
|
1240
|
+
},
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
|
|
1244
|
+
# Global instance for easy access
|
|
1245
|
+
_event_system: Optional[EventDrivenHookSystem] = None
|
|
1246
|
+
|
|
1247
|
+
|
|
1248
|
+
def get_event_system() -> EventDrivenHookSystem:
|
|
1249
|
+
"""Get or create global event system instance"""
|
|
1250
|
+
global _event_system
|
|
1251
|
+
if _event_system is None:
|
|
1252
|
+
_event_system = EventDrivenHookSystem()
|
|
1253
|
+
return _event_system
|
|
1254
|
+
|
|
1255
|
+
|
|
1256
|
+
# Convenience functions
|
|
1257
|
+
async def start_event_system() -> None:
|
|
1258
|
+
"""Start the event system"""
|
|
1259
|
+
system = get_event_system()
|
|
1260
|
+
await system.start()
|
|
1261
|
+
|
|
1262
|
+
|
|
1263
|
+
async def stop_event_system() -> None:
|
|
1264
|
+
"""Stop the event system"""
|
|
1265
|
+
system = get_event_system()
|
|
1266
|
+
await system.stop()
|
|
1267
|
+
|
|
1268
|
+
|
|
1269
|
+
async def execute_hook_with_event_system(
|
|
1270
|
+
hook_path: str,
|
|
1271
|
+
event_type: HookEvent,
|
|
1272
|
+
execution_context: Dict[str, Any],
|
|
1273
|
+
isolation_level: Optional[ResourceIsolationLevel] = None,
|
|
1274
|
+
priority: EventPriority = EventPriority.NORMAL,
|
|
1275
|
+
) -> str:
|
|
1276
|
+
"""Execute hook using the event system"""
|
|
1277
|
+
system = get_event_system()
|
|
1278
|
+
return await system.publish_hook_execution_event(
|
|
1279
|
+
hook_path, event_type, execution_context, isolation_level, priority
|
|
1280
|
+
)
|
|
1281
|
+
|
|
1282
|
+
|
|
1283
|
+
if __name__ == "__main__":
|
|
1284
|
+
# Example usage
|
|
1285
|
+
async def main():
|
|
1286
|
+
print("š Starting Event-Driven Hook System Architecture...")
|
|
1287
|
+
|
|
1288
|
+
# Initialize system with Redis broker and type isolation
|
|
1289
|
+
event_system = EventDrivenHookSystem(
|
|
1290
|
+
message_broker_type=MessageBrokerType.MEMORY, # Use MEMORY for demo
|
|
1291
|
+
isolation_level=ResourceIsolationLevel.TYPE_ISOLATED,
|
|
1292
|
+
max_concurrent_hooks=5,
|
|
1293
|
+
enable_persistence=True,
|
|
1294
|
+
)
|
|
1295
|
+
|
|
1296
|
+
try:
|
|
1297
|
+
# Start the system
|
|
1298
|
+
await event_system.start()
|
|
1299
|
+
|
|
1300
|
+
# Publish some test hook execution events
|
|
1301
|
+
print("\nš¤ Publishing hook execution events...")
|
|
1302
|
+
|
|
1303
|
+
event_ids = []
|
|
1304
|
+
for i in range(3):
|
|
1305
|
+
event_id = await event_system.publish_hook_execution_event(
|
|
1306
|
+
hook_path=f"test_hook_{i}.py",
|
|
1307
|
+
event_type=HookEvent.SESSION_START,
|
|
1308
|
+
execution_context={"test": True, "iteration": i},
|
|
1309
|
+
isolation_level=ResourceIsolationLevel.FULL_ISOLATION,
|
|
1310
|
+
priority=EventPriority.NORMAL,
|
|
1311
|
+
)
|
|
1312
|
+
event_ids.append(event_id)
|
|
1313
|
+
print(f" Published event {i + 1}: {event_id}")
|
|
1314
|
+
|
|
1315
|
+
# Publish a system alert
|
|
1316
|
+
alert_id = await event_system.publish_system_alert(
|
|
1317
|
+
alert_type="TEST_ALERT",
|
|
1318
|
+
message="This is a test alert from the event system",
|
|
1319
|
+
severity=EventPriority.HIGH,
|
|
1320
|
+
)
|
|
1321
|
+
print(f"\nšØ Published system alert: {alert_id}")
|
|
1322
|
+
|
|
1323
|
+
# Let events process
|
|
1324
|
+
print("\nā³ Processing events...")
|
|
1325
|
+
await asyncio.sleep(2)
|
|
1326
|
+
|
|
1327
|
+
# Get system status
|
|
1328
|
+
status = await event_system.get_system_status()
|
|
1329
|
+
print("\nš System Status:")
|
|
1330
|
+
print(f" Status: {status['status']}")
|
|
1331
|
+
print(f" Uptime: {status['uptime_seconds']:.1f}s")
|
|
1332
|
+
print(f" Events Published: {status['system_metrics']['events_published']}")
|
|
1333
|
+
print(f" Events Processed: {status['system_metrics']['events_processed']}")
|
|
1334
|
+
print(f" Hook Executions: {status['system_metrics']['hook_executions']}")
|
|
1335
|
+
print(f" Pending Events: {status['pending_events_count']}")
|
|
1336
|
+
|
|
1337
|
+
# Get message broker stats
|
|
1338
|
+
broker_stats = status["message_broker_stats"]
|
|
1339
|
+
print("\nšØ Message Broker Stats:")
|
|
1340
|
+
print(f" Messages Published: {broker_stats.get('messages_published', 0)}")
|
|
1341
|
+
print(f" Messages Delivered: {broker_stats.get('messages_delivered', 0)}")
|
|
1342
|
+
|
|
1343
|
+
# Get resource pool stats
|
|
1344
|
+
pool_stats = status["resource_pool_stats"]
|
|
1345
|
+
print("\nš Resource Pool Stats:")
|
|
1346
|
+
print(f" Total Executions: {pool_stats.get('total_executions', 0)}")
|
|
1347
|
+
print(f" Active Executions: {pool_stats.get('active_executions', 0)}")
|
|
1348
|
+
|
|
1349
|
+
# Get event flow diagram
|
|
1350
|
+
flow_diagram = event_system.get_event_flow_diagram()
|
|
1351
|
+
print("\nš Event Flow Diagram:")
|
|
1352
|
+
print(f" Event Types: {len(flow_diagram['event_types'])}")
|
|
1353
|
+
print(f" Isolation Levels: {flow_diagram['isolation_levels']}")
|
|
1354
|
+
print(f" Message Broker: {flow_diagram['message_broker_type']}")
|
|
1355
|
+
|
|
1356
|
+
print("\nā
Event-Driven Hook System demo completed successfully!")
|
|
1357
|
+
|
|
1358
|
+
except Exception as e:
|
|
1359
|
+
print(f"\nā Demo failed: {str(e)}")
|
|
1360
|
+
import traceback
|
|
1361
|
+
|
|
1362
|
+
traceback.print_exc()
|
|
1363
|
+
|
|
1364
|
+
finally:
|
|
1365
|
+
# Stop the system
|
|
1366
|
+
print("\nš Stopping event system...")
|
|
1367
|
+
await event_system.stop()
|
|
1368
|
+
print("ā
System stopped")
|
|
1369
|
+
|
|
1370
|
+
# Run the demo
|
|
1371
|
+
asyncio.run(main())
|