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,64 @@
|
|
|
1
|
+
"""Metrics utilities for the monitoring system.
|
|
2
|
+
|
|
3
|
+
This module contains functions for collecting, processing, and returning
|
|
4
|
+
current system metrics used by the monitoring endpoints.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from crackerjack.services.quality.quality_baseline_enhanced import (
|
|
11
|
+
EnhancedQualityBaselineService,
|
|
12
|
+
UnifiedMetrics,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
async def get_monitoring_current_metrics(
|
|
17
|
+
quality_service: EnhancedQualityBaselineService, job_manager: Any
|
|
18
|
+
) -> UnifiedMetrics:
|
|
19
|
+
"""Get current system metrics for monitoring API endpoints.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
quality_service: EnhancedQualityBaselineService with the quality data
|
|
23
|
+
job_manager: Job manager instance to access current job states
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
UnifiedMetrics containing current system metrics
|
|
27
|
+
"""
|
|
28
|
+
# Get current quality metrics from the service
|
|
29
|
+
current_baseline = await quality_service.aget_current_baseline()
|
|
30
|
+
|
|
31
|
+
# Calculate additional metrics
|
|
32
|
+
active_jobs = 0
|
|
33
|
+
error_count = 0
|
|
34
|
+
|
|
35
|
+
# Access job manager to get current status if possible
|
|
36
|
+
try:
|
|
37
|
+
if hasattr(job_manager, "get_active_jobs"):
|
|
38
|
+
active_jobs = len(job_manager.get_active_jobs() or [])
|
|
39
|
+
elif hasattr(job_manager, "active_jobs"):
|
|
40
|
+
active_jobs = len(job_manager.active_jobs or [])
|
|
41
|
+
|
|
42
|
+
if hasattr(job_manager, "get_error_count"):
|
|
43
|
+
error_count = job_manager.get_error_count()
|
|
44
|
+
elif hasattr(job_manager, "error_count"):
|
|
45
|
+
error_count = getattr(job_manager, "error_count", 0)
|
|
46
|
+
except Exception:
|
|
47
|
+
# If we can't access job info, use defaults
|
|
48
|
+
pass
|
|
49
|
+
|
|
50
|
+
# Create UnifiedMetrics instance with current data
|
|
51
|
+
metrics = UnifiedMetrics(
|
|
52
|
+
timestamp=datetime.now(),
|
|
53
|
+
quality_score=current_baseline.quality_score if current_baseline else 100,
|
|
54
|
+
test_coverage=current_baseline.coverage_percent if current_baseline else 0.0,
|
|
55
|
+
hook_duration=current_baseline.hook_duration if current_baseline else 0.0,
|
|
56
|
+
active_jobs=active_jobs,
|
|
57
|
+
error_count=error_count,
|
|
58
|
+
trend_direction=current_baseline.trend_direction
|
|
59
|
+
if current_baseline
|
|
60
|
+
else "stable",
|
|
61
|
+
predictions=current_baseline.predictions if current_baseline else {},
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
return metrics
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""Pydantic models for monitoring endpoints.
|
|
2
|
+
|
|
3
|
+
This module contains all data models used for request/response validation
|
|
4
|
+
and serialization in the monitoring system.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import typing as t
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
|
|
10
|
+
from pydantic import BaseModel
|
|
11
|
+
|
|
12
|
+
from crackerjack.services.quality.quality_baseline_enhanced import (
|
|
13
|
+
TrendDirection,
|
|
14
|
+
UnifiedMetrics,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class TelemetryEventModel(BaseModel):
|
|
19
|
+
event_type: str
|
|
20
|
+
timestamp: datetime
|
|
21
|
+
source: str | None = None
|
|
22
|
+
payload: t.Any = None
|
|
23
|
+
|
|
24
|
+
@classmethod
|
|
25
|
+
def from_dict(cls, data: dict[str, t.Any]) -> "TelemetryEventModel":
|
|
26
|
+
return cls(
|
|
27
|
+
event_type=data.get("event_type", ""),
|
|
28
|
+
timestamp=datetime.fromisoformat(data.get("timestamp")),
|
|
29
|
+
source=data.get("source"),
|
|
30
|
+
payload=data.get("payload"),
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class TelemetrySnapshotModel(BaseModel):
|
|
35
|
+
counts: dict[str, int]
|
|
36
|
+
recent_events: list[TelemetryEventModel]
|
|
37
|
+
last_error: TelemetryEventModel | None = None
|
|
38
|
+
|
|
39
|
+
@classmethod
|
|
40
|
+
def from_snapshot(cls, snapshot: dict[str, t.Any]) -> "TelemetrySnapshotModel":
|
|
41
|
+
events = [
|
|
42
|
+
TelemetryEventModel.from_dict(event)
|
|
43
|
+
for event in snapshot.get("recent_events", [])
|
|
44
|
+
]
|
|
45
|
+
last_error = snapshot.get("last_error")
|
|
46
|
+
return cls(
|
|
47
|
+
counts=snapshot.get("counts", {}),
|
|
48
|
+
recent_events=events,
|
|
49
|
+
last_error=(
|
|
50
|
+
TelemetryEventModel.from_dict(last_error)
|
|
51
|
+
if last_error is not None
|
|
52
|
+
else None
|
|
53
|
+
),
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class TelemetryResponseModel(BaseModel):
|
|
58
|
+
status: str
|
|
59
|
+
data: TelemetrySnapshotModel
|
|
60
|
+
timestamp: datetime
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class UnifiedMetricsModel(BaseModel):
|
|
64
|
+
timestamp: datetime
|
|
65
|
+
quality_score: int
|
|
66
|
+
test_coverage: float
|
|
67
|
+
hook_duration: float
|
|
68
|
+
active_jobs: int
|
|
69
|
+
error_count: int
|
|
70
|
+
trend_direction: TrendDirection
|
|
71
|
+
predictions: dict[str, t.Any] = {}
|
|
72
|
+
|
|
73
|
+
@classmethod
|
|
74
|
+
def from_domain(cls, metrics: UnifiedMetrics) -> "UnifiedMetricsModel":
|
|
75
|
+
return cls(
|
|
76
|
+
timestamp=metrics.timestamp,
|
|
77
|
+
quality_score=metrics.quality_score,
|
|
78
|
+
test_coverage=metrics.test_coverage,
|
|
79
|
+
hook_duration=metrics.hook_duration,
|
|
80
|
+
active_jobs=metrics.active_jobs,
|
|
81
|
+
error_count=metrics.error_count,
|
|
82
|
+
trend_direction=metrics.trend_direction,
|
|
83
|
+
predictions=metrics.predictions,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class HealthResponseModel(BaseModel):
|
|
88
|
+
status: str
|
|
89
|
+
data: UnifiedMetricsModel
|
|
90
|
+
timestamp: datetime
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"""Utility functions for monitoring endpoints.
|
|
2
|
+
|
|
3
|
+
This module contains helper functions for metrics aggregation, health checks,
|
|
4
|
+
and data filtering.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
import typing as t
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
|
|
11
|
+
from crackerjack.services.dependency_analyzer import DependencyGraph
|
|
12
|
+
from crackerjack.services.quality.quality_baseline_enhanced import (
|
|
13
|
+
EnhancedQualityBaselineService,
|
|
14
|
+
SystemHealthStatus,
|
|
15
|
+
TrendDirection,
|
|
16
|
+
UnifiedMetrics,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
async def get_current_metrics(
|
|
21
|
+
quality_service: EnhancedQualityBaselineService, job_manager: t.Any
|
|
22
|
+
) -> UnifiedMetrics:
|
|
23
|
+
"""Get current unified metrics."""
|
|
24
|
+
try:
|
|
25
|
+
# Get baseline from quality service
|
|
26
|
+
baseline = await quality_service.aget_baseline()
|
|
27
|
+
if not baseline:
|
|
28
|
+
# Return default metrics if no baseline exists
|
|
29
|
+
return UnifiedMetrics(
|
|
30
|
+
timestamp=datetime.now(),
|
|
31
|
+
quality_score=0,
|
|
32
|
+
test_coverage=0.0,
|
|
33
|
+
hook_duration=0.0,
|
|
34
|
+
active_jobs=len(job_manager.active_connections),
|
|
35
|
+
error_count=0,
|
|
36
|
+
trend_direction=TrendDirection.STABLE,
|
|
37
|
+
predictions={},
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
# Create metrics dict from baseline
|
|
41
|
+
current_metrics = {
|
|
42
|
+
"coverage_percent": baseline.coverage_percent,
|
|
43
|
+
"test_count": baseline.test_count,
|
|
44
|
+
"test_pass_rate": baseline.test_pass_rate,
|
|
45
|
+
"hook_failures": baseline.hook_failures,
|
|
46
|
+
"complexity_violations": baseline.complexity_violations,
|
|
47
|
+
"security_issues": baseline.security_issues,
|
|
48
|
+
"type_errors": baseline.type_errors,
|
|
49
|
+
"linting_issues": baseline.linting_issues,
|
|
50
|
+
"hook_duration": 0.0, # Would need to be tracked separately
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
unified = await asyncio.to_thread(
|
|
54
|
+
quality_service.create_unified_metrics,
|
|
55
|
+
current_metrics,
|
|
56
|
+
len(job_manager.active_connections)
|
|
57
|
+
if hasattr(job_manager, "active_connections")
|
|
58
|
+
else 0,
|
|
59
|
+
)
|
|
60
|
+
return unified
|
|
61
|
+
except Exception:
|
|
62
|
+
# Fallback to basic metrics if service fails
|
|
63
|
+
return UnifiedMetrics(
|
|
64
|
+
timestamp=datetime.now(),
|
|
65
|
+
quality_score=0,
|
|
66
|
+
test_coverage=0.0,
|
|
67
|
+
hook_duration=0.0,
|
|
68
|
+
active_jobs=len(job_manager.active_connections)
|
|
69
|
+
if hasattr(job_manager, "active_connections")
|
|
70
|
+
else 0,
|
|
71
|
+
error_count=0,
|
|
72
|
+
trend_direction=TrendDirection.STABLE,
|
|
73
|
+
predictions={},
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
async def get_system_health_status(
|
|
78
|
+
quality_service: EnhancedQualityBaselineService,
|
|
79
|
+
) -> SystemHealthStatus:
|
|
80
|
+
"""Get system health status."""
|
|
81
|
+
return await asyncio.to_thread(quality_service.get_system_health)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _filter_nodes_by_criteria(
|
|
85
|
+
nodes: list[t.Any], filter_type: str | None, include_external: bool
|
|
86
|
+
) -> list[t.Any]:
|
|
87
|
+
"""Filter nodes by type and external criteria."""
|
|
88
|
+
filtered = nodes
|
|
89
|
+
|
|
90
|
+
# Filter by type if specified
|
|
91
|
+
if filter_type:
|
|
92
|
+
filtered = [node for node in filtered if node.type == filter_type]
|
|
93
|
+
|
|
94
|
+
# Filter external dependencies if not included
|
|
95
|
+
if not include_external:
|
|
96
|
+
filtered = [
|
|
97
|
+
node
|
|
98
|
+
for node in filtered
|
|
99
|
+
if not node.file_path or "site-packages" not in node.file_path
|
|
100
|
+
]
|
|
101
|
+
|
|
102
|
+
return filtered
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _prioritize_and_limit_nodes(
|
|
106
|
+
nodes: list[t.Any], graph: DependencyGraph, max_nodes: int
|
|
107
|
+
) -> list[t.Any]:
|
|
108
|
+
"""Prioritize nodes and limit to max count."""
|
|
109
|
+
if len(nodes) <= max_nodes:
|
|
110
|
+
return nodes
|
|
111
|
+
|
|
112
|
+
def node_priority(node: t.Any) -> int:
|
|
113
|
+
edge_count = sum(
|
|
114
|
+
1 for edge in graph.edges if node.id in (edge.source, edge.target)
|
|
115
|
+
)
|
|
116
|
+
return int(node.complexity * edge_count)
|
|
117
|
+
|
|
118
|
+
nodes.sort(key=node_priority, reverse=True)
|
|
119
|
+
return nodes[:max_nodes]
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def _build_filtered_clusters(
|
|
123
|
+
graph: DependencyGraph, node_ids: set[str]
|
|
124
|
+
) -> dict[str, list[str]]:
|
|
125
|
+
"""Build filtered clusters containing only included nodes."""
|
|
126
|
+
filtered_clusters = {}
|
|
127
|
+
for cluster_name, cluster_nodes in graph.clusters.items():
|
|
128
|
+
filtered_cluster_nodes = [
|
|
129
|
+
node_id for node_id in cluster_nodes if node_id in node_ids
|
|
130
|
+
]
|
|
131
|
+
if filtered_cluster_nodes:
|
|
132
|
+
filtered_clusters[cluster_name] = filtered_cluster_nodes
|
|
133
|
+
return filtered_clusters
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
async def _apply_graph_filters(
|
|
137
|
+
graph: DependencyGraph, filters: dict[str, t.Any]
|
|
138
|
+
) -> DependencyGraph:
|
|
139
|
+
"""Apply filters to dependency graph."""
|
|
140
|
+
filtered_graph = DependencyGraph(
|
|
141
|
+
generated_at=graph.generated_at,
|
|
142
|
+
metrics=graph.metrics.copy(),
|
|
143
|
+
clusters=graph.clusters.copy(),
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
# Extract filter parameters
|
|
147
|
+
filter_type = filters.get("type")
|
|
148
|
+
max_nodes = filters.get("max_nodes", 1000)
|
|
149
|
+
include_external = filters.get("include_external", False)
|
|
150
|
+
|
|
151
|
+
# Apply filters to nodes
|
|
152
|
+
candidate_nodes = list(graph.nodes.values())
|
|
153
|
+
candidate_nodes = _filter_nodes_by_criteria(
|
|
154
|
+
candidate_nodes, filter_type, include_external
|
|
155
|
+
)
|
|
156
|
+
candidate_nodes = _prioritize_and_limit_nodes(candidate_nodes, graph, max_nodes)
|
|
157
|
+
|
|
158
|
+
# Build filtered graph
|
|
159
|
+
node_ids = {node.id for node in candidate_nodes}
|
|
160
|
+
for node in candidate_nodes:
|
|
161
|
+
filtered_graph.nodes[node.id] = node
|
|
162
|
+
|
|
163
|
+
# Add edges between filtered nodes
|
|
164
|
+
for edge in graph.edges:
|
|
165
|
+
if edge.source in node_ids and edge.target in node_ids:
|
|
166
|
+
filtered_graph.edges.append(edge)
|
|
167
|
+
|
|
168
|
+
# Update clusters
|
|
169
|
+
filtered_graph.clusters = _build_filtered_clusters(graph, node_ids)
|
|
170
|
+
|
|
171
|
+
return filtered_graph
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"""WebSocket connection manager for real-time monitoring.
|
|
2
|
+
|
|
3
|
+
This module manages WebSocket connections for metrics streaming and alert notifications.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import json
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
|
|
9
|
+
from fastapi import WebSocket
|
|
10
|
+
|
|
11
|
+
from crackerjack.services.quality.quality_baseline_enhanced import (
|
|
12
|
+
QualityAlert,
|
|
13
|
+
UnifiedMetrics,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class MonitoringWebSocketManager:
|
|
18
|
+
"""Manages WebSocket connections for real-time monitoring."""
|
|
19
|
+
|
|
20
|
+
def __init__(self) -> None:
|
|
21
|
+
self.active_connections: dict[str, WebSocket] = {}
|
|
22
|
+
self.metrics_subscribers: set[WebSocket] = set()
|
|
23
|
+
self.alerts_subscribers: set[WebSocket] = set()
|
|
24
|
+
|
|
25
|
+
async def connect_metrics(self, websocket: WebSocket, client_id: str) -> None:
|
|
26
|
+
"""Connect a client for metrics streaming."""
|
|
27
|
+
await websocket.accept()
|
|
28
|
+
self.active_connections[client_id] = websocket
|
|
29
|
+
self.metrics_subscribers.add(websocket)
|
|
30
|
+
|
|
31
|
+
async def connect_alerts(self, websocket: WebSocket, client_id: str) -> None:
|
|
32
|
+
"""Connect a client for alert notifications."""
|
|
33
|
+
await websocket.accept()
|
|
34
|
+
self.active_connections[client_id] = websocket
|
|
35
|
+
self.alerts_subscribers.add(websocket)
|
|
36
|
+
|
|
37
|
+
def disconnect(self, websocket: WebSocket, client_id: str) -> None:
|
|
38
|
+
"""Disconnect a client."""
|
|
39
|
+
if client_id in self.active_connections:
|
|
40
|
+
del self.active_connections[client_id]
|
|
41
|
+
self.metrics_subscribers.discard(websocket)
|
|
42
|
+
self.alerts_subscribers.discard(websocket)
|
|
43
|
+
|
|
44
|
+
async def broadcast_metrics(self, metrics: UnifiedMetrics) -> None:
|
|
45
|
+
"""Broadcast metrics to all connected metrics subscribers."""
|
|
46
|
+
message = {
|
|
47
|
+
"type": "metrics_update",
|
|
48
|
+
"data": metrics.to_dict(),
|
|
49
|
+
"timestamp": datetime.now().isoformat(),
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
disconnected = []
|
|
53
|
+
for websocket in self.metrics_subscribers:
|
|
54
|
+
try:
|
|
55
|
+
await websocket.send_text(json.dumps(message))
|
|
56
|
+
except Exception:
|
|
57
|
+
disconnected.append(websocket)
|
|
58
|
+
|
|
59
|
+
# Clean up disconnected clients
|
|
60
|
+
self.metrics_subscribers.difference_update(disconnected)
|
|
61
|
+
|
|
62
|
+
async def broadcast_alert(self, alert: QualityAlert) -> None:
|
|
63
|
+
"""Broadcast alert to all connected alert subscribers."""
|
|
64
|
+
message = {
|
|
65
|
+
"type": "alert",
|
|
66
|
+
"data": alert.to_dict(),
|
|
67
|
+
"timestamp": datetime.now().isoformat(),
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
disconnected = []
|
|
71
|
+
for websocket in self.alerts_subscribers:
|
|
72
|
+
try:
|
|
73
|
+
await websocket.send_text(json.dumps(message))
|
|
74
|
+
except Exception:
|
|
75
|
+
disconnected.append(websocket)
|
|
76
|
+
|
|
77
|
+
# Clean up disconnected clients
|
|
78
|
+
self.alerts_subscribers.difference_update(disconnected)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""WebSocket endpoint registration.
|
|
2
|
+
|
|
3
|
+
This module provides registration functions for all WebSocket endpoints
|
|
4
|
+
including metrics, intelligence, dependencies, and heatmap streaming.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .dependencies import register_dependency_websockets
|
|
8
|
+
from .heatmap import register_heatmap_websockets
|
|
9
|
+
from .intelligence import register_intelligence_websockets
|
|
10
|
+
from .metrics import register_metrics_websockets
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"register_metrics_websockets",
|
|
14
|
+
"register_intelligence_websockets",
|
|
15
|
+
"register_dependency_websockets",
|
|
16
|
+
"register_heatmap_websockets",
|
|
17
|
+
]
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"""WebSocket endpoints for dependency analysis.
|
|
2
|
+
|
|
3
|
+
This module handles real-time dependency graph visualization
|
|
4
|
+
and analysis WebSocket connections.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
import json
|
|
9
|
+
import typing as t
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
|
|
12
|
+
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
|
|
13
|
+
|
|
14
|
+
from crackerjack.services.dependency_analyzer import (
|
|
15
|
+
DependencyAnalyzer,
|
|
16
|
+
DependencyGraph,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
from ..filters import _apply_graph_filters
|
|
20
|
+
from ..websocket_manager import MonitoringWebSocketManager
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def register_dependency_websockets(
|
|
24
|
+
app: FastAPI,
|
|
25
|
+
ws_manager: MonitoringWebSocketManager,
|
|
26
|
+
dependency_analyzer: DependencyAnalyzer,
|
|
27
|
+
) -> None:
|
|
28
|
+
"""Register dependency-related WebSocket endpoints."""
|
|
29
|
+
|
|
30
|
+
@app.websocket("/ws/dependencies/graph")
|
|
31
|
+
async def websocket_dependency_graph(websocket: WebSocket) -> None:
|
|
32
|
+
"""WebSocket endpoint for dependency graph data."""
|
|
33
|
+
await _handle_dependency_graph_websocket(
|
|
34
|
+
websocket, ws_manager, dependency_analyzer
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
async def _handle_dependency_graph_websocket(
|
|
39
|
+
websocket: WebSocket,
|
|
40
|
+
ws_manager: MonitoringWebSocketManager,
|
|
41
|
+
dependency_analyzer: DependencyAnalyzer,
|
|
42
|
+
) -> None:
|
|
43
|
+
"""Handle dependency graph WebSocket connection."""
|
|
44
|
+
client_id = f"dependencies_{datetime.now().timestamp()}"
|
|
45
|
+
await ws_manager.connect_metrics(websocket, client_id)
|
|
46
|
+
|
|
47
|
+
try:
|
|
48
|
+
# Send initial message
|
|
49
|
+
await websocket.send_text(
|
|
50
|
+
json.dumps(
|
|
51
|
+
{
|
|
52
|
+
"type": "analysis_started",
|
|
53
|
+
"message": "Starting dependency analysis...",
|
|
54
|
+
"timestamp": datetime.now().isoformat(),
|
|
55
|
+
}
|
|
56
|
+
)
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# Generate dependency graph
|
|
60
|
+
graph = dependency_analyzer.analyze_project()
|
|
61
|
+
|
|
62
|
+
# Send the complete graph data
|
|
63
|
+
await websocket.send_text(
|
|
64
|
+
json.dumps(
|
|
65
|
+
{
|
|
66
|
+
"type": "graph_data",
|
|
67
|
+
"data": graph.to_dict(),
|
|
68
|
+
"timestamp": datetime.now().isoformat(),
|
|
69
|
+
}
|
|
70
|
+
)
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
# Listen for client requests
|
|
74
|
+
while True:
|
|
75
|
+
try:
|
|
76
|
+
message = await asyncio.wait_for(websocket.receive_text(), timeout=30.0)
|
|
77
|
+
data = json.loads(message)
|
|
78
|
+
|
|
79
|
+
await _handle_dependency_request(
|
|
80
|
+
websocket, dependency_analyzer, graph, data
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
except TimeoutError:
|
|
84
|
+
await websocket.send_text(
|
|
85
|
+
json.dumps(
|
|
86
|
+
{
|
|
87
|
+
"type": "keepalive",
|
|
88
|
+
"timestamp": datetime.now().isoformat(),
|
|
89
|
+
}
|
|
90
|
+
)
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
except WebSocketDisconnect:
|
|
94
|
+
ws_manager.disconnect(websocket, client_id)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
async def _handle_dependency_request(
|
|
98
|
+
websocket: WebSocket,
|
|
99
|
+
dependency_analyzer: DependencyAnalyzer,
|
|
100
|
+
graph: DependencyGraph,
|
|
101
|
+
data: dict[str, t.Any],
|
|
102
|
+
) -> None:
|
|
103
|
+
"""Handle dependency graph request."""
|
|
104
|
+
if data.get("type") == "filter_request":
|
|
105
|
+
filtered_graph = await _apply_graph_filters(graph, data.get("filters", {}))
|
|
106
|
+
await websocket.send_text(
|
|
107
|
+
json.dumps(
|
|
108
|
+
{
|
|
109
|
+
"type": "filtered_graph",
|
|
110
|
+
"data": filtered_graph.to_dict(),
|
|
111
|
+
"timestamp": datetime.now().isoformat(),
|
|
112
|
+
}
|
|
113
|
+
)
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
elif data.get("type") == "refresh_request":
|
|
117
|
+
fresh_graph = dependency_analyzer.analyze_project()
|
|
118
|
+
await websocket.send_text(
|
|
119
|
+
json.dumps(
|
|
120
|
+
{
|
|
121
|
+
"type": "graph_data",
|
|
122
|
+
"data": fresh_graph.to_dict(),
|
|
123
|
+
"timestamp": datetime.now().isoformat(),
|
|
124
|
+
}
|
|
125
|
+
)
|
|
126
|
+
)
|