moai-adk 0.25.4__py3-none-any.whl → 0.32.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of moai-adk might be problematic. Click here for more details.
- moai_adk/__init__.py +2 -5
- moai_adk/__main__.py +114 -82
- moai_adk/cli/__init__.py +6 -1
- moai_adk/cli/commands/__init__.py +1 -3
- moai_adk/cli/commands/analyze.py +5 -16
- moai_adk/cli/commands/doctor.py +6 -18
- moai_adk/cli/commands/init.py +56 -125
- moai_adk/cli/commands/language.py +14 -35
- moai_adk/cli/commands/status.py +9 -15
- moai_adk/cli/commands/update.py +1555 -190
- moai_adk/cli/prompts/init_prompts.py +112 -56
- 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 +672 -0
- moai_adk/cli/worktree/exceptions.py +89 -0
- moai_adk/cli/worktree/manager.py +490 -0
- moai_adk/cli/worktree/models.py +65 -0
- moai_adk/cli/worktree/registry.py +128 -0
- moai_adk/core/PHASE2_OPTIMIZATIONS.md +467 -0
- moai_adk/core/analysis/session_analyzer.py +17 -56
- moai_adk/core/claude_integration.py +26 -54
- moai_adk/core/command_helpers.py +10 -10
- moai_adk/core/comprehensive_monitoring_system.py +1183 -0
- moai_adk/core/config/auto_spec_config.py +5 -11
- moai_adk/core/config/migration.py +19 -9
- moai_adk/core/config/unified.py +436 -0
- moai_adk/core/context_manager.py +6 -12
- moai_adk/core/enterprise_features.py +1404 -0
- moai_adk/core/error_recovery_system.py +725 -112
- moai_adk/core/event_driven_hook_system.py +1371 -0
- moai_adk/core/git/__init__.py +8 -0
- moai_adk/core/git/branch_manager.py +3 -11
- moai_adk/core/git/checkpoint.py +1 -3
- moai_adk/core/git/conflict_detector.py +413 -0
- moai_adk/core/git/manager.py +91 -1
- moai_adk/core/hooks/post_tool_auto_spec_completion.py +56 -80
- moai_adk/core/input_validation_middleware.py +1006 -0
- moai_adk/core/integration/engine.py +6 -18
- moai_adk/core/integration/integration_tester.py +10 -9
- moai_adk/core/integration/utils.py +1 -1
- moai_adk/core/issue_creator.py +10 -28
- moai_adk/core/jit_context_loader.py +956 -0
- moai_adk/core/jit_enhanced_hook_manager.py +1987 -0
- moai_adk/core/language_config_resolver.py +485 -0
- moai_adk/core/language_validator.py +28 -41
- moai_adk/core/mcp/setup.py +15 -12
- moai_adk/core/merge/__init__.py +9 -0
- moai_adk/core/merge/analyzer.py +481 -0
- moai_adk/core/migration/alfred_to_moai_migrator.py +383 -0
- moai_adk/core/migration/backup_manager.py +78 -9
- moai_adk/core/migration/custom_element_scanner.py +358 -0
- moai_adk/core/migration/file_migrator.py +8 -17
- 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 +6 -10
- moai_adk/core/migration/version_migrator.py +3 -3
- moai_adk/core/performance/cache_system.py +8 -10
- moai_adk/core/phase_optimized_hook_scheduler.py +879 -0
- moai_adk/core/project/checker.py +2 -4
- moai_adk/core/project/detector.py +1 -3
- moai_adk/core/project/initializer.py +135 -23
- moai_adk/core/project/phase_executor.py +54 -81
- moai_adk/core/project/validator.py +6 -12
- moai_adk/core/quality/trust_checker.py +9 -27
- moai_adk/core/realtime_monitoring_dashboard.py +1724 -0
- moai_adk/core/robust_json_parser.py +611 -0
- moai_adk/core/rollback_manager.py +73 -148
- moai_adk/core/session_manager.py +10 -26
- moai_adk/core/skill_loading_system.py +579 -0
- moai_adk/core/spec/confidence_scoring.py +31 -100
- moai_adk/core/spec/ears_template_engine.py +351 -286
- moai_adk/core/spec/quality_validator.py +35 -69
- moai_adk/core/spec_status_manager.py +64 -74
- moai_adk/core/template/backup.py +45 -20
- moai_adk/core/template/config.py +112 -39
- moai_adk/core/template/merger.py +11 -19
- moai_adk/core/template/processor.py +253 -149
- moai_adk/core/template_engine.py +73 -40
- 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 +4 -12
- 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 +23 -72
- moai_adk/foundation/trust/validation_checklist.py +57 -162
- 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/alfred_detector.py +1 -3
- moai_adk/statusline/config.py +13 -4
- moai_adk/statusline/enhanced_output_style_detector.py +23 -15
- moai_adk/statusline/main.py +51 -15
- moai_adk/statusline/renderer.py +104 -48
- moai_adk/statusline/update_checker.py +3 -9
- moai_adk/statusline/version_reader.py +140 -46
- moai_adk/templates/.claude/agents/moai/ai-nano-banana.md +549 -0
- moai_adk/templates/.claude/agents/moai/builder-agent.md +445 -0
- moai_adk/templates/.claude/agents/moai/builder-command.md +1132 -0
- moai_adk/templates/.claude/agents/moai/builder-skill.md +601 -0
- moai_adk/templates/.claude/agents/moai/expert-backend.md +831 -0
- moai_adk/templates/.claude/agents/moai/expert-database.md +774 -0
- moai_adk/templates/.claude/agents/moai/expert-debug.md +396 -0
- moai_adk/templates/.claude/agents/moai/expert-devops.md +711 -0
- moai_adk/templates/.claude/agents/moai/expert-frontend.md +666 -0
- moai_adk/templates/.claude/agents/moai/expert-security.md +474 -0
- moai_adk/templates/.claude/agents/moai/expert-uiux.md +1038 -0
- moai_adk/templates/.claude/agents/moai/manager-claude-code.md +429 -0
- moai_adk/templates/.claude/agents/moai/manager-docs.md +570 -0
- moai_adk/templates/.claude/agents/moai/manager-git.md +937 -0
- moai_adk/templates/.claude/agents/moai/manager-project.md +891 -0
- moai_adk/templates/.claude/agents/moai/manager-quality.md +598 -0
- moai_adk/templates/.claude/agents/moai/manager-spec.md +713 -0
- moai_adk/templates/.claude/agents/moai/manager-strategy.md +600 -0
- moai_adk/templates/.claude/agents/moai/manager-tdd.md +603 -0
- moai_adk/templates/.claude/agents/moai/mcp-context7.md +369 -0
- moai_adk/templates/.claude/agents/moai/mcp-figma.md +1567 -0
- moai_adk/templates/.claude/agents/moai/mcp-notion.md +749 -0
- moai_adk/templates/.claude/agents/moai/mcp-playwright.md +427 -0
- moai_adk/templates/.claude/agents/moai/mcp-sequential-thinking.md +994 -0
- moai_adk/templates/.claude/commands/moai/0-project.md +1143 -0
- moai_adk/templates/.claude/commands/moai/1-plan.md +1435 -0
- moai_adk/templates/.claude/commands/moai/2-run.md +883 -0
- moai_adk/templates/.claude/commands/moai/3-sync.md +993 -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/moai/lib/checkpoint.py +244 -0
- 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 +921 -0
- moai_adk/templates/.claude/output-styles/moai/r2d2.md +380 -0
- moai_adk/templates/.claude/output-styles/moai/yoda.md +338 -0
- moai_adk/templates/.claude/settings.json +172 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/SKILL.md +247 -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-domain-backend/SKILL.md +319 -0
- moai_adk/templates/.claude/skills/moai-domain-database/SKILL.md +320 -0
- 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-frontend/SKILL.md +496 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/SKILL.md +453 -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 +491 -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-foundation-claude/SKILL.md +201 -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-context/SKILL.md +438 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/SKILL.md +515 -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 +346 -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-quality/SKILL.md +362 -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-integration-mcp/SKILL.md +352 -0
- moai_adk/templates/.claude/skills/moai-integration-mcp/modules/README.md +52 -0
- moai_adk/templates/.claude/skills/moai-integration-mcp/modules/error-handling.md +334 -0
- moai_adk/templates/.claude/skills/moai-integration-mcp/modules/integration-patterns.md +310 -0
- moai_adk/templates/.claude/skills/moai-integration-mcp/modules/security-authentication.md +256 -0
- moai_adk/templates/.claude/skills/moai-integration-mcp/modules/server-architecture.md +253 -0
- moai_adk/templates/.claude/skills/moai-lang-unified/README.md +133 -0
- moai_adk/templates/.claude/skills/moai-lang-unified/SKILL.md +296 -0
- moai_adk/templates/.claude/skills/moai-lang-unified/examples.md +1269 -0
- moai_adk/templates/.claude/skills/moai-lang-unified/reference.md +331 -0
- moai_adk/templates/.claude/skills/moai-library-mermaid/SKILL.md +298 -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 +316 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/advanced-patterns.md +336 -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-shadcn/SKILL.md +370 -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-platform-baas/README.md +186 -0
- moai_adk/templates/.claude/skills/moai-platform-baas/SKILL.md +290 -0
- moai_adk/templates/.claude/skills/moai-platform-baas/examples.md +1225 -0
- moai_adk/templates/.claude/skills/moai-platform-baas/reference.md +567 -0
- moai_adk/templates/.claude/skills/moai-platform-baas/scripts/provider-selector.py +323 -0
- moai_adk/templates/.claude/skills/moai-platform-baas/templates/stack-config.yaml +204 -0
- moai_adk/templates/.claude/skills/moai-workflow-jit-docs/SKILL.md +446 -0
- moai_adk/templates/.claude/skills/moai-workflow-jit-docs/advanced-patterns.md +379 -0
- moai_adk/templates/.claude/skills/moai-workflow-jit-docs/optimization.md +286 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/README.md +190 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/SKILL.md +387 -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 +135 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples/quick_start.py +196 -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/schemas/config-schema.json +316 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/schemas/tab_schema.json +1362 -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 +71 -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-templates/SKILL.md +374 -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-testing/LICENSE.txt +202 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/SKILL.md +453 -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/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/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 +410 -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 +103 -41
- moai_adk/templates/.git-hooks/pre-push +116 -21
- moai_adk/templates/.github/workflows/ci-universal.yml +513 -0
- moai_adk/templates/.github/workflows/security-secrets-check.yml +179 -0
- moai_adk/templates/.gitignore +184 -44
- moai_adk/templates/.mcp.json +7 -9
- moai_adk/templates/.moai/cache/personalization.json +10 -0
- moai_adk/templates/.moai/config/config.yaml +344 -0
- moai_adk/templates/.moai/config/presets/manual.yaml +28 -0
- moai_adk/templates/.moai/config/presets/personal.yaml +30 -0
- moai_adk/templates/.moai/config/presets/team.yaml +33 -0
- moai_adk/templates/.moai/config/questions/_schema.yaml +79 -0
- moai_adk/templates/.moai/config/questions/tab1-user.yaml +108 -0
- moai_adk/templates/.moai/config/questions/tab2-project.yaml +122 -0
- moai_adk/templates/.moai/config/questions/tab3-git.yaml +542 -0
- moai_adk/templates/.moai/config/questions/tab4-quality.yaml +167 -0
- moai_adk/templates/.moai/config/questions/tab5-system.yaml +152 -0
- moai_adk/templates/.moai/config/sections/git-strategy.yaml +40 -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 +15 -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 +86 -0
- moai_adk/templates/.moai/scripts/setup-glm.py +136 -0
- moai_adk/templates/CLAUDE.md +382 -501
- moai_adk/utils/__init__.py +24 -1
- moai_adk/utils/banner.py +7 -10
- moai_adk/utils/common.py +16 -30
- moai_adk/utils/link_validator.py +4 -12
- moai_adk/utils/safe_file_reader.py +2 -6
- moai_adk/utils/timeout.py +160 -0
- moai_adk/utils/toon_utils.py +256 -0
- moai_adk/version.py +22 -0
- moai_adk-0.32.8.dist-info/METADATA +2478 -0
- moai_adk-0.32.8.dist-info/RECORD +396 -0
- {moai_adk-0.25.4.dist-info → moai_adk-0.32.8.dist-info}/WHEEL +1 -1
- {moai_adk-0.25.4.dist-info → moai_adk-0.32.8.dist-info}/entry_points.txt +1 -0
- moai_adk/cli/commands/backup.py +0 -82
- moai_adk/cli/commands/improve_user_experience.py +0 -348
- moai_adk/cli/commands/migrate.py +0 -158
- moai_adk/cli/commands/validate_links.py +0 -118
- moai_adk/templates/.github/workflows/moai-gitflow.yml +0 -413
- moai_adk/templates/.github/workflows/moai-release-create.yml +0 -100
- moai_adk/templates/.github/workflows/moai-release-pipeline.yml +0 -188
- moai_adk/utils/user_experience.py +0 -531
- moai_adk-0.25.4.dist-info/METADATA +0 -2279
- moai_adk-0.25.4.dist-info/RECORD +0 -112
- {moai_adk-0.25.4.dist-info → moai_adk-0.32.8.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,530 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Unified Hook Timeout Manager
|
|
3
|
+
|
|
4
|
+
Prevents timeout conflicts across hooks by providing a centralized
|
|
5
|
+
timeout management system with proper resource cleanup and graceful degradation.
|
|
6
|
+
|
|
7
|
+
Architecture:
|
|
8
|
+
- Global timeout registry to prevent multiple signal.alarm() conflicts
|
|
9
|
+
- Cross-platform compatibility (Windows/Unix)
|
|
10
|
+
- Resource cleanup and memory monitoring
|
|
11
|
+
- Configurable timeout policies per hook type
|
|
12
|
+
- Graceful degradation with retry mechanisms
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import contextlib
|
|
16
|
+
import logging
|
|
17
|
+
import platform
|
|
18
|
+
import signal
|
|
19
|
+
import threading
|
|
20
|
+
import time
|
|
21
|
+
from dataclasses import dataclass, field
|
|
22
|
+
from datetime import datetime
|
|
23
|
+
from enum import Enum
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
from typing import Any, Callable, Dict, Optional, Set
|
|
26
|
+
|
|
27
|
+
import yaml
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class TimeoutPolicy(Enum):
|
|
31
|
+
"""Timeout policy types for different hook categories"""
|
|
32
|
+
|
|
33
|
+
FAST = "fast" # 1-2 seconds (PreTool hooks)
|
|
34
|
+
NORMAL = "normal" # 3-5 seconds (SessionStart/End)
|
|
35
|
+
SLOW = "slow" # 10-15 seconds (Complex operations)
|
|
36
|
+
CUSTOM = "custom" # User-defined timeout
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass
|
|
40
|
+
class HookTimeoutConfig:
|
|
41
|
+
"""Configuration for hook timeout behavior"""
|
|
42
|
+
|
|
43
|
+
policy: TimeoutPolicy = TimeoutPolicy.NORMAL
|
|
44
|
+
custom_timeout_ms: Optional[int] = None
|
|
45
|
+
retry_count: int = 0
|
|
46
|
+
retry_delay_ms: int = 100
|
|
47
|
+
graceful_degradation: bool = True
|
|
48
|
+
memory_limit_mb: Optional[int] = None
|
|
49
|
+
on_timeout_callback: Optional[Callable] = None
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@dataclass
|
|
53
|
+
class TimeoutSession:
|
|
54
|
+
"""Active timeout session tracking"""
|
|
55
|
+
|
|
56
|
+
hook_id: str
|
|
57
|
+
start_time: datetime
|
|
58
|
+
timeout_seconds: float
|
|
59
|
+
thread_id: int
|
|
60
|
+
callback: Optional[Callable] = None
|
|
61
|
+
completed: bool = False
|
|
62
|
+
cleanup_actions: list = field(default_factory=list)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class HookTimeoutError(Exception):
|
|
66
|
+
"""Enhanced timeout error with context"""
|
|
67
|
+
|
|
68
|
+
def __init__(
|
|
69
|
+
self,
|
|
70
|
+
message: str,
|
|
71
|
+
hook_id: str = "",
|
|
72
|
+
timeout_seconds: float = 0,
|
|
73
|
+
execution_time: float = 0,
|
|
74
|
+
will_retry: bool = False,
|
|
75
|
+
):
|
|
76
|
+
super().__init__(message)
|
|
77
|
+
self.hook_id = hook_id
|
|
78
|
+
self.timeout_seconds = timeout_seconds
|
|
79
|
+
self.execution_time = execution_time
|
|
80
|
+
self.will_retry = will_retry
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class UnifiedTimeoutManager:
|
|
84
|
+
"""Centralized timeout manager for all hooks
|
|
85
|
+
|
|
86
|
+
Features:
|
|
87
|
+
- Prevents signal conflicts by tracking active timeouts
|
|
88
|
+
- Cross-platform compatibility (Windows threading, Unix signals)
|
|
89
|
+
- Memory usage monitoring
|
|
90
|
+
- Configurable retry mechanisms
|
|
91
|
+
- Graceful degradation with proper cleanup
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
# Global singleton instance
|
|
95
|
+
_instance: Optional["UnifiedTimeoutManager"] = None
|
|
96
|
+
_lock = threading.Lock()
|
|
97
|
+
|
|
98
|
+
def __new__(cls) -> "UnifiedTimeoutManager":
|
|
99
|
+
"""Singleton pattern to ensure single timeout manager"""
|
|
100
|
+
if cls._instance is None:
|
|
101
|
+
with cls._lock:
|
|
102
|
+
if cls._instance is None:
|
|
103
|
+
cls._instance = super().__new__(cls)
|
|
104
|
+
return cls._instance
|
|
105
|
+
|
|
106
|
+
def __init__(self) -> None:
|
|
107
|
+
if hasattr(self, "_initialized"):
|
|
108
|
+
return
|
|
109
|
+
|
|
110
|
+
self._initialized = True
|
|
111
|
+
self._logger = logging.getLogger(__name__)
|
|
112
|
+
|
|
113
|
+
# Active timeout tracking
|
|
114
|
+
self._active_sessions: Dict[str, TimeoutSession] = {}
|
|
115
|
+
self._session_lock = threading.RLock()
|
|
116
|
+
|
|
117
|
+
# Platform detection
|
|
118
|
+
self._is_windows = platform.system() == "Windows"
|
|
119
|
+
|
|
120
|
+
# Signal management for Unix
|
|
121
|
+
self._original_signal_handler: Optional[Callable] = None
|
|
122
|
+
self._signal_lock = threading.Lock()
|
|
123
|
+
|
|
124
|
+
# Resource monitoring
|
|
125
|
+
self._memory_tracker: Dict[str, Any] = {}
|
|
126
|
+
self._cleanup_registry: Set[str] = set()
|
|
127
|
+
|
|
128
|
+
# Default timeout configurations
|
|
129
|
+
self._default_configs = {
|
|
130
|
+
TimeoutPolicy.FAST: HookTimeoutConfig(
|
|
131
|
+
policy=TimeoutPolicy.FAST,
|
|
132
|
+
custom_timeout_ms=2000, # 2 seconds
|
|
133
|
+
retry_count=1,
|
|
134
|
+
retry_delay_ms=100,
|
|
135
|
+
),
|
|
136
|
+
TimeoutPolicy.NORMAL: HookTimeoutConfig(
|
|
137
|
+
policy=TimeoutPolicy.NORMAL,
|
|
138
|
+
custom_timeout_ms=5000, # 5 seconds
|
|
139
|
+
retry_count=1,
|
|
140
|
+
retry_delay_ms=200,
|
|
141
|
+
),
|
|
142
|
+
TimeoutPolicy.SLOW: HookTimeoutConfig(
|
|
143
|
+
policy=TimeoutPolicy.SLOW,
|
|
144
|
+
custom_timeout_ms=15000, # 15 seconds
|
|
145
|
+
retry_count=2,
|
|
146
|
+
retry_delay_ms=500,
|
|
147
|
+
),
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
self._logger.info("UnifiedTimeoutManager initialized")
|
|
151
|
+
|
|
152
|
+
def load_config(self) -> Dict[str, Any]:
|
|
153
|
+
"""Load timeout configuration from project config"""
|
|
154
|
+
try:
|
|
155
|
+
config_file = Path(".moai/config/config.yaml")
|
|
156
|
+
if config_file.exists():
|
|
157
|
+
with open(config_file, "r", encoding="utf-8") as f:
|
|
158
|
+
config = yaml.safe_load(f) or {}
|
|
159
|
+
return config.get("hooks", {}).get("timeout_manager", {})
|
|
160
|
+
except Exception as e:
|
|
161
|
+
self._logger.warning(f"Failed to load timeout config: {e}")
|
|
162
|
+
return {}
|
|
163
|
+
|
|
164
|
+
def get_timeout_config(
|
|
165
|
+
self, hook_name: str, custom_config: Optional[HookTimeoutConfig] = None
|
|
166
|
+
) -> HookTimeoutConfig:
|
|
167
|
+
"""Get timeout configuration for a specific hook"""
|
|
168
|
+
if custom_config:
|
|
169
|
+
return custom_config
|
|
170
|
+
|
|
171
|
+
# Load from config file
|
|
172
|
+
config = self.load_config()
|
|
173
|
+
hook_configs = config.get("hook_configs", {})
|
|
174
|
+
|
|
175
|
+
if hook_name in hook_configs:
|
|
176
|
+
hook_config = hook_configs[hook_name]
|
|
177
|
+
policy_name = hook_config.get("policy", "normal")
|
|
178
|
+
policy = TimeoutPolicy(policy_name)
|
|
179
|
+
|
|
180
|
+
return HookTimeoutConfig(
|
|
181
|
+
policy=policy,
|
|
182
|
+
custom_timeout_ms=hook_config.get("timeout_ms"),
|
|
183
|
+
retry_count=hook_config.get("retry_count", 1),
|
|
184
|
+
retry_delay_ms=hook_config.get("retry_delay_ms", 200),
|
|
185
|
+
graceful_degradation=hook_config.get("graceful_degradation", True),
|
|
186
|
+
memory_limit_mb=hook_config.get("memory_limit_mb"),
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
# Use default based on hook name patterns
|
|
190
|
+
if "pre_tool" in hook_name.lower():
|
|
191
|
+
return self._default_configs[TimeoutPolicy.FAST]
|
|
192
|
+
elif any(x in hook_name.lower() for x in ["session_start", "session_end"]):
|
|
193
|
+
return self._default_configs[TimeoutPolicy.NORMAL]
|
|
194
|
+
else:
|
|
195
|
+
return self._default_configs[TimeoutPolicy.NORMAL]
|
|
196
|
+
|
|
197
|
+
def create_timeout_session(self, hook_name: str, config: Optional[HookTimeoutConfig] = None) -> TimeoutSession:
|
|
198
|
+
"""Create a new timeout session for a hook"""
|
|
199
|
+
if not config:
|
|
200
|
+
config = self.get_timeout_config(hook_name)
|
|
201
|
+
|
|
202
|
+
# Calculate timeout in seconds
|
|
203
|
+
timeout_ms = config.custom_timeout_ms
|
|
204
|
+
if timeout_ms is None:
|
|
205
|
+
# Default based on policy
|
|
206
|
+
policy_timeouts = {
|
|
207
|
+
TimeoutPolicy.FAST: 2000,
|
|
208
|
+
TimeoutPolicy.NORMAL: 5000,
|
|
209
|
+
TimeoutPolicy.SLOW: 15000,
|
|
210
|
+
}
|
|
211
|
+
timeout_ms = policy_timeouts.get(config.policy, 5000)
|
|
212
|
+
|
|
213
|
+
timeout_seconds = timeout_ms / 1000.0
|
|
214
|
+
|
|
215
|
+
# Generate unique hook ID
|
|
216
|
+
hook_id = f"{hook_name}_{int(time.time() * 1000)}_{threading.get_ident()}"
|
|
217
|
+
|
|
218
|
+
session = TimeoutSession(
|
|
219
|
+
hook_id=hook_id,
|
|
220
|
+
start_time=datetime.now(),
|
|
221
|
+
timeout_seconds=timeout_seconds,
|
|
222
|
+
thread_id=threading.get_ident(),
|
|
223
|
+
callback=config.on_timeout_callback,
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
with self._session_lock:
|
|
227
|
+
self._active_sessions[hook_id] = session
|
|
228
|
+
|
|
229
|
+
return session
|
|
230
|
+
|
|
231
|
+
def start_timeout(self, session: TimeoutSession) -> None:
|
|
232
|
+
"""Start timeout monitoring for a session"""
|
|
233
|
+
if self._is_windows:
|
|
234
|
+
self._start_windows_timeout(session)
|
|
235
|
+
else:
|
|
236
|
+
self._start_unix_timeout(session)
|
|
237
|
+
|
|
238
|
+
def _start_windows_timeout(self, session: TimeoutSession) -> None:
|
|
239
|
+
"""Windows: Use threading.Timer for timeout"""
|
|
240
|
+
|
|
241
|
+
def timeout_handler():
|
|
242
|
+
if session.hook_id in self._active_sessions and not session.completed:
|
|
243
|
+
execution_time = (datetime.now() - session.start_time).total_seconds()
|
|
244
|
+
error_msg = (
|
|
245
|
+
f"Hook {session.hook_id} timed out after "
|
|
246
|
+
f"{session.timeout_seconds}s (execution: {execution_time:.2f}s)"
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
# Execute callback if provided
|
|
250
|
+
if session.callback:
|
|
251
|
+
try:
|
|
252
|
+
session.callback(session)
|
|
253
|
+
except Exception as e:
|
|
254
|
+
self._logger.error(f"Timeout callback failed: {e}")
|
|
255
|
+
|
|
256
|
+
# Don't raise exception in timer thread, just mark as completed
|
|
257
|
+
session.completed = True
|
|
258
|
+
self._logger.warning(error_msg)
|
|
259
|
+
|
|
260
|
+
timer = threading.Timer(session.timeout_seconds, timeout_handler)
|
|
261
|
+
timer.daemon = True
|
|
262
|
+
timer.start()
|
|
263
|
+
|
|
264
|
+
# Store timer for cleanup
|
|
265
|
+
session.cleanup_actions.append(lambda: timer.cancel() if timer.is_alive() else None)
|
|
266
|
+
|
|
267
|
+
def _start_unix_timeout(self, session: TimeoutSession) -> None:
|
|
268
|
+
"""Unix: Use signal.SIGALRM for timeout"""
|
|
269
|
+
with self._signal_lock:
|
|
270
|
+
# Register our signal handler if not already done
|
|
271
|
+
if self._original_signal_handler is None:
|
|
272
|
+
self._original_signal_handler = signal.signal( # type: ignore[assignment]
|
|
273
|
+
signal.SIGALRM, self._unix_signal_handler
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
# Set alarm for this session
|
|
277
|
+
signal.alarm(int(session.timeout_seconds))
|
|
278
|
+
|
|
279
|
+
# Store cleanup action
|
|
280
|
+
session.cleanup_actions.append(lambda: signal.alarm(0))
|
|
281
|
+
|
|
282
|
+
def _unix_signal_handler(self, signum: int, frame) -> None:
|
|
283
|
+
"""Unix signal handler for timeout"""
|
|
284
|
+
with self._session_lock:
|
|
285
|
+
# Find the session that timed out
|
|
286
|
+
current_thread = threading.get_ident()
|
|
287
|
+
timed_out_session = None
|
|
288
|
+
|
|
289
|
+
for hook_id, session in self._active_sessions.items():
|
|
290
|
+
if session.thread_id == current_thread and not session.completed:
|
|
291
|
+
timed_out_session = session
|
|
292
|
+
break
|
|
293
|
+
|
|
294
|
+
if timed_out_session:
|
|
295
|
+
execution_time = (datetime.now() - timed_out_session.start_time).total_seconds()
|
|
296
|
+
error_msg = (
|
|
297
|
+
f"Hook {timed_out_session.hook_id} timed out after "
|
|
298
|
+
f"{timed_out_session.timeout_seconds}s (execution: {execution_time:.2f}s)"
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
# Execute callback if provided
|
|
302
|
+
if timed_out_session.callback:
|
|
303
|
+
try:
|
|
304
|
+
timed_out_session.callback(timed_out_session)
|
|
305
|
+
except Exception as e:
|
|
306
|
+
self._logger.error(f"Timeout callback failed: {e}")
|
|
307
|
+
|
|
308
|
+
# Mark as completed
|
|
309
|
+
timed_out_session.completed = True
|
|
310
|
+
|
|
311
|
+
# Raise timeout exception
|
|
312
|
+
raise HookTimeoutError(
|
|
313
|
+
error_msg,
|
|
314
|
+
hook_id=timed_out_session.hook_id,
|
|
315
|
+
timeout_seconds=timed_out_session.timeout_seconds,
|
|
316
|
+
execution_time=execution_time,
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
def cancel_timeout(self, session: TimeoutSession) -> None:
|
|
320
|
+
"""Cancel timeout for a session and perform cleanup"""
|
|
321
|
+
session.completed = True
|
|
322
|
+
|
|
323
|
+
# Execute cleanup actions
|
|
324
|
+
for cleanup_action in session.cleanup_actions:
|
|
325
|
+
try:
|
|
326
|
+
if cleanup_action:
|
|
327
|
+
cleanup_action()
|
|
328
|
+
except Exception as e:
|
|
329
|
+
self._logger.warning(f"Cleanup action failed: {e}")
|
|
330
|
+
|
|
331
|
+
# Remove from active sessions
|
|
332
|
+
with self._session_lock:
|
|
333
|
+
if session.hook_id in self._active_sessions:
|
|
334
|
+
del self._active_sessions[session.hook_id]
|
|
335
|
+
|
|
336
|
+
def execute_with_timeout(
|
|
337
|
+
self,
|
|
338
|
+
hook_name: str,
|
|
339
|
+
func: Callable,
|
|
340
|
+
*args,
|
|
341
|
+
config: Optional[HookTimeoutConfig] = None,
|
|
342
|
+
**kwargs,
|
|
343
|
+
) -> Any:
|
|
344
|
+
"""Execute a function with timeout management and retry logic"""
|
|
345
|
+
if not config:
|
|
346
|
+
config = self.get_timeout_config(hook_name)
|
|
347
|
+
|
|
348
|
+
last_exception: Optional[Exception] = None
|
|
349
|
+
|
|
350
|
+
for attempt in range(config.retry_count + 1):
|
|
351
|
+
session = self.create_timeout_session(hook_name, config)
|
|
352
|
+
|
|
353
|
+
try:
|
|
354
|
+
# Check memory limit if specified
|
|
355
|
+
if config.memory_limit_mb:
|
|
356
|
+
self._check_memory_usage(config.memory_limit_mb)
|
|
357
|
+
|
|
358
|
+
# Start timeout
|
|
359
|
+
self.start_timeout(session)
|
|
360
|
+
|
|
361
|
+
# Execute function
|
|
362
|
+
start_time = time.time()
|
|
363
|
+
result = func(*args, **kwargs)
|
|
364
|
+
execution_time = time.time() - start_time
|
|
365
|
+
|
|
366
|
+
# Cancel timeout on success
|
|
367
|
+
self.cancel_timeout(session)
|
|
368
|
+
|
|
369
|
+
self._logger.debug(f"Hook {hook_name} completed in {execution_time:.2f}s")
|
|
370
|
+
return result
|
|
371
|
+
|
|
372
|
+
except HookTimeoutError as e:
|
|
373
|
+
last_exception = e
|
|
374
|
+
self.cancel_timeout(session)
|
|
375
|
+
|
|
376
|
+
if attempt < config.retry_count:
|
|
377
|
+
self._logger.warning(f"Hook {hook_name} timeout, retrying ({attempt + 1}/{config.retry_count})")
|
|
378
|
+
time.sleep(config.retry_delay_ms / 1000.0)
|
|
379
|
+
else:
|
|
380
|
+
self._logger.error(f"Hook {hook_name} failed after {config.retry_count} retries")
|
|
381
|
+
|
|
382
|
+
if config.graceful_degradation:
|
|
383
|
+
return self._get_graceful_degradation_result(hook_name)
|
|
384
|
+
else:
|
|
385
|
+
raise
|
|
386
|
+
|
|
387
|
+
except Exception as e:
|
|
388
|
+
last_exception = e
|
|
389
|
+
self.cancel_timeout(session)
|
|
390
|
+
|
|
391
|
+
if attempt < config.retry_count:
|
|
392
|
+
self._logger.warning(f"Hook {hook_name} error, retrying ({attempt + 1}/{config.retry_count}): {e}")
|
|
393
|
+
time.sleep(config.retry_delay_ms / 1000.0)
|
|
394
|
+
else:
|
|
395
|
+
self._logger.error(f"Hook {hook_name} failed with exception: {e}")
|
|
396
|
+
raise
|
|
397
|
+
|
|
398
|
+
# This should not be reached, but handle just in case
|
|
399
|
+
if last_exception:
|
|
400
|
+
raise last_exception
|
|
401
|
+
|
|
402
|
+
def _check_memory_usage(self, limit_mb: int) -> None:
|
|
403
|
+
"""Check current memory usage against limit"""
|
|
404
|
+
try:
|
|
405
|
+
import psutil
|
|
406
|
+
|
|
407
|
+
process = psutil.Process()
|
|
408
|
+
memory_mb = process.memory_info().rss / 1024 / 1024
|
|
409
|
+
|
|
410
|
+
if memory_mb > limit_mb:
|
|
411
|
+
self._logger.warning(f"Memory usage ({memory_mb:.1f}MB) exceeds limit ({limit_mb}MB)")
|
|
412
|
+
# Could implement more aggressive cleanup here
|
|
413
|
+
except ImportError:
|
|
414
|
+
# psutil not available, skip memory checking
|
|
415
|
+
pass
|
|
416
|
+
except Exception as e:
|
|
417
|
+
self._logger.warning(f"Memory check failed: {e}")
|
|
418
|
+
|
|
419
|
+
def _get_graceful_degradation_result(self, hook_name: str) -> Any:
|
|
420
|
+
"""Return a safe default result for graceful degradation"""
|
|
421
|
+
# Return different defaults based on hook type
|
|
422
|
+
if "session_start" in hook_name.lower():
|
|
423
|
+
return {
|
|
424
|
+
"continue": True,
|
|
425
|
+
"systemMessage": "⚠️ Session start hook timeout - continuing with reduced functionality",
|
|
426
|
+
"graceful_degradation": True,
|
|
427
|
+
}
|
|
428
|
+
elif "session_end" in hook_name.lower():
|
|
429
|
+
return {
|
|
430
|
+
"continue": True,
|
|
431
|
+
"success": False,
|
|
432
|
+
"error": "Hook timeout but continuing due to graceful degradation",
|
|
433
|
+
"graceful_degradation": True,
|
|
434
|
+
}
|
|
435
|
+
elif "pre_tool" in hook_name.lower():
|
|
436
|
+
return {
|
|
437
|
+
"continue": True,
|
|
438
|
+
"systemMessage": "⚠️ Validation timeout - operation proceeding",
|
|
439
|
+
"graceful_degradation": True,
|
|
440
|
+
}
|
|
441
|
+
else:
|
|
442
|
+
return {
|
|
443
|
+
"continue": True,
|
|
444
|
+
"error": "Hook timeout but continuing due to graceful degradation",
|
|
445
|
+
"graceful_degradation": True,
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
def get_active_sessions(self) -> Dict[str, Dict[str, Any]]:
|
|
449
|
+
"""Get information about active timeout sessions"""
|
|
450
|
+
with self._session_lock:
|
|
451
|
+
return {
|
|
452
|
+
hook_id: {
|
|
453
|
+
"hook_id": session.hook_id,
|
|
454
|
+
"start_time": session.start_time.isoformat(),
|
|
455
|
+
"timeout_seconds": session.timeout_seconds,
|
|
456
|
+
"thread_id": session.thread_id,
|
|
457
|
+
"completed": session.completed,
|
|
458
|
+
"elapsed": (datetime.now() - session.start_time).total_seconds(),
|
|
459
|
+
}
|
|
460
|
+
for hook_id, session in self._active_sessions.items()
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
def cleanup_completed_sessions(self) -> int:
|
|
464
|
+
"""Clean up completed sessions and return count cleaned"""
|
|
465
|
+
with self._session_lock:
|
|
466
|
+
completed_ids = [hook_id for hook_id, session in self._active_sessions.items() if session.completed]
|
|
467
|
+
|
|
468
|
+
for hook_id in completed_ids:
|
|
469
|
+
del self._active_sessions[hook_id]
|
|
470
|
+
|
|
471
|
+
return len(completed_ids)
|
|
472
|
+
|
|
473
|
+
def shutdown(self) -> None:
|
|
474
|
+
"""Shutdown the timeout manager and clean up all resources"""
|
|
475
|
+
with self._session_lock:
|
|
476
|
+
# Cancel all active sessions
|
|
477
|
+
for session in list(self._active_sessions.values()):
|
|
478
|
+
try:
|
|
479
|
+
self.cancel_timeout(session)
|
|
480
|
+
except Exception as e:
|
|
481
|
+
self._logger.warning(f"Error cancelling session: {e}")
|
|
482
|
+
|
|
483
|
+
self._active_sessions.clear()
|
|
484
|
+
|
|
485
|
+
# Restore original signal handler on Unix
|
|
486
|
+
if not self._is_windows and self._original_signal_handler:
|
|
487
|
+
with self._signal_lock:
|
|
488
|
+
try:
|
|
489
|
+
signal.signal(signal.SIGALRM, self._original_signal_handler)
|
|
490
|
+
self._original_signal_handler = None
|
|
491
|
+
except Exception as e:
|
|
492
|
+
self._logger.warning(f"Error restoring signal handler: {e}")
|
|
493
|
+
|
|
494
|
+
self._logger.info("UnifiedTimeoutManager shutdown complete")
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
# Global instance
|
|
498
|
+
_timeout_manager = None
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
def get_timeout_manager() -> UnifiedTimeoutManager:
|
|
502
|
+
"""Get the global timeout manager instance"""
|
|
503
|
+
global _timeout_manager
|
|
504
|
+
if _timeout_manager is None:
|
|
505
|
+
_timeout_manager = UnifiedTimeoutManager()
|
|
506
|
+
return _timeout_manager
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
@contextlib.contextmanager
|
|
510
|
+
def hook_timeout_context(hook_name: str, config: Optional[HookTimeoutConfig] = None):
|
|
511
|
+
"""Context manager for hook execution with timeout management
|
|
512
|
+
|
|
513
|
+
Usage:
|
|
514
|
+
with hook_timeout_context("session_start", fast_config):
|
|
515
|
+
result = perform_hook_operations()
|
|
516
|
+
"""
|
|
517
|
+
manager = get_timeout_manager()
|
|
518
|
+
session = manager.create_timeout_session(hook_name, config)
|
|
519
|
+
|
|
520
|
+
try:
|
|
521
|
+
manager.start_timeout(session)
|
|
522
|
+
yield session
|
|
523
|
+
except Exception as e:
|
|
524
|
+
# Re-raise with enhanced context
|
|
525
|
+
if isinstance(e, HookTimeoutError):
|
|
526
|
+
raise
|
|
527
|
+
else:
|
|
528
|
+
raise
|
|
529
|
+
finally:
|
|
530
|
+
manager.cancel_timeout(session)
|