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
crackerjack/mixins/__init__.py
DELETED
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
import subprocess
|
|
2
|
-
import typing as t
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
|
|
5
|
-
from rich.console import Console
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class ErrorHandlingMixin:
|
|
9
|
-
def __init__(self) -> None:
|
|
10
|
-
self.console: Console
|
|
11
|
-
self.logger: t.Any
|
|
12
|
-
|
|
13
|
-
def handle_subprocess_error(
|
|
14
|
-
self,
|
|
15
|
-
error: Exception,
|
|
16
|
-
command: list[str],
|
|
17
|
-
operation_name: str,
|
|
18
|
-
critical: bool = False,
|
|
19
|
-
) -> bool:
|
|
20
|
-
error_msg = f"{operation_name} failed: {error}"
|
|
21
|
-
|
|
22
|
-
if hasattr(self, "logger") and self.logger:
|
|
23
|
-
self.logger.error(
|
|
24
|
-
error_msg,
|
|
25
|
-
command=" ".join(command),
|
|
26
|
-
error_type=type(error).__name__,
|
|
27
|
-
critical=critical,
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
if critical:
|
|
31
|
-
self.console.print(f"[red]🚨 CRITICAL: {error_msg}[/red]")
|
|
32
|
-
else:
|
|
33
|
-
self.console.print(f"[red]❌ {error_msg}[/red]")
|
|
34
|
-
|
|
35
|
-
return False
|
|
36
|
-
|
|
37
|
-
def handle_file_operation_error(
|
|
38
|
-
self,
|
|
39
|
-
error: Exception,
|
|
40
|
-
file_path: Path,
|
|
41
|
-
operation: str,
|
|
42
|
-
critical: bool = False,
|
|
43
|
-
) -> bool:
|
|
44
|
-
error_msg = f"Failed to {operation} {file_path}: {error}"
|
|
45
|
-
|
|
46
|
-
if hasattr(self, "logger") and self.logger:
|
|
47
|
-
self.logger.error(
|
|
48
|
-
error_msg,
|
|
49
|
-
file_path=str(file_path),
|
|
50
|
-
operation=operation,
|
|
51
|
-
error_type=type(error).__name__,
|
|
52
|
-
critical=critical,
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
if critical:
|
|
56
|
-
self.console.print(f"[red]🚨 CRITICAL: {error_msg}[/red]")
|
|
57
|
-
else:
|
|
58
|
-
self.console.print(f"[red]❌ {error_msg}[/red]")
|
|
59
|
-
|
|
60
|
-
return False
|
|
61
|
-
|
|
62
|
-
def handle_timeout_error(
|
|
63
|
-
self,
|
|
64
|
-
operation_name: str,
|
|
65
|
-
timeout_seconds: float,
|
|
66
|
-
command: list[str] | None = None,
|
|
67
|
-
) -> bool:
|
|
68
|
-
error_msg = f"{operation_name} timed out after {timeout_seconds}s"
|
|
69
|
-
|
|
70
|
-
if hasattr(self, "logger") and self.logger:
|
|
71
|
-
self.logger.warning(
|
|
72
|
-
error_msg,
|
|
73
|
-
timeout=timeout_seconds,
|
|
74
|
-
command=" ".join(command) if command else None,
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
self.console.print(f"[yellow]⏰ {error_msg}[/yellow]")
|
|
78
|
-
|
|
79
|
-
return False
|
|
80
|
-
|
|
81
|
-
def log_operation_success(
|
|
82
|
-
self,
|
|
83
|
-
operation_name: str,
|
|
84
|
-
details: dict[str, t.Any] | None = None,
|
|
85
|
-
) -> None:
|
|
86
|
-
if hasattr(self, "logger") and self.logger:
|
|
87
|
-
self.logger.info(
|
|
88
|
-
f"{operation_name} completed successfully", **(details or {})
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
def validate_required_tools(
|
|
92
|
-
self,
|
|
93
|
-
tools: dict[str, str],
|
|
94
|
-
operation_name: str,
|
|
95
|
-
) -> bool:
|
|
96
|
-
missing_tools = []
|
|
97
|
-
|
|
98
|
-
for tool_name, command in tools.items():
|
|
99
|
-
try:
|
|
100
|
-
subprocess.run(
|
|
101
|
-
[command, "--version"],
|
|
102
|
-
capture_output=True,
|
|
103
|
-
check=True,
|
|
104
|
-
timeout=5,
|
|
105
|
-
)
|
|
106
|
-
except (
|
|
107
|
-
subprocess.CalledProcessError,
|
|
108
|
-
subprocess.TimeoutExpired,
|
|
109
|
-
FileNotFoundError,
|
|
110
|
-
):
|
|
111
|
-
missing_tools.append(tool_name)
|
|
112
|
-
|
|
113
|
-
if missing_tools:
|
|
114
|
-
error_msg = f"Missing required tools for {operation_name}: {', '.join(missing_tools)}"
|
|
115
|
-
|
|
116
|
-
if hasattr(self, "logger") and self.logger:
|
|
117
|
-
self.logger.error(
|
|
118
|
-
error_msg,
|
|
119
|
-
missing_tools=missing_tools,
|
|
120
|
-
operation=operation_name,
|
|
121
|
-
)
|
|
122
|
-
|
|
123
|
-
self.console.print(f"[red]❌ {error_msg}[/red]")
|
|
124
|
-
return False
|
|
125
|
-
|
|
126
|
-
return True
|
|
127
|
-
|
|
128
|
-
def safe_get_attribute(
|
|
129
|
-
self,
|
|
130
|
-
obj: t.Any,
|
|
131
|
-
attribute: str,
|
|
132
|
-
default: t.Any = None,
|
|
133
|
-
operation_name: str = "attribute access",
|
|
134
|
-
) -> t.Any:
|
|
135
|
-
try:
|
|
136
|
-
return getattr(obj, attribute, default)
|
|
137
|
-
except Exception as e:
|
|
138
|
-
if hasattr(self, "logger") and self.logger:
|
|
139
|
-
self.logger.warning(
|
|
140
|
-
f"Error accessing {attribute} during {operation_name}: {e}",
|
|
141
|
-
attribute=attribute,
|
|
142
|
-
operation=operation_name,
|
|
143
|
-
error_type=type(e).__name__,
|
|
144
|
-
)
|
|
145
|
-
return default
|
crackerjack/services/config.py
DELETED
|
@@ -1,358 +0,0 @@
|
|
|
1
|
-
import subprocess
|
|
2
|
-
import typing as t
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
|
|
5
|
-
from rich.console import Console
|
|
6
|
-
|
|
7
|
-
from crackerjack.dynamic_config import DynamicConfigGenerator, generate_config_for_mode
|
|
8
|
-
from crackerjack.models.protocols import OptionsProtocol
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class ConfigurationService:
|
|
12
|
-
def __init__(self, console: Console, pkg_path: Path) -> None:
|
|
13
|
-
self.console = console
|
|
14
|
-
self.pkg_path = pkg_path
|
|
15
|
-
# Extract package directory name from the pkg_path and sanitize it
|
|
16
|
-
package_directory = pkg_path.name if pkg_path != Path.cwd() else None
|
|
17
|
-
if package_directory:
|
|
18
|
-
package_directory = package_directory.replace("-", "_")
|
|
19
|
-
self.config_generator = DynamicConfigGenerator(package_directory)
|
|
20
|
-
|
|
21
|
-
def update_precommit_config(self, options: OptionsProtocol) -> bool:
|
|
22
|
-
try:
|
|
23
|
-
mode = self._determine_config_mode(options)
|
|
24
|
-
# Extract package directory name from the pkg_path
|
|
25
|
-
package_directory = (
|
|
26
|
-
self.pkg_path.name if self.pkg_path != Path.cwd() else None
|
|
27
|
-
)
|
|
28
|
-
config_temp_path = generate_config_for_mode(
|
|
29
|
-
mode, package_directory=package_directory
|
|
30
|
-
)
|
|
31
|
-
if not config_temp_path:
|
|
32
|
-
self.console.print("[yellow]⚠️ No configuration generated[/ yellow]")
|
|
33
|
-
return False
|
|
34
|
-
|
|
35
|
-
config_file = self.pkg_path / ".pre-commit-config.yaml"
|
|
36
|
-
config_content = config_temp_path.read_text()
|
|
37
|
-
|
|
38
|
-
from crackerjack.services.filesystem import FileSystemService
|
|
39
|
-
|
|
40
|
-
config_content = FileSystemService.clean_trailing_whitespace_and_newlines(
|
|
41
|
-
config_content
|
|
42
|
-
)
|
|
43
|
-
config_file.write_text(config_content)
|
|
44
|
-
|
|
45
|
-
self._temp_config_path = config_temp_path
|
|
46
|
-
self.console.print("[green]✅[/ green] Pre-commit configuration generated")
|
|
47
|
-
|
|
48
|
-
if getattr(options, "update_precommit", False):
|
|
49
|
-
success = self._run_precommit_autoupdate()
|
|
50
|
-
if success:
|
|
51
|
-
self.console.print("[green]✅[/ green] Pre-commit hooks updated")
|
|
52
|
-
else:
|
|
53
|
-
self.console.print(
|
|
54
|
-
"[yellow]⚠️[/ yellow] Pre-commit autoupdate had issues"
|
|
55
|
-
)
|
|
56
|
-
|
|
57
|
-
self._update_dynamic_config_versions()
|
|
58
|
-
|
|
59
|
-
return True
|
|
60
|
-
except Exception as e:
|
|
61
|
-
self.console.print(
|
|
62
|
-
f"[red]❌[/ red] Failed to generate pre-commit config: {e}",
|
|
63
|
-
)
|
|
64
|
-
return False
|
|
65
|
-
|
|
66
|
-
def get_temp_config_path(self) -> str | None:
|
|
67
|
-
path = getattr(self, "_temp_config_path", None)
|
|
68
|
-
return str(path) if path else None
|
|
69
|
-
|
|
70
|
-
def _determine_config_mode(self, options: OptionsProtocol) -> str:
|
|
71
|
-
if options.experimental_hooks:
|
|
72
|
-
return "experimental"
|
|
73
|
-
if hasattr(options, "test") and options.test:
|
|
74
|
-
return "comprehensive"
|
|
75
|
-
return "comprehensive"
|
|
76
|
-
|
|
77
|
-
def validate_config(self) -> bool:
|
|
78
|
-
try:
|
|
79
|
-
config_file = self.pkg_path / ".pre-commit-config.yaml"
|
|
80
|
-
if not config_file.exists():
|
|
81
|
-
self.console.print(
|
|
82
|
-
"[yellow]⚠️ No pre-commit configuration found[/ yellow]",
|
|
83
|
-
)
|
|
84
|
-
return False
|
|
85
|
-
import yaml
|
|
86
|
-
|
|
87
|
-
with config_file.open() as f:
|
|
88
|
-
yaml_result = yaml.safe_load(f)
|
|
89
|
-
_ = (
|
|
90
|
-
t.cast("dict[str, t.Any]", yaml_result)
|
|
91
|
-
if yaml_result is not None
|
|
92
|
-
else {}
|
|
93
|
-
)
|
|
94
|
-
self.console.print("[green]✅[/ green] Pre-commit configuration is valid")
|
|
95
|
-
return True
|
|
96
|
-
except Exception as e:
|
|
97
|
-
self.console.print(f"[red]❌[/ red] Configuration validation failed: {e}")
|
|
98
|
-
return False
|
|
99
|
-
|
|
100
|
-
def backup_config(self) -> Path | None:
|
|
101
|
-
try:
|
|
102
|
-
config_file = self.pkg_path / ".pre-commit-config.yaml"
|
|
103
|
-
if not config_file.exists():
|
|
104
|
-
return None
|
|
105
|
-
import time
|
|
106
|
-
|
|
107
|
-
timestamp = int(time.time())
|
|
108
|
-
backup_file = self.pkg_path / f".pre-commit-config.yaml.backup.{timestamp}"
|
|
109
|
-
backup_file.write_text(config_file.read_text())
|
|
110
|
-
self.console.print(
|
|
111
|
-
f"[cyan]💾[/ cyan] Configuration backed up to {backup_file.name}",
|
|
112
|
-
)
|
|
113
|
-
return backup_file
|
|
114
|
-
except Exception as e:
|
|
115
|
-
self.console.print(
|
|
116
|
-
f"[yellow]⚠️[/ yellow] Failed to backup configuration: {e}",
|
|
117
|
-
)
|
|
118
|
-
return None
|
|
119
|
-
|
|
120
|
-
def restore_config(self, backup_file: Path) -> bool:
|
|
121
|
-
try:
|
|
122
|
-
if not backup_file.exists():
|
|
123
|
-
self.console.print(
|
|
124
|
-
f"[red]❌[/ red] Backup file not found: {backup_file}",
|
|
125
|
-
)
|
|
126
|
-
return False
|
|
127
|
-
config_file = self.pkg_path / ".pre-commit-config.yaml"
|
|
128
|
-
config_file.write_text(backup_file.read_text())
|
|
129
|
-
self.console.print(
|
|
130
|
-
f"[green]✅[/ green] Configuration restored from {backup_file.name}",
|
|
131
|
-
)
|
|
132
|
-
return True
|
|
133
|
-
except Exception as e:
|
|
134
|
-
self.console.print(f"[red]❌[/ red] Failed to restore configuration: {e}")
|
|
135
|
-
return False
|
|
136
|
-
|
|
137
|
-
def get_config_info(self) -> dict[str, t.Any]:
|
|
138
|
-
try:
|
|
139
|
-
config_file = self.pkg_path / ".pre-commit-config.yaml"
|
|
140
|
-
if not config_file.exists():
|
|
141
|
-
return {"exists": False}
|
|
142
|
-
import yaml
|
|
143
|
-
|
|
144
|
-
with config_file.open() as f:
|
|
145
|
-
yaml_result = yaml.safe_load(f)
|
|
146
|
-
config_data = yaml_result if isinstance(yaml_result, dict) else {}
|
|
147
|
-
repos = config_data.get("repos", [])
|
|
148
|
-
if not isinstance(repos, list):
|
|
149
|
-
repos = []
|
|
150
|
-
hook_count = sum(
|
|
151
|
-
len(repo.get("hooks", []))
|
|
152
|
-
for repo in t.cast(list[dict[str, t.Any]], repos)
|
|
153
|
-
if isinstance(repo, dict)
|
|
154
|
-
)
|
|
155
|
-
stat = config_file.stat()
|
|
156
|
-
|
|
157
|
-
return {
|
|
158
|
-
"exists": True,
|
|
159
|
-
"file_size": stat.st_size,
|
|
160
|
-
"modified_time": stat.st_mtime,
|
|
161
|
-
"repo_count": len(
|
|
162
|
-
[
|
|
163
|
-
r
|
|
164
|
-
for r in t.cast(list[dict[str, t.Any]], repos)
|
|
165
|
-
if isinstance(r, dict)
|
|
166
|
-
]
|
|
167
|
-
),
|
|
168
|
-
"hook_count": hook_count,
|
|
169
|
-
"repos": [
|
|
170
|
-
{
|
|
171
|
-
"repo": repo.get("repo", "unknown"),
|
|
172
|
-
"rev": repo.get("rev", "unknown"),
|
|
173
|
-
"hooks": len(repo.get("hooks", [])),
|
|
174
|
-
}
|
|
175
|
-
for repo in t.cast(list[dict[str, t.Any]], repos)
|
|
176
|
-
if isinstance(repo, dict)
|
|
177
|
-
],
|
|
178
|
-
}
|
|
179
|
-
except Exception as e:
|
|
180
|
-
return {"exists": True, "error": str(e)}
|
|
181
|
-
|
|
182
|
-
def update_pyproject_config(self, options: OptionsProtocol) -> bool:
|
|
183
|
-
try:
|
|
184
|
-
pyproject_file = self.pkg_path / "pyproject.toml"
|
|
185
|
-
if not pyproject_file.exists():
|
|
186
|
-
self.console.print("[yellow]⚠️ No pyproject.toml found[/ yellow]")
|
|
187
|
-
return False
|
|
188
|
-
from tomllib import loads
|
|
189
|
-
|
|
190
|
-
from tomli_w import dumps
|
|
191
|
-
|
|
192
|
-
with pyproject_file.open() as f:
|
|
193
|
-
content = f.read()
|
|
194
|
-
config = loads(content)
|
|
195
|
-
if "tool" not in config:
|
|
196
|
-
config["tool"] = {}
|
|
197
|
-
if "ruff" not in config["tool"]:
|
|
198
|
-
config["tool"]["ruff"] = {
|
|
199
|
-
"target-version": "py313",
|
|
200
|
-
"line-length": 88,
|
|
201
|
-
"fix": True,
|
|
202
|
-
"unsafe-fixes": True,
|
|
203
|
-
"show-fixes": True,
|
|
204
|
-
"output-format": "full",
|
|
205
|
-
}
|
|
206
|
-
config["tool"]["ruff"]["format"] = {"docstring - code-format": True}
|
|
207
|
-
config["tool"]["ruff"]["lint"] = {
|
|
208
|
-
"extend-select": ["C901", "F", "I", "UP"],
|
|
209
|
-
"ignore": ["E402", "F821"],
|
|
210
|
-
"fixable": ["ALL"],
|
|
211
|
-
}
|
|
212
|
-
if "pytest" not in config["tool"]:
|
|
213
|
-
config["tool"]["pytest"] = {
|
|
214
|
-
"ini_options": {
|
|
215
|
-
"asyncio_mode": "auto",
|
|
216
|
-
"timeout": 300,
|
|
217
|
-
"addopts": "- - cov=crackerjack - - cov-report=term",
|
|
218
|
-
"markers": [
|
|
219
|
-
"unit: marks test as a unit test",
|
|
220
|
-
"benchmark: mark test as a benchmark",
|
|
221
|
-
"integration: marks test as an integration test",
|
|
222
|
-
"no_leaks: detect asyncio task leaks",
|
|
223
|
-
],
|
|
224
|
-
},
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
from crackerjack.services.filesystem import FileSystemService
|
|
228
|
-
|
|
229
|
-
content = dumps(config)
|
|
230
|
-
content = FileSystemService.clean_trailing_whitespace_and_newlines(content)
|
|
231
|
-
with pyproject_file.open("w") as f:
|
|
232
|
-
f.write(content)
|
|
233
|
-
self.console.print(
|
|
234
|
-
"[green]✅[/ green] pyproject.toml configuration updated"
|
|
235
|
-
)
|
|
236
|
-
return True
|
|
237
|
-
except Exception as e:
|
|
238
|
-
self.console.print(f"[red]❌[/ red] Failed to update pyproject.toml: {e}")
|
|
239
|
-
return False
|
|
240
|
-
|
|
241
|
-
def _run_precommit_autoupdate(self) -> bool:
|
|
242
|
-
import subprocess
|
|
243
|
-
|
|
244
|
-
try:
|
|
245
|
-
self.console.print("[cyan]🔄[/ cyan] Running pre-commit autoupdate...")
|
|
246
|
-
result = self._execute_precommit_autoupdate()
|
|
247
|
-
|
|
248
|
-
if result.returncode == 0:
|
|
249
|
-
self._display_autoupdate_results(result.stdout)
|
|
250
|
-
return True
|
|
251
|
-
else:
|
|
252
|
-
self._handle_autoupdate_error(result.stderr)
|
|
253
|
-
return False
|
|
254
|
-
|
|
255
|
-
except subprocess.TimeoutExpired:
|
|
256
|
-
self.console.print("[red]❌[/ red] Pre-commit autoupdate timed out")
|
|
257
|
-
return False
|
|
258
|
-
except Exception as e:
|
|
259
|
-
self.console.print(
|
|
260
|
-
f"[red]❌[/ red] Failed to run pre-commit autoupdate: {e}"
|
|
261
|
-
)
|
|
262
|
-
return False
|
|
263
|
-
|
|
264
|
-
def _execute_precommit_autoupdate(self) -> subprocess.CompletedProcess[str]:
|
|
265
|
-
return subprocess.run(
|
|
266
|
-
["uv", "run", "pre-commit", "autoupdate"],
|
|
267
|
-
cwd=self.pkg_path,
|
|
268
|
-
capture_output=True,
|
|
269
|
-
text=True,
|
|
270
|
-
timeout=60,
|
|
271
|
-
)
|
|
272
|
-
|
|
273
|
-
def _display_autoupdate_results(self, stdout: str) -> None:
|
|
274
|
-
if self._has_updates(stdout):
|
|
275
|
-
for line in stdout.split("\n"):
|
|
276
|
-
if self._is_update_line(line):
|
|
277
|
-
self.console.print(f"[dim] {line.strip()}[/ dim]")
|
|
278
|
-
|
|
279
|
-
def _has_updates(self, stdout: str) -> bool:
|
|
280
|
-
stdout_lower = stdout.lower()
|
|
281
|
-
return "updating" in stdout_lower or "updated" in stdout_lower
|
|
282
|
-
|
|
283
|
-
def _is_update_line(self, line: str) -> bool:
|
|
284
|
-
return "updating" in line.lower() or "- >" in line
|
|
285
|
-
|
|
286
|
-
def _handle_autoupdate_error(self, stderr: str) -> None:
|
|
287
|
-
if stderr:
|
|
288
|
-
self.console.print(
|
|
289
|
-
f"[yellow]Pre-commit autoupdate stderr: [/ yellow] {stderr}"
|
|
290
|
-
)
|
|
291
|
-
|
|
292
|
-
def _update_dynamic_config_versions(self) -> None:
|
|
293
|
-
try:
|
|
294
|
-
self.console.print("[cyan]🔄[/ cyan] Updating dynamic config versions...")
|
|
295
|
-
|
|
296
|
-
version_updates = self._extract_version_updates()
|
|
297
|
-
if version_updates:
|
|
298
|
-
self._update_dynamic_config_file(version_updates)
|
|
299
|
-
|
|
300
|
-
except Exception as e:
|
|
301
|
-
self.console.print(
|
|
302
|
-
f"[yellow]⚠️[/ yellow] Failed to update dynamic config versions: {e}"
|
|
303
|
-
)
|
|
304
|
-
|
|
305
|
-
def _extract_version_updates(self) -> dict[str, str]:
|
|
306
|
-
config_file = self.pkg_path / ".pre-commit-config.yaml"
|
|
307
|
-
if not config_file.exists():
|
|
308
|
-
return {}
|
|
309
|
-
|
|
310
|
-
import yaml
|
|
311
|
-
|
|
312
|
-
with config_file.open() as f:
|
|
313
|
-
config = yaml.safe_load(f)
|
|
314
|
-
|
|
315
|
-
if not config or "repos" not in config:
|
|
316
|
-
return {}
|
|
317
|
-
|
|
318
|
-
version_updates = {}
|
|
319
|
-
repos: list[dict[str, t.Any]] = (
|
|
320
|
-
config.get("repos", []) if isinstance(config, dict) else []
|
|
321
|
-
)
|
|
322
|
-
for repo in repos:
|
|
323
|
-
repo_url = repo.get("repo", "")
|
|
324
|
-
rev = repo.get("rev", "")
|
|
325
|
-
if repo_url and rev:
|
|
326
|
-
version_updates[repo_url] = rev
|
|
327
|
-
|
|
328
|
-
return version_updates
|
|
329
|
-
|
|
330
|
-
def _update_dynamic_config_file(self, version_updates: dict[str, str]) -> None:
|
|
331
|
-
dynamic_config_path = self.pkg_path / "crackerjack" / "dynamic_config.py"
|
|
332
|
-
if dynamic_config_path.exists():
|
|
333
|
-
self._apply_version_updates(dynamic_config_path, version_updates)
|
|
334
|
-
|
|
335
|
-
def _apply_version_updates(
|
|
336
|
-
self, config_path: Path, version_updates: dict[str, str]
|
|
337
|
-
) -> None:
|
|
338
|
-
try:
|
|
339
|
-
content = config_path.read_text()
|
|
340
|
-
updated = False
|
|
341
|
-
|
|
342
|
-
for repo_url, new_rev in version_updates.items():
|
|
343
|
-
from .regex_patterns import update_repo_revision
|
|
344
|
-
|
|
345
|
-
new_content = update_repo_revision(content, repo_url, new_rev)
|
|
346
|
-
if new_content != content:
|
|
347
|
-
content = new_content
|
|
348
|
-
updated = True
|
|
349
|
-
self.console.print(f"[dim] Updated {repo_url} to {new_rev}[/ dim]")
|
|
350
|
-
|
|
351
|
-
if updated:
|
|
352
|
-
config_path.write_text(content)
|
|
353
|
-
self.console.print("[green]✅[/ green] Dynamic config versions updated")
|
|
354
|
-
|
|
355
|
-
except Exception as e:
|
|
356
|
-
self.console.print(
|
|
357
|
-
f"[yellow]⚠️[/ yellow] Failed to apply version updates: {e}"
|
|
358
|
-
)
|
crackerjack/ui/server_panels.py
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
"""Rich panel utilities for MCP server operations with consistent styling."""
|
|
2
|
-
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
|
|
5
|
-
from rich.console import Console
|
|
6
|
-
from rich.panel import Panel
|
|
7
|
-
from rich.text import Text
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class ServerPanels:
|
|
11
|
-
"""Rich panel utilities for server operations with 74-char width limit."""
|
|
12
|
-
|
|
13
|
-
WIDTH = 74 # Match session-mgmt-mcp width constraint
|
|
14
|
-
|
|
15
|
-
def __init__(self, console: Console | None = None) -> None:
|
|
16
|
-
self.console = console or Console()
|
|
17
|
-
|
|
18
|
-
def restart_header(self) -> None:
|
|
19
|
-
"""Display server restart header panel."""
|
|
20
|
-
panel = Panel(
|
|
21
|
-
"🔄 Restarting Crackerjack MCP Server...",
|
|
22
|
-
width=self.WIDTH,
|
|
23
|
-
title="Server Restart",
|
|
24
|
-
style="cyan",
|
|
25
|
-
)
|
|
26
|
-
self.console.print(panel)
|
|
27
|
-
|
|
28
|
-
def stop_servers(self, count: int) -> None:
|
|
29
|
-
"""Display stopping servers status."""
|
|
30
|
-
self.console.print("📴 Stopping existing servers...")
|
|
31
|
-
self.console.print(f"🛑 Stopping {count} server process(es)...")
|
|
32
|
-
|
|
33
|
-
def process_stopped(self, pid: int) -> None:
|
|
34
|
-
"""Display process stopped message."""
|
|
35
|
-
self.console.print(f"Stopping process {pid}...")
|
|
36
|
-
self.console.print(f"✅ Process {pid} terminated gracefully")
|
|
37
|
-
|
|
38
|
-
def stop_complete(self, count: int) -> None:
|
|
39
|
-
"""Display stop completion panel."""
|
|
40
|
-
panel = Panel(
|
|
41
|
-
f"✅ Successfully stopped {count} process(es)",
|
|
42
|
-
width=self.WIDTH,
|
|
43
|
-
title="Server Stopped",
|
|
44
|
-
style="green",
|
|
45
|
-
)
|
|
46
|
-
self.console.print(panel)
|
|
47
|
-
|
|
48
|
-
def cleanup_wait(self) -> None:
|
|
49
|
-
"""Display cleanup waiting message."""
|
|
50
|
-
self.console.print("⏳ Waiting for cleanup...")
|
|
51
|
-
|
|
52
|
-
def starting_server(self) -> None:
|
|
53
|
-
"""Display starting server message."""
|
|
54
|
-
self.console.print("🚀 Starting fresh server instance...")
|
|
55
|
-
self.console.print("🚀 Starting Crackerjack MCP Server...")
|
|
56
|
-
self.console.print("⏳ Waiting for server to start...")
|
|
57
|
-
|
|
58
|
-
def success_panel(
|
|
59
|
-
self,
|
|
60
|
-
http_endpoint: str | None = None,
|
|
61
|
-
websocket_monitor: str | None = None,
|
|
62
|
-
process_id: int | None = None,
|
|
63
|
-
) -> None:
|
|
64
|
-
"""Display success panel with server details."""
|
|
65
|
-
content = Text()
|
|
66
|
-
content.append("✅ Server started successfully!\n", style="green bold")
|
|
67
|
-
|
|
68
|
-
if http_endpoint:
|
|
69
|
-
content.append(f"🌐 HTTP Endpoint: {http_endpoint}\n", style="cyan")
|
|
70
|
-
|
|
71
|
-
if websocket_monitor:
|
|
72
|
-
content.append(f"🔌 WebSocket Monitor: {websocket_monitor}\n", style="cyan")
|
|
73
|
-
|
|
74
|
-
if process_id:
|
|
75
|
-
content.append(f"📊 Process ID: {process_id}", style="cyan")
|
|
76
|
-
|
|
77
|
-
panel = Panel(
|
|
78
|
-
content,
|
|
79
|
-
width=self.WIDTH,
|
|
80
|
-
title="Crackerjack MCP Server",
|
|
81
|
-
style="green",
|
|
82
|
-
)
|
|
83
|
-
self.console.print(panel)
|
|
84
|
-
|
|
85
|
-
def failure_panel(self, error: str) -> None:
|
|
86
|
-
"""Display failure panel with error details."""
|
|
87
|
-
panel = Panel(
|
|
88
|
-
f"❌ Server failed to start: {error}",
|
|
89
|
-
width=self.WIDTH,
|
|
90
|
-
title="Server Error",
|
|
91
|
-
style="red",
|
|
92
|
-
)
|
|
93
|
-
self.console.print(panel)
|
|
94
|
-
|
|
95
|
-
def start_panel(
|
|
96
|
-
self,
|
|
97
|
-
project_path: Path,
|
|
98
|
-
mode: str = "STDIO",
|
|
99
|
-
http_endpoint: str | None = None,
|
|
100
|
-
websocket_port: int | None = None,
|
|
101
|
-
) -> None:
|
|
102
|
-
"""Display server start panel with configuration details."""
|
|
103
|
-
content = Text()
|
|
104
|
-
content.append("🚀 Starting Crackerjack MCP Server...\n", style="green bold")
|
|
105
|
-
content.append(f"📁 Project: {project_path.name}\n", style="cyan")
|
|
106
|
-
content.append(f"🔗 Mode: {mode}\n", style="cyan")
|
|
107
|
-
|
|
108
|
-
if http_endpoint:
|
|
109
|
-
content.append(f"🌐 HTTP: {http_endpoint}\n", style="cyan")
|
|
110
|
-
|
|
111
|
-
if websocket_port:
|
|
112
|
-
content.append(f"🔌 WebSocket: {websocket_port}", style="cyan")
|
|
113
|
-
|
|
114
|
-
panel = Panel(
|
|
115
|
-
content,
|
|
116
|
-
width=self.WIDTH,
|
|
117
|
-
title="Server Configuration",
|
|
118
|
-
style="green",
|
|
119
|
-
)
|
|
120
|
-
self.console.print(panel)
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
def create_server_panels(console: Console | None = None) -> ServerPanels:
|
|
124
|
-
"""Factory function to create ServerPanels instance."""
|
|
125
|
-
return ServerPanels(console)
|