crackerjack 0.18.2__py3-none-any.whl → 0.45.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- crackerjack/README.md +19 -0
- crackerjack/__init__.py +96 -2
- crackerjack/__main__.py +637 -138
- crackerjack/adapters/README.md +18 -0
- crackerjack/adapters/__init__.py +39 -0
- crackerjack/adapters/_output_paths.py +167 -0
- crackerjack/adapters/_qa_adapter_base.py +309 -0
- crackerjack/adapters/_tool_adapter_base.py +706 -0
- crackerjack/adapters/ai/README.md +65 -0
- crackerjack/adapters/ai/__init__.py +5 -0
- crackerjack/adapters/ai/claude.py +853 -0
- crackerjack/adapters/complexity/README.md +53 -0
- crackerjack/adapters/complexity/__init__.py +10 -0
- crackerjack/adapters/complexity/complexipy.py +641 -0
- crackerjack/adapters/dependency/__init__.py +22 -0
- crackerjack/adapters/dependency/pip_audit.py +418 -0
- crackerjack/adapters/format/README.md +72 -0
- crackerjack/adapters/format/__init__.py +11 -0
- crackerjack/adapters/format/mdformat.py +313 -0
- crackerjack/adapters/format/ruff.py +516 -0
- crackerjack/adapters/lint/README.md +47 -0
- crackerjack/adapters/lint/__init__.py +11 -0
- crackerjack/adapters/lint/codespell.py +273 -0
- crackerjack/adapters/lsp/README.md +49 -0
- crackerjack/adapters/lsp/__init__.py +27 -0
- crackerjack/adapters/lsp/_base.py +194 -0
- crackerjack/adapters/lsp/_client.py +358 -0
- crackerjack/adapters/lsp/_manager.py +193 -0
- crackerjack/adapters/lsp/skylos.py +283 -0
- crackerjack/adapters/lsp/zuban.py +557 -0
- crackerjack/adapters/refactor/README.md +59 -0
- crackerjack/adapters/refactor/__init__.py +12 -0
- crackerjack/adapters/refactor/creosote.py +318 -0
- crackerjack/adapters/refactor/refurb.py +406 -0
- crackerjack/adapters/refactor/skylos.py +494 -0
- crackerjack/adapters/sast/README.md +132 -0
- crackerjack/adapters/sast/__init__.py +32 -0
- crackerjack/adapters/sast/_base.py +201 -0
- crackerjack/adapters/sast/bandit.py +423 -0
- crackerjack/adapters/sast/pyscn.py +405 -0
- crackerjack/adapters/sast/semgrep.py +241 -0
- crackerjack/adapters/security/README.md +111 -0
- crackerjack/adapters/security/__init__.py +17 -0
- crackerjack/adapters/security/gitleaks.py +339 -0
- crackerjack/adapters/type/README.md +52 -0
- crackerjack/adapters/type/__init__.py +12 -0
- crackerjack/adapters/type/pyrefly.py +402 -0
- crackerjack/adapters/type/ty.py +402 -0
- crackerjack/adapters/type/zuban.py +522 -0
- crackerjack/adapters/utility/README.md +51 -0
- crackerjack/adapters/utility/__init__.py +10 -0
- crackerjack/adapters/utility/checks.py +884 -0
- crackerjack/agents/README.md +264 -0
- crackerjack/agents/__init__.py +66 -0
- crackerjack/agents/architect_agent.py +238 -0
- crackerjack/agents/base.py +167 -0
- crackerjack/agents/claude_code_bridge.py +641 -0
- crackerjack/agents/coordinator.py +600 -0
- crackerjack/agents/documentation_agent.py +520 -0
- crackerjack/agents/dry_agent.py +585 -0
- crackerjack/agents/enhanced_coordinator.py +279 -0
- crackerjack/agents/enhanced_proactive_agent.py +185 -0
- crackerjack/agents/error_middleware.py +53 -0
- crackerjack/agents/formatting_agent.py +230 -0
- crackerjack/agents/helpers/__init__.py +9 -0
- crackerjack/agents/helpers/performance/__init__.py +22 -0
- crackerjack/agents/helpers/performance/performance_ast_analyzer.py +357 -0
- crackerjack/agents/helpers/performance/performance_pattern_detector.py +909 -0
- crackerjack/agents/helpers/performance/performance_recommender.py +572 -0
- crackerjack/agents/helpers/refactoring/__init__.py +22 -0
- crackerjack/agents/helpers/refactoring/code_transformer.py +536 -0
- crackerjack/agents/helpers/refactoring/complexity_analyzer.py +344 -0
- crackerjack/agents/helpers/refactoring/dead_code_detector.py +437 -0
- crackerjack/agents/helpers/test_creation/__init__.py +19 -0
- crackerjack/agents/helpers/test_creation/test_ast_analyzer.py +216 -0
- crackerjack/agents/helpers/test_creation/test_coverage_analyzer.py +643 -0
- crackerjack/agents/helpers/test_creation/test_template_generator.py +1031 -0
- crackerjack/agents/import_optimization_agent.py +1181 -0
- crackerjack/agents/performance_agent.py +325 -0
- crackerjack/agents/performance_helpers.py +205 -0
- crackerjack/agents/proactive_agent.py +55 -0
- crackerjack/agents/refactoring_agent.py +511 -0
- crackerjack/agents/refactoring_helpers.py +247 -0
- crackerjack/agents/security_agent.py +793 -0
- crackerjack/agents/semantic_agent.py +479 -0
- crackerjack/agents/semantic_helpers.py +356 -0
- crackerjack/agents/test_creation_agent.py +570 -0
- crackerjack/agents/test_specialist_agent.py +526 -0
- crackerjack/agents/tracker.py +110 -0
- crackerjack/api.py +647 -0
- crackerjack/cli/README.md +394 -0
- crackerjack/cli/__init__.py +24 -0
- crackerjack/cli/cache_handlers.py +209 -0
- crackerjack/cli/cache_handlers_enhanced.py +680 -0
- crackerjack/cli/facade.py +162 -0
- crackerjack/cli/formatting.py +13 -0
- crackerjack/cli/handlers/__init__.py +85 -0
- crackerjack/cli/handlers/advanced.py +103 -0
- crackerjack/cli/handlers/ai_features.py +62 -0
- crackerjack/cli/handlers/analytics.py +479 -0
- crackerjack/cli/handlers/changelog.py +271 -0
- crackerjack/cli/handlers/config_handlers.py +16 -0
- crackerjack/cli/handlers/coverage.py +84 -0
- crackerjack/cli/handlers/documentation.py +280 -0
- crackerjack/cli/handlers/main_handlers.py +497 -0
- crackerjack/cli/handlers/monitoring.py +371 -0
- crackerjack/cli/handlers.py +700 -0
- crackerjack/cli/interactive.py +488 -0
- crackerjack/cli/options.py +1216 -0
- crackerjack/cli/semantic_handlers.py +292 -0
- crackerjack/cli/utils.py +19 -0
- crackerjack/cli/version.py +19 -0
- crackerjack/code_cleaner.py +1307 -0
- crackerjack/config/README.md +472 -0
- crackerjack/config/__init__.py +275 -0
- crackerjack/config/global_lock_config.py +207 -0
- crackerjack/config/hooks.py +390 -0
- crackerjack/config/loader.py +239 -0
- crackerjack/config/settings.py +141 -0
- crackerjack/config/tool_commands.py +331 -0
- crackerjack/core/README.md +393 -0
- crackerjack/core/__init__.py +0 -0
- crackerjack/core/async_workflow_orchestrator.py +738 -0
- crackerjack/core/autofix_coordinator.py +282 -0
- crackerjack/core/container.py +105 -0
- crackerjack/core/enhanced_container.py +583 -0
- crackerjack/core/file_lifecycle.py +472 -0
- crackerjack/core/performance.py +244 -0
- crackerjack/core/performance_monitor.py +357 -0
- crackerjack/core/phase_coordinator.py +1227 -0
- crackerjack/core/proactive_workflow.py +267 -0
- crackerjack/core/resource_manager.py +425 -0
- crackerjack/core/retry.py +275 -0
- crackerjack/core/service_watchdog.py +601 -0
- crackerjack/core/session_coordinator.py +239 -0
- crackerjack/core/timeout_manager.py +563 -0
- crackerjack/core/websocket_lifecycle.py +410 -0
- crackerjack/core/workflow/__init__.py +21 -0
- crackerjack/core/workflow/workflow_ai_coordinator.py +863 -0
- crackerjack/core/workflow/workflow_event_orchestrator.py +1107 -0
- crackerjack/core/workflow/workflow_issue_parser.py +714 -0
- crackerjack/core/workflow/workflow_phase_executor.py +1158 -0
- crackerjack/core/workflow/workflow_security_gates.py +400 -0
- crackerjack/core/workflow_orchestrator.py +2243 -0
- crackerjack/data/README.md +11 -0
- crackerjack/data/__init__.py +8 -0
- crackerjack/data/models.py +79 -0
- crackerjack/data/repository.py +210 -0
- crackerjack/decorators/README.md +180 -0
- crackerjack/decorators/__init__.py +35 -0
- crackerjack/decorators/error_handling.py +649 -0
- crackerjack/decorators/error_handling_decorators.py +334 -0
- crackerjack/decorators/helpers.py +58 -0
- crackerjack/decorators/patterns.py +281 -0
- crackerjack/decorators/utils.py +58 -0
- crackerjack/docs/INDEX.md +11 -0
- crackerjack/docs/README.md +11 -0
- crackerjack/docs/generated/api/API_REFERENCE.md +10895 -0
- crackerjack/docs/generated/api/CLI_REFERENCE.md +109 -0
- crackerjack/docs/generated/api/CROSS_REFERENCES.md +1755 -0
- crackerjack/docs/generated/api/PROTOCOLS.md +3 -0
- crackerjack/docs/generated/api/SERVICES.md +1252 -0
- crackerjack/documentation/README.md +11 -0
- crackerjack/documentation/__init__.py +31 -0
- crackerjack/documentation/ai_templates.py +756 -0
- crackerjack/documentation/dual_output_generator.py +767 -0
- crackerjack/documentation/mkdocs_integration.py +518 -0
- crackerjack/documentation/reference_generator.py +1065 -0
- crackerjack/dynamic_config.py +678 -0
- crackerjack/errors.py +378 -0
- crackerjack/events/README.md +11 -0
- crackerjack/events/__init__.py +16 -0
- crackerjack/events/telemetry.py +175 -0
- crackerjack/events/workflow_bus.py +346 -0
- crackerjack/exceptions/README.md +301 -0
- crackerjack/exceptions/__init__.py +5 -0
- crackerjack/exceptions/config.py +4 -0
- crackerjack/exceptions/tool_execution_error.py +245 -0
- crackerjack/executors/README.md +591 -0
- crackerjack/executors/__init__.py +13 -0
- crackerjack/executors/async_hook_executor.py +938 -0
- crackerjack/executors/cached_hook_executor.py +316 -0
- crackerjack/executors/hook_executor.py +1295 -0
- crackerjack/executors/hook_lock_manager.py +708 -0
- crackerjack/executors/individual_hook_executor.py +739 -0
- crackerjack/executors/lsp_aware_hook_executor.py +349 -0
- crackerjack/executors/progress_hook_executor.py +282 -0
- crackerjack/executors/tool_proxy.py +433 -0
- crackerjack/hooks/README.md +485 -0
- crackerjack/hooks/lsp_hook.py +93 -0
- crackerjack/intelligence/README.md +557 -0
- crackerjack/intelligence/__init__.py +37 -0
- crackerjack/intelligence/adaptive_learning.py +693 -0
- crackerjack/intelligence/agent_orchestrator.py +485 -0
- crackerjack/intelligence/agent_registry.py +377 -0
- crackerjack/intelligence/agent_selector.py +439 -0
- crackerjack/intelligence/integration.py +250 -0
- crackerjack/interactive.py +719 -0
- crackerjack/managers/README.md +369 -0
- crackerjack/managers/__init__.py +11 -0
- crackerjack/managers/async_hook_manager.py +135 -0
- crackerjack/managers/hook_manager.py +585 -0
- crackerjack/managers/publish_manager.py +631 -0
- crackerjack/managers/test_command_builder.py +391 -0
- crackerjack/managers/test_executor.py +474 -0
- crackerjack/managers/test_manager.py +1357 -0
- crackerjack/managers/test_progress.py +187 -0
- crackerjack/mcp/README.md +374 -0
- crackerjack/mcp/__init__.py +0 -0
- crackerjack/mcp/cache.py +352 -0
- crackerjack/mcp/client_runner.py +121 -0
- crackerjack/mcp/context.py +802 -0
- crackerjack/mcp/dashboard.py +657 -0
- crackerjack/mcp/enhanced_progress_monitor.py +493 -0
- crackerjack/mcp/file_monitor.py +394 -0
- crackerjack/mcp/progress_components.py +607 -0
- crackerjack/mcp/progress_monitor.py +1016 -0
- crackerjack/mcp/rate_limiter.py +336 -0
- crackerjack/mcp/server.py +24 -0
- crackerjack/mcp/server_core.py +526 -0
- crackerjack/mcp/service_watchdog.py +505 -0
- crackerjack/mcp/state.py +407 -0
- crackerjack/mcp/task_manager.py +259 -0
- crackerjack/mcp/tools/README.md +27 -0
- crackerjack/mcp/tools/__init__.py +19 -0
- crackerjack/mcp/tools/core_tools.py +469 -0
- crackerjack/mcp/tools/error_analyzer.py +283 -0
- crackerjack/mcp/tools/execution_tools.py +384 -0
- crackerjack/mcp/tools/intelligence_tool_registry.py +46 -0
- crackerjack/mcp/tools/intelligence_tools.py +264 -0
- crackerjack/mcp/tools/monitoring_tools.py +628 -0
- crackerjack/mcp/tools/proactive_tools.py +367 -0
- crackerjack/mcp/tools/progress_tools.py +222 -0
- crackerjack/mcp/tools/semantic_tools.py +584 -0
- crackerjack/mcp/tools/utility_tools.py +358 -0
- crackerjack/mcp/tools/workflow_executor.py +699 -0
- crackerjack/mcp/websocket/README.md +31 -0
- crackerjack/mcp/websocket/__init__.py +14 -0
- crackerjack/mcp/websocket/app.py +54 -0
- crackerjack/mcp/websocket/endpoints.py +492 -0
- crackerjack/mcp/websocket/event_bridge.py +188 -0
- crackerjack/mcp/websocket/jobs.py +406 -0
- crackerjack/mcp/websocket/monitoring/__init__.py +25 -0
- crackerjack/mcp/websocket/monitoring/api/__init__.py +19 -0
- crackerjack/mcp/websocket/monitoring/api/dependencies.py +141 -0
- crackerjack/mcp/websocket/monitoring/api/heatmap.py +154 -0
- crackerjack/mcp/websocket/monitoring/api/intelligence.py +199 -0
- crackerjack/mcp/websocket/monitoring/api/metrics.py +203 -0
- crackerjack/mcp/websocket/monitoring/api/telemetry.py +101 -0
- crackerjack/mcp/websocket/monitoring/dashboard.py +18 -0
- crackerjack/mcp/websocket/monitoring/factory.py +109 -0
- crackerjack/mcp/websocket/monitoring/filters.py +10 -0
- crackerjack/mcp/websocket/monitoring/metrics.py +64 -0
- crackerjack/mcp/websocket/monitoring/models.py +90 -0
- crackerjack/mcp/websocket/monitoring/utils.py +171 -0
- crackerjack/mcp/websocket/monitoring/websocket_manager.py +78 -0
- crackerjack/mcp/websocket/monitoring/websockets/__init__.py +17 -0
- crackerjack/mcp/websocket/monitoring/websockets/dependencies.py +126 -0
- crackerjack/mcp/websocket/monitoring/websockets/heatmap.py +176 -0
- crackerjack/mcp/websocket/monitoring/websockets/intelligence.py +291 -0
- crackerjack/mcp/websocket/monitoring/websockets/metrics.py +291 -0
- crackerjack/mcp/websocket/monitoring_endpoints.py +21 -0
- crackerjack/mcp/websocket/server.py +174 -0
- crackerjack/mcp/websocket/websocket_handler.py +276 -0
- crackerjack/mcp/websocket_server.py +10 -0
- crackerjack/models/README.md +308 -0
- crackerjack/models/__init__.py +40 -0
- crackerjack/models/config.py +730 -0
- crackerjack/models/config_adapter.py +265 -0
- crackerjack/models/protocols.py +1535 -0
- crackerjack/models/pydantic_models.py +320 -0
- crackerjack/models/qa_config.py +145 -0
- crackerjack/models/qa_results.py +134 -0
- crackerjack/models/resource_protocols.py +299 -0
- crackerjack/models/results.py +35 -0
- crackerjack/models/semantic_models.py +258 -0
- crackerjack/models/task.py +173 -0
- crackerjack/models/test_models.py +60 -0
- crackerjack/monitoring/README.md +11 -0
- crackerjack/monitoring/__init__.py +0 -0
- crackerjack/monitoring/ai_agent_watchdog.py +405 -0
- crackerjack/monitoring/metrics_collector.py +427 -0
- crackerjack/monitoring/regression_prevention.py +580 -0
- crackerjack/monitoring/websocket_server.py +406 -0
- crackerjack/orchestration/README.md +340 -0
- crackerjack/orchestration/__init__.py +43 -0
- crackerjack/orchestration/advanced_orchestrator.py +894 -0
- crackerjack/orchestration/cache/README.md +312 -0
- crackerjack/orchestration/cache/__init__.py +37 -0
- crackerjack/orchestration/cache/memory_cache.py +338 -0
- crackerjack/orchestration/cache/tool_proxy_cache.py +340 -0
- crackerjack/orchestration/config.py +297 -0
- crackerjack/orchestration/coverage_improvement.py +180 -0
- crackerjack/orchestration/execution_strategies.py +361 -0
- crackerjack/orchestration/hook_orchestrator.py +1398 -0
- crackerjack/orchestration/strategies/README.md +401 -0
- crackerjack/orchestration/strategies/__init__.py +39 -0
- crackerjack/orchestration/strategies/adaptive_strategy.py +630 -0
- crackerjack/orchestration/strategies/parallel_strategy.py +237 -0
- crackerjack/orchestration/strategies/sequential_strategy.py +299 -0
- crackerjack/orchestration/test_progress_streamer.py +647 -0
- crackerjack/plugins/README.md +11 -0
- crackerjack/plugins/__init__.py +15 -0
- crackerjack/plugins/base.py +200 -0
- crackerjack/plugins/hooks.py +254 -0
- crackerjack/plugins/loader.py +335 -0
- crackerjack/plugins/managers.py +264 -0
- crackerjack/py313.py +191 -0
- crackerjack/security/README.md +11 -0
- crackerjack/security/__init__.py +0 -0
- crackerjack/security/audit.py +197 -0
- crackerjack/services/README.md +374 -0
- crackerjack/services/__init__.py +9 -0
- crackerjack/services/ai/README.md +295 -0
- crackerjack/services/ai/__init__.py +7 -0
- crackerjack/services/ai/advanced_optimizer.py +878 -0
- crackerjack/services/ai/contextual_ai_assistant.py +542 -0
- crackerjack/services/ai/embeddings.py +444 -0
- crackerjack/services/ai/intelligent_commit.py +328 -0
- crackerjack/services/ai/predictive_analytics.py +510 -0
- crackerjack/services/anomaly_detector.py +392 -0
- crackerjack/services/api_extractor.py +617 -0
- crackerjack/services/backup_service.py +467 -0
- crackerjack/services/bounded_status_operations.py +530 -0
- crackerjack/services/cache.py +369 -0
- crackerjack/services/changelog_automation.py +399 -0
- crackerjack/services/command_execution_service.py +305 -0
- crackerjack/services/config_integrity.py +132 -0
- crackerjack/services/config_merge.py +546 -0
- crackerjack/services/config_service.py +198 -0
- crackerjack/services/config_template.py +493 -0
- crackerjack/services/coverage_badge_service.py +173 -0
- crackerjack/services/coverage_ratchet.py +381 -0
- crackerjack/services/debug.py +733 -0
- crackerjack/services/dependency_analyzer.py +460 -0
- crackerjack/services/dependency_monitor.py +622 -0
- crackerjack/services/documentation_generator.py +493 -0
- crackerjack/services/documentation_service.py +704 -0
- crackerjack/services/enhanced_filesystem.py +497 -0
- crackerjack/services/enterprise_optimizer.py +865 -0
- crackerjack/services/error_pattern_analyzer.py +676 -0
- crackerjack/services/file_filter.py +221 -0
- crackerjack/services/file_hasher.py +149 -0
- crackerjack/services/file_io_service.py +361 -0
- crackerjack/services/file_modifier.py +615 -0
- crackerjack/services/filesystem.py +381 -0
- crackerjack/services/git.py +422 -0
- crackerjack/services/health_metrics.py +615 -0
- crackerjack/services/heatmap_generator.py +744 -0
- crackerjack/services/incremental_executor.py +380 -0
- crackerjack/services/initialization.py +823 -0
- crackerjack/services/input_validator.py +668 -0
- crackerjack/services/intelligent_commit.py +327 -0
- crackerjack/services/log_manager.py +289 -0
- crackerjack/services/logging.py +228 -0
- crackerjack/services/lsp_client.py +628 -0
- crackerjack/services/memory_optimizer.py +414 -0
- crackerjack/services/metrics.py +587 -0
- crackerjack/services/monitoring/README.md +30 -0
- crackerjack/services/monitoring/__init__.py +9 -0
- crackerjack/services/monitoring/dependency_monitor.py +678 -0
- crackerjack/services/monitoring/error_pattern_analyzer.py +676 -0
- crackerjack/services/monitoring/health_metrics.py +716 -0
- crackerjack/services/monitoring/metrics.py +587 -0
- crackerjack/services/monitoring/performance_benchmarks.py +410 -0
- crackerjack/services/monitoring/performance_cache.py +388 -0
- crackerjack/services/monitoring/performance_monitor.py +569 -0
- crackerjack/services/parallel_executor.py +527 -0
- crackerjack/services/pattern_cache.py +333 -0
- crackerjack/services/pattern_detector.py +478 -0
- crackerjack/services/patterns/__init__.py +142 -0
- crackerjack/services/patterns/agents.py +107 -0
- crackerjack/services/patterns/code/__init__.py +15 -0
- crackerjack/services/patterns/code/detection.py +118 -0
- crackerjack/services/patterns/code/imports.py +107 -0
- crackerjack/services/patterns/code/paths.py +159 -0
- crackerjack/services/patterns/code/performance.py +119 -0
- crackerjack/services/patterns/code/replacement.py +36 -0
- crackerjack/services/patterns/core.py +212 -0
- crackerjack/services/patterns/documentation/__init__.py +14 -0
- crackerjack/services/patterns/documentation/badges_markdown.py +96 -0
- crackerjack/services/patterns/documentation/comments_blocks.py +83 -0
- crackerjack/services/patterns/documentation/docstrings.py +89 -0
- crackerjack/services/patterns/formatting.py +226 -0
- crackerjack/services/patterns/operations.py +339 -0
- crackerjack/services/patterns/security/__init__.py +23 -0
- crackerjack/services/patterns/security/code_injection.py +122 -0
- crackerjack/services/patterns/security/credentials.py +190 -0
- crackerjack/services/patterns/security/path_traversal.py +221 -0
- crackerjack/services/patterns/security/unsafe_operations.py +216 -0
- crackerjack/services/patterns/templates.py +62 -0
- crackerjack/services/patterns/testing/__init__.py +18 -0
- crackerjack/services/patterns/testing/error_patterns.py +107 -0
- crackerjack/services/patterns/testing/pytest_output.py +126 -0
- crackerjack/services/patterns/tool_output/__init__.py +16 -0
- crackerjack/services/patterns/tool_output/bandit.py +72 -0
- crackerjack/services/patterns/tool_output/other.py +97 -0
- crackerjack/services/patterns/tool_output/pyright.py +67 -0
- crackerjack/services/patterns/tool_output/ruff.py +44 -0
- crackerjack/services/patterns/url_sanitization.py +114 -0
- crackerjack/services/patterns/utilities.py +42 -0
- crackerjack/services/patterns/utils.py +339 -0
- crackerjack/services/patterns/validation.py +46 -0
- crackerjack/services/patterns/versioning.py +62 -0
- crackerjack/services/predictive_analytics.py +523 -0
- crackerjack/services/profiler.py +280 -0
- crackerjack/services/quality/README.md +415 -0
- crackerjack/services/quality/__init__.py +11 -0
- crackerjack/services/quality/anomaly_detector.py +392 -0
- crackerjack/services/quality/pattern_cache.py +333 -0
- crackerjack/services/quality/pattern_detector.py +479 -0
- crackerjack/services/quality/qa_orchestrator.py +491 -0
- crackerjack/services/quality/quality_baseline.py +395 -0
- crackerjack/services/quality/quality_baseline_enhanced.py +649 -0
- crackerjack/services/quality/quality_intelligence.py +949 -0
- crackerjack/services/regex_patterns.py +58 -0
- crackerjack/services/regex_utils.py +483 -0
- crackerjack/services/secure_path_utils.py +524 -0
- crackerjack/services/secure_status_formatter.py +450 -0
- crackerjack/services/secure_subprocess.py +635 -0
- crackerjack/services/security.py +239 -0
- crackerjack/services/security_logger.py +495 -0
- crackerjack/services/server_manager.py +411 -0
- crackerjack/services/smart_scheduling.py +167 -0
- crackerjack/services/status_authentication.py +460 -0
- crackerjack/services/status_security_manager.py +315 -0
- crackerjack/services/terminal_utils.py +0 -0
- crackerjack/services/thread_safe_status_collector.py +441 -0
- crackerjack/services/tool_filter.py +368 -0
- crackerjack/services/tool_version_service.py +43 -0
- crackerjack/services/unified_config.py +115 -0
- crackerjack/services/validation_rate_limiter.py +220 -0
- crackerjack/services/vector_store.py +689 -0
- crackerjack/services/version_analyzer.py +461 -0
- crackerjack/services/version_checker.py +223 -0
- crackerjack/services/websocket_resource_limiter.py +438 -0
- crackerjack/services/zuban_lsp_service.py +391 -0
- crackerjack/slash_commands/README.md +11 -0
- crackerjack/slash_commands/__init__.py +59 -0
- crackerjack/slash_commands/init.md +112 -0
- crackerjack/slash_commands/run.md +197 -0
- crackerjack/slash_commands/status.md +127 -0
- crackerjack/tools/README.md +11 -0
- crackerjack/tools/__init__.py +30 -0
- crackerjack/tools/_git_utils.py +105 -0
- crackerjack/tools/check_added_large_files.py +139 -0
- crackerjack/tools/check_ast.py +105 -0
- crackerjack/tools/check_json.py +103 -0
- crackerjack/tools/check_jsonschema.py +297 -0
- crackerjack/tools/check_toml.py +103 -0
- crackerjack/tools/check_yaml.py +110 -0
- crackerjack/tools/codespell_wrapper.py +72 -0
- crackerjack/tools/end_of_file_fixer.py +202 -0
- crackerjack/tools/format_json.py +128 -0
- crackerjack/tools/mdformat_wrapper.py +114 -0
- crackerjack/tools/trailing_whitespace.py +198 -0
- crackerjack/tools/validate_input_validator_patterns.py +236 -0
- crackerjack/tools/validate_regex_patterns.py +188 -0
- crackerjack/ui/README.md +11 -0
- crackerjack/ui/__init__.py +1 -0
- crackerjack/ui/dashboard_renderer.py +28 -0
- crackerjack/ui/templates/README.md +11 -0
- crackerjack/utils/console_utils.py +13 -0
- crackerjack/utils/dependency_guard.py +230 -0
- crackerjack/utils/retry_utils.py +275 -0
- crackerjack/workflows/README.md +590 -0
- crackerjack/workflows/__init__.py +46 -0
- crackerjack/workflows/actions.py +811 -0
- crackerjack/workflows/auto_fix.py +444 -0
- crackerjack/workflows/container_builder.py +499 -0
- crackerjack/workflows/definitions.py +443 -0
- crackerjack/workflows/engine.py +177 -0
- crackerjack/workflows/event_bridge.py +242 -0
- crackerjack-0.45.2.dist-info/METADATA +1678 -0
- crackerjack-0.45.2.dist-info/RECORD +478 -0
- {crackerjack-0.18.2.dist-info → crackerjack-0.45.2.dist-info}/WHEEL +1 -1
- crackerjack-0.45.2.dist-info/entry_points.txt +2 -0
- crackerjack/.gitignore +0 -14
- crackerjack/.libcst.codemod.yaml +0 -18
- crackerjack/.pdm.toml +0 -1
- crackerjack/.pre-commit-config.yaml +0 -91
- crackerjack/.pytest_cache/.gitignore +0 -2
- crackerjack/.pytest_cache/CACHEDIR.TAG +0 -4
- crackerjack/.pytest_cache/README.md +0 -8
- crackerjack/.pytest_cache/v/cache/nodeids +0 -1
- crackerjack/.pytest_cache/v/cache/stepwise +0 -1
- crackerjack/.ruff_cache/.gitignore +0 -1
- crackerjack/.ruff_cache/0.1.11/3256171999636029978 +0 -0
- crackerjack/.ruff_cache/0.1.14/602324811142551221 +0 -0
- crackerjack/.ruff_cache/0.1.4/10355199064880463147 +0 -0
- crackerjack/.ruff_cache/0.1.6/15140459877605758699 +0 -0
- crackerjack/.ruff_cache/0.1.7/1790508110482614856 +0 -0
- crackerjack/.ruff_cache/0.1.9/17041001205004563469 +0 -0
- crackerjack/.ruff_cache/0.11.2/4070660268492669020 +0 -0
- crackerjack/.ruff_cache/0.11.3/9818742842212983150 +0 -0
- crackerjack/.ruff_cache/0.11.4/9818742842212983150 +0 -0
- crackerjack/.ruff_cache/0.11.6/3557596832929915217 +0 -0
- crackerjack/.ruff_cache/0.11.7/10386934055395314831 +0 -0
- crackerjack/.ruff_cache/0.11.7/3557596832929915217 +0 -0
- crackerjack/.ruff_cache/0.11.8/530407680854991027 +0 -0
- crackerjack/.ruff_cache/0.2.0/10047773857155985907 +0 -0
- crackerjack/.ruff_cache/0.2.1/8522267973936635051 +0 -0
- crackerjack/.ruff_cache/0.2.2/18053836298936336950 +0 -0
- crackerjack/.ruff_cache/0.3.0/12548816621480535786 +0 -0
- crackerjack/.ruff_cache/0.3.3/11081883392474770722 +0 -0
- crackerjack/.ruff_cache/0.3.4/676973378459347183 +0 -0
- crackerjack/.ruff_cache/0.3.5/16311176246009842383 +0 -0
- crackerjack/.ruff_cache/0.5.7/1493622539551733492 +0 -0
- crackerjack/.ruff_cache/0.5.7/6231957614044513175 +0 -0
- crackerjack/.ruff_cache/0.5.7/9932762556785938009 +0 -0
- crackerjack/.ruff_cache/0.6.0/11982804814124138945 +0 -0
- crackerjack/.ruff_cache/0.6.0/12055761203849489982 +0 -0
- crackerjack/.ruff_cache/0.6.2/1206147804896221174 +0 -0
- crackerjack/.ruff_cache/0.6.4/1206147804896221174 +0 -0
- crackerjack/.ruff_cache/0.6.5/1206147804896221174 +0 -0
- crackerjack/.ruff_cache/0.6.7/3657366982708166874 +0 -0
- crackerjack/.ruff_cache/0.6.9/285614542852677309 +0 -0
- crackerjack/.ruff_cache/0.7.1/1024065805990144819 +0 -0
- crackerjack/.ruff_cache/0.7.1/285614542852677309 +0 -0
- crackerjack/.ruff_cache/0.7.3/16061516852537040135 +0 -0
- crackerjack/.ruff_cache/0.8.4/16354268377385700367 +0 -0
- crackerjack/.ruff_cache/0.9.10/12813592349865671909 +0 -0
- crackerjack/.ruff_cache/0.9.10/923908772239632759 +0 -0
- crackerjack/.ruff_cache/0.9.3/13948373885254993391 +0 -0
- crackerjack/.ruff_cache/0.9.9/12813592349865671909 +0 -0
- crackerjack/.ruff_cache/0.9.9/8843823720003377982 +0 -0
- crackerjack/.ruff_cache/CACHEDIR.TAG +0 -1
- crackerjack/crackerjack.py +0 -855
- crackerjack/pyproject.toml +0 -214
- crackerjack-0.18.2.dist-info/METADATA +0 -420
- crackerjack-0.18.2.dist-info/RECORD +0 -59
- crackerjack-0.18.2.dist-info/entry_points.txt +0 -4
- {crackerjack-0.18.2.dist-info → crackerjack-0.45.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,628 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import time
|
|
3
|
+
import typing as t
|
|
4
|
+
from contextlib import suppress
|
|
5
|
+
|
|
6
|
+
from crackerjack.mcp.context import get_context
|
|
7
|
+
from crackerjack.services.bounded_status_operations import (
|
|
8
|
+
execute_bounded_status_operation,
|
|
9
|
+
)
|
|
10
|
+
from crackerjack.services.secure_status_formatter import (
|
|
11
|
+
StatusVerbosity,
|
|
12
|
+
format_secure_status,
|
|
13
|
+
get_secure_status_formatter,
|
|
14
|
+
)
|
|
15
|
+
from crackerjack.services.status_authentication import (
|
|
16
|
+
authenticate_status_request,
|
|
17
|
+
get_status_authenticator,
|
|
18
|
+
)
|
|
19
|
+
from crackerjack.services.status_security_manager import (
|
|
20
|
+
get_status_security_manager,
|
|
21
|
+
secure_status_operation,
|
|
22
|
+
validate_status_request,
|
|
23
|
+
)
|
|
24
|
+
from crackerjack.services.thread_safe_status_collector import (
|
|
25
|
+
get_thread_safe_status_collector,
|
|
26
|
+
)
|
|
27
|
+
from crackerjack.services.websocket_resource_limiter import (
|
|
28
|
+
get_websocket_resource_limiter,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _suggest_agent_for_context(state_manager: t.Any) -> dict[str, t.Any]:
|
|
33
|
+
suggestions = {
|
|
34
|
+
"recommended_agent": None,
|
|
35
|
+
"reason": "",
|
|
36
|
+
"usage": "",
|
|
37
|
+
"priority": "MEDIUM",
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
with suppress(Exception):
|
|
41
|
+
recent_errors = getattr(state_manager, "recent_errors", [])
|
|
42
|
+
stage_statuses = _get_stage_status_dict(state_manager)
|
|
43
|
+
|
|
44
|
+
if stage_statuses.get("tests") == "failed" or any(
|
|
45
|
+
"test" in str(error).lower() for error in recent_errors
|
|
46
|
+
):
|
|
47
|
+
suggestions.update(
|
|
48
|
+
{
|
|
49
|
+
"recommended_agent": "crackerjack - test-specialist",
|
|
50
|
+
"reason": "Test failures detected-specialist needed for debugging and fixes",
|
|
51
|
+
"usage": 'Task tool with subagent_type ="crackerjack - test-specialist"',
|
|
52
|
+
"priority": "HIGH",
|
|
53
|
+
}
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
elif any(
|
|
57
|
+
"security" in str(error).lower() or "bandit" in str(error).lower()
|
|
58
|
+
for error in recent_errors
|
|
59
|
+
):
|
|
60
|
+
suggestions.update(
|
|
61
|
+
{
|
|
62
|
+
"recommended_agent": "security-auditor",
|
|
63
|
+
"reason": "Security issues detected-immediate audit required",
|
|
64
|
+
"usage": 'Task tool with subagent_type ="security-auditor"',
|
|
65
|
+
"priority": "HIGH",
|
|
66
|
+
}
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
elif any("complex" in str(error).lower() for error in recent_errors):
|
|
70
|
+
suggestions.update(
|
|
71
|
+
{
|
|
72
|
+
"recommended_agent": "crackerjack-architect",
|
|
73
|
+
"reason": "Complexity issues detected-architectural review needed",
|
|
74
|
+
"usage": 'Task tool with subagent_type ="crackerjack-architect"',
|
|
75
|
+
"priority": "HIGH",
|
|
76
|
+
}
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
else:
|
|
80
|
+
suggestions.update(
|
|
81
|
+
{
|
|
82
|
+
"recommended_agent": "crackerjack-architect",
|
|
83
|
+
"reason": "Python project-ensure crackerjack compliance from the start",
|
|
84
|
+
"usage": 'Task tool with subagent_type ="crackerjack-architect"',
|
|
85
|
+
"priority": "MEDIUM",
|
|
86
|
+
}
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
return suggestions
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _create_error_response(message: str, success: bool = False) -> str:
|
|
93
|
+
import json
|
|
94
|
+
|
|
95
|
+
return json.dumps({"error": message, "success": success})
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _get_stage_status_dict(state_manager: t.Any) -> dict[str, str]:
|
|
99
|
+
stages = ["fast", "comprehensive", "tests", "cleaning"]
|
|
100
|
+
return {stage: state_manager.get_stage_status(stage) for stage in stages}
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _get_session_info(state_manager: t.Any) -> dict[str, t.Any]:
|
|
104
|
+
return {
|
|
105
|
+
"total_iterations": getattr(state_manager, "iteration_count", 0),
|
|
106
|
+
"current_iteration": getattr(state_manager, "current_iteration", 0),
|
|
107
|
+
"session_active": getattr(state_manager, "session_active", False),
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
async def _determine_next_action(state_manager: t.Any) -> dict[str, t.Any]:
|
|
112
|
+
stage_priorities = [
|
|
113
|
+
("fast", "Fast hooks not completed"),
|
|
114
|
+
("tests", "Tests not completed"),
|
|
115
|
+
("comprehensive", "Comprehensive hooks not completed"),
|
|
116
|
+
]
|
|
117
|
+
|
|
118
|
+
for stage, reason in stage_priorities:
|
|
119
|
+
if state_manager.get_stage_status(stage) != "completed":
|
|
120
|
+
return {
|
|
121
|
+
"recommended_action": "run_stage",
|
|
122
|
+
"parameters": {"stage": stage},
|
|
123
|
+
"reason": reason,
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
"recommended_action": "complete",
|
|
128
|
+
"parameters": {},
|
|
129
|
+
"reason": "All stages completed successfully",
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
async def _build_server_stats(context: t.Any) -> dict[str, t.Any]:
|
|
134
|
+
return {
|
|
135
|
+
"server_info": {
|
|
136
|
+
"project_path": str(context.config.project_path),
|
|
137
|
+
"websocket_port": getattr(context, "websocket_server_port", None),
|
|
138
|
+
"websocket_active": getattr(context, "websocket_server_process", None)
|
|
139
|
+
is not None,
|
|
140
|
+
},
|
|
141
|
+
"rate_limiting": {
|
|
142
|
+
"enabled": context.rate_limiter is not None,
|
|
143
|
+
"config": context.rate_limiter.config.__dict__
|
|
144
|
+
if context.rate_limiter
|
|
145
|
+
else None,
|
|
146
|
+
},
|
|
147
|
+
"resource_usage": {
|
|
148
|
+
"temp_files_count": len(list[t.Any](context.progress_dir.glob("*.json")))
|
|
149
|
+
if context.progress_dir.exists()
|
|
150
|
+
else 0,
|
|
151
|
+
"progress_dir": str(context.progress_dir),
|
|
152
|
+
},
|
|
153
|
+
"timestamp": time.time(),
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def _add_state_manager_stats(stats: dict[str, t.Any], state_manager: t.Any) -> None:
|
|
158
|
+
if state_manager:
|
|
159
|
+
stats["state_manager"] = {
|
|
160
|
+
"iteration_count": getattr(state_manager, "iteration_count", 0),
|
|
161
|
+
"session_active": getattr(state_manager, "session_active", False),
|
|
162
|
+
"issues_count": len(getattr(state_manager, "issues", [])),
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def _get_active_jobs(context: t.Any) -> list[dict[str, t.Any]]:
|
|
167
|
+
jobs: list[dict[str, t.Any]] = []
|
|
168
|
+
if not context.progress_dir.exists():
|
|
169
|
+
return jobs
|
|
170
|
+
|
|
171
|
+
with suppress(Exception):
|
|
172
|
+
for progress_file in context.progress_dir.glob("job-*.json"):
|
|
173
|
+
try:
|
|
174
|
+
progress_data = json.loads(progress_file.read_text())
|
|
175
|
+
jobs.append(
|
|
176
|
+
{
|
|
177
|
+
"job_id": progress_data.get("job_id", "unknown"),
|
|
178
|
+
"status": progress_data.get("status", "unknown"),
|
|
179
|
+
"iteration": progress_data.get("iteration", 0),
|
|
180
|
+
"max_iterations": progress_data.get("max_iterations", 10),
|
|
181
|
+
"current_stage": progress_data.get("current_stage", "unknown"),
|
|
182
|
+
"overall_progress": progress_data.get("overall_progress", 0),
|
|
183
|
+
"stage_progress": progress_data.get("stage_progress", 0),
|
|
184
|
+
"message": progress_data.get("message", ""),
|
|
185
|
+
"timestamp": progress_data.get("timestamp", ""),
|
|
186
|
+
"error_counts": progress_data.get("error_counts", {}),
|
|
187
|
+
},
|
|
188
|
+
)
|
|
189
|
+
except (json.JSONDecodeError, KeyError):
|
|
190
|
+
continue
|
|
191
|
+
|
|
192
|
+
return jobs
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
async def _get_comprehensive_status_secure(
|
|
196
|
+
client_id: str = "mcp_client",
|
|
197
|
+
client_ip: str = "127.0.0.1",
|
|
198
|
+
auth_header: str | None = None,
|
|
199
|
+
verbosity: StatusVerbosity = StatusVerbosity.STANDARD,
|
|
200
|
+
) -> dict[str, t.Any]:
|
|
201
|
+
auth_manager = get_status_authenticator()
|
|
202
|
+
try:
|
|
203
|
+
credentials = await authenticate_status_request(
|
|
204
|
+
auth_header, client_ip, "get_comprehensive_status"
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
if not auth_manager.is_operation_allowed(
|
|
208
|
+
"get_comprehensive_status", credentials.access_level
|
|
209
|
+
):
|
|
210
|
+
return {"error": "Insufficient privileges for comprehensive status"}
|
|
211
|
+
|
|
212
|
+
except Exception as e:
|
|
213
|
+
return {"error": f"Authentication failed: {e}"}
|
|
214
|
+
|
|
215
|
+
try:
|
|
216
|
+
await validate_status_request(client_id, "get_comprehensive_status", {})
|
|
217
|
+
except Exception as e:
|
|
218
|
+
return {"error": f"Security validation failed: {e}"}
|
|
219
|
+
|
|
220
|
+
try:
|
|
221
|
+
result: dict[str, t.Any] = await execute_bounded_status_operation(
|
|
222
|
+
"status_collection",
|
|
223
|
+
client_id,
|
|
224
|
+
_collect_comprehensive_status_internal,
|
|
225
|
+
client_id,
|
|
226
|
+
verbosity,
|
|
227
|
+
)
|
|
228
|
+
return result
|
|
229
|
+
except Exception as e:
|
|
230
|
+
return {"error": f"Resource limit exceeded: {e}"}
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
async def _collect_comprehensive_status_internal(
|
|
234
|
+
client_id: str = "mcp_client",
|
|
235
|
+
verbosity: StatusVerbosity = StatusVerbosity.STANDARD,
|
|
236
|
+
) -> dict[str, t.Any]:
|
|
237
|
+
collector = get_thread_safe_status_collector()
|
|
238
|
+
|
|
239
|
+
try:
|
|
240
|
+
snapshot = await collector.collect_comprehensive_status(
|
|
241
|
+
client_id=client_id,
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
status = {
|
|
245
|
+
"services": snapshot.services,
|
|
246
|
+
"jobs": snapshot.jobs,
|
|
247
|
+
"server_stats": snapshot.server_stats,
|
|
248
|
+
"collection_info": {
|
|
249
|
+
"timestamp": snapshot.timestamp,
|
|
250
|
+
"duration": snapshot.collection_duration,
|
|
251
|
+
"is_complete": snapshot.is_complete,
|
|
252
|
+
"errors": snapshot.errors,
|
|
253
|
+
},
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
context = None
|
|
257
|
+
with suppress(RuntimeError):
|
|
258
|
+
context = get_context()
|
|
259
|
+
|
|
260
|
+
if context:
|
|
261
|
+
state_manager = getattr(context, "state_manager", None)
|
|
262
|
+
if state_manager:
|
|
263
|
+
status["agent_suggestions"] = _suggest_agent_for_context(state_manager)
|
|
264
|
+
|
|
265
|
+
return status
|
|
266
|
+
|
|
267
|
+
except Exception as e:
|
|
268
|
+
return {"error": f"Failed to collect comprehensive status: {e}"}
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
async def _get_comprehensive_status() -> dict[str, t.Any]:
|
|
272
|
+
return await _get_comprehensive_status_secure()
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def register_monitoring_tools(mcp_app: t.Any) -> None:
|
|
276
|
+
_register_stage_status_tool(mcp_app)
|
|
277
|
+
_register_next_action_tool(mcp_app)
|
|
278
|
+
_register_server_stats_tool(mcp_app)
|
|
279
|
+
_register_comprehensive_status_tool(mcp_app)
|
|
280
|
+
_register_command_help_tool(mcp_app)
|
|
281
|
+
_register_filtered_status_tool(mcp_app)
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def _register_stage_status_tool(mcp_app: t.Any) -> None:
|
|
285
|
+
@mcp_app.tool() # type: ignore[misc] # type: ignore[misc]
|
|
286
|
+
async def get_stage_status() -> str:
|
|
287
|
+
client_id = "mcp_client"
|
|
288
|
+
|
|
289
|
+
try:
|
|
290
|
+
await validate_status_request(client_id, "get_stage_status", {})
|
|
291
|
+
|
|
292
|
+
context = get_context()
|
|
293
|
+
if not context:
|
|
294
|
+
return _create_error_response("Server context not available")
|
|
295
|
+
|
|
296
|
+
state_manager = getattr(context, "state_manager", None)
|
|
297
|
+
if not state_manager:
|
|
298
|
+
return _create_error_response("State manager not available")
|
|
299
|
+
|
|
300
|
+
result = await execute_bounded_status_operation(
|
|
301
|
+
"stage_status",
|
|
302
|
+
client_id,
|
|
303
|
+
_build_stage_status,
|
|
304
|
+
state_manager,
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
return json.dumps(result, indent=2)
|
|
308
|
+
|
|
309
|
+
except Exception as e:
|
|
310
|
+
return f'{{"error": "Failed to get stage status: {e}"}}'
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
async def _build_stage_status(state_manager: t.Any) -> dict[str, t.Any]:
|
|
314
|
+
return {
|
|
315
|
+
"stages": _get_stage_status_dict(state_manager),
|
|
316
|
+
"session": _get_session_info(state_manager),
|
|
317
|
+
"timestamp": time.time(),
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
def _register_next_action_tool(mcp_app: t.Any) -> None:
|
|
322
|
+
@mcp_app.tool() # type: ignore[misc] # type: ignore[misc]
|
|
323
|
+
async def get_next_action() -> str:
|
|
324
|
+
client_id = "mcp_client"
|
|
325
|
+
|
|
326
|
+
try:
|
|
327
|
+
await validate_status_request(client_id, "get_next_action", {})
|
|
328
|
+
|
|
329
|
+
context = get_context()
|
|
330
|
+
if not context:
|
|
331
|
+
return _create_error_response("Server context not available")
|
|
332
|
+
|
|
333
|
+
state_manager = getattr(context, "state_manager", None)
|
|
334
|
+
if not state_manager:
|
|
335
|
+
return '{"recommended_action": "initialize", "reason": "No state manager available"}'
|
|
336
|
+
|
|
337
|
+
action = await execute_bounded_status_operation(
|
|
338
|
+
"next_action",
|
|
339
|
+
client_id,
|
|
340
|
+
_determine_next_action,
|
|
341
|
+
state_manager,
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
return json.dumps(action, indent=2)
|
|
345
|
+
|
|
346
|
+
except Exception as e:
|
|
347
|
+
return f'{{"error": "Failed to determine next action: {e}"}}'
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
def _register_server_stats_tool(mcp_app: t.Any) -> None:
|
|
351
|
+
@mcp_app.tool() # type: ignore[misc] # type: ignore[misc]
|
|
352
|
+
async def get_server_stats() -> str:
|
|
353
|
+
client_id = "mcp_client"
|
|
354
|
+
|
|
355
|
+
try:
|
|
356
|
+
await validate_status_request(client_id, "get_server_stats", {})
|
|
357
|
+
|
|
358
|
+
async with await secure_status_operation(
|
|
359
|
+
client_id, "get_server_stats", timeout=15.0
|
|
360
|
+
):
|
|
361
|
+
context = get_context()
|
|
362
|
+
if not context:
|
|
363
|
+
formatter = get_secure_status_formatter()
|
|
364
|
+
error_response = formatter.format_error_response(
|
|
365
|
+
"Server context not available",
|
|
366
|
+
)
|
|
367
|
+
return json.dumps(error_response, indent=2)
|
|
368
|
+
|
|
369
|
+
raw_stats = await execute_bounded_status_operation(
|
|
370
|
+
"server_stats",
|
|
371
|
+
client_id,
|
|
372
|
+
_build_server_stats_secure,
|
|
373
|
+
context,
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
secure_stats = format_secure_status(
|
|
377
|
+
raw_stats,
|
|
378
|
+
project_root=context.config.project_path,
|
|
379
|
+
user_context="mcp_client",
|
|
380
|
+
)
|
|
381
|
+
|
|
382
|
+
return json.dumps(secure_stats, indent=2)
|
|
383
|
+
|
|
384
|
+
except Exception as e:
|
|
385
|
+
formatter = get_secure_status_formatter()
|
|
386
|
+
error_response = formatter.format_error_response(
|
|
387
|
+
str(e),
|
|
388
|
+
)
|
|
389
|
+
return json.dumps(error_response, indent=2)
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
async def _build_server_stats_secure(context: t.Any) -> dict[str, t.Any]:
|
|
393
|
+
stats = await _build_server_stats(context)
|
|
394
|
+
|
|
395
|
+
state_manager = getattr(context, "state_manager", None)
|
|
396
|
+
_add_state_manager_stats(stats, state_manager)
|
|
397
|
+
|
|
398
|
+
security_manager = get_status_security_manager()
|
|
399
|
+
stats["security_status"] = security_manager.get_security_status()
|
|
400
|
+
|
|
401
|
+
with suppress(Exception):
|
|
402
|
+
resource_limiter = get_websocket_resource_limiter()
|
|
403
|
+
stats["websocket_resources"] = resource_limiter.get_resource_status()
|
|
404
|
+
|
|
405
|
+
return stats
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
def _register_comprehensive_status_tool(mcp_app: t.Any) -> None:
|
|
409
|
+
@mcp_app.tool() # type: ignore[misc]
|
|
410
|
+
async def get_comprehensive_status() -> str:
|
|
411
|
+
client_id = "mcp_client"
|
|
412
|
+
client_ip = "127.0.0.1"
|
|
413
|
+
|
|
414
|
+
try:
|
|
415
|
+
async with await secure_status_operation(
|
|
416
|
+
client_id,
|
|
417
|
+
"get_comprehensive_status",
|
|
418
|
+
):
|
|
419
|
+
raw_status = await _get_comprehensive_status_secure(
|
|
420
|
+
client_id=client_id,
|
|
421
|
+
client_ip=client_ip,
|
|
422
|
+
)
|
|
423
|
+
|
|
424
|
+
context = get_context()
|
|
425
|
+
project_root = context.config.project_path if context else None
|
|
426
|
+
|
|
427
|
+
secure_status = format_secure_status(
|
|
428
|
+
raw_status,
|
|
429
|
+
project_root=project_root,
|
|
430
|
+
user_context="mcp_client",
|
|
431
|
+
)
|
|
432
|
+
|
|
433
|
+
return json.dumps(secure_status, indent=2)
|
|
434
|
+
|
|
435
|
+
except Exception as e:
|
|
436
|
+
formatter = get_secure_status_formatter()
|
|
437
|
+
error_response = formatter.format_error_response(
|
|
438
|
+
str(e),
|
|
439
|
+
)
|
|
440
|
+
return json.dumps(error_response, indent=2)
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
def _register_command_help_tool(mcp_app: t.Any) -> None:
|
|
444
|
+
@mcp_app.tool() # type: ignore[misc]
|
|
445
|
+
async def list_slash_commands() -> str:
|
|
446
|
+
try:
|
|
447
|
+
commands = {
|
|
448
|
+
"/ crackerjack: run": {
|
|
449
|
+
"description": "Run full iterative auto-fixing with AI agent, tests, progress tracking, and verbose output",
|
|
450
|
+
"usage": "Direct execution-no parameters needed",
|
|
451
|
+
"features": [
|
|
452
|
+
"Up to 10 iterations of quality improvement",
|
|
453
|
+
"Real-time WebSocket progress streaming",
|
|
454
|
+
"Advanced orchestrator with adaptive strategies",
|
|
455
|
+
"Automatic service management",
|
|
456
|
+
"Debug mode support",
|
|
457
|
+
],
|
|
458
|
+
},
|
|
459
|
+
"/ crackerjack: status": {
|
|
460
|
+
"description": "Get comprehensive system status including servers, jobs, and resource usage",
|
|
461
|
+
"usage": "Direct execution-no parameters needed",
|
|
462
|
+
"features": [
|
|
463
|
+
"MCP server health monitoring",
|
|
464
|
+
"WebSocket server status",
|
|
465
|
+
"Active job tracking",
|
|
466
|
+
"Resource usage metrics",
|
|
467
|
+
"Error counts and progress data",
|
|
468
|
+
],
|
|
469
|
+
},
|
|
470
|
+
"/ crackerjack: init": {
|
|
471
|
+
"description": "Initialize or update crackerjack configuration with smart configuration merging",
|
|
472
|
+
"usage": "Optional parameters: target_path (defaults to current directory)",
|
|
473
|
+
"kwargs": {
|
|
474
|
+
"force": "boolean-force overwrite existing configurations"
|
|
475
|
+
},
|
|
476
|
+
"features": [
|
|
477
|
+
"Smart merge preserving existing configurations",
|
|
478
|
+
"Universal Python project compatibility",
|
|
479
|
+
"pyproject.toml and pre-commit setup",
|
|
480
|
+
"Documentation and MCP configuration",
|
|
481
|
+
"Non-destructive configuration updates",
|
|
482
|
+
],
|
|
483
|
+
},
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
return json.dumps(
|
|
487
|
+
{
|
|
488
|
+
"available_commands": list[t.Any](commands.keys()),
|
|
489
|
+
"command_details": commands,
|
|
490
|
+
"total_commands": len(commands),
|
|
491
|
+
},
|
|
492
|
+
indent=2,
|
|
493
|
+
)
|
|
494
|
+
|
|
495
|
+
except Exception as e:
|
|
496
|
+
return json.dumps(
|
|
497
|
+
{
|
|
498
|
+
"error": f"Failed to list[t.Any] slash commands: {e}",
|
|
499
|
+
"success": False,
|
|
500
|
+
},
|
|
501
|
+
indent=2,
|
|
502
|
+
)
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
def _validate_status_components(components: str) -> tuple[set[str], str | None]:
|
|
506
|
+
valid_components = {"services", "jobs", "resources", "all"}
|
|
507
|
+
requested = {c.strip().lower() for c in components.split(", ")}
|
|
508
|
+
|
|
509
|
+
invalid = requested - valid_components
|
|
510
|
+
if invalid:
|
|
511
|
+
return set(), f"Invalid components: {invalid}. Valid: {valid_components}"
|
|
512
|
+
|
|
513
|
+
return requested, None
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
def _get_services_status() -> dict[str, t.Any]:
|
|
517
|
+
from crackerjack.services.server_manager import (
|
|
518
|
+
find_mcp_server_processes,
|
|
519
|
+
find_websocket_server_processes,
|
|
520
|
+
)
|
|
521
|
+
|
|
522
|
+
mcp_processes = find_mcp_server_processes()
|
|
523
|
+
websocket_processes = find_websocket_server_processes()
|
|
524
|
+
|
|
525
|
+
return {
|
|
526
|
+
"mcp_server": {
|
|
527
|
+
"running": len(mcp_processes) > 0,
|
|
528
|
+
"processes": mcp_processes,
|
|
529
|
+
},
|
|
530
|
+
"websocket_server": {
|
|
531
|
+
"running": len(websocket_processes) > 0,
|
|
532
|
+
"processes": websocket_processes,
|
|
533
|
+
},
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
def _get_resources_status(context: t.Any) -> dict[str, t.Any]:
|
|
538
|
+
temp_files_count = (
|
|
539
|
+
len(list[t.Any](context.progress_dir.glob("*.json")))
|
|
540
|
+
if context.progress_dir.exists()
|
|
541
|
+
else 0
|
|
542
|
+
)
|
|
543
|
+
|
|
544
|
+
return {
|
|
545
|
+
"temp_files_count": temp_files_count,
|
|
546
|
+
"progress_dir": str(context.progress_dir),
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
|
|
550
|
+
async def _build_filtered_status(
|
|
551
|
+
requested: set[str], context: t.Any
|
|
552
|
+
) -> dict[str, t.Any]:
|
|
553
|
+
filtered_status: dict[str, t.Any] = {"timestamp": time.time()}
|
|
554
|
+
|
|
555
|
+
if "services" in requested:
|
|
556
|
+
filtered_status["services"] = _get_services_status()
|
|
557
|
+
|
|
558
|
+
if "jobs" in requested:
|
|
559
|
+
filtered_status["jobs"] = {"active": _get_active_jobs(context)}
|
|
560
|
+
|
|
561
|
+
if "resources" in requested:
|
|
562
|
+
filtered_status["resources"] = _get_resources_status(context)
|
|
563
|
+
|
|
564
|
+
return filtered_status
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
def _register_filtered_status_tool(mcp_app: t.Any) -> None:
|
|
568
|
+
@mcp_app.tool() # type: ignore[misc]
|
|
569
|
+
async def get_filtered_status(components: str = "all") -> str:
|
|
570
|
+
client_id = "mcp_client"
|
|
571
|
+
|
|
572
|
+
try:
|
|
573
|
+
await validate_status_request(
|
|
574
|
+
client_id, "get_filtered_status", {"components": components}
|
|
575
|
+
)
|
|
576
|
+
|
|
577
|
+
return await _process_filtered_status_request(client_id, components)
|
|
578
|
+
|
|
579
|
+
except Exception as e:
|
|
580
|
+
return _format_status_error(str(e))
|
|
581
|
+
|
|
582
|
+
|
|
583
|
+
async def _process_filtered_status_request(client_id: str, components: str) -> str:
|
|
584
|
+
requested, error = _validate_status_components(components)
|
|
585
|
+
if error:
|
|
586
|
+
return _format_status_error(error)
|
|
587
|
+
|
|
588
|
+
async with await secure_status_operation(
|
|
589
|
+
client_id, "get_filtered_status", timeout=20.0
|
|
590
|
+
):
|
|
591
|
+
return await _collect_status_data(client_id, requested)
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
async def _collect_status_data(client_id: str, requested: set[str]) -> str:
|
|
595
|
+
context = get_context()
|
|
596
|
+
|
|
597
|
+
if "all" in requested:
|
|
598
|
+
raw_status = await _get_comprehensive_status_secure(
|
|
599
|
+
client_id=client_id,
|
|
600
|
+
)
|
|
601
|
+
else:
|
|
602
|
+
if not context:
|
|
603
|
+
return _format_status_error("Server context not available")
|
|
604
|
+
|
|
605
|
+
raw_status = await execute_bounded_status_operation(
|
|
606
|
+
"filtered_status",
|
|
607
|
+
client_id,
|
|
608
|
+
_build_filtered_status,
|
|
609
|
+
requested,
|
|
610
|
+
context,
|
|
611
|
+
)
|
|
612
|
+
|
|
613
|
+
return _apply_secure_formatting(raw_status, context)
|
|
614
|
+
|
|
615
|
+
|
|
616
|
+
def _apply_secure_formatting(raw_status: dict[str, t.Any], context: t.Any) -> str:
|
|
617
|
+
project_root = context.config.project_path if context else None
|
|
618
|
+
secure_status = format_secure_status(
|
|
619
|
+
raw_status,
|
|
620
|
+
project_root=project_root,
|
|
621
|
+
user_context="mcp_client",
|
|
622
|
+
)
|
|
623
|
+
return json.dumps(secure_status, indent=2)
|
|
624
|
+
|
|
625
|
+
|
|
626
|
+
def _format_status_error(error_message: str) -> str:
|
|
627
|
+
formatter = get_secure_status_formatter()
|
|
628
|
+
return json.dumps(formatter.format_error_response(error_message), indent=2)
|