crackerjack 0.33.0__py3-none-any.whl โ 0.33.1__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.
Potentially problematic release.
This version of crackerjack might be problematic. Click here for more details.
- crackerjack/__main__.py +1350 -34
- crackerjack/adapters/__init__.py +17 -0
- crackerjack/adapters/lsp_client.py +358 -0
- crackerjack/adapters/rust_tool_adapter.py +194 -0
- crackerjack/adapters/rust_tool_manager.py +193 -0
- crackerjack/adapters/skylos_adapter.py +231 -0
- crackerjack/adapters/zuban_adapter.py +560 -0
- crackerjack/agents/base.py +7 -3
- crackerjack/agents/coordinator.py +271 -33
- crackerjack/agents/documentation_agent.py +9 -15
- crackerjack/agents/dry_agent.py +3 -15
- crackerjack/agents/formatting_agent.py +1 -1
- crackerjack/agents/import_optimization_agent.py +36 -180
- crackerjack/agents/performance_agent.py +17 -98
- crackerjack/agents/performance_helpers.py +7 -31
- crackerjack/agents/proactive_agent.py +1 -3
- crackerjack/agents/refactoring_agent.py +16 -85
- crackerjack/agents/refactoring_helpers.py +7 -42
- crackerjack/agents/security_agent.py +9 -48
- crackerjack/agents/test_creation_agent.py +356 -513
- crackerjack/agents/test_specialist_agent.py +0 -4
- crackerjack/api.py +6 -25
- crackerjack/cli/cache_handlers.py +204 -0
- crackerjack/cli/cache_handlers_enhanced.py +683 -0
- crackerjack/cli/facade.py +100 -0
- crackerjack/cli/handlers.py +224 -9
- crackerjack/cli/interactive.py +6 -4
- crackerjack/cli/options.py +642 -55
- crackerjack/cli/utils.py +2 -1
- crackerjack/code_cleaner.py +58 -117
- crackerjack/config/global_lock_config.py +8 -48
- crackerjack/config/hooks.py +53 -62
- crackerjack/core/async_workflow_orchestrator.py +24 -34
- crackerjack/core/autofix_coordinator.py +3 -17
- crackerjack/core/enhanced_container.py +4 -13
- crackerjack/core/file_lifecycle.py +12 -89
- crackerjack/core/performance.py +2 -2
- crackerjack/core/performance_monitor.py +15 -55
- crackerjack/core/phase_coordinator.py +104 -204
- crackerjack/core/resource_manager.py +14 -90
- crackerjack/core/service_watchdog.py +62 -95
- crackerjack/core/session_coordinator.py +149 -0
- crackerjack/core/timeout_manager.py +14 -72
- crackerjack/core/websocket_lifecycle.py +13 -78
- crackerjack/core/workflow_orchestrator.py +171 -174
- crackerjack/docs/INDEX.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/__init__.py +31 -0
- crackerjack/documentation/ai_templates.py +756 -0
- crackerjack/documentation/dual_output_generator.py +765 -0
- crackerjack/documentation/mkdocs_integration.py +518 -0
- crackerjack/documentation/reference_generator.py +977 -0
- crackerjack/dynamic_config.py +55 -50
- crackerjack/executors/async_hook_executor.py +10 -15
- crackerjack/executors/cached_hook_executor.py +117 -43
- crackerjack/executors/hook_executor.py +8 -34
- crackerjack/executors/hook_lock_manager.py +26 -183
- crackerjack/executors/individual_hook_executor.py +13 -11
- crackerjack/executors/lsp_aware_hook_executor.py +270 -0
- crackerjack/executors/tool_proxy.py +417 -0
- crackerjack/hooks/lsp_hook.py +79 -0
- crackerjack/intelligence/adaptive_learning.py +25 -10
- crackerjack/intelligence/agent_orchestrator.py +2 -5
- crackerjack/intelligence/agent_registry.py +34 -24
- crackerjack/intelligence/agent_selector.py +5 -7
- crackerjack/interactive.py +17 -6
- crackerjack/managers/async_hook_manager.py +0 -1
- crackerjack/managers/hook_manager.py +79 -1
- crackerjack/managers/publish_manager.py +44 -8
- crackerjack/managers/test_command_builder.py +1 -15
- crackerjack/managers/test_executor.py +1 -3
- crackerjack/managers/test_manager.py +98 -7
- crackerjack/managers/test_manager_backup.py +10 -9
- crackerjack/mcp/cache.py +2 -2
- crackerjack/mcp/client_runner.py +1 -1
- crackerjack/mcp/context.py +191 -68
- crackerjack/mcp/dashboard.py +7 -5
- crackerjack/mcp/enhanced_progress_monitor.py +31 -28
- crackerjack/mcp/file_monitor.py +30 -23
- crackerjack/mcp/progress_components.py +31 -21
- crackerjack/mcp/progress_monitor.py +50 -53
- crackerjack/mcp/rate_limiter.py +6 -6
- crackerjack/mcp/server_core.py +17 -16
- crackerjack/mcp/service_watchdog.py +2 -1
- crackerjack/mcp/state.py +4 -7
- crackerjack/mcp/task_manager.py +11 -9
- crackerjack/mcp/tools/core_tools.py +173 -32
- crackerjack/mcp/tools/error_analyzer.py +3 -2
- crackerjack/mcp/tools/execution_tools.py +8 -10
- crackerjack/mcp/tools/execution_tools_backup.py +42 -30
- crackerjack/mcp/tools/intelligence_tool_registry.py +7 -5
- crackerjack/mcp/tools/intelligence_tools.py +5 -2
- crackerjack/mcp/tools/monitoring_tools.py +33 -70
- crackerjack/mcp/tools/proactive_tools.py +24 -11
- crackerjack/mcp/tools/progress_tools.py +5 -8
- crackerjack/mcp/tools/utility_tools.py +20 -14
- crackerjack/mcp/tools/workflow_executor.py +62 -40
- crackerjack/mcp/websocket/app.py +8 -0
- crackerjack/mcp/websocket/endpoints.py +352 -357
- crackerjack/mcp/websocket/jobs.py +40 -57
- crackerjack/mcp/websocket/monitoring_endpoints.py +2935 -0
- crackerjack/mcp/websocket/server.py +7 -25
- crackerjack/mcp/websocket/websocket_handler.py +6 -17
- crackerjack/mixins/__init__.py +0 -2
- crackerjack/mixins/error_handling.py +1 -70
- crackerjack/models/config.py +12 -1
- crackerjack/models/config_adapter.py +49 -1
- crackerjack/models/protocols.py +122 -122
- crackerjack/models/resource_protocols.py +55 -210
- crackerjack/monitoring/ai_agent_watchdog.py +13 -13
- crackerjack/monitoring/metrics_collector.py +426 -0
- crackerjack/monitoring/regression_prevention.py +8 -8
- crackerjack/monitoring/websocket_server.py +643 -0
- crackerjack/orchestration/advanced_orchestrator.py +11 -6
- crackerjack/orchestration/coverage_improvement.py +3 -3
- crackerjack/orchestration/execution_strategies.py +26 -6
- crackerjack/orchestration/test_progress_streamer.py +8 -5
- crackerjack/plugins/base.py +2 -2
- crackerjack/plugins/hooks.py +7 -0
- crackerjack/plugins/managers.py +11 -8
- crackerjack/security/__init__.py +0 -1
- crackerjack/security/audit.py +6 -35
- crackerjack/services/anomaly_detector.py +392 -0
- crackerjack/services/api_extractor.py +615 -0
- crackerjack/services/backup_service.py +2 -2
- crackerjack/services/bounded_status_operations.py +15 -152
- crackerjack/services/cache.py +127 -1
- crackerjack/services/changelog_automation.py +395 -0
- crackerjack/services/config.py +15 -9
- crackerjack/services/config_merge.py +19 -80
- crackerjack/services/config_template.py +506 -0
- crackerjack/services/contextual_ai_assistant.py +48 -22
- crackerjack/services/coverage_badge_service.py +171 -0
- crackerjack/services/coverage_ratchet.py +27 -25
- crackerjack/services/debug.py +3 -3
- crackerjack/services/dependency_analyzer.py +460 -0
- crackerjack/services/dependency_monitor.py +14 -11
- crackerjack/services/documentation_generator.py +491 -0
- crackerjack/services/documentation_service.py +675 -0
- crackerjack/services/enhanced_filesystem.py +6 -5
- crackerjack/services/enterprise_optimizer.py +865 -0
- crackerjack/services/error_pattern_analyzer.py +676 -0
- crackerjack/services/file_hasher.py +1 -1
- crackerjack/services/git.py +8 -25
- crackerjack/services/health_metrics.py +10 -8
- crackerjack/services/heatmap_generator.py +735 -0
- crackerjack/services/initialization.py +11 -30
- crackerjack/services/input_validator.py +5 -97
- crackerjack/services/intelligent_commit.py +327 -0
- crackerjack/services/log_manager.py +15 -12
- crackerjack/services/logging.py +4 -3
- crackerjack/services/lsp_client.py +628 -0
- crackerjack/services/memory_optimizer.py +19 -87
- crackerjack/services/metrics.py +42 -33
- crackerjack/services/parallel_executor.py +9 -67
- crackerjack/services/pattern_cache.py +1 -1
- crackerjack/services/pattern_detector.py +6 -6
- crackerjack/services/performance_benchmarks.py +18 -59
- crackerjack/services/performance_cache.py +20 -81
- crackerjack/services/performance_monitor.py +27 -95
- crackerjack/services/predictive_analytics.py +510 -0
- crackerjack/services/quality_baseline.py +234 -0
- crackerjack/services/quality_baseline_enhanced.py +646 -0
- crackerjack/services/quality_intelligence.py +785 -0
- crackerjack/services/regex_patterns.py +605 -524
- crackerjack/services/regex_utils.py +43 -123
- crackerjack/services/secure_path_utils.py +5 -164
- crackerjack/services/secure_status_formatter.py +30 -141
- crackerjack/services/secure_subprocess.py +11 -92
- crackerjack/services/security.py +9 -41
- crackerjack/services/security_logger.py +12 -24
- crackerjack/services/server_manager.py +124 -16
- crackerjack/services/status_authentication.py +16 -159
- crackerjack/services/status_security_manager.py +4 -131
- crackerjack/services/thread_safe_status_collector.py +19 -125
- crackerjack/services/unified_config.py +21 -13
- crackerjack/services/validation_rate_limiter.py +5 -54
- crackerjack/services/version_analyzer.py +459 -0
- crackerjack/services/version_checker.py +1 -1
- crackerjack/services/websocket_resource_limiter.py +10 -144
- crackerjack/services/zuban_lsp_service.py +390 -0
- crackerjack/slash_commands/__init__.py +2 -7
- crackerjack/slash_commands/run.md +2 -2
- crackerjack/tools/validate_input_validator_patterns.py +14 -40
- crackerjack/tools/validate_regex_patterns.py +19 -48
- {crackerjack-0.33.0.dist-info โ crackerjack-0.33.1.dist-info}/METADATA +196 -25
- crackerjack-0.33.1.dist-info/RECORD +229 -0
- crackerjack/CLAUDE.md +0 -207
- crackerjack/RULES.md +0 -380
- crackerjack/py313.py +0 -234
- crackerjack-0.33.0.dist-info/RECORD +0 -187
- {crackerjack-0.33.0.dist-info โ crackerjack-0.33.1.dist-info}/WHEEL +0 -0
- {crackerjack-0.33.0.dist-info โ crackerjack-0.33.1.dist-info}/entry_points.txt +0 -0
- {crackerjack-0.33.0.dist-info โ crackerjack-0.33.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
from rich.console import Console
|
|
5
|
+
|
|
6
|
+
from crackerjack.core.workflow_orchestrator import WorkflowOrchestrator
|
|
7
|
+
from crackerjack.models.protocols import OptionsProtocol
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class CrackerjackCLIFacade:
|
|
11
|
+
def __init__(
|
|
12
|
+
self,
|
|
13
|
+
console: Console | None = None,
|
|
14
|
+
pkg_path: Path | None = None,
|
|
15
|
+
) -> None:
|
|
16
|
+
self.console = console or Console(force_terminal=True)
|
|
17
|
+
self.pkg_path = pkg_path or Path.cwd()
|
|
18
|
+
self.orchestrator = WorkflowOrchestrator(
|
|
19
|
+
console=self.console,
|
|
20
|
+
pkg_path=self.pkg_path,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
def process(self, options: OptionsProtocol) -> None:
|
|
24
|
+
try:
|
|
25
|
+
if self._should_handle_special_mode(options):
|
|
26
|
+
self._handle_special_modes(options)
|
|
27
|
+
return
|
|
28
|
+
success = asyncio.run(self.orchestrator.run_complete_workflow(options))
|
|
29
|
+
if not success:
|
|
30
|
+
self.console.print("[red]โ Workflow completed with errors[/ red]")
|
|
31
|
+
else:
|
|
32
|
+
self.console.print(
|
|
33
|
+
"[green]๐ Workflow completed successfully ![/ green]"
|
|
34
|
+
)
|
|
35
|
+
except KeyboardInterrupt:
|
|
36
|
+
self.console.print("\n[yellow]โน๏ธ Operation cancelled by user[/ yellow]")
|
|
37
|
+
raise SystemExit(130)
|
|
38
|
+
except Exception as e:
|
|
39
|
+
self.console.print(f"[red]๐ฅ Unexpected error: {e}[/ red]")
|
|
40
|
+
if options.verbose:
|
|
41
|
+
import traceback
|
|
42
|
+
|
|
43
|
+
self.console.print(f"[dim]{traceback.format_exc()}[/ dim]")
|
|
44
|
+
raise SystemExit(1)
|
|
45
|
+
|
|
46
|
+
async def process_async(self, options: OptionsProtocol) -> None:
|
|
47
|
+
await asyncio.to_thread(self.process, options)
|
|
48
|
+
|
|
49
|
+
def _should_handle_special_mode(self, options: OptionsProtocol) -> bool:
|
|
50
|
+
return (
|
|
51
|
+
getattr(options, "start_mcp_server", False)
|
|
52
|
+
or getattr(options, "enterprise_batch", False)
|
|
53
|
+
or getattr(options, "monitor_dashboard", False)
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
def _handle_special_modes(self, options: OptionsProtocol) -> None:
|
|
57
|
+
if getattr(options, "start_mcp_server", False):
|
|
58
|
+
self._start_mcp_server()
|
|
59
|
+
elif getattr(options, "enterprise_batch", False):
|
|
60
|
+
self._handle_enterprise_batch(options)
|
|
61
|
+
elif getattr(options, "monitor_dashboard", False):
|
|
62
|
+
self._handle_monitor_dashboard(options)
|
|
63
|
+
|
|
64
|
+
def _start_mcp_server(self) -> None:
|
|
65
|
+
try:
|
|
66
|
+
from crackerjack.mcp.server import main as start_mcp_main
|
|
67
|
+
|
|
68
|
+
self.console.print(
|
|
69
|
+
"[bold cyan]๐ค Starting Crackerjack MCP Server...[/ bold cyan]",
|
|
70
|
+
)
|
|
71
|
+
start_mcp_main(str(self.pkg_path))
|
|
72
|
+
except ImportError:
|
|
73
|
+
self.console.print(
|
|
74
|
+
"[red]โ MCP server requires additional dependencies[/ red]",
|
|
75
|
+
)
|
|
76
|
+
self.console.print("[yellow]Install with: uv sync --group mcp[/ yellow]")
|
|
77
|
+
raise SystemExit(1)
|
|
78
|
+
except Exception as e:
|
|
79
|
+
self.console.print(f"[red]โ Failed to start MCP server: {e}[/ red]")
|
|
80
|
+
raise SystemExit(1)
|
|
81
|
+
|
|
82
|
+
def _handle_enterprise_batch(self, options: OptionsProtocol) -> None:
|
|
83
|
+
self.console.print(
|
|
84
|
+
"[red]โ Enterprise batch processing is not yet implemented[/ red]"
|
|
85
|
+
)
|
|
86
|
+
raise SystemExit(1)
|
|
87
|
+
|
|
88
|
+
def _handle_monitor_dashboard(self, options: OptionsProtocol) -> None:
|
|
89
|
+
self.console.print("[red]โ Monitoring dashboard is not yet implemented[/ red]")
|
|
90
|
+
raise SystemExit(1)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def create_crackerjack_runner(
|
|
94
|
+
console: Console | None = None,
|
|
95
|
+
pkg_path: Path | None = None,
|
|
96
|
+
) -> CrackerjackCLIFacade:
|
|
97
|
+
return CrackerjackCLIFacade(console=console, pkg_path=pkg_path)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
CrackerjackRunner = CrackerjackCLIFacade
|
crackerjack/cli/handlers.py
CHANGED
|
@@ -1,26 +1,31 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import os
|
|
3
3
|
import sys
|
|
4
|
+
import typing as t
|
|
4
5
|
from pathlib import Path
|
|
5
6
|
|
|
6
7
|
from rich.console import Console
|
|
7
8
|
|
|
8
9
|
from .options import Options
|
|
9
10
|
|
|
11
|
+
if t.TYPE_CHECKING:
|
|
12
|
+
from crackerjack.services.config_template import (
|
|
13
|
+
ConfigTemplateService,
|
|
14
|
+
ConfigUpdateInfo,
|
|
15
|
+
)
|
|
16
|
+
|
|
10
17
|
|
|
11
18
|
def setup_ai_agent_env(ai_agent: bool, debug_mode: bool = False) -> None:
|
|
12
|
-
# Only set debug environment variable if debug mode is explicitly enabled
|
|
13
19
|
if debug_mode:
|
|
14
20
|
os.environ["CRACKERJACK_DEBUG"] = "1"
|
|
15
21
|
|
|
16
22
|
if ai_agent:
|
|
17
23
|
os.environ["AI_AGENT"] = "1"
|
|
18
|
-
|
|
24
|
+
|
|
19
25
|
if debug_mode:
|
|
20
26
|
os.environ["AI_AGENT_DEBUG"] = "1"
|
|
21
27
|
os.environ["AI_AGENT_VERBOSE"] = "1"
|
|
22
28
|
|
|
23
|
-
# Show debug configuration when debug mode is enabled
|
|
24
29
|
console = Console()
|
|
25
30
|
console.print(
|
|
26
31
|
"[bold cyan]๐ AI Agent Debug Mode Configuration: [/ bold cyan]",
|
|
@@ -91,6 +96,24 @@ def handle_dashboard_mode(dev_mode: bool = False) -> None:
|
|
|
91
96
|
console.print("\n[yellow]๐ Dashboard stopped[/ yellow]")
|
|
92
97
|
|
|
93
98
|
|
|
99
|
+
def handle_unified_dashboard_mode(port: int = 8675, dev_mode: bool = False) -> None:
|
|
100
|
+
from crackerjack.monitoring.websocket_server import CrackerjackMonitoringServer
|
|
101
|
+
|
|
102
|
+
console = Console()
|
|
103
|
+
console.print("[bold green]๐ Starting Unified Monitoring Dashboard[/bold green]")
|
|
104
|
+
console.print(
|
|
105
|
+
f"[bold cyan]๐ WebSocket server on port {port} with real-time streaming and web UI[/bold cyan]",
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
try:
|
|
109
|
+
server = CrackerjackMonitoringServer()
|
|
110
|
+
asyncio.run(server.start_monitoring(port))
|
|
111
|
+
except KeyboardInterrupt:
|
|
112
|
+
console.print("\n[yellow]๐ Unified Dashboard stopped[/yellow]")
|
|
113
|
+
except Exception as e:
|
|
114
|
+
console.print(f"\n[red]โ Unified Dashboard failed: {e}[/red]")
|
|
115
|
+
|
|
116
|
+
|
|
94
117
|
def handle_watchdog_mode() -> None:
|
|
95
118
|
from crackerjack.mcp.service_watchdog import main as start_watchdog
|
|
96
119
|
|
|
@@ -145,6 +168,61 @@ def handle_restart_mcp_server(websocket_port: int | None = None) -> None:
|
|
|
145
168
|
raise SystemExit(1)
|
|
146
169
|
|
|
147
170
|
|
|
171
|
+
def handle_start_zuban_lsp(port: int = 8677, mode: str = "tcp") -> None:
|
|
172
|
+
"""Start Zuban LSP server."""
|
|
173
|
+
from crackerjack.services.zuban_lsp_service import create_zuban_lsp_service
|
|
174
|
+
|
|
175
|
+
console = Console()
|
|
176
|
+
console.print("[bold cyan]๐ Starting Zuban LSP Server[/bold cyan]")
|
|
177
|
+
|
|
178
|
+
async def _start() -> None:
|
|
179
|
+
lsp_service = await create_zuban_lsp_service(
|
|
180
|
+
port=port, mode=mode, console=console
|
|
181
|
+
)
|
|
182
|
+
if await lsp_service.start():
|
|
183
|
+
console.print(
|
|
184
|
+
f"[bold green]โ
Zuban LSP server started on port {port} ({mode} mode)[/bold green]"
|
|
185
|
+
)
|
|
186
|
+
else:
|
|
187
|
+
console.print("[bold red]โ Failed to start Zuban LSP server[/bold red]")
|
|
188
|
+
raise SystemExit(1)
|
|
189
|
+
|
|
190
|
+
try:
|
|
191
|
+
asyncio.run(_start())
|
|
192
|
+
except KeyboardInterrupt:
|
|
193
|
+
console.print("\n[yellow]๐ Zuban LSP startup interrupted[/yellow]")
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def handle_stop_zuban_lsp() -> None:
|
|
197
|
+
"""Stop Zuban LSP server."""
|
|
198
|
+
from crackerjack.services.server_manager import stop_zuban_lsp
|
|
199
|
+
|
|
200
|
+
console = Console()
|
|
201
|
+
console.print("[bold red]๐ Stopping Zuban LSP Server[/bold red]")
|
|
202
|
+
|
|
203
|
+
if stop_zuban_lsp(console):
|
|
204
|
+
console.print(
|
|
205
|
+
"\n[bold green]โ
Zuban LSP server stopped successfully[/bold green]"
|
|
206
|
+
)
|
|
207
|
+
else:
|
|
208
|
+
console.print("\n[bold red]โ Failed to stop Zuban LSP server[/bold red]")
|
|
209
|
+
raise SystemExit(1)
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def handle_restart_zuban_lsp(port: int = 8677, mode: str = "tcp") -> None:
|
|
213
|
+
"""Restart Zuban LSP server."""
|
|
214
|
+
from crackerjack.services.server_manager import restart_zuban_lsp
|
|
215
|
+
|
|
216
|
+
console = Console()
|
|
217
|
+
if restart_zuban_lsp(console):
|
|
218
|
+
console.print(
|
|
219
|
+
"\n[bold green]โ
Zuban LSP server restart completed[/bold green]"
|
|
220
|
+
)
|
|
221
|
+
else:
|
|
222
|
+
console.print("\n[bold red]โ Zuban LSP server restart failed[/bold red]")
|
|
223
|
+
raise SystemExit(1)
|
|
224
|
+
|
|
225
|
+
|
|
148
226
|
def handle_interactive_mode(options: Options) -> None:
|
|
149
227
|
from crackerjack.cli.utils import get_package_version
|
|
150
228
|
|
|
@@ -164,7 +242,6 @@ def handle_standard_mode(
|
|
|
164
242
|
|
|
165
243
|
console = Console()
|
|
166
244
|
|
|
167
|
-
# Configure global lock manager from CLI options
|
|
168
245
|
from crackerjack.executors.hook_lock_manager import hook_lock_manager
|
|
169
246
|
|
|
170
247
|
hook_lock_manager.configure_from_options(options)
|
|
@@ -180,7 +257,7 @@ def handle_standard_mode(
|
|
|
180
257
|
pkg_path = Path.cwd()
|
|
181
258
|
|
|
182
259
|
if async_mode:
|
|
183
|
-
|
|
260
|
+
async_orchestrator = AsyncWorkflowOrchestrator(
|
|
184
261
|
console=console,
|
|
185
262
|
pkg_path=pkg_path,
|
|
186
263
|
dry_run=getattr(options, "dry_run", False),
|
|
@@ -188,9 +265,11 @@ def handle_standard_mode(
|
|
|
188
265
|
verbose=options.verbose,
|
|
189
266
|
debug=getattr(options, "debug", False),
|
|
190
267
|
)
|
|
191
|
-
success = asyncio.run(
|
|
268
|
+
success = asyncio.run(
|
|
269
|
+
async_orchestrator.run_complete_workflow_async(options)
|
|
270
|
+
)
|
|
192
271
|
else:
|
|
193
|
-
|
|
272
|
+
sync_orchestrator = WorkflowOrchestrator(
|
|
194
273
|
console=console,
|
|
195
274
|
pkg_path=pkg_path,
|
|
196
275
|
dry_run=getattr(options, "dry_run", False),
|
|
@@ -198,7 +277,7 @@ def handle_standard_mode(
|
|
|
198
277
|
verbose=options.verbose,
|
|
199
278
|
debug=getattr(options, "debug", False),
|
|
200
279
|
)
|
|
201
|
-
success =
|
|
280
|
+
success = sync_orchestrator.run_complete_workflow_sync(options)
|
|
202
281
|
|
|
203
282
|
if not success:
|
|
204
283
|
raise SystemExit(1)
|
|
@@ -210,7 +289,6 @@ def handle_orchestrated_mode(options: Options, job_id: str | None = None) -> Non
|
|
|
210
289
|
console = Console()
|
|
211
290
|
console.print("[bold bright_blue]๐ ORCHESTRATED MODE ENABLED[/ bold bright_blue]")
|
|
212
291
|
|
|
213
|
-
# Configure global lock manager from CLI options
|
|
214
292
|
from crackerjack.executors.hook_lock_manager import hook_lock_manager
|
|
215
293
|
|
|
216
294
|
hook_lock_manager.configure_from_options(options)
|
|
@@ -283,3 +361,140 @@ def handle_orchestrated_mode(options: Options, job_id: str | None = None) -> Non
|
|
|
283
361
|
except Exception as e:
|
|
284
362
|
console.print(f"\n[red]๐ฅ Orchestrated workflow error: {e}[/ red]")
|
|
285
363
|
sys.exit(1)
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
def handle_config_updates(options: Options) -> None:
|
|
367
|
+
"""Handle configuration update commands."""
|
|
368
|
+
from crackerjack.services.config_template import ConfigTemplateService
|
|
369
|
+
|
|
370
|
+
console = Console()
|
|
371
|
+
pkg_path = Path.cwd()
|
|
372
|
+
config_service = ConfigTemplateService(console, pkg_path)
|
|
373
|
+
|
|
374
|
+
if options.check_config_updates:
|
|
375
|
+
_handle_check_updates(config_service, pkg_path, console)
|
|
376
|
+
elif options.apply_config_updates:
|
|
377
|
+
_handle_apply_updates(
|
|
378
|
+
config_service, pkg_path, options.config_interactive, console
|
|
379
|
+
)
|
|
380
|
+
elif options.diff_config:
|
|
381
|
+
_handle_diff_config(config_service, pkg_path, options.diff_config, console)
|
|
382
|
+
elif options.refresh_cache:
|
|
383
|
+
_handle_refresh_cache(config_service, pkg_path, console)
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
def _handle_check_updates(
|
|
387
|
+
config_service: "ConfigTemplateService", pkg_path: Path, console: Console
|
|
388
|
+
) -> None:
|
|
389
|
+
"""Handle checking for configuration updates."""
|
|
390
|
+
console.print("[bold cyan]๐ Checking for configuration updates...[/bold cyan]")
|
|
391
|
+
updates = config_service.check_updates(pkg_path)
|
|
392
|
+
|
|
393
|
+
if not updates:
|
|
394
|
+
console.print("[green]โ
No configuration templates available[/green]")
|
|
395
|
+
return
|
|
396
|
+
|
|
397
|
+
has_updates = any(update.needs_update for update in updates.values())
|
|
398
|
+
if not has_updates:
|
|
399
|
+
console.print("[green]โ
All configurations are up to date[/green]")
|
|
400
|
+
return
|
|
401
|
+
|
|
402
|
+
_display_available_updates(updates, console)
|
|
403
|
+
console.print("\nUse --apply-config-updates to apply these updates")
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
def _handle_apply_updates(
|
|
407
|
+
config_service: "ConfigTemplateService",
|
|
408
|
+
pkg_path: Path,
|
|
409
|
+
interactive: bool,
|
|
410
|
+
console: Console,
|
|
411
|
+
) -> None:
|
|
412
|
+
"""Handle applying configuration updates."""
|
|
413
|
+
console.print("[bold cyan]๐ง Applying configuration updates...[/bold cyan]")
|
|
414
|
+
updates = config_service.check_updates(pkg_path)
|
|
415
|
+
|
|
416
|
+
if not updates:
|
|
417
|
+
console.print("[yellow]โ ๏ธ No configuration templates available[/yellow]")
|
|
418
|
+
return
|
|
419
|
+
|
|
420
|
+
configs_to_update = _get_configs_needing_update(updates)
|
|
421
|
+
if not configs_to_update:
|
|
422
|
+
console.print("[green]โ
All configurations are already up to date[/green]")
|
|
423
|
+
return
|
|
424
|
+
|
|
425
|
+
success_count = _apply_config_updates_batch(
|
|
426
|
+
config_service, configs_to_update, pkg_path, interactive, console
|
|
427
|
+
)
|
|
428
|
+
_report_update_results(success_count, len(configs_to_update), console)
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
def _handle_diff_config(
|
|
432
|
+
config_service: "ConfigTemplateService",
|
|
433
|
+
pkg_path: Path,
|
|
434
|
+
config_type: str,
|
|
435
|
+
console: Console,
|
|
436
|
+
) -> None:
|
|
437
|
+
"""Handle showing configuration diff."""
|
|
438
|
+
console.print(f"[bold cyan]๐ Showing diff for {config_type}...[/bold cyan]")
|
|
439
|
+
diff_preview = config_service._generate_diff_preview(config_type, pkg_path)
|
|
440
|
+
console.print(f"\nChanges for {config_type}:")
|
|
441
|
+
console.print(diff_preview)
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
def _handle_refresh_cache(
|
|
445
|
+
config_service: "ConfigTemplateService", pkg_path: Path, console: Console
|
|
446
|
+
) -> None:
|
|
447
|
+
"""Handle refreshing pre-commit cache."""
|
|
448
|
+
console.print("[bold cyan]๐งน Refreshing pre-commit cache...[/bold cyan]")
|
|
449
|
+
config_service._invalidate_precommit_cache(pkg_path)
|
|
450
|
+
console.print("[green]โ
Pre-commit cache refreshed[/green]")
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
def _display_available_updates(
|
|
454
|
+
updates: dict[str, "ConfigUpdateInfo"], console: Console
|
|
455
|
+
) -> None:
|
|
456
|
+
"""Display available configuration updates."""
|
|
457
|
+
console.print("[yellow]๐ Available updates:[/yellow]")
|
|
458
|
+
for config_type, update_info in updates.items():
|
|
459
|
+
if update_info.needs_update:
|
|
460
|
+
console.print(
|
|
461
|
+
f" โข {config_type}: {update_info.current_version} โ {update_info.latest_version}"
|
|
462
|
+
)
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
def _get_configs_needing_update(updates: dict[str, "ConfigUpdateInfo"]) -> list[str]:
|
|
466
|
+
"""Get list of configurations that need updates."""
|
|
467
|
+
return [
|
|
468
|
+
config_type
|
|
469
|
+
for config_type, update_info in updates.items()
|
|
470
|
+
if update_info.needs_update
|
|
471
|
+
]
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
def _apply_config_updates_batch(
|
|
475
|
+
config_service: "ConfigTemplateService",
|
|
476
|
+
configs: list[str],
|
|
477
|
+
pkg_path: Path,
|
|
478
|
+
interactive: bool,
|
|
479
|
+
console: Console,
|
|
480
|
+
) -> int:
|
|
481
|
+
"""Apply configuration updates in batch and return success count."""
|
|
482
|
+
success_count = 0
|
|
483
|
+
for config_type in configs:
|
|
484
|
+
if config_service.apply_update(config_type, pkg_path, interactive=interactive):
|
|
485
|
+
success_count += 1
|
|
486
|
+
return success_count
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
def _report_update_results(
|
|
490
|
+
success_count: int, total_count: int, console: Console
|
|
491
|
+
) -> None:
|
|
492
|
+
"""Report the results of configuration updates."""
|
|
493
|
+
if success_count == total_count:
|
|
494
|
+
console.print(
|
|
495
|
+
f"[green]โ
Successfully updated {success_count} configurations[/green]"
|
|
496
|
+
)
|
|
497
|
+
else:
|
|
498
|
+
console.print(
|
|
499
|
+
f"[yellow]โ ๏ธ Updated {success_count}/{total_count} configurations[/yellow]"
|
|
500
|
+
)
|
crackerjack/cli/interactive.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import time
|
|
2
|
+
import typing as t
|
|
2
3
|
from enum import Enum, auto
|
|
3
4
|
|
|
4
5
|
from rich.box import ROUNDED
|
|
@@ -146,7 +147,7 @@ class InteractiveWorkflowManager:
|
|
|
146
147
|
|
|
147
148
|
def _setup_commit_task(self, options: OptionsProtocol) -> None:
|
|
148
149
|
if options.commit:
|
|
149
|
-
all_deps = list(self.tasks.keys())
|
|
150
|
+
all_deps = list[t.Any](self.tasks.keys())
|
|
150
151
|
self.add_task(
|
|
151
152
|
"commit",
|
|
152
153
|
"Commit changes and push to Git",
|
|
@@ -193,9 +194,10 @@ class InteractiveWorkflowManager:
|
|
|
193
194
|
task.start()
|
|
194
195
|
try:
|
|
195
196
|
phase_method = getattr(self.orchestrator, task.phase_method)
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
197
|
+
success_result = phase_method(options)
|
|
198
|
+
success_bool = bool(success_result)
|
|
199
|
+
task.complete(success_bool)
|
|
200
|
+
return success_bool
|
|
199
201
|
except Exception as e:
|
|
200
202
|
error = CrackerjackError(
|
|
201
203
|
message=str(e),
|