crackerjack 0.37.9__py3-none-any.whl → 0.45.2__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.
- crackerjack/README.md +19 -0
- crackerjack/__init__.py +30 -1
- crackerjack/__main__.py +342 -1263
- crackerjack/adapters/README.md +18 -0
- crackerjack/adapters/__init__.py +27 -5
- crackerjack/adapters/_output_paths.py +167 -0
- crackerjack/adapters/_qa_adapter_base.py +309 -0
- crackerjack/adapters/_tool_adapter_base.py +706 -0
- crackerjack/adapters/ai/README.md +65 -0
- crackerjack/adapters/ai/__init__.py +5 -0
- crackerjack/adapters/ai/claude.py +853 -0
- crackerjack/adapters/complexity/README.md +53 -0
- crackerjack/adapters/complexity/__init__.py +10 -0
- crackerjack/adapters/complexity/complexipy.py +641 -0
- crackerjack/adapters/dependency/__init__.py +22 -0
- crackerjack/adapters/dependency/pip_audit.py +418 -0
- crackerjack/adapters/format/README.md +72 -0
- crackerjack/adapters/format/__init__.py +11 -0
- crackerjack/adapters/format/mdformat.py +313 -0
- crackerjack/adapters/format/ruff.py +516 -0
- crackerjack/adapters/lint/README.md +47 -0
- crackerjack/adapters/lint/__init__.py +11 -0
- crackerjack/adapters/lint/codespell.py +273 -0
- crackerjack/adapters/lsp/README.md +49 -0
- crackerjack/adapters/lsp/__init__.py +27 -0
- crackerjack/adapters/{rust_tool_manager.py → lsp/_manager.py} +3 -3
- crackerjack/adapters/{skylos_adapter.py → lsp/skylos.py} +59 -7
- crackerjack/adapters/{zuban_adapter.py → lsp/zuban.py} +3 -6
- crackerjack/adapters/refactor/README.md +59 -0
- crackerjack/adapters/refactor/__init__.py +12 -0
- crackerjack/adapters/refactor/creosote.py +318 -0
- crackerjack/adapters/refactor/refurb.py +406 -0
- crackerjack/adapters/refactor/skylos.py +494 -0
- crackerjack/adapters/sast/README.md +132 -0
- crackerjack/adapters/sast/__init__.py +32 -0
- crackerjack/adapters/sast/_base.py +201 -0
- crackerjack/adapters/sast/bandit.py +423 -0
- crackerjack/adapters/sast/pyscn.py +405 -0
- crackerjack/adapters/sast/semgrep.py +241 -0
- crackerjack/adapters/security/README.md +111 -0
- crackerjack/adapters/security/__init__.py +17 -0
- crackerjack/adapters/security/gitleaks.py +339 -0
- crackerjack/adapters/type/README.md +52 -0
- crackerjack/adapters/type/__init__.py +12 -0
- crackerjack/adapters/type/pyrefly.py +402 -0
- crackerjack/adapters/type/ty.py +402 -0
- crackerjack/adapters/type/zuban.py +522 -0
- crackerjack/adapters/utility/README.md +51 -0
- crackerjack/adapters/utility/__init__.py +10 -0
- crackerjack/adapters/utility/checks.py +884 -0
- crackerjack/agents/README.md +264 -0
- crackerjack/agents/__init__.py +40 -12
- crackerjack/agents/base.py +1 -0
- crackerjack/agents/claude_code_bridge.py +641 -0
- crackerjack/agents/coordinator.py +49 -53
- crackerjack/agents/dry_agent.py +187 -3
- crackerjack/agents/enhanced_coordinator.py +279 -0
- crackerjack/agents/enhanced_proactive_agent.py +185 -0
- crackerjack/agents/error_middleware.py +53 -0
- crackerjack/agents/formatting_agent.py +6 -8
- crackerjack/agents/helpers/__init__.py +9 -0
- crackerjack/agents/helpers/performance/__init__.py +22 -0
- crackerjack/agents/helpers/performance/performance_ast_analyzer.py +357 -0
- crackerjack/agents/helpers/performance/performance_pattern_detector.py +909 -0
- crackerjack/agents/helpers/performance/performance_recommender.py +572 -0
- crackerjack/agents/helpers/refactoring/__init__.py +22 -0
- crackerjack/agents/helpers/refactoring/code_transformer.py +536 -0
- crackerjack/agents/helpers/refactoring/complexity_analyzer.py +344 -0
- crackerjack/agents/helpers/refactoring/dead_code_detector.py +437 -0
- crackerjack/agents/helpers/test_creation/__init__.py +19 -0
- crackerjack/agents/helpers/test_creation/test_ast_analyzer.py +216 -0
- crackerjack/agents/helpers/test_creation/test_coverage_analyzer.py +643 -0
- crackerjack/agents/helpers/test_creation/test_template_generator.py +1031 -0
- crackerjack/agents/performance_agent.py +121 -1152
- crackerjack/agents/refactoring_agent.py +156 -655
- crackerjack/agents/semantic_agent.py +479 -0
- crackerjack/agents/semantic_helpers.py +356 -0
- crackerjack/agents/test_creation_agent.py +19 -1605
- crackerjack/api.py +5 -7
- crackerjack/cli/README.md +394 -0
- crackerjack/cli/__init__.py +1 -1
- crackerjack/cli/cache_handlers.py +23 -18
- crackerjack/cli/cache_handlers_enhanced.py +1 -4
- crackerjack/cli/facade.py +70 -8
- crackerjack/cli/formatting.py +13 -0
- crackerjack/cli/handlers/__init__.py +85 -0
- crackerjack/cli/handlers/advanced.py +103 -0
- crackerjack/cli/handlers/ai_features.py +62 -0
- crackerjack/cli/handlers/analytics.py +479 -0
- crackerjack/cli/handlers/changelog.py +271 -0
- crackerjack/cli/handlers/config_handlers.py +16 -0
- crackerjack/cli/handlers/coverage.py +84 -0
- crackerjack/cli/handlers/documentation.py +280 -0
- crackerjack/cli/handlers/main_handlers.py +497 -0
- crackerjack/cli/handlers/monitoring.py +371 -0
- crackerjack/cli/handlers.py +249 -49
- crackerjack/cli/interactive.py +8 -5
- crackerjack/cli/options.py +203 -110
- crackerjack/cli/semantic_handlers.py +292 -0
- crackerjack/cli/version.py +19 -0
- crackerjack/code_cleaner.py +60 -24
- crackerjack/config/README.md +472 -0
- crackerjack/config/__init__.py +256 -0
- crackerjack/config/global_lock_config.py +191 -54
- crackerjack/config/hooks.py +188 -16
- crackerjack/config/loader.py +239 -0
- crackerjack/config/settings.py +141 -0
- crackerjack/config/tool_commands.py +331 -0
- crackerjack/core/README.md +393 -0
- crackerjack/core/async_workflow_orchestrator.py +79 -53
- crackerjack/core/autofix_coordinator.py +22 -9
- crackerjack/core/container.py +10 -9
- crackerjack/core/enhanced_container.py +9 -9
- crackerjack/core/performance.py +1 -1
- crackerjack/core/performance_monitor.py +5 -3
- crackerjack/core/phase_coordinator.py +1018 -634
- crackerjack/core/proactive_workflow.py +3 -3
- crackerjack/core/retry.py +275 -0
- crackerjack/core/service_watchdog.py +167 -23
- crackerjack/core/session_coordinator.py +187 -382
- crackerjack/core/timeout_manager.py +161 -44
- crackerjack/core/workflow/__init__.py +21 -0
- crackerjack/core/workflow/workflow_ai_coordinator.py +863 -0
- crackerjack/core/workflow/workflow_event_orchestrator.py +1107 -0
- crackerjack/core/workflow/workflow_issue_parser.py +714 -0
- crackerjack/core/workflow/workflow_phase_executor.py +1158 -0
- crackerjack/core/workflow/workflow_security_gates.py +400 -0
- crackerjack/core/workflow_orchestrator.py +1247 -953
- crackerjack/data/README.md +11 -0
- crackerjack/data/__init__.py +8 -0
- crackerjack/data/models.py +79 -0
- crackerjack/data/repository.py +210 -0
- crackerjack/decorators/README.md +180 -0
- crackerjack/decorators/__init__.py +35 -0
- crackerjack/decorators/error_handling.py +649 -0
- crackerjack/decorators/error_handling_decorators.py +334 -0
- crackerjack/decorators/helpers.py +58 -0
- crackerjack/decorators/patterns.py +281 -0
- crackerjack/decorators/utils.py +58 -0
- crackerjack/docs/README.md +11 -0
- crackerjack/docs/generated/api/CLI_REFERENCE.md +1 -1
- crackerjack/documentation/README.md +11 -0
- crackerjack/documentation/ai_templates.py +1 -1
- crackerjack/documentation/dual_output_generator.py +11 -9
- crackerjack/documentation/reference_generator.py +104 -59
- crackerjack/dynamic_config.py +52 -61
- crackerjack/errors.py +1 -1
- crackerjack/events/README.md +11 -0
- crackerjack/events/__init__.py +16 -0
- crackerjack/events/telemetry.py +175 -0
- crackerjack/events/workflow_bus.py +346 -0
- crackerjack/exceptions/README.md +301 -0
- crackerjack/exceptions/__init__.py +5 -0
- crackerjack/exceptions/config.py +4 -0
- crackerjack/exceptions/tool_execution_error.py +245 -0
- crackerjack/executors/README.md +591 -0
- crackerjack/executors/__init__.py +2 -0
- crackerjack/executors/async_hook_executor.py +539 -77
- crackerjack/executors/cached_hook_executor.py +3 -3
- crackerjack/executors/hook_executor.py +967 -102
- crackerjack/executors/hook_lock_manager.py +31 -22
- crackerjack/executors/individual_hook_executor.py +66 -32
- crackerjack/executors/lsp_aware_hook_executor.py +136 -57
- crackerjack/executors/progress_hook_executor.py +282 -0
- crackerjack/executors/tool_proxy.py +23 -7
- crackerjack/hooks/README.md +485 -0
- crackerjack/hooks/lsp_hook.py +8 -9
- crackerjack/intelligence/README.md +557 -0
- crackerjack/interactive.py +37 -10
- crackerjack/managers/README.md +369 -0
- crackerjack/managers/async_hook_manager.py +41 -57
- crackerjack/managers/hook_manager.py +449 -79
- crackerjack/managers/publish_manager.py +81 -36
- crackerjack/managers/test_command_builder.py +290 -12
- crackerjack/managers/test_executor.py +93 -8
- crackerjack/managers/test_manager.py +1082 -75
- crackerjack/managers/test_progress.py +118 -26
- crackerjack/mcp/README.md +374 -0
- crackerjack/mcp/cache.py +25 -2
- crackerjack/mcp/client_runner.py +35 -18
- crackerjack/mcp/context.py +9 -9
- crackerjack/mcp/dashboard.py +24 -8
- crackerjack/mcp/enhanced_progress_monitor.py +34 -23
- crackerjack/mcp/file_monitor.py +27 -6
- crackerjack/mcp/progress_components.py +45 -34
- crackerjack/mcp/progress_monitor.py +6 -9
- crackerjack/mcp/rate_limiter.py +11 -7
- crackerjack/mcp/server.py +2 -0
- crackerjack/mcp/server_core.py +187 -55
- crackerjack/mcp/service_watchdog.py +12 -9
- crackerjack/mcp/task_manager.py +2 -2
- crackerjack/mcp/tools/README.md +27 -0
- crackerjack/mcp/tools/__init__.py +2 -0
- crackerjack/mcp/tools/core_tools.py +75 -52
- crackerjack/mcp/tools/execution_tools.py +87 -31
- crackerjack/mcp/tools/intelligence_tools.py +2 -2
- crackerjack/mcp/tools/proactive_tools.py +1 -1
- crackerjack/mcp/tools/semantic_tools.py +584 -0
- crackerjack/mcp/tools/utility_tools.py +180 -132
- crackerjack/mcp/tools/workflow_executor.py +87 -46
- crackerjack/mcp/websocket/README.md +31 -0
- crackerjack/mcp/websocket/app.py +11 -1
- crackerjack/mcp/websocket/event_bridge.py +188 -0
- crackerjack/mcp/websocket/jobs.py +27 -4
- crackerjack/mcp/websocket/monitoring/__init__.py +25 -0
- crackerjack/mcp/websocket/monitoring/api/__init__.py +19 -0
- crackerjack/mcp/websocket/monitoring/api/dependencies.py +141 -0
- crackerjack/mcp/websocket/monitoring/api/heatmap.py +154 -0
- crackerjack/mcp/websocket/monitoring/api/intelligence.py +199 -0
- crackerjack/mcp/websocket/monitoring/api/metrics.py +203 -0
- crackerjack/mcp/websocket/monitoring/api/telemetry.py +101 -0
- crackerjack/mcp/websocket/monitoring/dashboard.py +18 -0
- crackerjack/mcp/websocket/monitoring/factory.py +109 -0
- crackerjack/mcp/websocket/monitoring/filters.py +10 -0
- crackerjack/mcp/websocket/monitoring/metrics.py +64 -0
- crackerjack/mcp/websocket/monitoring/models.py +90 -0
- crackerjack/mcp/websocket/monitoring/utils.py +171 -0
- crackerjack/mcp/websocket/monitoring/websocket_manager.py +78 -0
- crackerjack/mcp/websocket/monitoring/websockets/__init__.py +17 -0
- crackerjack/mcp/websocket/monitoring/websockets/dependencies.py +126 -0
- crackerjack/mcp/websocket/monitoring/websockets/heatmap.py +176 -0
- crackerjack/mcp/websocket/monitoring/websockets/intelligence.py +291 -0
- crackerjack/mcp/websocket/monitoring/websockets/metrics.py +291 -0
- crackerjack/mcp/websocket/monitoring_endpoints.py +16 -2930
- crackerjack/mcp/websocket/server.py +1 -3
- crackerjack/mcp/websocket/websocket_handler.py +107 -6
- crackerjack/models/README.md +308 -0
- crackerjack/models/__init__.py +10 -1
- crackerjack/models/config.py +639 -22
- crackerjack/models/config_adapter.py +6 -6
- crackerjack/models/protocols.py +1167 -23
- crackerjack/models/pydantic_models.py +320 -0
- crackerjack/models/qa_config.py +145 -0
- crackerjack/models/qa_results.py +134 -0
- crackerjack/models/results.py +35 -0
- crackerjack/models/semantic_models.py +258 -0
- crackerjack/models/task.py +19 -3
- crackerjack/models/test_models.py +60 -0
- crackerjack/monitoring/README.md +11 -0
- crackerjack/monitoring/ai_agent_watchdog.py +5 -4
- crackerjack/monitoring/metrics_collector.py +4 -3
- crackerjack/monitoring/regression_prevention.py +4 -3
- crackerjack/monitoring/websocket_server.py +4 -241
- crackerjack/orchestration/README.md +340 -0
- crackerjack/orchestration/__init__.py +43 -0
- crackerjack/orchestration/advanced_orchestrator.py +20 -67
- crackerjack/orchestration/cache/README.md +312 -0
- crackerjack/orchestration/cache/__init__.py +37 -0
- crackerjack/orchestration/cache/memory_cache.py +338 -0
- crackerjack/orchestration/cache/tool_proxy_cache.py +340 -0
- crackerjack/orchestration/config.py +297 -0
- crackerjack/orchestration/coverage_improvement.py +13 -6
- crackerjack/orchestration/execution_strategies.py +6 -6
- crackerjack/orchestration/hook_orchestrator.py +1398 -0
- crackerjack/orchestration/strategies/README.md +401 -0
- crackerjack/orchestration/strategies/__init__.py +39 -0
- crackerjack/orchestration/strategies/adaptive_strategy.py +630 -0
- crackerjack/orchestration/strategies/parallel_strategy.py +237 -0
- crackerjack/orchestration/strategies/sequential_strategy.py +299 -0
- crackerjack/orchestration/test_progress_streamer.py +1 -1
- crackerjack/plugins/README.md +11 -0
- crackerjack/plugins/hooks.py +3 -2
- crackerjack/plugins/loader.py +3 -3
- crackerjack/plugins/managers.py +1 -1
- crackerjack/py313.py +191 -0
- crackerjack/security/README.md +11 -0
- crackerjack/services/README.md +374 -0
- crackerjack/services/__init__.py +8 -21
- crackerjack/services/ai/README.md +295 -0
- crackerjack/services/ai/__init__.py +7 -0
- crackerjack/services/ai/advanced_optimizer.py +878 -0
- crackerjack/services/{contextual_ai_assistant.py → ai/contextual_ai_assistant.py} +5 -3
- crackerjack/services/ai/embeddings.py +444 -0
- crackerjack/services/ai/intelligent_commit.py +328 -0
- crackerjack/services/ai/predictive_analytics.py +510 -0
- crackerjack/services/api_extractor.py +5 -3
- crackerjack/services/bounded_status_operations.py +45 -5
- crackerjack/services/cache.py +249 -318
- crackerjack/services/changelog_automation.py +7 -3
- crackerjack/services/command_execution_service.py +305 -0
- crackerjack/services/config_integrity.py +83 -39
- crackerjack/services/config_merge.py +9 -6
- crackerjack/services/config_service.py +198 -0
- crackerjack/services/config_template.py +13 -26
- crackerjack/services/coverage_badge_service.py +6 -4
- crackerjack/services/coverage_ratchet.py +53 -27
- crackerjack/services/debug.py +18 -7
- crackerjack/services/dependency_analyzer.py +4 -4
- crackerjack/services/dependency_monitor.py +13 -13
- crackerjack/services/documentation_generator.py +4 -2
- crackerjack/services/documentation_service.py +62 -33
- crackerjack/services/enhanced_filesystem.py +81 -27
- crackerjack/services/enterprise_optimizer.py +1 -1
- crackerjack/services/error_pattern_analyzer.py +10 -10
- crackerjack/services/file_filter.py +221 -0
- crackerjack/services/file_hasher.py +5 -7
- crackerjack/services/file_io_service.py +361 -0
- crackerjack/services/file_modifier.py +615 -0
- crackerjack/services/filesystem.py +80 -109
- crackerjack/services/git.py +99 -5
- crackerjack/services/health_metrics.py +4 -6
- crackerjack/services/heatmap_generator.py +12 -3
- crackerjack/services/incremental_executor.py +380 -0
- crackerjack/services/initialization.py +101 -49
- crackerjack/services/log_manager.py +2 -2
- crackerjack/services/logging.py +120 -68
- crackerjack/services/lsp_client.py +12 -12
- crackerjack/services/memory_optimizer.py +27 -22
- crackerjack/services/monitoring/README.md +30 -0
- crackerjack/services/monitoring/__init__.py +9 -0
- crackerjack/services/monitoring/dependency_monitor.py +678 -0
- crackerjack/services/monitoring/error_pattern_analyzer.py +676 -0
- crackerjack/services/monitoring/health_metrics.py +716 -0
- crackerjack/services/monitoring/metrics.py +587 -0
- crackerjack/services/{performance_benchmarks.py → monitoring/performance_benchmarks.py} +100 -14
- crackerjack/services/{performance_cache.py → monitoring/performance_cache.py} +21 -15
- crackerjack/services/{performance_monitor.py → monitoring/performance_monitor.py} +10 -6
- crackerjack/services/parallel_executor.py +166 -55
- crackerjack/services/patterns/__init__.py +142 -0
- crackerjack/services/patterns/agents.py +107 -0
- crackerjack/services/patterns/code/__init__.py +15 -0
- crackerjack/services/patterns/code/detection.py +118 -0
- crackerjack/services/patterns/code/imports.py +107 -0
- crackerjack/services/patterns/code/paths.py +159 -0
- crackerjack/services/patterns/code/performance.py +119 -0
- crackerjack/services/patterns/code/replacement.py +36 -0
- crackerjack/services/patterns/core.py +212 -0
- crackerjack/services/patterns/documentation/__init__.py +14 -0
- crackerjack/services/patterns/documentation/badges_markdown.py +96 -0
- crackerjack/services/patterns/documentation/comments_blocks.py +83 -0
- crackerjack/services/patterns/documentation/docstrings.py +89 -0
- crackerjack/services/patterns/formatting.py +226 -0
- crackerjack/services/patterns/operations.py +339 -0
- crackerjack/services/patterns/security/__init__.py +23 -0
- crackerjack/services/patterns/security/code_injection.py +122 -0
- crackerjack/services/patterns/security/credentials.py +190 -0
- crackerjack/services/patterns/security/path_traversal.py +221 -0
- crackerjack/services/patterns/security/unsafe_operations.py +216 -0
- crackerjack/services/patterns/templates.py +62 -0
- crackerjack/services/patterns/testing/__init__.py +18 -0
- crackerjack/services/patterns/testing/error_patterns.py +107 -0
- crackerjack/services/patterns/testing/pytest_output.py +126 -0
- crackerjack/services/patterns/tool_output/__init__.py +16 -0
- crackerjack/services/patterns/tool_output/bandit.py +72 -0
- crackerjack/services/patterns/tool_output/other.py +97 -0
- crackerjack/services/patterns/tool_output/pyright.py +67 -0
- crackerjack/services/patterns/tool_output/ruff.py +44 -0
- crackerjack/services/patterns/url_sanitization.py +114 -0
- crackerjack/services/patterns/utilities.py +42 -0
- crackerjack/services/patterns/utils.py +339 -0
- crackerjack/services/patterns/validation.py +46 -0
- crackerjack/services/patterns/versioning.py +62 -0
- crackerjack/services/predictive_analytics.py +21 -8
- crackerjack/services/profiler.py +280 -0
- crackerjack/services/quality/README.md +415 -0
- crackerjack/services/quality/__init__.py +11 -0
- crackerjack/services/quality/anomaly_detector.py +392 -0
- crackerjack/services/quality/pattern_cache.py +333 -0
- crackerjack/services/quality/pattern_detector.py +479 -0
- crackerjack/services/quality/qa_orchestrator.py +491 -0
- crackerjack/services/{quality_baseline.py → quality/quality_baseline.py} +163 -2
- crackerjack/services/{quality_baseline_enhanced.py → quality/quality_baseline_enhanced.py} +4 -1
- crackerjack/services/{quality_intelligence.py → quality/quality_intelligence.py} +180 -16
- crackerjack/services/regex_patterns.py +58 -2987
- crackerjack/services/regex_utils.py +55 -29
- crackerjack/services/secure_status_formatter.py +42 -15
- crackerjack/services/secure_subprocess.py +35 -2
- crackerjack/services/security.py +16 -8
- crackerjack/services/server_manager.py +40 -51
- crackerjack/services/smart_scheduling.py +46 -6
- crackerjack/services/status_authentication.py +3 -3
- crackerjack/services/thread_safe_status_collector.py +1 -0
- crackerjack/services/tool_filter.py +368 -0
- crackerjack/services/tool_version_service.py +9 -5
- crackerjack/services/unified_config.py +43 -351
- crackerjack/services/vector_store.py +689 -0
- crackerjack/services/version_analyzer.py +6 -4
- crackerjack/services/version_checker.py +14 -8
- crackerjack/services/zuban_lsp_service.py +5 -4
- crackerjack/slash_commands/README.md +11 -0
- crackerjack/slash_commands/init.md +2 -12
- crackerjack/slash_commands/run.md +84 -50
- crackerjack/tools/README.md +11 -0
- crackerjack/tools/__init__.py +30 -0
- crackerjack/tools/_git_utils.py +105 -0
- crackerjack/tools/check_added_large_files.py +139 -0
- crackerjack/tools/check_ast.py +105 -0
- crackerjack/tools/check_json.py +103 -0
- crackerjack/tools/check_jsonschema.py +297 -0
- crackerjack/tools/check_toml.py +103 -0
- crackerjack/tools/check_yaml.py +110 -0
- crackerjack/tools/codespell_wrapper.py +72 -0
- crackerjack/tools/end_of_file_fixer.py +202 -0
- crackerjack/tools/format_json.py +128 -0
- crackerjack/tools/mdformat_wrapper.py +114 -0
- crackerjack/tools/trailing_whitespace.py +198 -0
- crackerjack/tools/validate_regex_patterns.py +7 -3
- crackerjack/ui/README.md +11 -0
- crackerjack/ui/dashboard_renderer.py +28 -0
- crackerjack/ui/templates/README.md +11 -0
- crackerjack/utils/console_utils.py +13 -0
- crackerjack/utils/dependency_guard.py +230 -0
- crackerjack/utils/retry_utils.py +275 -0
- crackerjack/workflows/README.md +590 -0
- crackerjack/workflows/__init__.py +46 -0
- crackerjack/workflows/actions.py +811 -0
- crackerjack/workflows/auto_fix.py +444 -0
- crackerjack/workflows/container_builder.py +499 -0
- crackerjack/workflows/definitions.py +443 -0
- crackerjack/workflows/engine.py +177 -0
- crackerjack/workflows/event_bridge.py +242 -0
- {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/METADATA +678 -98
- crackerjack-0.45.2.dist-info/RECORD +478 -0
- {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/WHEEL +1 -1
- crackerjack/managers/test_manager_backup.py +0 -1075
- crackerjack/mcp/tools/execution_tools_backup.py +0 -1011
- crackerjack/mixins/__init__.py +0 -3
- crackerjack/mixins/error_handling.py +0 -145
- crackerjack/services/config.py +0 -358
- crackerjack/ui/server_panels.py +0 -125
- crackerjack-0.37.9.dist-info/RECORD +0 -231
- /crackerjack/adapters/{rust_tool_adapter.py → lsp/_base.py} +0 -0
- /crackerjack/adapters/{lsp_client.py → lsp/_client.py} +0 -0
- {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/entry_points.txt +0 -0
- {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"""WebSocket bridge for routing WorkflowEventBus events to connected clients.
|
|
2
|
+
|
|
3
|
+
This module provides the EventBusWebSocketBridge class that connects the
|
|
4
|
+
WorkflowEventBus to WebSocket clients, enabling real-time workflow progress
|
|
5
|
+
updates without polling.
|
|
6
|
+
|
|
7
|
+
Phase 7.3: WebSocket Streaming for Real-Time Updates
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import typing as t
|
|
13
|
+
from collections import defaultdict
|
|
14
|
+
|
|
15
|
+
from acb.depends import Inject, depends
|
|
16
|
+
|
|
17
|
+
from crackerjack.events.workflow_bus import WorkflowEvent, WorkflowEventBus
|
|
18
|
+
|
|
19
|
+
if t.TYPE_CHECKING:
|
|
20
|
+
from acb.actions.events import Event
|
|
21
|
+
from fastapi import WebSocket
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@depends.inject
|
|
25
|
+
class EventBusWebSocketBridge:
|
|
26
|
+
"""Bridges workflow events to WebSocket clients for real-time updates.
|
|
27
|
+
|
|
28
|
+
This class subscribes to all WorkflowEvent types from the WorkflowEventBus
|
|
29
|
+
and routes them to appropriate WebSocket clients based on job_id.
|
|
30
|
+
|
|
31
|
+
Architecture:
|
|
32
|
+
WorkflowActions → WorkflowEventBus → EventBusWebSocketBridge → WebSocket Clients
|
|
33
|
+
|
|
34
|
+
Usage:
|
|
35
|
+
bridge = EventBusWebSocketBridge(event_bus)
|
|
36
|
+
await bridge.register_client(job_id, websocket)
|
|
37
|
+
# Events automatically routed to client
|
|
38
|
+
await bridge.unregister_client(job_id, websocket)
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
def __init__(
|
|
42
|
+
self,
|
|
43
|
+
event_bus: Inject[WorkflowEventBus] = None,
|
|
44
|
+
) -> None:
|
|
45
|
+
"""Initialize event bridge with WorkflowEventBus.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
event_bus: WorkflowEventBus instance (injected via DI)
|
|
49
|
+
"""
|
|
50
|
+
self._event_bus = event_bus
|
|
51
|
+
self._clients: dict[str, list[WebSocket]] = defaultdict(list)
|
|
52
|
+
self._subscription_ids: list[str] = []
|
|
53
|
+
|
|
54
|
+
# Subscribe to all workflow events
|
|
55
|
+
if self._event_bus:
|
|
56
|
+
self._subscribe_to_events()
|
|
57
|
+
|
|
58
|
+
def _subscribe_to_events(self) -> None:
|
|
59
|
+
"""Subscribe to all WorkflowEvent types for event routing."""
|
|
60
|
+
for event_type in WorkflowEvent:
|
|
61
|
+
subscription_id = self._event_bus.subscribe(
|
|
62
|
+
event_type,
|
|
63
|
+
self._handle_workflow_event,
|
|
64
|
+
)
|
|
65
|
+
self._subscription_ids.append(subscription_id)
|
|
66
|
+
|
|
67
|
+
async def _handle_workflow_event(self, event: Event) -> None:
|
|
68
|
+
"""Handle workflow event and route to appropriate clients.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
event: ACB Event object with workflow event data
|
|
72
|
+
"""
|
|
73
|
+
# Extract job_id from event payload
|
|
74
|
+
# Events include step_id in format "action_name_timestamp" or "workflow_id"
|
|
75
|
+
payload = event.payload
|
|
76
|
+
step_id = payload.get("step_id", "")
|
|
77
|
+
|
|
78
|
+
if not step_id:
|
|
79
|
+
# No step_id in payload, skip routing
|
|
80
|
+
return
|
|
81
|
+
|
|
82
|
+
# For now, broadcast to all connected clients
|
|
83
|
+
# In future, could parse step_id to extract workflow_id/job_id for filtering
|
|
84
|
+
all_clients: list[WebSocket] = []
|
|
85
|
+
for clients in self._clients.values():
|
|
86
|
+
all_clients.extend(clients)
|
|
87
|
+
|
|
88
|
+
if not all_clients:
|
|
89
|
+
# No clients connected
|
|
90
|
+
return
|
|
91
|
+
|
|
92
|
+
# Transform event to WebSocket message format
|
|
93
|
+
message = self._transform_event_to_message(event)
|
|
94
|
+
|
|
95
|
+
# Send to all clients
|
|
96
|
+
await self._broadcast_to_clients(all_clients, message)
|
|
97
|
+
|
|
98
|
+
def _transform_event_to_message(self, event: Event) -> dict[str, t.Any]:
|
|
99
|
+
"""Transform ACB Event to WebSocket message format.
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
event: ACB Event object
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
dict with event_type, data, and timestamp
|
|
106
|
+
"""
|
|
107
|
+
return {
|
|
108
|
+
"event_type": event.event_type.value
|
|
109
|
+
if hasattr(event.event_type, "value")
|
|
110
|
+
else str(event.event_type),
|
|
111
|
+
"data": event.payload,
|
|
112
|
+
"timestamp": event.payload.get("timestamp"),
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async def _broadcast_to_clients(
|
|
116
|
+
self,
|
|
117
|
+
clients: list[WebSocket],
|
|
118
|
+
message: dict[str, t.Any],
|
|
119
|
+
) -> None:
|
|
120
|
+
"""Broadcast message to all clients, removing disconnected ones.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
clients: List of WebSocket clients to send to
|
|
124
|
+
message: Message data to send
|
|
125
|
+
"""
|
|
126
|
+
disconnected: list[WebSocket] = []
|
|
127
|
+
|
|
128
|
+
for websocket in clients:
|
|
129
|
+
try:
|
|
130
|
+
await websocket.send_json(message)
|
|
131
|
+
except Exception:
|
|
132
|
+
# Client disconnected, mark for removal
|
|
133
|
+
disconnected.append(websocket)
|
|
134
|
+
|
|
135
|
+
# Remove disconnected clients
|
|
136
|
+
for websocket in disconnected:
|
|
137
|
+
clients.remove(websocket)
|
|
138
|
+
|
|
139
|
+
async def register_client(self, job_id: str, websocket: WebSocket) -> None:
|
|
140
|
+
"""Register WebSocket client for job-specific event updates.
|
|
141
|
+
|
|
142
|
+
Args:
|
|
143
|
+
job_id: Job identifier to subscribe to
|
|
144
|
+
websocket: WebSocket connection to send events to
|
|
145
|
+
"""
|
|
146
|
+
self._clients[job_id].append(websocket)
|
|
147
|
+
|
|
148
|
+
async def unregister_client(self, job_id: str, websocket: WebSocket) -> None:
|
|
149
|
+
"""Unregister WebSocket client from event updates.
|
|
150
|
+
|
|
151
|
+
Args:
|
|
152
|
+
job_id: Job identifier to unsubscribe from
|
|
153
|
+
websocket: WebSocket connection to remove
|
|
154
|
+
"""
|
|
155
|
+
if job_id in self._clients:
|
|
156
|
+
with suppress(ValueError):
|
|
157
|
+
self._clients[job_id].remove(websocket)
|
|
158
|
+
|
|
159
|
+
# Clean up empty job client lists
|
|
160
|
+
if not self._clients[job_id]:
|
|
161
|
+
del self._clients[job_id]
|
|
162
|
+
|
|
163
|
+
def get_active_connections(self) -> int:
|
|
164
|
+
"""Get count of active WebSocket connections.
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
Total number of active WebSocket connections across all jobs
|
|
168
|
+
"""
|
|
169
|
+
return sum(len(clients) for clients in self._clients.values())
|
|
170
|
+
|
|
171
|
+
def get_jobs_with_clients(self) -> list[str]:
|
|
172
|
+
"""Get list of job IDs with active clients.
|
|
173
|
+
|
|
174
|
+
Returns:
|
|
175
|
+
List of job_id strings that have connected clients
|
|
176
|
+
"""
|
|
177
|
+
return [job_id for job_id, clients in self._clients.items() if clients]
|
|
178
|
+
|
|
179
|
+
def cleanup(self) -> None:
|
|
180
|
+
"""Cleanup event subscriptions and client connections."""
|
|
181
|
+
# Unsubscribe from all events
|
|
182
|
+
if self._event_bus:
|
|
183
|
+
for subscription_id in self._subscription_ids:
|
|
184
|
+
self._event_bus.unsubscribe(subscription_id)
|
|
185
|
+
|
|
186
|
+
# Clear client lists
|
|
187
|
+
self._clients.clear()
|
|
188
|
+
self._subscription_ids.clear()
|
|
@@ -5,15 +5,23 @@ import typing as t
|
|
|
5
5
|
import uuid
|
|
6
6
|
from contextlib import suppress
|
|
7
7
|
from pathlib import Path
|
|
8
|
-
from typing import Any
|
|
8
|
+
from typing import Any, Final
|
|
9
|
+
from uuid import UUID, uuid4
|
|
9
10
|
|
|
10
|
-
from
|
|
11
|
+
from acb import console
|
|
12
|
+
from acb.depends import depends
|
|
11
13
|
|
|
12
14
|
from crackerjack.core.timeout_manager import TimeoutStrategy, get_timeout_manager
|
|
13
15
|
from crackerjack.services.input_validator import get_input_validator
|
|
14
16
|
from crackerjack.services.secure_path_utils import SecurePathValidator
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
# Phase 9.3: ACB Integration - Module registration for dependency injection
|
|
19
|
+
# Note: Currently using file-based JSON storage for job tracking
|
|
20
|
+
# Future enhancement: Consider ACB SQL adapter for scalability if needed
|
|
21
|
+
MODULE_ID: Final[UUID] = uuid4()
|
|
22
|
+
MODULE_STATUS: Final[str] = "stable"
|
|
23
|
+
|
|
24
|
+
# console imported from acb
|
|
17
25
|
|
|
18
26
|
|
|
19
27
|
class JobManager:
|
|
@@ -380,4 +388,19 @@ class JobManager:
|
|
|
380
388
|
|
|
381
389
|
def cleanup(self) -> None:
|
|
382
390
|
self.is_running = False
|
|
383
|
-
console.print("[blue]Job manager cleanup completed[/
|
|
391
|
+
console.print("[blue]Job manager cleanup completed[/blue]")
|
|
392
|
+
|
|
393
|
+
@property
|
|
394
|
+
def module_id(self) -> UUID:
|
|
395
|
+
"""Reference to module-level MODULE_ID for ACB integration."""
|
|
396
|
+
return MODULE_ID
|
|
397
|
+
|
|
398
|
+
@property
|
|
399
|
+
def module_status(self) -> str:
|
|
400
|
+
"""Module status for ACB integration."""
|
|
401
|
+
return MODULE_STATUS
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
# Phase 9.3: ACB Integration - Register JobManager with dependency injection system
|
|
405
|
+
with suppress(Exception):
|
|
406
|
+
depends.set(JobManager)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Monitoring endpoints module.
|
|
2
|
+
|
|
3
|
+
This module provides WebSocket and REST API endpoints for real-time
|
|
4
|
+
monitoring, metrics streaming, intelligence features, and error analysis.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .factory import create_monitoring_endpoints
|
|
8
|
+
from .models import (
|
|
9
|
+
HealthResponseModel,
|
|
10
|
+
TelemetryEventModel,
|
|
11
|
+
TelemetryResponseModel,
|
|
12
|
+
TelemetrySnapshotModel,
|
|
13
|
+
UnifiedMetricsModel,
|
|
14
|
+
)
|
|
15
|
+
from .websocket_manager import MonitoringWebSocketManager
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"create_monitoring_endpoints",
|
|
19
|
+
"MonitoringWebSocketManager",
|
|
20
|
+
"TelemetryEventModel",
|
|
21
|
+
"TelemetrySnapshotModel",
|
|
22
|
+
"TelemetryResponseModel",
|
|
23
|
+
"UnifiedMetricsModel",
|
|
24
|
+
"HealthResponseModel",
|
|
25
|
+
]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""REST API endpoint registration.
|
|
2
|
+
|
|
3
|
+
This module provides registration functions for all REST API endpoints
|
|
4
|
+
including telemetry, metrics, intelligence, dependencies, and heatmap analysis.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .dependencies import register_dependency_api_endpoints
|
|
8
|
+
from .heatmap import register_heatmap_api_endpoints
|
|
9
|
+
from .intelligence import register_intelligence_api_endpoints
|
|
10
|
+
from .metrics import register_metrics_api_endpoints
|
|
11
|
+
from .telemetry import register_telemetry_api_endpoints
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"register_telemetry_api_endpoints",
|
|
15
|
+
"register_metrics_api_endpoints",
|
|
16
|
+
"register_intelligence_api_endpoints",
|
|
17
|
+
"register_dependency_api_endpoints",
|
|
18
|
+
"register_heatmap_api_endpoints",
|
|
19
|
+
]
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"""REST API endpoints for dependency analysis.
|
|
2
|
+
|
|
3
|
+
This module provides HTTP endpoints for dependency graph visualization,
|
|
4
|
+
metrics, clustering, and analysis triggers.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
|
|
9
|
+
from fastapi import FastAPI, HTTPException
|
|
10
|
+
from fastapi.responses import JSONResponse
|
|
11
|
+
|
|
12
|
+
from crackerjack.services.dependency_analyzer import (
|
|
13
|
+
DependencyAnalyzer,
|
|
14
|
+
DependencyGraph,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
from ..filters import _apply_graph_filters
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def register_dependency_api_endpoints(
|
|
21
|
+
app: FastAPI, dependency_analyzer: DependencyAnalyzer
|
|
22
|
+
) -> None:
|
|
23
|
+
"""Register dependency-related REST API endpoints."""
|
|
24
|
+
|
|
25
|
+
@app.get("/api/dependencies/graph")
|
|
26
|
+
async def get_dependency_graph(
|
|
27
|
+
filter_type: str = None,
|
|
28
|
+
max_nodes: int = 1000,
|
|
29
|
+
include_external: bool = False,
|
|
30
|
+
) -> None:
|
|
31
|
+
"""Get dependency graph data."""
|
|
32
|
+
return await _handle_dependency_graph_request(
|
|
33
|
+
dependency_analyzer, filter_type, max_nodes, include_external
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
@app.get("/api/dependencies/metrics")
|
|
37
|
+
async def get_dependency_metrics() -> None:
|
|
38
|
+
"""Get dependency graph metrics."""
|
|
39
|
+
return await _handle_dependency_metrics_request(dependency_analyzer)
|
|
40
|
+
|
|
41
|
+
@app.get("/api/dependencies/clusters")
|
|
42
|
+
async def get_dependency_clusters() -> None:
|
|
43
|
+
"""Get dependency graph clusters."""
|
|
44
|
+
return await _handle_dependency_clusters_request(dependency_analyzer)
|
|
45
|
+
|
|
46
|
+
@app.post("/api/dependencies/analyze")
|
|
47
|
+
async def trigger_dependency_analysis(request: dict) -> None:
|
|
48
|
+
"""Trigger fresh dependency analysis."""
|
|
49
|
+
return await _handle_dependency_analysis_request(dependency_analyzer, request)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
async def _handle_dependency_graph_request(
|
|
53
|
+
dependency_analyzer: DependencyAnalyzer,
|
|
54
|
+
filter_type: str | None,
|
|
55
|
+
max_nodes: int,
|
|
56
|
+
include_external: bool,
|
|
57
|
+
) -> JSONResponse:
|
|
58
|
+
"""Handle dependency graph API request."""
|
|
59
|
+
try:
|
|
60
|
+
graph = dependency_analyzer.analyze_project()
|
|
61
|
+
|
|
62
|
+
# Apply filters if requested
|
|
63
|
+
if filter_type or max_nodes < len(graph.nodes):
|
|
64
|
+
filters = {
|
|
65
|
+
"type": filter_type,
|
|
66
|
+
"max_nodes": max_nodes,
|
|
67
|
+
"include_external": include_external,
|
|
68
|
+
}
|
|
69
|
+
graph = await _apply_graph_filters(graph, filters)
|
|
70
|
+
|
|
71
|
+
return JSONResponse(
|
|
72
|
+
{
|
|
73
|
+
"status": "success",
|
|
74
|
+
"data": graph.to_dict(),
|
|
75
|
+
"timestamp": datetime.now().isoformat(),
|
|
76
|
+
}
|
|
77
|
+
)
|
|
78
|
+
except Exception as e:
|
|
79
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
async def _handle_dependency_metrics_request(
|
|
83
|
+
dependency_analyzer: DependencyAnalyzer,
|
|
84
|
+
) -> JSONResponse:
|
|
85
|
+
"""Handle dependency metrics API request."""
|
|
86
|
+
try:
|
|
87
|
+
graph = dependency_analyzer.analyze_project()
|
|
88
|
+
|
|
89
|
+
return JSONResponse(
|
|
90
|
+
{
|
|
91
|
+
"status": "success",
|
|
92
|
+
"data": graph.metrics,
|
|
93
|
+
"timestamp": datetime.now().isoformat(),
|
|
94
|
+
}
|
|
95
|
+
)
|
|
96
|
+
except Exception as e:
|
|
97
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
async def _handle_dependency_clusters_request(
|
|
101
|
+
dependency_analyzer: DependencyAnalyzer,
|
|
102
|
+
) -> JSONResponse:
|
|
103
|
+
"""Handle dependency clusters API request."""
|
|
104
|
+
try:
|
|
105
|
+
graph = dependency_analyzer.analyze_project()
|
|
106
|
+
|
|
107
|
+
return JSONResponse(
|
|
108
|
+
{
|
|
109
|
+
"status": "success",
|
|
110
|
+
"data": graph.clusters,
|
|
111
|
+
"timestamp": datetime.now().isoformat(),
|
|
112
|
+
}
|
|
113
|
+
)
|
|
114
|
+
except Exception as e:
|
|
115
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
async def _handle_dependency_analysis_request(
|
|
119
|
+
dependency_analyzer: DependencyAnalyzer, request: dict
|
|
120
|
+
) -> JSONResponse:
|
|
121
|
+
"""Handle dependency analysis trigger API request."""
|
|
122
|
+
try:
|
|
123
|
+
# Reset analyzer for fresh analysis
|
|
124
|
+
dependency_analyzer.dependency_graph = DependencyGraph()
|
|
125
|
+
graph = dependency_analyzer.analyze_project()
|
|
126
|
+
|
|
127
|
+
return JSONResponse(
|
|
128
|
+
{
|
|
129
|
+
"status": "success",
|
|
130
|
+
"message": "Dependency analysis completed",
|
|
131
|
+
"data": {
|
|
132
|
+
"nodes": len(graph.nodes),
|
|
133
|
+
"edges": len(graph.edges),
|
|
134
|
+
"clusters": len(graph.clusters),
|
|
135
|
+
"metrics": graph.metrics,
|
|
136
|
+
},
|
|
137
|
+
"timestamp": datetime.now().isoformat(),
|
|
138
|
+
}
|
|
139
|
+
)
|
|
140
|
+
except Exception as e:
|
|
141
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"""REST API endpoints for error heatmap analysis.
|
|
2
|
+
|
|
3
|
+
This module provides HTTP endpoints for file-based, temporal, and
|
|
4
|
+
function-based error heatmap visualization and pattern analysis.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
|
|
9
|
+
from fastapi import FastAPI, HTTPException
|
|
10
|
+
from fastapi.responses import JSONResponse
|
|
11
|
+
|
|
12
|
+
from crackerjack.services.cache import CrackerjackCache
|
|
13
|
+
from crackerjack.services.monitoring.error_pattern_analyzer import (
|
|
14
|
+
ErrorPatternAnalyzer,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def register_heatmap_api_endpoints(
|
|
19
|
+
app: FastAPI, error_analyzer: ErrorPatternAnalyzer, cache: CrackerjackCache
|
|
20
|
+
) -> None:
|
|
21
|
+
"""Register heatmap-related REST API endpoints."""
|
|
22
|
+
|
|
23
|
+
@app.get("/api/heatmap/file_errors")
|
|
24
|
+
async def get_file_error_heatmap() -> None:
|
|
25
|
+
"""Get error heat map by file."""
|
|
26
|
+
return await _handle_file_error_heatmap_request(error_analyzer)
|
|
27
|
+
|
|
28
|
+
@app.get("/api/heatmap/temporal_errors")
|
|
29
|
+
async def get_temporal_error_heatmap(time_buckets: int = 24) -> None:
|
|
30
|
+
"""Get error heat map over time."""
|
|
31
|
+
return await _handle_temporal_error_heatmap_request(
|
|
32
|
+
error_analyzer, time_buckets
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
@app.get("/api/heatmap/function_errors")
|
|
36
|
+
async def get_function_error_heatmap() -> None:
|
|
37
|
+
"""Get error heat map by function."""
|
|
38
|
+
return await _handle_function_error_heatmap_request(error_analyzer)
|
|
39
|
+
|
|
40
|
+
@app.get("/api/error_patterns")
|
|
41
|
+
async def get_error_patterns(
|
|
42
|
+
days: int = 30, min_occurrences: int = 2, severity: str | None = None
|
|
43
|
+
) -> None:
|
|
44
|
+
"""Get analyzed error patterns."""
|
|
45
|
+
return await _handle_error_patterns_request(
|
|
46
|
+
error_analyzer, days, min_occurrences, severity
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
@app.post("/api/trigger_error_analysis")
|
|
50
|
+
async def trigger_error_analysis(request: dict) -> None:
|
|
51
|
+
"""Trigger fresh error pattern analysis."""
|
|
52
|
+
return await _handle_trigger_error_analysis_request(
|
|
53
|
+
error_analyzer, cache, request
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
async def _handle_file_error_heatmap_request(
|
|
58
|
+
error_analyzer: ErrorPatternAnalyzer,
|
|
59
|
+
) -> JSONResponse:
|
|
60
|
+
"""Handle file error heatmap API request."""
|
|
61
|
+
try:
|
|
62
|
+
error_analyzer.analyze_error_patterns(days=30)
|
|
63
|
+
heatmap = error_analyzer.generate_file_error_heatmap()
|
|
64
|
+
return JSONResponse(heatmap.to_dict())
|
|
65
|
+
except Exception as e:
|
|
66
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
async def _handle_temporal_error_heatmap_request(
|
|
70
|
+
error_analyzer: ErrorPatternAnalyzer, time_buckets: int
|
|
71
|
+
) -> JSONResponse:
|
|
72
|
+
"""Handle temporal error heatmap API request."""
|
|
73
|
+
try:
|
|
74
|
+
error_analyzer.analyze_error_patterns(days=30)
|
|
75
|
+
heatmap = error_analyzer.generate_temporal_heatmap(time_buckets=time_buckets)
|
|
76
|
+
return JSONResponse(heatmap.to_dict())
|
|
77
|
+
except Exception as e:
|
|
78
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
async def _handle_function_error_heatmap_request(
|
|
82
|
+
error_analyzer: ErrorPatternAnalyzer,
|
|
83
|
+
) -> JSONResponse:
|
|
84
|
+
"""Handle function error heatmap API request."""
|
|
85
|
+
try:
|
|
86
|
+
error_analyzer.analyze_error_patterns(days=30)
|
|
87
|
+
heatmap = error_analyzer.generate_function_error_heatmap()
|
|
88
|
+
return JSONResponse(heatmap.to_dict())
|
|
89
|
+
except Exception as e:
|
|
90
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
async def _handle_error_patterns_request(
|
|
94
|
+
error_analyzer: ErrorPatternAnalyzer,
|
|
95
|
+
days: int,
|
|
96
|
+
min_occurrences: int,
|
|
97
|
+
severity: str | None,
|
|
98
|
+
) -> JSONResponse:
|
|
99
|
+
"""Handle error patterns API request."""
|
|
100
|
+
try:
|
|
101
|
+
patterns = error_analyzer.analyze_error_patterns(
|
|
102
|
+
days=days, min_occurrences=min_occurrences
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
# Filter by severity if specified
|
|
106
|
+
if severity:
|
|
107
|
+
patterns = [p for p in patterns if p.severity == severity]
|
|
108
|
+
|
|
109
|
+
return JSONResponse(
|
|
110
|
+
{
|
|
111
|
+
"patterns": [pattern.to_dict() for pattern in patterns],
|
|
112
|
+
"total_count": len(patterns),
|
|
113
|
+
"analysis_period_days": days,
|
|
114
|
+
"generated_at": datetime.now().isoformat(),
|
|
115
|
+
}
|
|
116
|
+
)
|
|
117
|
+
except Exception as e:
|
|
118
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
async def _handle_trigger_error_analysis_request(
|
|
122
|
+
error_analyzer: ErrorPatternAnalyzer, cache: CrackerjackCache, request: dict
|
|
123
|
+
) -> JSONResponse:
|
|
124
|
+
"""Handle trigger error analysis API request."""
|
|
125
|
+
try:
|
|
126
|
+
days = request.get("days", 30)
|
|
127
|
+
min_occurrences = request.get("min_occurrences", 2)
|
|
128
|
+
|
|
129
|
+
# Perform fresh analysis
|
|
130
|
+
patterns = error_analyzer.analyze_error_patterns(
|
|
131
|
+
days=days, min_occurrences=min_occurrences
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
# Store results in cache
|
|
135
|
+
cache_key = f"error_patterns_{days}d"
|
|
136
|
+
cache.set(cache_key, [p.to_dict() for p in patterns], ttl_seconds=1800)
|
|
137
|
+
|
|
138
|
+
severity_breakdown = {
|
|
139
|
+
severity: len([p for p in patterns if p.severity == severity])
|
|
140
|
+
for severity in ("low", "medium", "high", "critical")
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return JSONResponse(
|
|
144
|
+
{
|
|
145
|
+
"status": "success",
|
|
146
|
+
"message": "Error pattern analysis completed",
|
|
147
|
+
"patterns_found": len(patterns),
|
|
148
|
+
"analysis_period_days": days,
|
|
149
|
+
"severity_breakdown": severity_breakdown,
|
|
150
|
+
"generated_at": datetime.now().isoformat(),
|
|
151
|
+
}
|
|
152
|
+
)
|
|
153
|
+
except Exception as e:
|
|
154
|
+
raise HTTPException(status_code=500, detail=str(e))
|