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
|
@@ -126,6 +126,59 @@ def find_safe_pattern_for_text(text: str) -> list[str]:
|
|
|
126
126
|
return matches
|
|
127
127
|
|
|
128
128
|
|
|
129
|
+
def _determine_suggested_name(original_pattern: str) -> str:
|
|
130
|
+
"""Determine a suggested name for the pattern based on its content.
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
original_pattern: The regex pattern to analyze
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
Suggested pattern name
|
|
137
|
+
"""
|
|
138
|
+
if "python.*-.*m" in original_pattern:
|
|
139
|
+
return "fix_python_command_spacing"
|
|
140
|
+
if r"\-\s*\-" in original_pattern:
|
|
141
|
+
return "fix_double_dash_spacing"
|
|
142
|
+
if "token" in original_pattern.lower():
|
|
143
|
+
return "fix_token_pattern"
|
|
144
|
+
if "password" in original_pattern.lower():
|
|
145
|
+
return "fix_password_pattern"
|
|
146
|
+
|
|
147
|
+
keyword_pattern = CompiledPatternCache.get_compiled_pattern(r"[a-zA-Z]+")
|
|
148
|
+
keywords = keyword_pattern.findall(original_pattern)
|
|
149
|
+
if keywords:
|
|
150
|
+
return f"fix_{'_'.join(keywords[:3])}_pattern".lower()
|
|
151
|
+
|
|
152
|
+
return "fix_custom_pattern"
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def _build_test_cases(original_pattern: str, sample_text: str) -> list[tuple[str, str]]:
|
|
156
|
+
"""Build test cases based on pattern and sample text.
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
original_pattern: The regex pattern
|
|
160
|
+
sample_text: Optional sample text to include
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
List of (input, expected_output) test case tuples
|
|
164
|
+
"""
|
|
165
|
+
test_cases = []
|
|
166
|
+
|
|
167
|
+
if sample_text:
|
|
168
|
+
test_cases.append((sample_text, "Expected output needed"))
|
|
169
|
+
|
|
170
|
+
if "-" in original_pattern:
|
|
171
|
+
test_cases.extend(
|
|
172
|
+
[
|
|
173
|
+
("word - word", "word-word"),
|
|
174
|
+
("already-good", "already-good"),
|
|
175
|
+
("multiple - word - spacing", "multiple-word - spacing"),
|
|
176
|
+
]
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
return test_cases
|
|
180
|
+
|
|
181
|
+
|
|
129
182
|
def suggest_migration_for_re_sub(
|
|
130
183
|
original_pattern: str, original_replacement: str, sample_text: str = ""
|
|
131
184
|
) -> dict[str, t.Any]:
|
|
@@ -157,35 +210,8 @@ def suggest_migration_for_re_sub(
|
|
|
157
210
|
if matches:
|
|
158
211
|
suggestion["needs_new_pattern"] = False
|
|
159
212
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
elif r"\-\s*\-" in original_pattern:
|
|
163
|
-
suggestion["suggested_name"] = "fix_double_dash_spacing"
|
|
164
|
-
elif "token" in original_pattern.lower():
|
|
165
|
-
suggestion["suggested_name"] = "fix_token_pattern"
|
|
166
|
-
elif "password" in original_pattern.lower():
|
|
167
|
-
suggestion["suggested_name"] = "fix_password_pattern"
|
|
168
|
-
else:
|
|
169
|
-
keyword_pattern = CompiledPatternCache.get_compiled_pattern(r"[a-zA-Z]+")
|
|
170
|
-
keywords = keyword_pattern.findall(original_pattern)
|
|
171
|
-
if keywords:
|
|
172
|
-
suggestion["suggested_name"] = (
|
|
173
|
-
f"fix_{'_'.join(keywords[:3])}_pattern".lower()
|
|
174
|
-
)
|
|
175
|
-
else:
|
|
176
|
-
suggestion["suggested_name"] = "fix_custom_pattern"
|
|
177
|
-
|
|
178
|
-
if sample_text:
|
|
179
|
-
suggestion["test_cases_needed"].append((sample_text, "Expected output needed"))
|
|
180
|
-
|
|
181
|
-
if "-" in original_pattern:
|
|
182
|
-
suggestion["test_cases_needed"].extend(
|
|
183
|
-
[
|
|
184
|
-
("word - word", "word-word"),
|
|
185
|
-
("already-good", "already-good"),
|
|
186
|
-
("multiple - word - spacing", "multiple-word - spacing"),
|
|
187
|
-
]
|
|
188
|
-
)
|
|
213
|
+
suggestion["suggested_name"] = _determine_suggested_name(original_pattern)
|
|
214
|
+
suggestion["test_cases_needed"] = _build_test_cases(original_pattern, sample_text)
|
|
189
215
|
|
|
190
216
|
return suggestion
|
|
191
217
|
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import tempfile
|
|
2
|
+
import time
|
|
2
3
|
import typing as t
|
|
4
|
+
from contextlib import suppress
|
|
3
5
|
from enum import Enum
|
|
4
6
|
from pathlib import Path
|
|
5
7
|
|
|
8
|
+
from crackerjack.models.protocols import SecureStatusFormatterProtocol, ServiceProtocol
|
|
9
|
+
|
|
10
|
+
from .regex_patterns import SAFE_PATTERNS, CompiledPatternCache, sanitize_internal_urls
|
|
6
11
|
from .security_logger import get_security_logger
|
|
7
12
|
|
|
8
13
|
|
|
@@ -13,7 +18,7 @@ class StatusVerbosity(str, Enum):
|
|
|
13
18
|
FULL = "full"
|
|
14
19
|
|
|
15
20
|
|
|
16
|
-
class SecureStatusFormatter:
|
|
21
|
+
class SecureStatusFormatter(SecureStatusFormatterProtocol, ServiceProtocol):
|
|
17
22
|
SENSITIVE_PATTERNS = {
|
|
18
23
|
"absolute_paths": [
|
|
19
24
|
r"(/[^/\s]*){2, }",
|
|
@@ -64,6 +69,42 @@ class SecureStatusFormatter:
|
|
|
64
69
|
self.project_root = project_root or Path.cwd()
|
|
65
70
|
self.security_logger = get_security_logger()
|
|
66
71
|
|
|
72
|
+
def initialize(self) -> None:
|
|
73
|
+
pass
|
|
74
|
+
|
|
75
|
+
def cleanup(self) -> None:
|
|
76
|
+
pass
|
|
77
|
+
|
|
78
|
+
def health_check(self) -> bool:
|
|
79
|
+
return True
|
|
80
|
+
|
|
81
|
+
def shutdown(self) -> None:
|
|
82
|
+
pass
|
|
83
|
+
|
|
84
|
+
def metrics(self) -> dict[str, t.Any]:
|
|
85
|
+
return {}
|
|
86
|
+
|
|
87
|
+
def is_healthy(self) -> bool:
|
|
88
|
+
return True
|
|
89
|
+
|
|
90
|
+
def register_resource(self, resource: t.Any) -> None:
|
|
91
|
+
pass
|
|
92
|
+
|
|
93
|
+
def cleanup_resource(self, resource: t.Any) -> None:
|
|
94
|
+
pass
|
|
95
|
+
|
|
96
|
+
def record_error(self, error: Exception) -> None:
|
|
97
|
+
pass
|
|
98
|
+
|
|
99
|
+
def increment_requests(self) -> None:
|
|
100
|
+
pass
|
|
101
|
+
|
|
102
|
+
def get_custom_metric(self, name: str) -> t.Any:
|
|
103
|
+
return None
|
|
104
|
+
|
|
105
|
+
def set_custom_metric(self, name: str, value: t.Any) -> None:
|
|
106
|
+
pass
|
|
107
|
+
|
|
67
108
|
def format_status(
|
|
68
109
|
self,
|
|
69
110
|
status_data: dict[str, t.Any],
|
|
@@ -181,8 +222,6 @@ class SecureStatusFormatter:
|
|
|
181
222
|
return text
|
|
182
223
|
|
|
183
224
|
def _sanitize_paths(self, text: str) -> str:
|
|
184
|
-
from .regex_patterns import SAFE_PATTERNS
|
|
185
|
-
|
|
186
225
|
unix_path_pattern = SAFE_PATTERNS.get("detect_absolute_unix_paths")
|
|
187
226
|
|
|
188
227
|
if not unix_path_pattern:
|
|
@@ -202,10 +241,6 @@ class SecureStatusFormatter:
|
|
|
202
241
|
return text
|
|
203
242
|
|
|
204
243
|
def _process_path_pattern(self, text: str, pattern_str: str) -> str:
|
|
205
|
-
from contextlib import suppress
|
|
206
|
-
|
|
207
|
-
from .regex_patterns import CompiledPatternCache
|
|
208
|
-
|
|
209
244
|
with suppress(Exception):
|
|
210
245
|
compiled = CompiledPatternCache.get_compiled_pattern(pattern_str)
|
|
211
246
|
matches = compiled.findall(text)
|
|
@@ -236,8 +271,6 @@ class SecureStatusFormatter:
|
|
|
236
271
|
return text.replace(match, "[REDACTED_PATH]")
|
|
237
272
|
|
|
238
273
|
def _sanitize_internal_urls(self, text: str) -> str:
|
|
239
|
-
from .regex_patterns import sanitize_internal_urls
|
|
240
|
-
|
|
241
274
|
return sanitize_internal_urls(text)
|
|
242
275
|
|
|
243
276
|
def _mask_potential_secrets(self, text: str) -> str:
|
|
@@ -254,8 +287,6 @@ class SecureStatusFormatter:
|
|
|
254
287
|
return "[INTERNAL_URL]" in text or "[REDACTED_PATH]" in text
|
|
255
288
|
|
|
256
289
|
def _get_validated_secret_patterns(self) -> list[t.Any]:
|
|
257
|
-
from .regex_patterns import SAFE_PATTERNS
|
|
258
|
-
|
|
259
290
|
patterns = []
|
|
260
291
|
long_alphanumeric = SAFE_PATTERNS.get("detect_long_alphanumeric_tokens")
|
|
261
292
|
base64_like = SAFE_PATTERNS.get("detect_base64_like_strings")
|
|
@@ -278,8 +309,6 @@ class SecureStatusFormatter:
|
|
|
278
309
|
def _apply_fallback_secret_patterns(self, text: str) -> str:
|
|
279
310
|
for pattern_str in self.SENSITIVE_PATTERNS["secrets"]:
|
|
280
311
|
try:
|
|
281
|
-
from .regex_patterns import CompiledPatternCache
|
|
282
|
-
|
|
283
312
|
compiled = CompiledPatternCache.get_compiled_pattern(pattern_str)
|
|
284
313
|
text = self._mask_pattern_matches(text, compiled.findall(text))
|
|
285
314
|
except Exception:
|
|
@@ -317,8 +346,6 @@ class SecureStatusFormatter:
|
|
|
317
346
|
return obj
|
|
318
347
|
|
|
319
348
|
def _get_timestamp(self) -> float:
|
|
320
|
-
import time
|
|
321
|
-
|
|
322
349
|
return time.time()
|
|
323
350
|
|
|
324
351
|
def format_error_response(
|
|
@@ -445,9 +445,42 @@ class SecureSubprocessExecutor:
|
|
|
445
445
|
try:
|
|
446
446
|
resolved_path = cwd_path.resolve()
|
|
447
447
|
|
|
448
|
+
# Get the original path's components to check for path traversal patterns
|
|
449
|
+
original_path_obj = Path(cwd)
|
|
450
|
+
original_parts = original_path_obj.parts
|
|
451
|
+
if ".." in original_parts or any(
|
|
452
|
+
part.startswith("../") for part in original_parts
|
|
453
|
+
):
|
|
454
|
+
# Check if the resolved path is within the safe base (project directory or temp)
|
|
455
|
+
safe_root = (
|
|
456
|
+
Path.cwd().parent.resolve()
|
|
457
|
+
) # Use parent of project root as broader safe root
|
|
458
|
+
try:
|
|
459
|
+
resolved_path.relative_to(safe_root)
|
|
460
|
+
except ValueError:
|
|
461
|
+
# If relative_to raises ValueError, path is outside safe root
|
|
462
|
+
path_str = str(resolved_path)
|
|
463
|
+
self.security_logger.log_path_traversal_attempt(
|
|
464
|
+
attempted_path=path_str,
|
|
465
|
+
base_directory=str(safe_root),
|
|
466
|
+
)
|
|
467
|
+
raise CommandValidationError(
|
|
468
|
+
f"Dangerous working directory: {path_str}"
|
|
469
|
+
)
|
|
470
|
+
|
|
448
471
|
path_str = str(resolved_path)
|
|
449
|
-
|
|
450
|
-
|
|
472
|
+
# Check for system directories, including macOS /private variants
|
|
473
|
+
if path_str.startswith(
|
|
474
|
+
(
|
|
475
|
+
"/etc",
|
|
476
|
+
"/usr/bin",
|
|
477
|
+
"/bin",
|
|
478
|
+
"/sbin",
|
|
479
|
+
"/private/etc",
|
|
480
|
+
"/private/usr/bin",
|
|
481
|
+
"/private/bin",
|
|
482
|
+
"/private/sbin",
|
|
483
|
+
)
|
|
451
484
|
):
|
|
452
485
|
self.security_logger.log_path_traversal_attempt(
|
|
453
486
|
attempted_path=path_str,
|
crackerjack/services/security.py
CHANGED
|
@@ -5,14 +5,15 @@ from contextlib import suppress
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
|
|
7
7
|
from crackerjack.errors import FileError, SecurityError
|
|
8
|
+
from crackerjack.models.protocols import SecurityServiceProtocol
|
|
8
9
|
from crackerjack.services.regex_patterns import SAFE_PATTERNS
|
|
9
10
|
|
|
10
11
|
|
|
11
|
-
class SecurityService:
|
|
12
|
+
class SecurityService(SecurityServiceProtocol):
|
|
12
13
|
TOKEN_PATTERN_NAMES = [
|
|
13
14
|
"mask_pypi_token",
|
|
14
15
|
"mask_github_token",
|
|
15
|
-
"mask_generic_long_token",
|
|
16
|
+
"mask_generic_long_token", # Changed from "mask_github_long_token" to correct name
|
|
16
17
|
"mask_token_assignment",
|
|
17
18
|
"mask_password_assignment",
|
|
18
19
|
]
|
|
@@ -188,21 +189,28 @@ class SecurityService:
|
|
|
188
189
|
secrets = []
|
|
189
190
|
|
|
190
191
|
patterns = {
|
|
191
|
-
"api_key": r
|
|
192
|
-
"password": r
|
|
193
|
-
"token": r
|
|
192
|
+
"api_key": r"(?i)(?:api[_-]?key)[\s]*[=:][\s]*[\"']([A-Za-z0-9_-]{20,})[\"']",
|
|
193
|
+
"password": r"(?i)(?:password)[\s]*[=:][\s]*[\"']([^\"'\s]{8,})[\"']",
|
|
194
|
+
"token": r"(?i)(?:token)[\s]*[=:][\s]*[\"']([A-Za-z0-9_-]{20,})[\"']",
|
|
194
195
|
}
|
|
195
196
|
|
|
196
197
|
import re
|
|
197
198
|
|
|
198
199
|
for secret_type, pattern in patterns.items():
|
|
199
|
-
matches = re.finditer(pattern, content
|
|
200
|
+
matches = re.finditer(pattern, content)
|
|
200
201
|
for match in matches:
|
|
202
|
+
# Extract the captured group (the secret value)
|
|
203
|
+
secret_value = match.group(1)
|
|
204
|
+
|
|
205
|
+
# Calculate line number where the match occurs
|
|
206
|
+
line_start_pos = match.start()
|
|
207
|
+
line_num = content[:line_start_pos].count("\n") + 1
|
|
208
|
+
|
|
201
209
|
secrets.append(
|
|
202
210
|
{
|
|
203
211
|
"type": secret_type,
|
|
204
|
-
"value":
|
|
205
|
-
"line":
|
|
212
|
+
"value": secret_value[:10] + "...",
|
|
213
|
+
"line": line_num,
|
|
206
214
|
}
|
|
207
215
|
)
|
|
208
216
|
return secrets
|
|
@@ -5,9 +5,10 @@ import time
|
|
|
5
5
|
import typing as t
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
|
|
8
|
-
from
|
|
8
|
+
from acb.console import Console
|
|
9
|
+
from acb.depends import Inject, depends
|
|
10
|
+
from mcp_common.ui import ServerPanels
|
|
9
11
|
|
|
10
|
-
from ..ui.server_panels import create_server_panels
|
|
11
12
|
from .secure_subprocess import execute_secure_subprocess
|
|
12
13
|
from .security_logger import get_security_logger
|
|
13
14
|
|
|
@@ -198,18 +199,17 @@ def stop_process(pid: int, force: bool = False) -> bool:
|
|
|
198
199
|
return True
|
|
199
200
|
|
|
200
201
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
console = Console()
|
|
204
|
-
|
|
205
|
-
panels = create_server_panels(console)
|
|
202
|
+
@depends.inject
|
|
203
|
+
def stop_mcp_server(console: Inject[Console]) -> bool:
|
|
206
204
|
processes = find_mcp_server_processes()
|
|
207
205
|
|
|
208
206
|
if not processes:
|
|
209
207
|
console.print("[yellow]⚠️ No MCP server processes found[/ yellow]")
|
|
210
208
|
return True
|
|
211
209
|
|
|
212
|
-
|
|
210
|
+
ServerPanels.info(
|
|
211
|
+
title="MCP Server", message=f"Stopping {len(processes)} process(es)"
|
|
212
|
+
)
|
|
213
213
|
|
|
214
214
|
success = True
|
|
215
215
|
for proc in processes:
|
|
@@ -221,15 +221,16 @@ def stop_mcp_server(console: Console | None = None) -> bool:
|
|
|
221
221
|
success = False
|
|
222
222
|
|
|
223
223
|
if success:
|
|
224
|
-
|
|
224
|
+
ServerPanels.info(
|
|
225
|
+
title="MCP Server",
|
|
226
|
+
message=f"Successfully stopped {len(processes)} process(es)",
|
|
227
|
+
)
|
|
225
228
|
|
|
226
229
|
return success
|
|
227
230
|
|
|
228
231
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
console = Console()
|
|
232
|
-
|
|
232
|
+
@depends.inject
|
|
233
|
+
def stop_websocket_server(console: Inject[Console]) -> bool:
|
|
233
234
|
processes = find_websocket_server_processes()
|
|
234
235
|
|
|
235
236
|
if not processes:
|
|
@@ -248,11 +249,9 @@ def stop_websocket_server(console: Console | None = None) -> bool:
|
|
|
248
249
|
return success
|
|
249
250
|
|
|
250
251
|
|
|
251
|
-
|
|
252
|
+
@depends.inject
|
|
253
|
+
def stop_zuban_lsp(console: Inject[Console]) -> bool:
|
|
252
254
|
"""Stop running zuban LSP server processes."""
|
|
253
|
-
if console is None:
|
|
254
|
-
console = Console()
|
|
255
|
-
|
|
256
255
|
processes = find_zuban_lsp_processes()
|
|
257
256
|
|
|
258
257
|
if not processes:
|
|
@@ -271,33 +270,30 @@ def stop_zuban_lsp(console: Console | None = None) -> bool:
|
|
|
271
270
|
return success
|
|
272
271
|
|
|
273
272
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
websocket_success = stop_websocket_server(console)
|
|
280
|
-
zuban_lsp_success = stop_zuban_lsp(console)
|
|
273
|
+
@depends.inject
|
|
274
|
+
def stop_all_servers(console: Inject[Console]) -> bool:
|
|
275
|
+
mcp_success = stop_mcp_server()
|
|
276
|
+
websocket_success = stop_websocket_server()
|
|
277
|
+
zuban_lsp_success = stop_zuban_lsp()
|
|
281
278
|
|
|
282
279
|
return mcp_success and websocket_success and zuban_lsp_success
|
|
283
280
|
|
|
284
281
|
|
|
282
|
+
@depends.inject
|
|
285
283
|
def restart_mcp_server(
|
|
286
284
|
websocket_port: int | None = None,
|
|
287
|
-
console: Console
|
|
285
|
+
console: Inject[Console] = None,
|
|
288
286
|
) -> bool:
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
panels = create_server_panels(console)
|
|
293
|
-
panels.restart_header()
|
|
287
|
+
ServerPanels.info(
|
|
288
|
+
title="MCP Server", message="Restarting Crackerjack MCP Server..."
|
|
289
|
+
)
|
|
294
290
|
|
|
295
|
-
stop_mcp_server(
|
|
291
|
+
stop_mcp_server()
|
|
296
292
|
|
|
297
|
-
|
|
293
|
+
ServerPanels.simple_message("⏳ Waiting for cleanup...", style="dim")
|
|
298
294
|
time.sleep(2)
|
|
299
295
|
|
|
300
|
-
|
|
296
|
+
ServerPanels.simple_message("🚀 Starting new server instance...", style="green")
|
|
301
297
|
try:
|
|
302
298
|
cmd = [sys.executable, "-m", "crackerjack", "--start-mcp-server"]
|
|
303
299
|
if websocket_port:
|
|
@@ -323,35 +319,30 @@ def restart_mcp_server(
|
|
|
323
319
|
|
|
324
320
|
# Display success panel with server details
|
|
325
321
|
http_endpoint = "http://127.0.0.1:8676/mcp"
|
|
326
|
-
websocket_monitor = (
|
|
327
|
-
f"ws://127.0.0.1:{websocket_port or 8675}" if websocket_port else None
|
|
328
|
-
)
|
|
329
322
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
323
|
+
ServerPanels.startup_success(
|
|
324
|
+
server_name="Crackerjack MCP",
|
|
325
|
+
endpoint=http_endpoint,
|
|
333
326
|
process_id=process.pid,
|
|
334
327
|
)
|
|
335
328
|
return True
|
|
336
329
|
|
|
337
330
|
except Exception as e:
|
|
338
|
-
|
|
331
|
+
ServerPanels.error(title="MCP Restart Error", message=str(e))
|
|
339
332
|
return False
|
|
340
333
|
|
|
341
334
|
|
|
342
|
-
|
|
335
|
+
@depends.inject
|
|
336
|
+
def restart_zuban_lsp(console: Inject[Console]) -> bool:
|
|
343
337
|
"""Restart zuban LSP server."""
|
|
344
|
-
if console is None:
|
|
345
|
-
console = Console()
|
|
346
|
-
|
|
347
338
|
console.print("[bold cyan]🔄 Restarting Zuban LSP server...[/ bold cyan]")
|
|
348
339
|
|
|
349
|
-
stop_zuban_lsp(
|
|
340
|
+
stop_zuban_lsp()
|
|
350
341
|
|
|
351
|
-
console.print("⏳ Waiting for cleanup
|
|
342
|
+
console.print("⏳ Waiting for cleanup")
|
|
352
343
|
time.sleep(2)
|
|
353
344
|
|
|
354
|
-
console.print("🚀 Starting new Zuban LSP server
|
|
345
|
+
console.print("🚀 Starting new Zuban LSP server")
|
|
355
346
|
try:
|
|
356
347
|
cmd = [sys.executable, "-m", "crackerjack", "--start-zuban-lsp"]
|
|
357
348
|
|
|
@@ -378,10 +369,8 @@ def restart_zuban_lsp(console: Console | None = None) -> bool:
|
|
|
378
369
|
return False
|
|
379
370
|
|
|
380
371
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
console = Console()
|
|
384
|
-
|
|
372
|
+
@depends.inject
|
|
373
|
+
def list_server_status(console: Inject[Console]) -> None:
|
|
385
374
|
console.print("[bold cyan]📊 Crackerjack Server Status[/ bold cyan]")
|
|
386
375
|
|
|
387
376
|
mcp_processes = find_mcp_server_processes()
|
|
@@ -1,18 +1,60 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import subprocess
|
|
3
|
+
import typing as t
|
|
4
|
+
from contextlib import suppress
|
|
3
5
|
from datetime import datetime, timedelta
|
|
4
6
|
from pathlib import Path
|
|
5
7
|
|
|
6
|
-
from
|
|
8
|
+
from acb.console import Console
|
|
9
|
+
from acb.depends import Inject, depends
|
|
7
10
|
|
|
11
|
+
from crackerjack.models.protocols import ServiceProtocol, SmartSchedulingServiceProtocol
|
|
8
12
|
|
|
9
|
-
|
|
10
|
-
|
|
13
|
+
|
|
14
|
+
class SmartSchedulingService(SmartSchedulingServiceProtocol, ServiceProtocol):
|
|
15
|
+
@depends.inject
|
|
16
|
+
def __init__(self, console: Inject[Console], project_path: Path) -> None:
|
|
11
17
|
self.console = console
|
|
12
18
|
self.project_path = project_path
|
|
13
19
|
self.cache_dir = Path.home() / ".cache" / "crackerjack"
|
|
14
20
|
self.cache_dir.mkdir(parents=True, exist_ok=True)
|
|
15
21
|
|
|
22
|
+
def initialize(self) -> None:
|
|
23
|
+
pass
|
|
24
|
+
|
|
25
|
+
def cleanup(self) -> None:
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
def health_check(self) -> bool:
|
|
29
|
+
return True
|
|
30
|
+
|
|
31
|
+
def shutdown(self) -> None:
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
def metrics(self) -> dict[str, t.Any]:
|
|
35
|
+
return {}
|
|
36
|
+
|
|
37
|
+
def is_healthy(self) -> bool:
|
|
38
|
+
return True
|
|
39
|
+
|
|
40
|
+
def register_resource(self, resource: t.Any) -> None:
|
|
41
|
+
pass
|
|
42
|
+
|
|
43
|
+
def cleanup_resource(self, resource: t.Any) -> None:
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
def record_error(self, error: Exception) -> None:
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
def increment_requests(self) -> None:
|
|
50
|
+
pass
|
|
51
|
+
|
|
52
|
+
def get_custom_metric(self, name: str) -> t.Any:
|
|
53
|
+
return None
|
|
54
|
+
|
|
55
|
+
def set_custom_metric(self, name: str, value: t.Any) -> None:
|
|
56
|
+
pass
|
|
57
|
+
|
|
16
58
|
def should_scheduled_init(self) -> bool:
|
|
17
59
|
init_schedule = os.environ.get("CRACKERJACK_INIT_SCHEDULE", "weekly")
|
|
18
60
|
|
|
@@ -77,8 +119,6 @@ class SmartSchedulingService:
|
|
|
77
119
|
timestamp_file = self.cache_dir / f"{self.project_path.name}.init_timestamp"
|
|
78
120
|
|
|
79
121
|
if timestamp_file.exists():
|
|
80
|
-
from contextlib import suppress
|
|
81
|
-
|
|
82
122
|
with suppress(OSError, ValueError):
|
|
83
123
|
timestamp_str = timestamp_file.read_text().strip()
|
|
84
124
|
return datetime.fromisoformat(timestamp_str)
|
|
@@ -109,7 +149,7 @@ class SmartSchedulingService:
|
|
|
109
149
|
def _has_recent_activity(self) -> bool:
|
|
110
150
|
try:
|
|
111
151
|
result = subprocess.run(
|
|
112
|
-
["git", "log", "-
|
|
152
|
+
["git", "log", "-1", "--since=24.hours", "--oneline"],
|
|
113
153
|
cwd=self.project_path,
|
|
114
154
|
capture_output=True,
|
|
115
155
|
text=True,
|
|
@@ -18,9 +18,9 @@ class AccessLevel(str, Enum):
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
class AuthenticationMethod(str, Enum):
|
|
21
|
-
API_KEY = "api_key"
|
|
22
|
-
JWT_TOKEN = "jwt_token"
|
|
23
|
-
HMAC_SIGNATURE = "hmac_signature"
|
|
21
|
+
API_KEY = "api_key" # nosec B105
|
|
22
|
+
JWT_TOKEN = "jwt_token" # nosec B105
|
|
23
|
+
HMAC_SIGNATURE = "hmac_signature" # nosec B105
|
|
24
24
|
LOCAL_ONLY = "local_only"
|
|
25
25
|
|
|
26
26
|
|