crackerjack 0.18.2__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 +96 -2
- crackerjack/__main__.py +637 -138
- crackerjack/adapters/README.md +18 -0
- crackerjack/adapters/__init__.py +39 -0
- 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/lsp/_base.py +194 -0
- crackerjack/adapters/lsp/_client.py +358 -0
- crackerjack/adapters/lsp/_manager.py +193 -0
- crackerjack/adapters/lsp/skylos.py +283 -0
- crackerjack/adapters/lsp/zuban.py +557 -0
- 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 +66 -0
- crackerjack/agents/architect_agent.py +238 -0
- crackerjack/agents/base.py +167 -0
- crackerjack/agents/claude_code_bridge.py +641 -0
- crackerjack/agents/coordinator.py +600 -0
- crackerjack/agents/documentation_agent.py +520 -0
- crackerjack/agents/dry_agent.py +585 -0
- 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 +230 -0
- 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/import_optimization_agent.py +1181 -0
- crackerjack/agents/performance_agent.py +325 -0
- crackerjack/agents/performance_helpers.py +205 -0
- crackerjack/agents/proactive_agent.py +55 -0
- crackerjack/agents/refactoring_agent.py +511 -0
- crackerjack/agents/refactoring_helpers.py +247 -0
- crackerjack/agents/security_agent.py +793 -0
- crackerjack/agents/semantic_agent.py +479 -0
- crackerjack/agents/semantic_helpers.py +356 -0
- crackerjack/agents/test_creation_agent.py +570 -0
- crackerjack/agents/test_specialist_agent.py +526 -0
- crackerjack/agents/tracker.py +110 -0
- crackerjack/api.py +647 -0
- crackerjack/cli/README.md +394 -0
- crackerjack/cli/__init__.py +24 -0
- crackerjack/cli/cache_handlers.py +209 -0
- crackerjack/cli/cache_handlers_enhanced.py +680 -0
- crackerjack/cli/facade.py +162 -0
- 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 +700 -0
- crackerjack/cli/interactive.py +488 -0
- crackerjack/cli/options.py +1216 -0
- crackerjack/cli/semantic_handlers.py +292 -0
- crackerjack/cli/utils.py +19 -0
- crackerjack/cli/version.py +19 -0
- crackerjack/code_cleaner.py +1307 -0
- crackerjack/config/README.md +472 -0
- crackerjack/config/__init__.py +275 -0
- crackerjack/config/global_lock_config.py +207 -0
- crackerjack/config/hooks.py +390 -0
- 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/__init__.py +0 -0
- crackerjack/core/async_workflow_orchestrator.py +738 -0
- crackerjack/core/autofix_coordinator.py +282 -0
- crackerjack/core/container.py +105 -0
- crackerjack/core/enhanced_container.py +583 -0
- crackerjack/core/file_lifecycle.py +472 -0
- crackerjack/core/performance.py +244 -0
- crackerjack/core/performance_monitor.py +357 -0
- crackerjack/core/phase_coordinator.py +1227 -0
- crackerjack/core/proactive_workflow.py +267 -0
- crackerjack/core/resource_manager.py +425 -0
- crackerjack/core/retry.py +275 -0
- crackerjack/core/service_watchdog.py +601 -0
- crackerjack/core/session_coordinator.py +239 -0
- crackerjack/core/timeout_manager.py +563 -0
- crackerjack/core/websocket_lifecycle.py +410 -0
- 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 +2243 -0
- 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/INDEX.md +11 -0
- crackerjack/docs/README.md +11 -0
- crackerjack/docs/generated/api/API_REFERENCE.md +10895 -0
- crackerjack/docs/generated/api/CLI_REFERENCE.md +109 -0
- crackerjack/docs/generated/api/CROSS_REFERENCES.md +1755 -0
- crackerjack/docs/generated/api/PROTOCOLS.md +3 -0
- crackerjack/docs/generated/api/SERVICES.md +1252 -0
- crackerjack/documentation/README.md +11 -0
- crackerjack/documentation/__init__.py +31 -0
- crackerjack/documentation/ai_templates.py +756 -0
- crackerjack/documentation/dual_output_generator.py +767 -0
- crackerjack/documentation/mkdocs_integration.py +518 -0
- crackerjack/documentation/reference_generator.py +1065 -0
- crackerjack/dynamic_config.py +678 -0
- crackerjack/errors.py +378 -0
- 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 +13 -0
- crackerjack/executors/async_hook_executor.py +938 -0
- crackerjack/executors/cached_hook_executor.py +316 -0
- crackerjack/executors/hook_executor.py +1295 -0
- crackerjack/executors/hook_lock_manager.py +708 -0
- crackerjack/executors/individual_hook_executor.py +739 -0
- crackerjack/executors/lsp_aware_hook_executor.py +349 -0
- crackerjack/executors/progress_hook_executor.py +282 -0
- crackerjack/executors/tool_proxy.py +433 -0
- crackerjack/hooks/README.md +485 -0
- crackerjack/hooks/lsp_hook.py +93 -0
- crackerjack/intelligence/README.md +557 -0
- crackerjack/intelligence/__init__.py +37 -0
- crackerjack/intelligence/adaptive_learning.py +693 -0
- crackerjack/intelligence/agent_orchestrator.py +485 -0
- crackerjack/intelligence/agent_registry.py +377 -0
- crackerjack/intelligence/agent_selector.py +439 -0
- crackerjack/intelligence/integration.py +250 -0
- crackerjack/interactive.py +719 -0
- crackerjack/managers/README.md +369 -0
- crackerjack/managers/__init__.py +11 -0
- crackerjack/managers/async_hook_manager.py +135 -0
- crackerjack/managers/hook_manager.py +585 -0
- crackerjack/managers/publish_manager.py +631 -0
- crackerjack/managers/test_command_builder.py +391 -0
- crackerjack/managers/test_executor.py +474 -0
- crackerjack/managers/test_manager.py +1357 -0
- crackerjack/managers/test_progress.py +187 -0
- crackerjack/mcp/README.md +374 -0
- crackerjack/mcp/__init__.py +0 -0
- crackerjack/mcp/cache.py +352 -0
- crackerjack/mcp/client_runner.py +121 -0
- crackerjack/mcp/context.py +802 -0
- crackerjack/mcp/dashboard.py +657 -0
- crackerjack/mcp/enhanced_progress_monitor.py +493 -0
- crackerjack/mcp/file_monitor.py +394 -0
- crackerjack/mcp/progress_components.py +607 -0
- crackerjack/mcp/progress_monitor.py +1016 -0
- crackerjack/mcp/rate_limiter.py +336 -0
- crackerjack/mcp/server.py +24 -0
- crackerjack/mcp/server_core.py +526 -0
- crackerjack/mcp/service_watchdog.py +505 -0
- crackerjack/mcp/state.py +407 -0
- crackerjack/mcp/task_manager.py +259 -0
- crackerjack/mcp/tools/README.md +27 -0
- crackerjack/mcp/tools/__init__.py +19 -0
- crackerjack/mcp/tools/core_tools.py +469 -0
- crackerjack/mcp/tools/error_analyzer.py +283 -0
- crackerjack/mcp/tools/execution_tools.py +384 -0
- crackerjack/mcp/tools/intelligence_tool_registry.py +46 -0
- crackerjack/mcp/tools/intelligence_tools.py +264 -0
- crackerjack/mcp/tools/monitoring_tools.py +628 -0
- crackerjack/mcp/tools/proactive_tools.py +367 -0
- crackerjack/mcp/tools/progress_tools.py +222 -0
- crackerjack/mcp/tools/semantic_tools.py +584 -0
- crackerjack/mcp/tools/utility_tools.py +358 -0
- crackerjack/mcp/tools/workflow_executor.py +699 -0
- crackerjack/mcp/websocket/README.md +31 -0
- crackerjack/mcp/websocket/__init__.py +14 -0
- crackerjack/mcp/websocket/app.py +54 -0
- crackerjack/mcp/websocket/endpoints.py +492 -0
- crackerjack/mcp/websocket/event_bridge.py +188 -0
- crackerjack/mcp/websocket/jobs.py +406 -0
- 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 +21 -0
- crackerjack/mcp/websocket/server.py +174 -0
- crackerjack/mcp/websocket/websocket_handler.py +276 -0
- crackerjack/mcp/websocket_server.py +10 -0
- crackerjack/models/README.md +308 -0
- crackerjack/models/__init__.py +40 -0
- crackerjack/models/config.py +730 -0
- crackerjack/models/config_adapter.py +265 -0
- crackerjack/models/protocols.py +1535 -0
- crackerjack/models/pydantic_models.py +320 -0
- crackerjack/models/qa_config.py +145 -0
- crackerjack/models/qa_results.py +134 -0
- crackerjack/models/resource_protocols.py +299 -0
- crackerjack/models/results.py +35 -0
- crackerjack/models/semantic_models.py +258 -0
- crackerjack/models/task.py +173 -0
- crackerjack/models/test_models.py +60 -0
- crackerjack/monitoring/README.md +11 -0
- crackerjack/monitoring/__init__.py +0 -0
- crackerjack/monitoring/ai_agent_watchdog.py +405 -0
- crackerjack/monitoring/metrics_collector.py +427 -0
- crackerjack/monitoring/regression_prevention.py +580 -0
- crackerjack/monitoring/websocket_server.py +406 -0
- crackerjack/orchestration/README.md +340 -0
- crackerjack/orchestration/__init__.py +43 -0
- crackerjack/orchestration/advanced_orchestrator.py +894 -0
- 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 +180 -0
- crackerjack/orchestration/execution_strategies.py +361 -0
- 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 +647 -0
- crackerjack/plugins/README.md +11 -0
- crackerjack/plugins/__init__.py +15 -0
- crackerjack/plugins/base.py +200 -0
- crackerjack/plugins/hooks.py +254 -0
- crackerjack/plugins/loader.py +335 -0
- crackerjack/plugins/managers.py +264 -0
- crackerjack/py313.py +191 -0
- crackerjack/security/README.md +11 -0
- crackerjack/security/__init__.py +0 -0
- crackerjack/security/audit.py +197 -0
- crackerjack/services/README.md +374 -0
- crackerjack/services/__init__.py +9 -0
- crackerjack/services/ai/README.md +295 -0
- crackerjack/services/ai/__init__.py +7 -0
- crackerjack/services/ai/advanced_optimizer.py +878 -0
- crackerjack/services/ai/contextual_ai_assistant.py +542 -0
- 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/anomaly_detector.py +392 -0
- crackerjack/services/api_extractor.py +617 -0
- crackerjack/services/backup_service.py +467 -0
- crackerjack/services/bounded_status_operations.py +530 -0
- crackerjack/services/cache.py +369 -0
- crackerjack/services/changelog_automation.py +399 -0
- crackerjack/services/command_execution_service.py +305 -0
- crackerjack/services/config_integrity.py +132 -0
- crackerjack/services/config_merge.py +546 -0
- crackerjack/services/config_service.py +198 -0
- crackerjack/services/config_template.py +493 -0
- crackerjack/services/coverage_badge_service.py +173 -0
- crackerjack/services/coverage_ratchet.py +381 -0
- crackerjack/services/debug.py +733 -0
- crackerjack/services/dependency_analyzer.py +460 -0
- crackerjack/services/dependency_monitor.py +622 -0
- crackerjack/services/documentation_generator.py +493 -0
- crackerjack/services/documentation_service.py +704 -0
- crackerjack/services/enhanced_filesystem.py +497 -0
- crackerjack/services/enterprise_optimizer.py +865 -0
- crackerjack/services/error_pattern_analyzer.py +676 -0
- crackerjack/services/file_filter.py +221 -0
- crackerjack/services/file_hasher.py +149 -0
- crackerjack/services/file_io_service.py +361 -0
- crackerjack/services/file_modifier.py +615 -0
- crackerjack/services/filesystem.py +381 -0
- crackerjack/services/git.py +422 -0
- crackerjack/services/health_metrics.py +615 -0
- crackerjack/services/heatmap_generator.py +744 -0
- crackerjack/services/incremental_executor.py +380 -0
- crackerjack/services/initialization.py +823 -0
- crackerjack/services/input_validator.py +668 -0
- crackerjack/services/intelligent_commit.py +327 -0
- crackerjack/services/log_manager.py +289 -0
- crackerjack/services/logging.py +228 -0
- crackerjack/services/lsp_client.py +628 -0
- crackerjack/services/memory_optimizer.py +414 -0
- crackerjack/services/metrics.py +587 -0
- 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/monitoring/performance_benchmarks.py +410 -0
- crackerjack/services/monitoring/performance_cache.py +388 -0
- crackerjack/services/monitoring/performance_monitor.py +569 -0
- crackerjack/services/parallel_executor.py +527 -0
- crackerjack/services/pattern_cache.py +333 -0
- crackerjack/services/pattern_detector.py +478 -0
- 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 +523 -0
- 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/quality_baseline.py +395 -0
- crackerjack/services/quality/quality_baseline_enhanced.py +649 -0
- crackerjack/services/quality/quality_intelligence.py +949 -0
- crackerjack/services/regex_patterns.py +58 -0
- crackerjack/services/regex_utils.py +483 -0
- crackerjack/services/secure_path_utils.py +524 -0
- crackerjack/services/secure_status_formatter.py +450 -0
- crackerjack/services/secure_subprocess.py +635 -0
- crackerjack/services/security.py +239 -0
- crackerjack/services/security_logger.py +495 -0
- crackerjack/services/server_manager.py +411 -0
- crackerjack/services/smart_scheduling.py +167 -0
- crackerjack/services/status_authentication.py +460 -0
- crackerjack/services/status_security_manager.py +315 -0
- crackerjack/services/terminal_utils.py +0 -0
- crackerjack/services/thread_safe_status_collector.py +441 -0
- crackerjack/services/tool_filter.py +368 -0
- crackerjack/services/tool_version_service.py +43 -0
- crackerjack/services/unified_config.py +115 -0
- crackerjack/services/validation_rate_limiter.py +220 -0
- crackerjack/services/vector_store.py +689 -0
- crackerjack/services/version_analyzer.py +461 -0
- crackerjack/services/version_checker.py +223 -0
- crackerjack/services/websocket_resource_limiter.py +438 -0
- crackerjack/services/zuban_lsp_service.py +391 -0
- crackerjack/slash_commands/README.md +11 -0
- crackerjack/slash_commands/__init__.py +59 -0
- crackerjack/slash_commands/init.md +112 -0
- crackerjack/slash_commands/run.md +197 -0
- crackerjack/slash_commands/status.md +127 -0
- 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_input_validator_patterns.py +236 -0
- crackerjack/tools/validate_regex_patterns.py +188 -0
- crackerjack/ui/README.md +11 -0
- crackerjack/ui/__init__.py +1 -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.45.2.dist-info/METADATA +1678 -0
- crackerjack-0.45.2.dist-info/RECORD +478 -0
- {crackerjack-0.18.2.dist-info → crackerjack-0.45.2.dist-info}/WHEEL +1 -1
- crackerjack-0.45.2.dist-info/entry_points.txt +2 -0
- crackerjack/.gitignore +0 -14
- crackerjack/.libcst.codemod.yaml +0 -18
- crackerjack/.pdm.toml +0 -1
- crackerjack/.pre-commit-config.yaml +0 -91
- crackerjack/.pytest_cache/.gitignore +0 -2
- crackerjack/.pytest_cache/CACHEDIR.TAG +0 -4
- crackerjack/.pytest_cache/README.md +0 -8
- crackerjack/.pytest_cache/v/cache/nodeids +0 -1
- crackerjack/.pytest_cache/v/cache/stepwise +0 -1
- crackerjack/.ruff_cache/.gitignore +0 -1
- crackerjack/.ruff_cache/0.1.11/3256171999636029978 +0 -0
- crackerjack/.ruff_cache/0.1.14/602324811142551221 +0 -0
- crackerjack/.ruff_cache/0.1.4/10355199064880463147 +0 -0
- crackerjack/.ruff_cache/0.1.6/15140459877605758699 +0 -0
- crackerjack/.ruff_cache/0.1.7/1790508110482614856 +0 -0
- crackerjack/.ruff_cache/0.1.9/17041001205004563469 +0 -0
- crackerjack/.ruff_cache/0.11.2/4070660268492669020 +0 -0
- crackerjack/.ruff_cache/0.11.3/9818742842212983150 +0 -0
- crackerjack/.ruff_cache/0.11.4/9818742842212983150 +0 -0
- crackerjack/.ruff_cache/0.11.6/3557596832929915217 +0 -0
- crackerjack/.ruff_cache/0.11.7/10386934055395314831 +0 -0
- crackerjack/.ruff_cache/0.11.7/3557596832929915217 +0 -0
- crackerjack/.ruff_cache/0.11.8/530407680854991027 +0 -0
- crackerjack/.ruff_cache/0.2.0/10047773857155985907 +0 -0
- crackerjack/.ruff_cache/0.2.1/8522267973936635051 +0 -0
- crackerjack/.ruff_cache/0.2.2/18053836298936336950 +0 -0
- crackerjack/.ruff_cache/0.3.0/12548816621480535786 +0 -0
- crackerjack/.ruff_cache/0.3.3/11081883392474770722 +0 -0
- crackerjack/.ruff_cache/0.3.4/676973378459347183 +0 -0
- crackerjack/.ruff_cache/0.3.5/16311176246009842383 +0 -0
- crackerjack/.ruff_cache/0.5.7/1493622539551733492 +0 -0
- crackerjack/.ruff_cache/0.5.7/6231957614044513175 +0 -0
- crackerjack/.ruff_cache/0.5.7/9932762556785938009 +0 -0
- crackerjack/.ruff_cache/0.6.0/11982804814124138945 +0 -0
- crackerjack/.ruff_cache/0.6.0/12055761203849489982 +0 -0
- crackerjack/.ruff_cache/0.6.2/1206147804896221174 +0 -0
- crackerjack/.ruff_cache/0.6.4/1206147804896221174 +0 -0
- crackerjack/.ruff_cache/0.6.5/1206147804896221174 +0 -0
- crackerjack/.ruff_cache/0.6.7/3657366982708166874 +0 -0
- crackerjack/.ruff_cache/0.6.9/285614542852677309 +0 -0
- crackerjack/.ruff_cache/0.7.1/1024065805990144819 +0 -0
- crackerjack/.ruff_cache/0.7.1/285614542852677309 +0 -0
- crackerjack/.ruff_cache/0.7.3/16061516852537040135 +0 -0
- crackerjack/.ruff_cache/0.8.4/16354268377385700367 +0 -0
- crackerjack/.ruff_cache/0.9.10/12813592349865671909 +0 -0
- crackerjack/.ruff_cache/0.9.10/923908772239632759 +0 -0
- crackerjack/.ruff_cache/0.9.3/13948373885254993391 +0 -0
- crackerjack/.ruff_cache/0.9.9/12813592349865671909 +0 -0
- crackerjack/.ruff_cache/0.9.9/8843823720003377982 +0 -0
- crackerjack/.ruff_cache/CACHEDIR.TAG +0 -1
- crackerjack/crackerjack.py +0 -855
- crackerjack/pyproject.toml +0 -214
- crackerjack-0.18.2.dist-info/METADATA +0 -420
- crackerjack-0.18.2.dist-info/RECORD +0 -59
- crackerjack-0.18.2.dist-info/entry_points.txt +0 -4
- {crackerjack-0.18.2.dist-info → crackerjack-0.45.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
"""Unified WebSocket server for real-time monitoring dashboard."""
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import json
|
|
5
|
+
import logging
|
|
6
|
+
import typing as t
|
|
7
|
+
from contextlib import suppress
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
import uvicorn
|
|
12
|
+
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
|
|
13
|
+
from fastapi.responses import HTMLResponse, JSONResponse
|
|
14
|
+
|
|
15
|
+
from crackerjack.mcp.websocket.monitoring_endpoints import MonitoringWebSocketManager
|
|
16
|
+
from crackerjack.monitoring.ai_agent_watchdog import AIAgentWatchdog
|
|
17
|
+
from crackerjack.monitoring.metrics_collector import (
|
|
18
|
+
MetricsCollector,
|
|
19
|
+
UnifiedDashboardMetrics,
|
|
20
|
+
)
|
|
21
|
+
from crackerjack.services.acb_cache_adapter import CrackerjackCache
|
|
22
|
+
from crackerjack.ui.dashboard_renderer import render_monitoring_dashboard
|
|
23
|
+
|
|
24
|
+
logger = logging.getLogger(__name__)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class CrackerjackMonitoringServer:
|
|
28
|
+
"""
|
|
29
|
+
Unified monitoring server for Crackerjack with real-time WebSocket streaming.
|
|
30
|
+
|
|
31
|
+
Provides comprehensive monitoring capabilities:
|
|
32
|
+
- Real-time metrics via WebSocket
|
|
33
|
+
- Historical data storage and retrieval
|
|
34
|
+
- AI agent performance tracking
|
|
35
|
+
- System health monitoring
|
|
36
|
+
- Interactive dashboard interface
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
def __init__(self, port: int = 8675, host: str = "localhost"):
|
|
40
|
+
self.port = port
|
|
41
|
+
self.host = host
|
|
42
|
+
|
|
43
|
+
# Core services
|
|
44
|
+
self.app = FastAPI(title="Crackerjack Monitoring", version="1.0.0")
|
|
45
|
+
self.cache = CrackerjackCache()
|
|
46
|
+
self.metrics_collector = MetricsCollector(self.cache)
|
|
47
|
+
self.websocket_manager = MonitoringWebSocketManager()
|
|
48
|
+
self.ai_watchdog = AIAgentWatchdog()
|
|
49
|
+
|
|
50
|
+
# Server state
|
|
51
|
+
self.is_running = False
|
|
52
|
+
self.server_task: asyncio.Task[None] | None = None
|
|
53
|
+
|
|
54
|
+
# WebSocket connections
|
|
55
|
+
self.active_connections: dict[str, WebSocket] = {}
|
|
56
|
+
self.metrics_subscribers: set[WebSocket] = set()
|
|
57
|
+
self.alerts_subscribers: set[WebSocket] = set()
|
|
58
|
+
|
|
59
|
+
self._setup_routes()
|
|
60
|
+
self._setup_websocket_endpoints()
|
|
61
|
+
|
|
62
|
+
def _setup_routes(self) -> None:
|
|
63
|
+
"""Setup HTTP API routes."""
|
|
64
|
+
|
|
65
|
+
@self.app.get("/")
|
|
66
|
+
async def dashboard() -> HTMLResponse:
|
|
67
|
+
"""Main dashboard interface."""
|
|
68
|
+
return HTMLResponse(content=self._get_dashboard_html())
|
|
69
|
+
|
|
70
|
+
@self.app.get("/api/status")
|
|
71
|
+
async def status() -> JSONResponse:
|
|
72
|
+
"""Get server status."""
|
|
73
|
+
return JSONResponse(
|
|
74
|
+
{
|
|
75
|
+
"status": "running" if self.is_running else "stopped",
|
|
76
|
+
"timestamp": datetime.now().isoformat(),
|
|
77
|
+
"host": self.host,
|
|
78
|
+
"port": self.port,
|
|
79
|
+
"metrics_collecting": self.metrics_collector.is_collecting,
|
|
80
|
+
"active_connections": len(self.active_connections),
|
|
81
|
+
}
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
@self.app.get("/api/metrics")
|
|
85
|
+
async def current_metrics() -> JSONResponse:
|
|
86
|
+
"""Get current metrics snapshot."""
|
|
87
|
+
return JSONResponse(self.metrics_collector.get_current_metrics().to_dict())
|
|
88
|
+
|
|
89
|
+
@self.app.get("/api/metrics/summary")
|
|
90
|
+
async def metrics_summary() -> JSONResponse:
|
|
91
|
+
"""Get metrics summary for quick display."""
|
|
92
|
+
return JSONResponse(self.metrics_collector.get_metrics_summary())
|
|
93
|
+
|
|
94
|
+
@self.app.get("/api/metrics/history")
|
|
95
|
+
async def metrics_history(hours: int = 1) -> JSONResponse:
|
|
96
|
+
"""Get metrics history."""
|
|
97
|
+
history = self.metrics_collector.get_metrics_history(hours)
|
|
98
|
+
return JSONResponse([m.to_dict() for m in history])
|
|
99
|
+
|
|
100
|
+
@self.app.get("/api/agents/status")
|
|
101
|
+
async def agents_status() -> JSONResponse:
|
|
102
|
+
"""Get AI agent status and performance."""
|
|
103
|
+
return JSONResponse(
|
|
104
|
+
{
|
|
105
|
+
"agents": {
|
|
106
|
+
name: {
|
|
107
|
+
"total_handled": metrics.total_issues_handled,
|
|
108
|
+
"success_rate": metrics.successful_fixes
|
|
109
|
+
/ max(1, metrics.total_issues_handled),
|
|
110
|
+
"avg_confidence": metrics.average_confidence,
|
|
111
|
+
"avg_execution_time": metrics.average_execution_time,
|
|
112
|
+
"recent_failures": len(metrics.recent_failures),
|
|
113
|
+
}
|
|
114
|
+
for name, metrics in self.ai_watchdog.performance_metrics.items()
|
|
115
|
+
},
|
|
116
|
+
"alerts": [
|
|
117
|
+
{
|
|
118
|
+
"level": alert.level,
|
|
119
|
+
"message": alert.message,
|
|
120
|
+
"agent": alert.agent_name,
|
|
121
|
+
"timestamp": alert.timestamp.isoformat(),
|
|
122
|
+
}
|
|
123
|
+
for alert in self.ai_watchdog.get_recent_alerts(hours=1)
|
|
124
|
+
],
|
|
125
|
+
}
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
@self.app.post("/api/metrics/record")
|
|
129
|
+
async def record_metrics(data: dict[str, Any]) -> JSONResponse:
|
|
130
|
+
"""Record metrics from external sources."""
|
|
131
|
+
try:
|
|
132
|
+
if "job_start" in data:
|
|
133
|
+
self.metrics_collector.record_job_start(data["job_start"]["job_id"])
|
|
134
|
+
|
|
135
|
+
if "job_completion" in data:
|
|
136
|
+
completion = data["job_completion"]
|
|
137
|
+
self.metrics_collector.record_job_completion(
|
|
138
|
+
completion["job_id"], completion.get("success", True)
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
if "quality_data" in data:
|
|
142
|
+
quality = data["quality_data"]
|
|
143
|
+
self.metrics_collector.record_quality_data(
|
|
144
|
+
quality.get("issues_found", 0),
|
|
145
|
+
quality.get("issues_fixed", 0),
|
|
146
|
+
quality.get("coverage", 0.0),
|
|
147
|
+
quality.get("success_rate", 0.0),
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
return JSONResponse({"status": "recorded"})
|
|
151
|
+
except Exception as e:
|
|
152
|
+
logger.error(f"Error recording metrics: {e}")
|
|
153
|
+
return JSONResponse({"error": str(e)}, status_code=400)
|
|
154
|
+
|
|
155
|
+
def _setup_websocket_endpoints(self) -> None:
|
|
156
|
+
"""Setup WebSocket endpoints for real-time communication."""
|
|
157
|
+
self.app.websocket("/ws/metrics")(self._handle_metrics_websocket)
|
|
158
|
+
self.app.websocket("/ws/alerts")(self._handle_alerts_websocket)
|
|
159
|
+
|
|
160
|
+
async def _handle_metrics_websocket(self, websocket: WebSocket) -> None:
|
|
161
|
+
"""Handle metrics WebSocket connection."""
|
|
162
|
+
client_id = f"metrics_{datetime.now().timestamp()}"
|
|
163
|
+
await websocket.accept()
|
|
164
|
+
|
|
165
|
+
try:
|
|
166
|
+
await self._setup_metrics_connection(websocket, client_id)
|
|
167
|
+
await self._send_initial_metrics(websocket)
|
|
168
|
+
await self._handle_metrics_messages(websocket)
|
|
169
|
+
finally:
|
|
170
|
+
self._cleanup_connection(websocket, client_id)
|
|
171
|
+
|
|
172
|
+
async def _handle_alerts_websocket(self, websocket: WebSocket) -> None:
|
|
173
|
+
"""Handle alerts WebSocket connection."""
|
|
174
|
+
client_id = f"alerts_{datetime.now().timestamp()}"
|
|
175
|
+
await websocket.accept()
|
|
176
|
+
|
|
177
|
+
try:
|
|
178
|
+
await self._setup_alerts_connection(websocket, client_id)
|
|
179
|
+
await self._send_initial_alerts(websocket)
|
|
180
|
+
await self._handle_alerts_messages(websocket)
|
|
181
|
+
finally:
|
|
182
|
+
self._cleanup_connection(websocket, client_id)
|
|
183
|
+
|
|
184
|
+
async def _setup_metrics_connection(
|
|
185
|
+
self, websocket: WebSocket, client_id: str
|
|
186
|
+
) -> None:
|
|
187
|
+
"""Setup metrics websocket connection."""
|
|
188
|
+
self.active_connections[client_id] = websocket
|
|
189
|
+
self.metrics_subscribers.add(websocket)
|
|
190
|
+
|
|
191
|
+
async def _setup_alerts_connection(
|
|
192
|
+
self, websocket: WebSocket, client_id: str
|
|
193
|
+
) -> None:
|
|
194
|
+
"""Setup alerts websocket connection."""
|
|
195
|
+
self.active_connections[client_id] = websocket
|
|
196
|
+
self.alerts_subscribers.add(websocket)
|
|
197
|
+
|
|
198
|
+
async def _send_initial_metrics(self, websocket: WebSocket) -> None:
|
|
199
|
+
"""Send initial metrics to websocket client."""
|
|
200
|
+
current_metrics = self.metrics_collector.get_current_metrics()
|
|
201
|
+
await websocket.send_text(
|
|
202
|
+
json.dumps(
|
|
203
|
+
{
|
|
204
|
+
"type": "initial_metrics",
|
|
205
|
+
"data": current_metrics.to_dict(),
|
|
206
|
+
}
|
|
207
|
+
)
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
async def _send_initial_alerts(self, websocket: WebSocket) -> None:
|
|
211
|
+
"""Send initial alerts to websocket client."""
|
|
212
|
+
recent_alerts = self.ai_watchdog.get_recent_alerts(hours=24)
|
|
213
|
+
await websocket.send_text(
|
|
214
|
+
json.dumps(
|
|
215
|
+
{
|
|
216
|
+
"type": "initial_alerts",
|
|
217
|
+
"data": [
|
|
218
|
+
{
|
|
219
|
+
"level": alert.level,
|
|
220
|
+
"message": alert.message,
|
|
221
|
+
"agent": alert.agent_name,
|
|
222
|
+
"timestamp": alert.timestamp.isoformat(),
|
|
223
|
+
}
|
|
224
|
+
for alert in recent_alerts
|
|
225
|
+
],
|
|
226
|
+
}
|
|
227
|
+
)
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
async def _handle_metrics_messages(self, websocket: WebSocket) -> None:
|
|
231
|
+
"""Handle incoming metrics websocket messages."""
|
|
232
|
+
while True:
|
|
233
|
+
try:
|
|
234
|
+
message = await websocket.receive_text()
|
|
235
|
+
data = json.loads(message)
|
|
236
|
+
await self._process_websocket_message(websocket, data)
|
|
237
|
+
except WebSocketDisconnect:
|
|
238
|
+
break
|
|
239
|
+
except Exception as e:
|
|
240
|
+
logger.error(f"WebSocket error: {e}")
|
|
241
|
+
break
|
|
242
|
+
|
|
243
|
+
async def _handle_alerts_messages(self, websocket: WebSocket) -> None:
|
|
244
|
+
"""Handle incoming alerts websocket messages."""
|
|
245
|
+
while True:
|
|
246
|
+
try:
|
|
247
|
+
message = await websocket.receive_text()
|
|
248
|
+
data = json.loads(message)
|
|
249
|
+
await self._process_websocket_message(websocket, data)
|
|
250
|
+
except WebSocketDisconnect:
|
|
251
|
+
break
|
|
252
|
+
except Exception as e:
|
|
253
|
+
logger.error(f"WebSocket error: {e}")
|
|
254
|
+
break
|
|
255
|
+
|
|
256
|
+
async def _process_websocket_message(
|
|
257
|
+
self, websocket: WebSocket, data: dict[str, Any]
|
|
258
|
+
) -> None:
|
|
259
|
+
"""Process incoming websocket message."""
|
|
260
|
+
if data.get("type") == "ping":
|
|
261
|
+
await websocket.send_text(
|
|
262
|
+
json.dumps(
|
|
263
|
+
{
|
|
264
|
+
"type": "pong",
|
|
265
|
+
"timestamp": datetime.now().isoformat(),
|
|
266
|
+
}
|
|
267
|
+
)
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
def _cleanup_connection(self, websocket: WebSocket, client_id: str) -> None:
|
|
271
|
+
"""Clean up a WebSocket connection."""
|
|
272
|
+
if client_id in self.active_connections:
|
|
273
|
+
del self.active_connections[client_id]
|
|
274
|
+
self.metrics_subscribers.discard(websocket)
|
|
275
|
+
self.alerts_subscribers.discard(websocket)
|
|
276
|
+
|
|
277
|
+
async def start_monitoring(self, port: int | None = None) -> None:
|
|
278
|
+
"""Start the monitoring server with real-time updates."""
|
|
279
|
+
if self.is_running:
|
|
280
|
+
logger.warning("Monitoring server already running")
|
|
281
|
+
return
|
|
282
|
+
|
|
283
|
+
server_port = port or self.port
|
|
284
|
+
|
|
285
|
+
try:
|
|
286
|
+
# Start metrics collection
|
|
287
|
+
await self.metrics_collector.start_collection()
|
|
288
|
+
|
|
289
|
+
# Setup metrics listener for WebSocket broadcasting
|
|
290
|
+
self.metrics_collector.add_metrics_listener(self._broadcast_metrics)
|
|
291
|
+
|
|
292
|
+
# Start the web server
|
|
293
|
+
config = uvicorn.Config(
|
|
294
|
+
self.app,
|
|
295
|
+
host=self.host,
|
|
296
|
+
port=server_port,
|
|
297
|
+
log_level="info",
|
|
298
|
+
)
|
|
299
|
+
server = uvicorn.Server(config)
|
|
300
|
+
|
|
301
|
+
self.server_task = asyncio.create_task(server.serve())
|
|
302
|
+
self.is_running = True
|
|
303
|
+
|
|
304
|
+
logger.info(
|
|
305
|
+
f"🚀 Crackerjack Monitoring Server started on http://{self.host}:{server_port}"
|
|
306
|
+
)
|
|
307
|
+
logger.info(f"📊 Dashboard available at http://{self.host}:{server_port}/")
|
|
308
|
+
logger.info("🔗 WebSocket endpoints:")
|
|
309
|
+
logger.info(f" - Metrics: ws://{self.host}:{server_port}/ws/metrics")
|
|
310
|
+
logger.info(f" - Alerts: ws://{self.host}:{server_port}/ws/alerts")
|
|
311
|
+
|
|
312
|
+
# Wait for server to complete
|
|
313
|
+
await self.server_task
|
|
314
|
+
|
|
315
|
+
except Exception as e:
|
|
316
|
+
logger.error(f"Error starting monitoring server: {e}")
|
|
317
|
+
await self.stop_monitoring()
|
|
318
|
+
raise
|
|
319
|
+
|
|
320
|
+
async def stop_monitoring(self) -> None:
|
|
321
|
+
"""Stop the monitoring server."""
|
|
322
|
+
if not self.is_running:
|
|
323
|
+
return
|
|
324
|
+
|
|
325
|
+
self.is_running = False
|
|
326
|
+
|
|
327
|
+
try:
|
|
328
|
+
# Stop metrics collection
|
|
329
|
+
await self.metrics_collector.stop_collection()
|
|
330
|
+
|
|
331
|
+
# Close all WebSocket connections
|
|
332
|
+
for websocket in list[t.Any](self.active_connections.values()):
|
|
333
|
+
with suppress(Exception):
|
|
334
|
+
await websocket.close()
|
|
335
|
+
self.active_connections.clear()
|
|
336
|
+
self.metrics_subscribers.clear()
|
|
337
|
+
self.alerts_subscribers.clear()
|
|
338
|
+
|
|
339
|
+
# Stop server task
|
|
340
|
+
if self.server_task and not self.server_task.done():
|
|
341
|
+
self.server_task.cancel()
|
|
342
|
+
try:
|
|
343
|
+
await self.server_task
|
|
344
|
+
except asyncio.CancelledError:
|
|
345
|
+
pass
|
|
346
|
+
|
|
347
|
+
logger.info("🔻 Crackerjack Monitoring Server stopped")
|
|
348
|
+
|
|
349
|
+
except Exception as e:
|
|
350
|
+
logger.error(f"Error stopping monitoring server: {e}")
|
|
351
|
+
|
|
352
|
+
def _broadcast_metrics(self, metrics: UnifiedDashboardMetrics) -> None:
|
|
353
|
+
"""Broadcast metrics to all connected WebSocket clients."""
|
|
354
|
+
if not self.metrics_subscribers:
|
|
355
|
+
return
|
|
356
|
+
|
|
357
|
+
message = {
|
|
358
|
+
"type": "metrics_update",
|
|
359
|
+
"data": metrics.to_dict(),
|
|
360
|
+
"timestamp": datetime.now().isoformat(),
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
# Use asyncio to broadcast to all subscribers
|
|
364
|
+
asyncio.create_task(self._async_broadcast_metrics(message))
|
|
365
|
+
|
|
366
|
+
async def _async_broadcast_metrics(self, message: dict[str, Any]) -> None:
|
|
367
|
+
"""Async broadcast helper."""
|
|
368
|
+
disconnected = []
|
|
369
|
+
for websocket in self.metrics_subscribers:
|
|
370
|
+
try:
|
|
371
|
+
await websocket.send_text(json.dumps(message))
|
|
372
|
+
except Exception:
|
|
373
|
+
disconnected.append(websocket)
|
|
374
|
+
|
|
375
|
+
# Clean up disconnected clients
|
|
376
|
+
self.metrics_subscribers.difference_update(disconnected)
|
|
377
|
+
|
|
378
|
+
def _get_dashboard_html(self) -> str:
|
|
379
|
+
"""Generate the dashboard HTML interface."""
|
|
380
|
+
return render_monitoring_dashboard()
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
# Convenience function for quick server startup
|
|
384
|
+
async def start_crackerjack_monitoring_server(
|
|
385
|
+
port: int = 8675, host: str = "localhost"
|
|
386
|
+
) -> CrackerjackMonitoringServer:
|
|
387
|
+
"""Start a Crackerjack monitoring server."""
|
|
388
|
+
server = CrackerjackMonitoringServer(port=port, host=host)
|
|
389
|
+
await server.start_monitoring()
|
|
390
|
+
return server
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
if __name__ == "__main__":
|
|
394
|
+
import sys
|
|
395
|
+
|
|
396
|
+
port = int(sys.argv[1]) if len(sys.argv) > 1 else 8675
|
|
397
|
+
|
|
398
|
+
async def main() -> None:
|
|
399
|
+
server = CrackerjackMonitoringServer(port=port)
|
|
400
|
+
try:
|
|
401
|
+
await server.start_monitoring()
|
|
402
|
+
except KeyboardInterrupt:
|
|
403
|
+
logger.info("Shutting down monitoring server")
|
|
404
|
+
await server.stop_monitoring()
|
|
405
|
+
|
|
406
|
+
asyncio.run(main())
|