crackerjack 0.31.9__py3-none-any.whl → 0.31.12__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/CLAUDE.md +288 -705
- crackerjack/__main__.py +22 -8
- crackerjack/agents/__init__.py +0 -3
- crackerjack/agents/architect_agent.py +0 -43
- crackerjack/agents/base.py +1 -9
- crackerjack/agents/coordinator.py +2 -148
- crackerjack/agents/documentation_agent.py +109 -81
- crackerjack/agents/dry_agent.py +122 -97
- crackerjack/agents/formatting_agent.py +3 -16
- crackerjack/agents/import_optimization_agent.py +1174 -130
- crackerjack/agents/performance_agent.py +956 -188
- crackerjack/agents/performance_helpers.py +229 -0
- crackerjack/agents/proactive_agent.py +1 -48
- crackerjack/agents/refactoring_agent.py +516 -246
- crackerjack/agents/refactoring_helpers.py +282 -0
- crackerjack/agents/security_agent.py +393 -90
- crackerjack/agents/test_creation_agent.py +1776 -120
- crackerjack/agents/test_specialist_agent.py +59 -15
- crackerjack/agents/tracker.py +0 -102
- crackerjack/api.py +145 -37
- crackerjack/cli/handlers.py +48 -30
- crackerjack/cli/interactive.py +11 -11
- crackerjack/cli/options.py +66 -4
- crackerjack/code_cleaner.py +808 -148
- crackerjack/config/global_lock_config.py +110 -0
- crackerjack/config/hooks.py +43 -64
- crackerjack/core/async_workflow_orchestrator.py +247 -97
- crackerjack/core/autofix_coordinator.py +192 -109
- crackerjack/core/enhanced_container.py +46 -63
- crackerjack/core/file_lifecycle.py +549 -0
- crackerjack/core/performance.py +9 -8
- crackerjack/core/performance_monitor.py +395 -0
- crackerjack/core/phase_coordinator.py +282 -95
- crackerjack/core/proactive_workflow.py +9 -58
- crackerjack/core/resource_manager.py +501 -0
- crackerjack/core/service_watchdog.py +490 -0
- crackerjack/core/session_coordinator.py +4 -8
- crackerjack/core/timeout_manager.py +504 -0
- crackerjack/core/websocket_lifecycle.py +475 -0
- crackerjack/core/workflow_orchestrator.py +355 -204
- crackerjack/dynamic_config.py +47 -6
- crackerjack/errors.py +3 -4
- crackerjack/executors/async_hook_executor.py +63 -13
- crackerjack/executors/cached_hook_executor.py +14 -14
- crackerjack/executors/hook_executor.py +100 -37
- crackerjack/executors/hook_lock_manager.py +856 -0
- crackerjack/executors/individual_hook_executor.py +120 -86
- crackerjack/intelligence/__init__.py +0 -7
- crackerjack/intelligence/adaptive_learning.py +13 -86
- crackerjack/intelligence/agent_orchestrator.py +15 -78
- crackerjack/intelligence/agent_registry.py +12 -59
- crackerjack/intelligence/agent_selector.py +31 -92
- crackerjack/intelligence/integration.py +1 -41
- crackerjack/interactive.py +9 -9
- crackerjack/managers/async_hook_manager.py +25 -8
- crackerjack/managers/hook_manager.py +9 -9
- crackerjack/managers/publish_manager.py +57 -59
- crackerjack/managers/test_command_builder.py +6 -36
- crackerjack/managers/test_executor.py +9 -61
- crackerjack/managers/test_manager.py +52 -62
- crackerjack/managers/test_manager_backup.py +77 -127
- crackerjack/managers/test_progress.py +4 -23
- crackerjack/mcp/cache.py +5 -12
- crackerjack/mcp/client_runner.py +10 -10
- crackerjack/mcp/context.py +64 -6
- crackerjack/mcp/dashboard.py +14 -11
- crackerjack/mcp/enhanced_progress_monitor.py +55 -55
- crackerjack/mcp/file_monitor.py +72 -42
- crackerjack/mcp/progress_components.py +103 -84
- crackerjack/mcp/progress_monitor.py +122 -49
- crackerjack/mcp/rate_limiter.py +12 -12
- crackerjack/mcp/server_core.py +16 -22
- crackerjack/mcp/service_watchdog.py +26 -26
- crackerjack/mcp/state.py +15 -0
- crackerjack/mcp/tools/core_tools.py +95 -39
- crackerjack/mcp/tools/error_analyzer.py +6 -32
- crackerjack/mcp/tools/execution_tools.py +1 -56
- crackerjack/mcp/tools/execution_tools_backup.py +35 -131
- crackerjack/mcp/tools/intelligence_tool_registry.py +0 -36
- crackerjack/mcp/tools/intelligence_tools.py +2 -55
- crackerjack/mcp/tools/monitoring_tools.py +308 -145
- crackerjack/mcp/tools/proactive_tools.py +12 -42
- crackerjack/mcp/tools/progress_tools.py +23 -15
- crackerjack/mcp/tools/utility_tools.py +3 -40
- crackerjack/mcp/tools/workflow_executor.py +40 -60
- crackerjack/mcp/websocket/app.py +0 -3
- crackerjack/mcp/websocket/endpoints.py +206 -268
- crackerjack/mcp/websocket/jobs.py +213 -66
- crackerjack/mcp/websocket/server.py +84 -6
- crackerjack/mcp/websocket/websocket_handler.py +137 -29
- crackerjack/models/config_adapter.py +3 -16
- crackerjack/models/protocols.py +162 -3
- crackerjack/models/resource_protocols.py +454 -0
- crackerjack/models/task.py +3 -3
- crackerjack/monitoring/__init__.py +0 -0
- crackerjack/monitoring/ai_agent_watchdog.py +25 -71
- crackerjack/monitoring/regression_prevention.py +28 -87
- crackerjack/orchestration/advanced_orchestrator.py +44 -78
- crackerjack/orchestration/coverage_improvement.py +10 -60
- crackerjack/orchestration/execution_strategies.py +16 -16
- crackerjack/orchestration/test_progress_streamer.py +61 -53
- crackerjack/plugins/base.py +1 -1
- crackerjack/plugins/managers.py +22 -20
- crackerjack/py313.py +65 -21
- crackerjack/services/backup_service.py +467 -0
- crackerjack/services/bounded_status_operations.py +627 -0
- crackerjack/services/cache.py +7 -9
- crackerjack/services/config.py +35 -52
- crackerjack/services/config_integrity.py +5 -16
- crackerjack/services/config_merge.py +542 -0
- crackerjack/services/contextual_ai_assistant.py +17 -19
- crackerjack/services/coverage_ratchet.py +51 -76
- crackerjack/services/debug.py +25 -39
- crackerjack/services/dependency_monitor.py +52 -50
- crackerjack/services/enhanced_filesystem.py +14 -11
- crackerjack/services/file_hasher.py +1 -1
- crackerjack/services/filesystem.py +1 -12
- crackerjack/services/git.py +78 -44
- crackerjack/services/health_metrics.py +31 -27
- crackerjack/services/initialization.py +281 -433
- crackerjack/services/input_validator.py +760 -0
- crackerjack/services/log_manager.py +16 -16
- crackerjack/services/logging.py +7 -6
- crackerjack/services/metrics.py +43 -43
- crackerjack/services/pattern_cache.py +2 -31
- crackerjack/services/pattern_detector.py +26 -63
- crackerjack/services/performance_benchmarks.py +20 -45
- crackerjack/services/regex_patterns.py +2887 -0
- crackerjack/services/regex_utils.py +537 -0
- crackerjack/services/secure_path_utils.py +683 -0
- crackerjack/services/secure_status_formatter.py +534 -0
- crackerjack/services/secure_subprocess.py +605 -0
- crackerjack/services/security.py +47 -10
- crackerjack/services/security_logger.py +492 -0
- crackerjack/services/server_manager.py +109 -50
- crackerjack/services/smart_scheduling.py +8 -25
- crackerjack/services/status_authentication.py +603 -0
- crackerjack/services/status_security_manager.py +442 -0
- crackerjack/services/thread_safe_status_collector.py +546 -0
- crackerjack/services/tool_version_service.py +1 -23
- crackerjack/services/unified_config.py +36 -58
- crackerjack/services/validation_rate_limiter.py +269 -0
- crackerjack/services/version_checker.py +9 -40
- crackerjack/services/websocket_resource_limiter.py +572 -0
- crackerjack/slash_commands/__init__.py +52 -2
- crackerjack/tools/__init__.py +0 -0
- crackerjack/tools/validate_input_validator_patterns.py +262 -0
- crackerjack/tools/validate_regex_patterns.py +198 -0
- {crackerjack-0.31.9.dist-info → crackerjack-0.31.12.dist-info}/METADATA +197 -12
- crackerjack-0.31.12.dist-info/RECORD +178 -0
- crackerjack/cli/facade.py +0 -104
- crackerjack-0.31.9.dist-info/RECORD +0 -149
- {crackerjack-0.31.9.dist-info → crackerjack-0.31.12.dist-info}/WHEEL +0 -0
- {crackerjack-0.31.9.dist-info → crackerjack-0.31.12.dist-info}/entry_points.txt +0 -0
- {crackerjack-0.31.9.dist-info → crackerjack-0.31.12.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
"""Workflow execution engine for MCP tools.
|
|
2
|
-
|
|
3
|
-
This module handles the core workflow execution logic, including orchestrator setup,
|
|
4
|
-
iteration management, and result handling. Split from execution_tools.py for better
|
|
5
|
-
separation of concerns.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
1
|
import asyncio
|
|
9
2
|
import time
|
|
10
3
|
import typing as t
|
|
@@ -18,13 +11,11 @@ from .progress_tools import _update_progress
|
|
|
18
11
|
async def execute_crackerjack_workflow(
|
|
19
12
|
args: str, kwargs: dict[str, t.Any]
|
|
20
13
|
) -> dict[str, t.Any]:
|
|
21
|
-
"""Execute the main crackerjack workflow with progress tracking."""
|
|
22
14
|
job_id = str(uuid.uuid4())[:8]
|
|
23
15
|
|
|
24
16
|
try:
|
|
25
17
|
return await _execute_crackerjack_sync(job_id, args, kwargs, get_context())
|
|
26
18
|
except Exception as e:
|
|
27
|
-
# Add full traceback for debugging
|
|
28
19
|
import traceback
|
|
29
20
|
|
|
30
21
|
error_details = traceback.format_exc()
|
|
@@ -43,13 +34,10 @@ async def _execute_crackerjack_sync(
|
|
|
43
34
|
kwargs: dict[str, t.Any],
|
|
44
35
|
context: t.Any,
|
|
45
36
|
) -> dict[str, t.Any]:
|
|
46
|
-
"""Execute crackerjack workflow synchronously with progress tracking."""
|
|
47
|
-
# Initialize execution environment
|
|
48
37
|
setup_result = await _initialize_execution(job_id, args, kwargs, context)
|
|
49
38
|
if setup_result.get("status") == "failed":
|
|
50
39
|
return setup_result
|
|
51
40
|
|
|
52
|
-
# Set up orchestrator
|
|
53
41
|
orchestrator_result = await _setup_orchestrator(
|
|
54
42
|
job_id, args, kwargs, setup_result["working_dir"], context
|
|
55
43
|
)
|
|
@@ -58,7 +46,6 @@ async def _execute_crackerjack_sync(
|
|
|
58
46
|
|
|
59
47
|
orchestrator = orchestrator_result["orchestrator"]
|
|
60
48
|
|
|
61
|
-
# Run workflow iterations
|
|
62
49
|
return await _run_workflow_iterations(job_id, orchestrator, kwargs, context)
|
|
63
50
|
|
|
64
51
|
|
|
@@ -68,7 +55,6 @@ async def _initialize_execution(
|
|
|
68
55
|
kwargs: dict[str, t.Any],
|
|
69
56
|
context: t.Any,
|
|
70
57
|
) -> dict[str, t.Any]:
|
|
71
|
-
"""Initialize execution environment and validate parameters."""
|
|
72
58
|
_update_progress(
|
|
73
59
|
job_id,
|
|
74
60
|
{
|
|
@@ -79,7 +65,9 @@ async def _initialize_execution(
|
|
|
79
65
|
context,
|
|
80
66
|
)
|
|
81
67
|
|
|
82
|
-
#
|
|
68
|
+
# Ensure WebSocket server is running for progress tracking
|
|
69
|
+
await _ensure_websocket_server_running(job_id, context)
|
|
70
|
+
|
|
83
71
|
working_dir = kwargs.get("working_directory", ".")
|
|
84
72
|
from pathlib import Path
|
|
85
73
|
|
|
@@ -115,7 +103,6 @@ async def _setup_orchestrator(
|
|
|
115
103
|
working_dir: t.Any,
|
|
116
104
|
context: t.Any,
|
|
117
105
|
) -> dict[str, t.Any]:
|
|
118
|
-
"""Set up the appropriate orchestrator based on configuration."""
|
|
119
106
|
_update_progress(
|
|
120
107
|
job_id,
|
|
121
108
|
{
|
|
@@ -126,9 +113,7 @@ async def _setup_orchestrator(
|
|
|
126
113
|
context,
|
|
127
114
|
)
|
|
128
115
|
|
|
129
|
-
use_advanced = kwargs.get(
|
|
130
|
-
"advanced_orchestration", False
|
|
131
|
-
) # Temporarily disable advanced orchestration
|
|
116
|
+
use_advanced = kwargs.get("advanced_orchestration", False)
|
|
132
117
|
|
|
133
118
|
try:
|
|
134
119
|
if use_advanced:
|
|
@@ -155,7 +140,6 @@ async def _setup_orchestrator(
|
|
|
155
140
|
async def _create_advanced_orchestrator(
|
|
156
141
|
working_dir: t.Any, kwargs: dict[str, t.Any], context: t.Any
|
|
157
142
|
) -> t.Any:
|
|
158
|
-
"""Create advanced async orchestrator with dependency injection."""
|
|
159
143
|
from pathlib import Path
|
|
160
144
|
|
|
161
145
|
from crackerjack.core.async_workflow_orchestrator import AsyncWorkflowOrchestrator
|
|
@@ -163,11 +147,12 @@ async def _create_advanced_orchestrator(
|
|
|
163
147
|
|
|
164
148
|
container = EnhancedContainer()
|
|
165
149
|
|
|
166
|
-
# Register services with the container
|
|
167
150
|
await _register_core_services(container, Path(working_dir))
|
|
168
151
|
|
|
169
152
|
orchestrator = AsyncWorkflowOrchestrator(
|
|
170
153
|
pkg_path=Path(working_dir),
|
|
154
|
+
verbose=kwargs.get("verbose", False),
|
|
155
|
+
debug=kwargs.get("debug", False),
|
|
171
156
|
)
|
|
172
157
|
|
|
173
158
|
return orchestrator
|
|
@@ -176,7 +161,6 @@ async def _create_advanced_orchestrator(
|
|
|
176
161
|
def _create_standard_orchestrator(
|
|
177
162
|
working_dir: t.Any, kwargs: dict[str, t.Any]
|
|
178
163
|
) -> t.Any:
|
|
179
|
-
"""Create standard synchronous orchestrator."""
|
|
180
164
|
from pathlib import Path
|
|
181
165
|
|
|
182
166
|
from crackerjack.core.workflow_orchestrator import WorkflowOrchestrator
|
|
@@ -185,7 +169,6 @@ def _create_standard_orchestrator(
|
|
|
185
169
|
|
|
186
170
|
|
|
187
171
|
async def _register_core_services(container: t.Any, working_dir: t.Any) -> None:
|
|
188
|
-
"""Register core services with the dependency injection container."""
|
|
189
172
|
from rich.console import Console
|
|
190
173
|
|
|
191
174
|
from crackerjack.core.enhanced_container import ServiceLifetime
|
|
@@ -201,7 +184,6 @@ async def _register_core_services(container: t.Any, working_dir: t.Any) -> None:
|
|
|
201
184
|
|
|
202
185
|
console = Console()
|
|
203
186
|
|
|
204
|
-
# Register managers
|
|
205
187
|
container.register_service(
|
|
206
188
|
HookManagerProtocol,
|
|
207
189
|
AsyncHookManager(console, working_dir),
|
|
@@ -220,7 +202,6 @@ async def _register_core_services(container: t.Any, working_dir: t.Any) -> None:
|
|
|
220
202
|
ServiceLifetime.SINGLETON,
|
|
221
203
|
)
|
|
222
204
|
|
|
223
|
-
# Register filesystem service
|
|
224
205
|
container.register_service(
|
|
225
206
|
EnhancedFileSystemService,
|
|
226
207
|
EnhancedFileSystemService(),
|
|
@@ -234,7 +215,6 @@ async def _run_workflow_iterations(
|
|
|
234
215
|
kwargs: dict[str, t.Any],
|
|
235
216
|
context: t.Any,
|
|
236
217
|
) -> dict[str, t.Any]:
|
|
237
|
-
"""Run workflow iterations until completion or max attempts."""
|
|
238
218
|
options = _create_workflow_options(kwargs)
|
|
239
219
|
max_iterations = kwargs.get("max_iterations", 10)
|
|
240
220
|
|
|
@@ -256,9 +236,8 @@ async def _run_workflow_iterations(
|
|
|
256
236
|
)
|
|
257
237
|
|
|
258
238
|
if success:
|
|
259
|
-
# Attempt coverage improvement after successful execution (if enabled)
|
|
260
239
|
coverage_result = None
|
|
261
|
-
if kwargs.get("boost_coverage", False):
|
|
240
|
+
if kwargs.get("boost_coverage", False):
|
|
262
241
|
coverage_result = await _attempt_coverage_improvement(
|
|
263
242
|
job_id, orchestrator, context
|
|
264
243
|
)
|
|
@@ -266,7 +245,6 @@ async def _run_workflow_iterations(
|
|
|
266
245
|
job_id, iteration + 1, context, coverage_result
|
|
267
246
|
)
|
|
268
247
|
|
|
269
|
-
# Handle retry logic
|
|
270
248
|
if iteration < max_iterations - 1:
|
|
271
249
|
await _handle_iteration_retry(job_id, iteration, context)
|
|
272
250
|
|
|
@@ -277,13 +255,10 @@ async def _run_workflow_iterations(
|
|
|
277
255
|
|
|
278
256
|
|
|
279
257
|
def _create_workflow_options(kwargs: dict[str, t.Any]) -> t.Any:
|
|
280
|
-
"""Create workflow options from kwargs."""
|
|
281
258
|
from types import SimpleNamespace
|
|
282
259
|
|
|
283
|
-
# Create options object with all required attributes from OptionsProtocol
|
|
284
260
|
options = SimpleNamespace()
|
|
285
261
|
|
|
286
|
-
# Core execution options
|
|
287
262
|
options.commit = kwargs.get("commit", False)
|
|
288
263
|
options.interactive = kwargs.get("interactive", False)
|
|
289
264
|
options.no_config_updates = kwargs.get("no_config_updates", False)
|
|
@@ -295,11 +270,9 @@ def _create_workflow_options(kwargs: dict[str, t.Any]) -> t.Any:
|
|
|
295
270
|
options.ai_agent = kwargs.get("ai_agent", True)
|
|
296
271
|
options.async_mode = kwargs.get("async_mode", True)
|
|
297
272
|
|
|
298
|
-
# Test options
|
|
299
273
|
options.test_workers = kwargs.get("test_workers", 0)
|
|
300
274
|
options.test_timeout = kwargs.get("test_timeout", 0)
|
|
301
275
|
|
|
302
|
-
# Publishing options
|
|
303
276
|
options.publish = kwargs.get("publish")
|
|
304
277
|
options.bump = kwargs.get("bump")
|
|
305
278
|
options.all = kwargs.get("all")
|
|
@@ -309,23 +282,18 @@ def _create_workflow_options(kwargs: dict[str, t.Any]) -> t.Any:
|
|
|
309
282
|
options.cleanup_pypi = kwargs.get("cleanup_pypi", False)
|
|
310
283
|
options.keep_releases = kwargs.get("keep_releases", 10)
|
|
311
284
|
|
|
312
|
-
# Server options
|
|
313
285
|
options.start_mcp_server = kwargs.get("start_mcp_server", False)
|
|
314
286
|
|
|
315
|
-
# Hook options
|
|
316
287
|
options.update_precommit = kwargs.get("update_precommit", False)
|
|
317
288
|
options.experimental_hooks = kwargs.get("experimental_hooks", False)
|
|
318
289
|
options.enable_pyrefly = kwargs.get("enable_pyrefly", False)
|
|
319
290
|
options.enable_ty = kwargs.get("enable_ty", False)
|
|
320
291
|
|
|
321
|
-
# Cleanup options
|
|
322
292
|
options.cleanup = kwargs.get("cleanup")
|
|
323
293
|
|
|
324
|
-
# Coverage and progress
|
|
325
294
|
options.coverage = kwargs.get("coverage", False)
|
|
326
295
|
options.track_progress = kwargs.get("track_progress", False)
|
|
327
296
|
|
|
328
|
-
# Speed options
|
|
329
297
|
options.fast = kwargs.get("fast", False)
|
|
330
298
|
options.comp = kwargs.get("comp", False)
|
|
331
299
|
|
|
@@ -339,11 +307,8 @@ async def _execute_single_iteration(
|
|
|
339
307
|
iteration: int,
|
|
340
308
|
context: t.Any,
|
|
341
309
|
) -> bool:
|
|
342
|
-
"""Execute a single workflow iteration."""
|
|
343
310
|
try:
|
|
344
|
-
# Check for orchestrator workflow methods
|
|
345
311
|
if hasattr(orchestrator, "run_complete_workflow_async"):
|
|
346
|
-
# AsyncWorkflowOrchestrator - method returns awaitable
|
|
347
312
|
result = orchestrator.run_complete_workflow_async(options)
|
|
348
313
|
if result is None:
|
|
349
314
|
raise ValueError(
|
|
@@ -351,7 +316,6 @@ async def _execute_single_iteration(
|
|
|
351
316
|
)
|
|
352
317
|
return await result
|
|
353
318
|
elif hasattr(orchestrator, "run_complete_workflow"):
|
|
354
|
-
# Standard WorkflowOrchestrator - method is async and returns awaitable boolean
|
|
355
319
|
result = orchestrator.run_complete_workflow(options)
|
|
356
320
|
if result is None:
|
|
357
321
|
raise ValueError(
|
|
@@ -366,14 +330,12 @@ async def _execute_single_iteration(
|
|
|
366
330
|
)
|
|
367
331
|
return await result
|
|
368
332
|
elif hasattr(orchestrator, "run"):
|
|
369
|
-
# Fallback for synchronous orchestrators
|
|
370
333
|
return orchestrator.run(options)
|
|
371
334
|
else:
|
|
372
335
|
raise ValueError(
|
|
373
336
|
f"Orchestrator {type(orchestrator)} has no recognized workflow execution method"
|
|
374
337
|
)
|
|
375
338
|
except Exception as e:
|
|
376
|
-
# Add detailed error info for debugging
|
|
377
339
|
raise RuntimeError(
|
|
378
340
|
f"Error in _execute_single_iteration (iteration {iteration}): {e}"
|
|
379
341
|
) from e
|
|
@@ -385,7 +347,6 @@ def _create_success_result(
|
|
|
385
347
|
context: t.Any,
|
|
386
348
|
coverage_result: dict[str, t.Any] | None = None,
|
|
387
349
|
) -> dict[str, t.Any]:
|
|
388
|
-
"""Create success result with completion data."""
|
|
389
350
|
result = {
|
|
390
351
|
"job_id": job_id,
|
|
391
352
|
"status": "completed",
|
|
@@ -402,7 +363,6 @@ def _create_success_result(
|
|
|
402
363
|
|
|
403
364
|
|
|
404
365
|
async def _handle_iteration_retry(job_id: str, iteration: int, context: t.Any) -> None:
|
|
405
|
-
"""Handle retry logic between iterations."""
|
|
406
366
|
_update_progress(
|
|
407
367
|
job_id,
|
|
408
368
|
{
|
|
@@ -414,14 +374,12 @@ async def _handle_iteration_retry(job_id: str, iteration: int, context: t.Any) -
|
|
|
414
374
|
context,
|
|
415
375
|
)
|
|
416
376
|
|
|
417
|
-
# Brief pause between iterations
|
|
418
377
|
await asyncio.sleep(1)
|
|
419
378
|
|
|
420
379
|
|
|
421
380
|
async def _handle_iteration_error(
|
|
422
381
|
job_id: str, iteration: int, error: Exception, context: t.Any
|
|
423
382
|
) -> dict[str, t.Any]:
|
|
424
|
-
"""Handle errors during iteration execution."""
|
|
425
383
|
_update_progress(
|
|
426
384
|
job_id,
|
|
427
385
|
{
|
|
@@ -445,7 +403,6 @@ async def _handle_iteration_error(
|
|
|
445
403
|
async def _attempt_coverage_improvement(
|
|
446
404
|
job_id: str, orchestrator: t.Any, context: t.Any
|
|
447
405
|
) -> dict[str, t.Any]:
|
|
448
|
-
"""Attempt proactive coverage improvement after successful workflow execution."""
|
|
449
406
|
try:
|
|
450
407
|
_update_progress(
|
|
451
408
|
job_id,
|
|
@@ -457,23 +414,19 @@ async def _attempt_coverage_improvement(
|
|
|
457
414
|
context,
|
|
458
415
|
)
|
|
459
416
|
|
|
460
|
-
# Get project path from orchestrator
|
|
461
417
|
project_path = getattr(orchestrator, "pkg_path", None)
|
|
462
418
|
if not project_path:
|
|
463
419
|
return {"status": "skipped", "reason": "No project path available"}
|
|
464
420
|
|
|
465
|
-
# Import coverage improvement orchestrator
|
|
466
421
|
from crackerjack.orchestration.coverage_improvement import (
|
|
467
422
|
create_coverage_improvement_orchestrator,
|
|
468
423
|
)
|
|
469
424
|
|
|
470
|
-
# Create coverage orchestrator
|
|
471
425
|
coverage_orchestrator = await create_coverage_improvement_orchestrator(
|
|
472
426
|
project_path,
|
|
473
427
|
console=getattr(orchestrator, "console", None),
|
|
474
428
|
)
|
|
475
429
|
|
|
476
|
-
# Check if improvement is needed
|
|
477
430
|
should_improve = await coverage_orchestrator.should_improve_coverage()
|
|
478
431
|
if not should_improve:
|
|
479
432
|
_update_progress(
|
|
@@ -481,18 +434,16 @@ async def _attempt_coverage_improvement(
|
|
|
481
434
|
{
|
|
482
435
|
"type": "coverage_improvement",
|
|
483
436
|
"status": "skipped",
|
|
484
|
-
"message": "Coverage improvement not needed (already at 100%)",
|
|
437
|
+
"message": "Coverage improvement not needed (already at 100 %)",
|
|
485
438
|
},
|
|
486
439
|
context,
|
|
487
440
|
)
|
|
488
|
-
return {"status": "skipped", "reason": "Coverage at 100%"}
|
|
441
|
+
return {"status": "skipped", "reason": "Coverage at 100 %"}
|
|
489
442
|
|
|
490
|
-
# Create agent context (simplified)
|
|
491
443
|
from crackerjack.agents.base import AgentContext
|
|
492
444
|
|
|
493
445
|
agent_context = AgentContext(project_path=project_path, console=None)
|
|
494
446
|
|
|
495
|
-
# Execute coverage improvement
|
|
496
447
|
_update_progress(
|
|
497
448
|
job_id,
|
|
498
449
|
{
|
|
@@ -507,7 +458,6 @@ async def _attempt_coverage_improvement(
|
|
|
507
458
|
agent_context
|
|
508
459
|
)
|
|
509
460
|
|
|
510
|
-
# Update progress with results
|
|
511
461
|
if improvement_result["status"] == "completed":
|
|
512
462
|
_update_progress(
|
|
513
463
|
job_id,
|
|
@@ -556,7 +506,6 @@ async def _attempt_coverage_improvement(
|
|
|
556
506
|
def _create_failure_result(
|
|
557
507
|
job_id: str, max_iterations: int, context: t.Any
|
|
558
508
|
) -> dict[str, t.Any]:
|
|
559
|
-
"""Create failure result when max iterations exceeded."""
|
|
560
509
|
return {
|
|
561
510
|
"job_id": job_id,
|
|
562
511
|
"status": "failed",
|
|
@@ -564,3 +513,34 @@ def _create_failure_result(
|
|
|
564
513
|
"timestamp": time.time(),
|
|
565
514
|
"success": False,
|
|
566
515
|
}
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
async def _ensure_websocket_server_running(job_id: str, context: t.Any) -> None:
|
|
519
|
+
"""Ensure WebSocket server is running for progress tracking during crackerjack:run."""
|
|
520
|
+
try:
|
|
521
|
+
from crackerjack.mcp.progress_components import ServiceManager
|
|
522
|
+
|
|
523
|
+
# Initialize and start services if needed
|
|
524
|
+
service_manager = ServiceManager()
|
|
525
|
+
await service_manager.ensure_services_running()
|
|
526
|
+
|
|
527
|
+
_update_progress(
|
|
528
|
+
job_id,
|
|
529
|
+
{
|
|
530
|
+
"type": "service_check",
|
|
531
|
+
"status": "websocket_ready",
|
|
532
|
+
"message": "WebSocket server ensured running for progress tracking",
|
|
533
|
+
},
|
|
534
|
+
context,
|
|
535
|
+
)
|
|
536
|
+
except Exception as e:
|
|
537
|
+
# Don't fail the whole workflow if WebSocket server fails to start
|
|
538
|
+
_update_progress(
|
|
539
|
+
job_id,
|
|
540
|
+
{
|
|
541
|
+
"type": "service_check",
|
|
542
|
+
"status": "websocket_warning",
|
|
543
|
+
"message": f"WebSocket server auto-start failed: {e}. Progress tracking may be limited.",
|
|
544
|
+
},
|
|
545
|
+
context,
|
|
546
|
+
)
|
crackerjack/mcp/websocket/app.py
CHANGED
|
@@ -15,12 +15,10 @@ def create_websocket_app(job_manager: JobManager, progress_dir: Path) -> FastAPI
|
|
|
15
15
|
version="1.0.0",
|
|
16
16
|
)
|
|
17
17
|
|
|
18
|
-
# Store job_manager in app state for startup/shutdown events
|
|
19
18
|
app.state.job_manager = job_manager
|
|
20
19
|
|
|
21
20
|
@app.on_event("startup")
|
|
22
21
|
async def startup_event() -> None:
|
|
23
|
-
"""Start background tasks."""
|
|
24
22
|
if job_manager:
|
|
25
23
|
asyncio.create_task(job_manager.monitor_progress_files())
|
|
26
24
|
asyncio.create_task(job_manager.cleanup_old_jobs())
|
|
@@ -28,7 +26,6 @@ def create_websocket_app(job_manager: JobManager, progress_dir: Path) -> FastAPI
|
|
|
28
26
|
|
|
29
27
|
@app.on_event("shutdown")
|
|
30
28
|
async def shutdown_event() -> None:
|
|
31
|
-
"""Cleanup on shutdown."""
|
|
32
29
|
if job_manager:
|
|
33
30
|
job_manager.cleanup()
|
|
34
31
|
|