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
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import time
|
|
2
2
|
import typing as t
|
|
3
|
-
from contextlib import suppress
|
|
4
3
|
from pathlib import Path
|
|
5
4
|
|
|
6
|
-
from
|
|
5
|
+
from acb.console import Console
|
|
6
|
+
from rich.console import Group
|
|
7
7
|
from rich.panel import Panel
|
|
8
8
|
from rich.table import Table
|
|
9
9
|
|
|
@@ -24,7 +24,7 @@ from crackerjack.executors.individual_hook_executor import (
|
|
|
24
24
|
from crackerjack.managers.test_manager import TestManagementImpl
|
|
25
25
|
from crackerjack.models.protocols import OptionsProtocol
|
|
26
26
|
from crackerjack.models.task import HookResult
|
|
27
|
-
from crackerjack.services.metrics import get_metrics_collector
|
|
27
|
+
from crackerjack.services.monitoring.metrics import get_metrics_collector
|
|
28
28
|
|
|
29
29
|
from .execution_strategies import (
|
|
30
30
|
AICoordinationMode,
|
|
@@ -101,94 +101,47 @@ class CorrelationTracker:
|
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
|
|
104
|
-
class
|
|
104
|
+
class ProgressStreamer:
|
|
105
|
+
"""Base class for streaming progress updates during orchestration."""
|
|
106
|
+
|
|
105
107
|
def __init__(
|
|
106
108
|
self,
|
|
107
109
|
config: OrchestrationConfig | None = None,
|
|
108
110
|
session: SessionCoordinator | None = None,
|
|
109
111
|
) -> None:
|
|
110
|
-
|
|
111
|
-
|
|
112
|
+
self.config = config
|
|
113
|
+
self.session = session
|
|
112
114
|
|
|
113
115
|
def update_stage(self, stage: str, substage: str = "") -> None:
|
|
116
|
+
"""Update current stage."""
|
|
114
117
|
pass
|
|
115
118
|
|
|
116
119
|
def update_hook_progress(self, progress: HookProgress) -> None:
|
|
120
|
+
"""Update hook progress."""
|
|
117
121
|
pass
|
|
118
122
|
|
|
119
123
|
def _stream_update(self, data: dict[str, t.Any]) -> None:
|
|
124
|
+
"""Stream update data."""
|
|
120
125
|
pass
|
|
121
126
|
|
|
122
127
|
|
|
123
|
-
class ProgressStreamer:
|
|
128
|
+
class MinimalProgressStreamer(ProgressStreamer):
|
|
124
129
|
def __init__(
|
|
125
130
|
self,
|
|
126
|
-
config: OrchestrationConfig,
|
|
127
|
-
session: SessionCoordinator,
|
|
131
|
+
config: OrchestrationConfig | None = None,
|
|
132
|
+
session: SessionCoordinator | None = None,
|
|
128
133
|
) -> None:
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
self.current_stage = "initialization"
|
|
132
|
-
self.current_substage = ""
|
|
133
|
-
self.hook_progress: dict[str, HookProgress] = {}
|
|
134
|
+
# Minimal implementation doesn't use config or session
|
|
135
|
+
pass
|
|
134
136
|
|
|
135
137
|
def update_stage(self, stage: str, substage: str = "") -> None:
|
|
136
|
-
|
|
137
|
-
self.current_substage = substage
|
|
138
|
-
self._stream_update(
|
|
139
|
-
{
|
|
140
|
-
"type": "stage_update",
|
|
141
|
-
"stage": stage,
|
|
142
|
-
"substage": substage,
|
|
143
|
-
"timestamp": time.time(),
|
|
144
|
-
},
|
|
145
|
-
)
|
|
138
|
+
pass
|
|
146
139
|
|
|
147
140
|
def update_hook_progress(self, progress: HookProgress) -> None:
|
|
148
|
-
|
|
149
|
-
self._stream_update(
|
|
150
|
-
{
|
|
151
|
-
"type": "hook_progress",
|
|
152
|
-
"hook_name": progress.hook_name,
|
|
153
|
-
"progress": progress.to_dict(),
|
|
154
|
-
"timestamp": time.time(),
|
|
155
|
-
},
|
|
156
|
-
)
|
|
157
|
-
|
|
158
|
-
def _stream_update(self, update_data: dict[str, t.Any]) -> None:
|
|
159
|
-
self.session.update_stage(
|
|
160
|
-
self.current_stage,
|
|
161
|
-
f"{self.current_substage}: {update_data.get('hook_name', 'processing')}",
|
|
162
|
-
)
|
|
163
|
-
|
|
164
|
-
if hasattr(self.session, "web_job_id") and self.session.web_job_id:
|
|
165
|
-
self._update_websocket_progress(update_data)
|
|
166
|
-
|
|
167
|
-
def _update_websocket_progress(self, update_data: dict[str, t.Any]) -> None:
|
|
168
|
-
with suppress(Exception):
|
|
169
|
-
if hasattr(self.session, "progress_file") and self.session.progress_file:
|
|
170
|
-
import json
|
|
171
|
-
|
|
172
|
-
progress_data: dict[str, t.Any] = {}
|
|
173
|
-
if self.session.progress_file.exists():
|
|
174
|
-
with self.session.progress_file.open() as f:
|
|
175
|
-
progress_data = json.load(f)
|
|
176
|
-
|
|
177
|
-
progress_data.update(
|
|
178
|
-
{
|
|
179
|
-
"current_stage": self.current_stage,
|
|
180
|
-
"current_substage": self.current_substage,
|
|
181
|
-
"hook_progress": {
|
|
182
|
-
name: prog.to_dict()
|
|
183
|
-
for name, prog in self.hook_progress.items()
|
|
184
|
-
},
|
|
185
|
-
"last_update": update_data,
|
|
186
|
-
"updated_at": time.time(),
|
|
187
|
-
},
|
|
188
|
-
)
|
|
141
|
+
pass
|
|
189
142
|
|
|
190
|
-
|
|
191
|
-
|
|
143
|
+
def _stream_update(self, data: dict[str, t.Any]) -> None:
|
|
144
|
+
pass
|
|
192
145
|
|
|
193
146
|
|
|
194
147
|
class AdvancedWorkflowOrchestrator:
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
# Orchestration Cache
|
|
2
|
+
|
|
3
|
+
> Crackerjack Docs: [Main](<../../../README.md>) | [CLAUDE.md](../../../docs/guides/CLAUDE.md) | [Orchestration](<../README.md>) | [Cache](<./README.md>)
|
|
4
|
+
|
|
5
|
+
High-performance caching infrastructure for hook execution results with content-based invalidation.
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
The orchestration cache provides intelligent result caching for pre-commit hooks and QA checks. By using content-based cache keys (file hashes + configuration), it achieves **~70% cache hit rates** in typical workflows, dramatically reducing execution time for unchanged code.
|
|
10
|
+
|
|
11
|
+
## Key Components
|
|
12
|
+
|
|
13
|
+
### tool_proxy_cache.py - Content-Based Caching
|
|
14
|
+
|
|
15
|
+
**ToolProxyCacheAdapter** - Main cache implementation:
|
|
16
|
+
|
|
17
|
+
- Content-based cache keys using SHA256 file hashing
|
|
18
|
+
- Configurable TTL (time-to-live) per result
|
|
19
|
+
- Automatic invalidation on file content changes
|
|
20
|
+
- Integration with existing tool_proxy infrastructure
|
|
21
|
+
- Compression support for large results
|
|
22
|
+
- In-memory storage with optional disk persistence
|
|
23
|
+
|
|
24
|
+
**Cache Key Format:**
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
{hook_name}:{config_hash}:{content_hash}
|
|
28
|
+
|
|
29
|
+
Example:
|
|
30
|
+
ruff-format:a3f21b8c:7d9e4a2f
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**ToolProxyCacheSettings** - Configuration model:
|
|
34
|
+
|
|
35
|
+
- `default_ttl` - Default time-to-live in seconds (default: 3600)
|
|
36
|
+
- `max_cache_size_mb` - Maximum cache size in MB (default: 100)
|
|
37
|
+
- `enable_compression` - Enable result compression (default: True)
|
|
38
|
+
|
|
39
|
+
### memory_cache.py - In-Memory Cache
|
|
40
|
+
|
|
41
|
+
**MemoryCacheAdapter** - Simple LRU cache:
|
|
42
|
+
|
|
43
|
+
- Fast in-memory storage
|
|
44
|
+
- Least Recently Used (LRU) eviction
|
|
45
|
+
- No persistence (ephemeral)
|
|
46
|
+
- Useful for testing and development
|
|
47
|
+
|
|
48
|
+
## Usage Examples
|
|
49
|
+
|
|
50
|
+
### Basic Caching
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
from pathlib import Path
|
|
54
|
+
from crackerjack.orchestration.cache import ToolProxyCacheAdapter
|
|
55
|
+
from crackerjack.config.hooks import HookDefinition
|
|
56
|
+
from crackerjack.models.task import HookResult
|
|
57
|
+
|
|
58
|
+
# Initialize cache
|
|
59
|
+
cache = ToolProxyCacheAdapter()
|
|
60
|
+
await cache.init()
|
|
61
|
+
|
|
62
|
+
# Define hook and files
|
|
63
|
+
hook = HookDefinition(name="ruff-format", command=["ruff", "format"])
|
|
64
|
+
files = [Path("src/main.py"), Path("src/utils.py")]
|
|
65
|
+
|
|
66
|
+
# Compute cache key
|
|
67
|
+
cache_key = cache.compute_key(hook, files)
|
|
68
|
+
|
|
69
|
+
# Check cache before execution
|
|
70
|
+
cached_result = await cache.get(cache_key)
|
|
71
|
+
if cached_result:
|
|
72
|
+
print(f"Cache hit! Skipping {hook.name}")
|
|
73
|
+
return cached_result
|
|
74
|
+
|
|
75
|
+
# Execute hook and cache result
|
|
76
|
+
result = await execute_hook(hook)
|
|
77
|
+
await cache.set(cache_key, result, ttl=3600)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Custom TTL Configuration
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
from crackerjack.orchestration.cache import (
|
|
84
|
+
ToolProxyCacheAdapter,
|
|
85
|
+
ToolProxyCacheSettings,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
# Configure cache with custom settings
|
|
89
|
+
settings = ToolProxyCacheSettings(
|
|
90
|
+
default_ttl=7200, # 2 hours
|
|
91
|
+
max_cache_size_mb=250,
|
|
92
|
+
enable_compression=True,
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
cache = ToolProxyCacheAdapter(settings=settings)
|
|
96
|
+
await cache.init()
|
|
97
|
+
|
|
98
|
+
# Cache critical hook results longer
|
|
99
|
+
security_result = await run_security_check()
|
|
100
|
+
await cache.set(cache_key, security_result, ttl=86400) # 24 hours
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Cache Statistics
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
# Get cache performance metrics
|
|
107
|
+
stats = await cache.get_stats()
|
|
108
|
+
|
|
109
|
+
print(f"Total entries: {stats['total_entries']}")
|
|
110
|
+
print(f"Active entries: {stats['active_entries']}")
|
|
111
|
+
print(f"Expired entries: {stats['expired_entries']}")
|
|
112
|
+
print(f"Cache directory: {stats['cache_dir']}")
|
|
113
|
+
|
|
114
|
+
# Calculate hit rate
|
|
115
|
+
hit_rate = stats["active_entries"] / stats["total_entries"]
|
|
116
|
+
print(f"Cache hit rate: {hit_rate:.1%}")
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Manual Cache Invalidation
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
# Clear all cached results
|
|
123
|
+
await cache.clear()
|
|
124
|
+
|
|
125
|
+
# Clear specific hook results
|
|
126
|
+
for key in cache._cache.keys():
|
|
127
|
+
if key.startswith("ruff-format:"):
|
|
128
|
+
del cache._cache[key]
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Cache Key Computation
|
|
132
|
+
|
|
133
|
+
The cache key is computed from three components:
|
|
134
|
+
|
|
135
|
+
1. **Hook Name**: Identifies the tool (ruff-format, pyright, etc.)
|
|
136
|
+
1. **Config Hash**: SHA256 of hook configuration (command, timeout, stage, security level)
|
|
137
|
+
1. **Content Hash**: SHA256 of all input file contents
|
|
138
|
+
|
|
139
|
+
**Example computation:**
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
# Hook configuration
|
|
143
|
+
config_data = {
|
|
144
|
+
"name": "ruff-format",
|
|
145
|
+
"command": ["ruff", "format", "--check"],
|
|
146
|
+
"timeout": 60,
|
|
147
|
+
"stage": "fast",
|
|
148
|
+
"security_level": "low",
|
|
149
|
+
}
|
|
150
|
+
config_hash = hashlib.sha256(
|
|
151
|
+
json.dumps(config_data, sort_keys=True).encode()
|
|
152
|
+
).hexdigest()[:16]
|
|
153
|
+
|
|
154
|
+
# File contents
|
|
155
|
+
content_hasher = hashlib.sha256()
|
|
156
|
+
for file_path in sorted(files):
|
|
157
|
+
content_hasher.update(file_path.read_bytes())
|
|
158
|
+
content_hash = content_hasher.hexdigest()[:16]
|
|
159
|
+
|
|
160
|
+
# Final key
|
|
161
|
+
cache_key = f"{hook.name}:{config_hash}:{content_hash}"
|
|
162
|
+
# Result: "ruff-format:a3f21b8c7d9e4a2f:7b8c3e1d9f2a6b4c"
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Cache Invalidation Strategy
|
|
166
|
+
|
|
167
|
+
Cache entries are automatically invalidated when:
|
|
168
|
+
|
|
169
|
+
1. **TTL Expiration**: Entry exceeds configured time-to-live
|
|
170
|
+
1. **Content Changes**: File content hash changes
|
|
171
|
+
1. **Configuration Changes**: Hook configuration modified
|
|
172
|
+
1. **Manual Invalidation**: Explicit `clear()` call
|
|
173
|
+
|
|
174
|
+
**Automatic Invalidation:**
|
|
175
|
+
|
|
176
|
+
```python
|
|
177
|
+
# First execution - cache miss
|
|
178
|
+
files = [Path("src/main.py")]
|
|
179
|
+
key = cache.compute_key(hook, files)
|
|
180
|
+
result1 = await cache.get(key) # None
|
|
181
|
+
|
|
182
|
+
await execute_and_cache(hook, files, key)
|
|
183
|
+
|
|
184
|
+
# Second execution - cache hit (same content)
|
|
185
|
+
result2 = await cache.get(key) # HookResult (cached)
|
|
186
|
+
|
|
187
|
+
# Modify file
|
|
188
|
+
Path("src/main.py").write_text("# Modified")
|
|
189
|
+
|
|
190
|
+
# Third execution - cache miss (content changed)
|
|
191
|
+
key_new = cache.compute_key(hook, files) # Different content_hash
|
|
192
|
+
result3 = await cache.get(key_new) # None
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Configuration
|
|
196
|
+
|
|
197
|
+
### Via Settings YAML
|
|
198
|
+
|
|
199
|
+
```yaml
|
|
200
|
+
# settings/crackerjack.yaml
|
|
201
|
+
cache:
|
|
202
|
+
default_ttl: 3600
|
|
203
|
+
max_cache_size_mb: 100
|
|
204
|
+
enable_compression: true
|
|
205
|
+
cache_dir: .crackerjack/cache
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Via Code
|
|
209
|
+
|
|
210
|
+
```python
|
|
211
|
+
from pathlib import Path
|
|
212
|
+
from crackerjack.orchestration.cache import (
|
|
213
|
+
ToolProxyCacheAdapter,
|
|
214
|
+
ToolProxyCacheSettings,
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
settings = ToolProxyCacheSettings(
|
|
218
|
+
default_ttl=3600,
|
|
219
|
+
max_cache_size_mb=100,
|
|
220
|
+
enable_compression=True,
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
cache = ToolProxyCacheAdapter(
|
|
224
|
+
settings=settings,
|
|
225
|
+
cache_dir=Path.cwd() / ".crackerjack" / "cache",
|
|
226
|
+
)
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## Performance Impact
|
|
230
|
+
|
|
231
|
+
**Before Caching:**
|
|
232
|
+
|
|
233
|
+
- Every hook executes on every run
|
|
234
|
+
- ~30-60s for comprehensive hooks
|
|
235
|
+
- Redundant work on unchanged files
|
|
236
|
+
|
|
237
|
+
**With 70% Cache Hit Rate:**
|
|
238
|
+
|
|
239
|
+
- Only 30% of hooks execute
|
|
240
|
+
- ~10-20s for comprehensive hooks
|
|
241
|
+
- 2-3x faster workflow execution
|
|
242
|
+
|
|
243
|
+
**Example Workflow:**
|
|
244
|
+
|
|
245
|
+
```
|
|
246
|
+
Without cache: 45s total (15 hooks × 3s each)
|
|
247
|
+
With cache: 15s total (5 misses × 3s each)
|
|
248
|
+
Speedup: 3x faster
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## Best Practices
|
|
252
|
+
|
|
253
|
+
1. **Use Content-Based Keys**: Always compute keys from file content, not timestamps
|
|
254
|
+
1. **Configure TTL Appropriately**:
|
|
255
|
+
- Fast hooks: 1 hour (3600s)
|
|
256
|
+
- Comprehensive hooks: 2-4 hours (7200-14400s)
|
|
257
|
+
- Security checks: 24 hours (86400s)
|
|
258
|
+
1. **Monitor Hit Rates**: Aim for 60-80% hit rates in typical development
|
|
259
|
+
1. **Clear Stale Entries**: Periodically clear expired entries
|
|
260
|
+
1. **Size Management**: Monitor cache size, adjust `max_cache_size_mb` if needed
|
|
261
|
+
1. **Compression**: Enable for large results (security scans, type checking)
|
|
262
|
+
|
|
263
|
+
## Architecture Integration
|
|
264
|
+
|
|
265
|
+
The cache integrates with:
|
|
266
|
+
|
|
267
|
+
- **Hook Orchestration**: `ExecutionStrategyProtocol` implementations
|
|
268
|
+
- **QA Adapters**: `QAAdapterProtocol` implementations
|
|
269
|
+
- **Performance Monitoring**: Cache hit rates tracked in metrics
|
|
270
|
+
- **ACB Module System**: Registered via `MODULE_ID` (UUID7)
|
|
271
|
+
|
|
272
|
+
```python
|
|
273
|
+
# ACB Integration
|
|
274
|
+
from acb.depends import depends
|
|
275
|
+
from crackerjack.orchestration.cache import ToolProxyCacheAdapter
|
|
276
|
+
|
|
277
|
+
# Register cache adapter
|
|
278
|
+
depends.set(ToolProxyCacheAdapter)
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
# Use via dependency injection
|
|
282
|
+
@depends.inject
|
|
283
|
+
async def execute_with_cache(
|
|
284
|
+
cache: ToolProxyCacheAdapter = depends(),
|
|
285
|
+
) -> HookResult:
|
|
286
|
+
"""Execute hook with caching."""
|
|
287
|
+
key = cache.compute_key(hook, files)
|
|
288
|
+
|
|
289
|
+
# Check cache
|
|
290
|
+
if cached := await cache.get(key):
|
|
291
|
+
return cached
|
|
292
|
+
|
|
293
|
+
# Execute and cache
|
|
294
|
+
result = await execute_hook(hook)
|
|
295
|
+
await cache.set(key, result)
|
|
296
|
+
return result
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
## Related Documentation
|
|
300
|
+
|
|
301
|
+
- [Orchestration Strategies](<../strategies/README.md>) - Execution strategies using cache
|
|
302
|
+
- [Hook Orchestration](<../README.md>) - Overall orchestration
|
|
303
|
+
- [Models](<../../models/README.md>) - HookResult and cache protocols
|
|
304
|
+
- [CLAUDE.md](../../../docs/guides/CLAUDE.md) - Architecture patterns
|
|
305
|
+
|
|
306
|
+
## Future Enhancements
|
|
307
|
+
|
|
308
|
+
- Redis backend for distributed caching
|
|
309
|
+
- Cache warming strategies (pre-populate common files)
|
|
310
|
+
- Adaptive TTL based on change frequency
|
|
311
|
+
- Cache compression for disk persistence
|
|
312
|
+
- Multi-level caching (L1: memory, L2: disk, L3: Redis)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""Cache adapters for hook orchestration.
|
|
2
|
+
|
|
3
|
+
This package provides caching strategies for hook results:
|
|
4
|
+
- ToolProxyCacheAdapter: Bridges to existing tool_proxy cache infrastructure
|
|
5
|
+
- MemoryCacheAdapter: In-memory LRU cache for testing
|
|
6
|
+
- RedisCacheAdapter: Redis-backed caching (Phase 4+)
|
|
7
|
+
|
|
8
|
+
Cache Strategy:
|
|
9
|
+
- Content-based keys: {hook_name}:{config_hash}:{content_hash}
|
|
10
|
+
- TTL support: Configurable time-to-live per result
|
|
11
|
+
- Cache invalidation: Automatic on file content changes
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"ToolProxyCacheAdapter",
|
|
18
|
+
"MemoryCacheAdapter",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# Lazy imports
|
|
23
|
+
from typing import Any
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def __getattr__(name: str) -> Any:
|
|
27
|
+
if name == "ToolProxyCacheAdapter":
|
|
28
|
+
from crackerjack.orchestration.cache.tool_proxy_cache import (
|
|
29
|
+
ToolProxyCacheAdapter,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
return ToolProxyCacheAdapter
|
|
33
|
+
elif name == "MemoryCacheAdapter":
|
|
34
|
+
from crackerjack.orchestration.cache.memory_cache import MemoryCacheAdapter
|
|
35
|
+
|
|
36
|
+
return MemoryCacheAdapter
|
|
37
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|