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
|
@@ -29,7 +29,7 @@ from crackerjack.services.websocket_resource_limiter import (
|
|
|
29
29
|
)
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
def _suggest_agent_for_context(state_manager) -> dict[str, t.Any]:
|
|
32
|
+
def _suggest_agent_for_context(state_manager: t.Any) -> dict[str, t.Any]:
|
|
33
33
|
suggestions = {
|
|
34
34
|
"recommended_agent": None,
|
|
35
35
|
"reason": "",
|
|
@@ -95,12 +95,12 @@ def _create_error_response(message: str, success: bool = False) -> str:
|
|
|
95
95
|
return json.dumps({"error": message, "success": success})
|
|
96
96
|
|
|
97
97
|
|
|
98
|
-
def _get_stage_status_dict(state_manager) -> dict[str, str]:
|
|
98
|
+
def _get_stage_status_dict(state_manager: t.Any) -> dict[str, str]:
|
|
99
99
|
stages = ["fast", "comprehensive", "tests", "cleaning"]
|
|
100
100
|
return {stage: state_manager.get_stage_status(stage) for stage in stages}
|
|
101
101
|
|
|
102
102
|
|
|
103
|
-
def _get_session_info(state_manager) -> dict[str, t.Any]:
|
|
103
|
+
def _get_session_info(state_manager: t.Any) -> dict[str, t.Any]:
|
|
104
104
|
return {
|
|
105
105
|
"total_iterations": getattr(state_manager, "iteration_count", 0),
|
|
106
106
|
"current_iteration": getattr(state_manager, "current_iteration", 0),
|
|
@@ -108,7 +108,7 @@ def _get_session_info(state_manager) -> dict[str, t.Any]:
|
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
|
|
111
|
-
def _determine_next_action(state_manager) -> dict[str, t.Any]:
|
|
111
|
+
async def _determine_next_action(state_manager: t.Any) -> dict[str, t.Any]:
|
|
112
112
|
stage_priorities = [
|
|
113
113
|
("fast", "Fast hooks not completed"),
|
|
114
114
|
("tests", "Tests not completed"),
|
|
@@ -130,7 +130,7 @@ def _determine_next_action(state_manager) -> dict[str, t.Any]:
|
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
|
|
133
|
-
def _build_server_stats(context) -> dict[str, t.Any]:
|
|
133
|
+
async def _build_server_stats(context: t.Any) -> dict[str, t.Any]:
|
|
134
134
|
return {
|
|
135
135
|
"server_info": {
|
|
136
136
|
"project_path": str(context.config.project_path),
|
|
@@ -145,7 +145,7 @@ def _build_server_stats(context) -> dict[str, t.Any]:
|
|
|
145
145
|
else None,
|
|
146
146
|
},
|
|
147
147
|
"resource_usage": {
|
|
148
|
-
"temp_files_count": len(list(context.progress_dir.glob("*.json")))
|
|
148
|
+
"temp_files_count": len(list[t.Any](context.progress_dir.glob("*.json")))
|
|
149
149
|
if context.progress_dir.exists()
|
|
150
150
|
else 0,
|
|
151
151
|
"progress_dir": str(context.progress_dir),
|
|
@@ -154,7 +154,7 @@ def _build_server_stats(context) -> dict[str, t.Any]:
|
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
|
|
157
|
-
def _add_state_manager_stats(stats: dict, state_manager) -> None:
|
|
157
|
+
def _add_state_manager_stats(stats: dict[str, t.Any], state_manager: t.Any) -> None:
|
|
158
158
|
if state_manager:
|
|
159
159
|
stats["state_manager"] = {
|
|
160
160
|
"iteration_count": getattr(state_manager, "iteration_count", 0),
|
|
@@ -163,8 +163,8 @@ def _add_state_manager_stats(stats: dict, state_manager) -> None:
|
|
|
163
163
|
}
|
|
164
164
|
|
|
165
165
|
|
|
166
|
-
def _get_active_jobs(context) -> list[dict[str, t.Any]]:
|
|
167
|
-
jobs = []
|
|
166
|
+
def _get_active_jobs(context: t.Any) -> list[dict[str, t.Any]]:
|
|
167
|
+
jobs: list[dict[str, t.Any]] = []
|
|
168
168
|
if not context.progress_dir.exists():
|
|
169
169
|
return jobs
|
|
170
170
|
|
|
@@ -198,16 +198,12 @@ async def _get_comprehensive_status_secure(
|
|
|
198
198
|
auth_header: str | None = None,
|
|
199
199
|
verbosity: StatusVerbosity = StatusVerbosity.STANDARD,
|
|
200
200
|
) -> dict[str, t.Any]:
|
|
201
|
-
"""Get comprehensive status with full security integration."""
|
|
202
|
-
|
|
203
|
-
# 1. Authentication
|
|
204
201
|
auth_manager = get_status_authenticator()
|
|
205
202
|
try:
|
|
206
203
|
credentials = await authenticate_status_request(
|
|
207
204
|
auth_header, client_ip, "get_comprehensive_status"
|
|
208
205
|
)
|
|
209
206
|
|
|
210
|
-
# Check if operation is allowed for this auth level
|
|
211
207
|
if not auth_manager.is_operation_allowed(
|
|
212
208
|
"get_comprehensive_status", credentials.access_level
|
|
213
209
|
):
|
|
@@ -216,21 +212,20 @@ async def _get_comprehensive_status_secure(
|
|
|
216
212
|
except Exception as e:
|
|
217
213
|
return {"error": f"Authentication failed: {e}"}
|
|
218
214
|
|
|
219
|
-
# 2. Security validation
|
|
220
215
|
try:
|
|
221
216
|
await validate_status_request(client_id, "get_comprehensive_status", {})
|
|
222
217
|
except Exception as e:
|
|
223
218
|
return {"error": f"Security validation failed: {e}"}
|
|
224
219
|
|
|
225
|
-
# 3. Resource management with bounded operations
|
|
226
220
|
try:
|
|
227
|
-
|
|
221
|
+
result: dict[str, t.Any] = await execute_bounded_status_operation(
|
|
228
222
|
"status_collection",
|
|
229
223
|
client_id,
|
|
230
224
|
_collect_comprehensive_status_internal,
|
|
231
225
|
client_id,
|
|
232
226
|
verbosity,
|
|
233
227
|
)
|
|
228
|
+
return result
|
|
234
229
|
except Exception as e:
|
|
235
230
|
return {"error": f"Resource limit exceeded: {e}"}
|
|
236
231
|
|
|
@@ -239,18 +234,13 @@ async def _collect_comprehensive_status_internal(
|
|
|
239
234
|
client_id: str = "mcp_client",
|
|
240
235
|
verbosity: StatusVerbosity = StatusVerbosity.STANDARD,
|
|
241
236
|
) -> dict[str, t.Any]:
|
|
242
|
-
"""Internal comprehensive status collection using thread-safe collector."""
|
|
243
|
-
|
|
244
|
-
# Use thread-safe status collector
|
|
245
237
|
collector = get_thread_safe_status_collector()
|
|
246
238
|
|
|
247
239
|
try:
|
|
248
|
-
# Collect status with thread safety and proper timeout handling
|
|
249
240
|
snapshot = await collector.collect_comprehensive_status(
|
|
250
241
|
client_id=client_id,
|
|
251
242
|
)
|
|
252
243
|
|
|
253
|
-
# Build final status from snapshot
|
|
254
244
|
status = {
|
|
255
245
|
"services": snapshot.services,
|
|
256
246
|
"jobs": snapshot.jobs,
|
|
@@ -263,7 +253,6 @@ async def _collect_comprehensive_status_internal(
|
|
|
263
253
|
},
|
|
264
254
|
}
|
|
265
255
|
|
|
266
|
-
# Add agent suggestions if available
|
|
267
256
|
context = None
|
|
268
257
|
with suppress(RuntimeError):
|
|
269
258
|
context = get_context()
|
|
@@ -280,7 +269,6 @@ async def _collect_comprehensive_status_internal(
|
|
|
280
269
|
|
|
281
270
|
|
|
282
271
|
async def _get_comprehensive_status() -> dict[str, t.Any]:
|
|
283
|
-
"""Legacy wrapper for backward compatibility."""
|
|
284
272
|
return await _get_comprehensive_status_secure()
|
|
285
273
|
|
|
286
274
|
|
|
@@ -294,12 +282,11 @@ def register_monitoring_tools(mcp_app: t.Any) -> None:
|
|
|
294
282
|
|
|
295
283
|
|
|
296
284
|
def _register_stage_status_tool(mcp_app: t.Any) -> None:
|
|
297
|
-
@mcp_app.tool()
|
|
285
|
+
@mcp_app.tool() # type: ignore[misc] # type: ignore[misc]
|
|
298
286
|
async def get_stage_status() -> str:
|
|
299
287
|
client_id = "mcp_client"
|
|
300
288
|
|
|
301
289
|
try:
|
|
302
|
-
# Security validation
|
|
303
290
|
await validate_status_request(client_id, "get_stage_status", {})
|
|
304
291
|
|
|
305
292
|
context = get_context()
|
|
@@ -310,7 +297,6 @@ def _register_stage_status_tool(mcp_app: t.Any) -> None:
|
|
|
310
297
|
if not state_manager:
|
|
311
298
|
return _create_error_response("State manager not available")
|
|
312
299
|
|
|
313
|
-
# Use bounded operation for resource protection
|
|
314
300
|
result = await execute_bounded_status_operation(
|
|
315
301
|
"stage_status",
|
|
316
302
|
client_id,
|
|
@@ -324,8 +310,7 @@ def _register_stage_status_tool(mcp_app: t.Any) -> None:
|
|
|
324
310
|
return f'{{"error": "Failed to get stage status: {e}"}}'
|
|
325
311
|
|
|
326
312
|
|
|
327
|
-
def _build_stage_status(state_manager) -> dict[str, t.Any]:
|
|
328
|
-
"""Build stage status with bounded resource usage."""
|
|
313
|
+
async def _build_stage_status(state_manager: t.Any) -> dict[str, t.Any]:
|
|
329
314
|
return {
|
|
330
315
|
"stages": _get_stage_status_dict(state_manager),
|
|
331
316
|
"session": _get_session_info(state_manager),
|
|
@@ -334,12 +319,11 @@ def _build_stage_status(state_manager) -> dict[str, t.Any]:
|
|
|
334
319
|
|
|
335
320
|
|
|
336
321
|
def _register_next_action_tool(mcp_app: t.Any) -> None:
|
|
337
|
-
@mcp_app.tool()
|
|
322
|
+
@mcp_app.tool() # type: ignore[misc] # type: ignore[misc]
|
|
338
323
|
async def get_next_action() -> str:
|
|
339
324
|
client_id = "mcp_client"
|
|
340
325
|
|
|
341
326
|
try:
|
|
342
|
-
# Security validation
|
|
343
327
|
await validate_status_request(client_id, "get_next_action", {})
|
|
344
328
|
|
|
345
329
|
context = get_context()
|
|
@@ -350,7 +334,6 @@ def _register_next_action_tool(mcp_app: t.Any) -> None:
|
|
|
350
334
|
if not state_manager:
|
|
351
335
|
return '{"recommended_action": "initialize", "reason": "No state manager available"}'
|
|
352
336
|
|
|
353
|
-
# Use bounded operation for consistency
|
|
354
337
|
action = await execute_bounded_status_operation(
|
|
355
338
|
"next_action",
|
|
356
339
|
client_id,
|
|
@@ -365,19 +348,16 @@ def _register_next_action_tool(mcp_app: t.Any) -> None:
|
|
|
365
348
|
|
|
366
349
|
|
|
367
350
|
def _register_server_stats_tool(mcp_app: t.Any) -> None:
|
|
368
|
-
@mcp_app.tool()
|
|
351
|
+
@mcp_app.tool() # type: ignore[misc] # type: ignore[misc]
|
|
369
352
|
async def get_server_stats() -> str:
|
|
370
353
|
client_id = "mcp_client"
|
|
371
354
|
|
|
372
355
|
try:
|
|
373
|
-
# Security validation
|
|
374
356
|
await validate_status_request(client_id, "get_server_stats", {})
|
|
375
357
|
|
|
376
|
-
# Use secure status operation with resource limits
|
|
377
358
|
async with await secure_status_operation(
|
|
378
359
|
client_id, "get_server_stats", timeout=15.0
|
|
379
360
|
):
|
|
380
|
-
# Get context
|
|
381
361
|
context = get_context()
|
|
382
362
|
if not context:
|
|
383
363
|
formatter = get_secure_status_formatter()
|
|
@@ -386,7 +366,6 @@ def _register_server_stats_tool(mcp_app: t.Any) -> None:
|
|
|
386
366
|
)
|
|
387
367
|
return json.dumps(error_response, indent=2)
|
|
388
368
|
|
|
389
|
-
# Get raw stats with bounded operation
|
|
390
369
|
raw_stats = await execute_bounded_status_operation(
|
|
391
370
|
"server_stats",
|
|
392
371
|
client_id,
|
|
@@ -394,7 +373,6 @@ def _register_server_stats_tool(mcp_app: t.Any) -> None:
|
|
|
394
373
|
context,
|
|
395
374
|
)
|
|
396
375
|
|
|
397
|
-
# Apply secure formatting
|
|
398
376
|
secure_stats = format_secure_status(
|
|
399
377
|
raw_stats,
|
|
400
378
|
project_root=context.config.project_path,
|
|
@@ -404,7 +382,6 @@ def _register_server_stats_tool(mcp_app: t.Any) -> None:
|
|
|
404
382
|
return json.dumps(secure_stats, indent=2)
|
|
405
383
|
|
|
406
384
|
except Exception as e:
|
|
407
|
-
# Use secure error formatting
|
|
408
385
|
formatter = get_secure_status_formatter()
|
|
409
386
|
error_response = formatter.format_error_response(
|
|
410
387
|
str(e),
|
|
@@ -412,23 +389,16 @@ def _register_server_stats_tool(mcp_app: t.Any) -> None:
|
|
|
412
389
|
return json.dumps(error_response, indent=2)
|
|
413
390
|
|
|
414
391
|
|
|
415
|
-
def _build_server_stats_secure(context) -> dict[str, t.Any]:
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
# Build base stats
|
|
419
|
-
stats = _build_server_stats(context)
|
|
392
|
+
async def _build_server_stats_secure(context: t.Any) -> dict[str, t.Any]:
|
|
393
|
+
stats = await _build_server_stats(context)
|
|
420
394
|
|
|
421
|
-
# Add state manager stats
|
|
422
395
|
state_manager = getattr(context, "state_manager", None)
|
|
423
396
|
_add_state_manager_stats(stats, state_manager)
|
|
424
397
|
|
|
425
|
-
# Add security status
|
|
426
398
|
security_manager = get_status_security_manager()
|
|
427
399
|
stats["security_status"] = security_manager.get_security_status()
|
|
428
400
|
|
|
429
|
-
# Add resource limiter status if available
|
|
430
401
|
with suppress(Exception):
|
|
431
|
-
# Resource limiter may not be initialized
|
|
432
402
|
resource_limiter = get_websocket_resource_limiter()
|
|
433
403
|
stats["websocket_resources"] = resource_limiter.get_resource_status()
|
|
434
404
|
|
|
@@ -436,25 +406,21 @@ def _build_server_stats_secure(context) -> dict[str, t.Any]:
|
|
|
436
406
|
|
|
437
407
|
|
|
438
408
|
def _register_comprehensive_status_tool(mcp_app: t.Any) -> None:
|
|
439
|
-
@mcp_app.tool()
|
|
409
|
+
@mcp_app.tool() # type: ignore[misc]
|
|
440
410
|
async def get_comprehensive_status() -> str:
|
|
441
411
|
client_id = "mcp_client"
|
|
442
412
|
client_ip = "127.0.0.1"
|
|
443
413
|
|
|
444
414
|
try:
|
|
445
|
-
# Use secure status operation with request lock
|
|
446
415
|
async with await secure_status_operation(
|
|
447
416
|
client_id,
|
|
448
417
|
"get_comprehensive_status",
|
|
449
418
|
):
|
|
450
|
-
# Get raw status data with full security integration
|
|
451
419
|
raw_status = await _get_comprehensive_status_secure(
|
|
452
420
|
client_id=client_id,
|
|
453
421
|
client_ip=client_ip,
|
|
454
|
-
# Local-only access (auth_header defaults to None)
|
|
455
422
|
)
|
|
456
423
|
|
|
457
|
-
# Apply secure formatting
|
|
458
424
|
context = get_context()
|
|
459
425
|
project_root = context.config.project_path if context else None
|
|
460
426
|
|
|
@@ -467,7 +433,6 @@ def _register_comprehensive_status_tool(mcp_app: t.Any) -> None:
|
|
|
467
433
|
return json.dumps(secure_status, indent=2)
|
|
468
434
|
|
|
469
435
|
except Exception as e:
|
|
470
|
-
# Use secure error formatting
|
|
471
436
|
formatter = get_secure_status_formatter()
|
|
472
437
|
error_response = formatter.format_error_response(
|
|
473
438
|
str(e),
|
|
@@ -476,7 +441,7 @@ def _register_comprehensive_status_tool(mcp_app: t.Any) -> None:
|
|
|
476
441
|
|
|
477
442
|
|
|
478
443
|
def _register_command_help_tool(mcp_app: t.Any) -> None:
|
|
479
|
-
@mcp_app.tool()
|
|
444
|
+
@mcp_app.tool() # type: ignore[misc]
|
|
480
445
|
async def list_slash_commands() -> str:
|
|
481
446
|
try:
|
|
482
447
|
commands = {
|
|
@@ -520,7 +485,7 @@ def _register_command_help_tool(mcp_app: t.Any) -> None:
|
|
|
520
485
|
|
|
521
486
|
return json.dumps(
|
|
522
487
|
{
|
|
523
|
-
"available_commands": list(commands.keys()),
|
|
488
|
+
"available_commands": list[t.Any](commands.keys()),
|
|
524
489
|
"command_details": commands,
|
|
525
490
|
"total_commands": len(commands),
|
|
526
491
|
},
|
|
@@ -529,7 +494,10 @@ def _register_command_help_tool(mcp_app: t.Any) -> None:
|
|
|
529
494
|
|
|
530
495
|
except Exception as e:
|
|
531
496
|
return json.dumps(
|
|
532
|
-
{
|
|
497
|
+
{
|
|
498
|
+
"error": f"Failed to list[t.Any] slash commands: {e}",
|
|
499
|
+
"success": False,
|
|
500
|
+
},
|
|
533
501
|
indent=2,
|
|
534
502
|
)
|
|
535
503
|
|
|
@@ -545,7 +513,7 @@ def _validate_status_components(components: str) -> tuple[set[str], str | None]:
|
|
|
545
513
|
return requested, None
|
|
546
514
|
|
|
547
515
|
|
|
548
|
-
def _get_services_status() -> dict:
|
|
516
|
+
def _get_services_status() -> dict[str, t.Any]:
|
|
549
517
|
from crackerjack.services.server_manager import (
|
|
550
518
|
find_mcp_server_processes,
|
|
551
519
|
find_websocket_server_processes,
|
|
@@ -566,9 +534,9 @@ def _get_services_status() -> dict:
|
|
|
566
534
|
}
|
|
567
535
|
|
|
568
536
|
|
|
569
|
-
def _get_resources_status(context: t.Any) -> dict:
|
|
537
|
+
def _get_resources_status(context: t.Any) -> dict[str, t.Any]:
|
|
570
538
|
temp_files_count = (
|
|
571
|
-
len(list(context.progress_dir.glob("*.json")))
|
|
539
|
+
len(list[t.Any](context.progress_dir.glob("*.json")))
|
|
572
540
|
if context.progress_dir.exists()
|
|
573
541
|
else 0
|
|
574
542
|
)
|
|
@@ -579,8 +547,10 @@ def _get_resources_status(context: t.Any) -> dict:
|
|
|
579
547
|
}
|
|
580
548
|
|
|
581
549
|
|
|
582
|
-
def _build_filtered_status(
|
|
583
|
-
|
|
550
|
+
async def _build_filtered_status(
|
|
551
|
+
requested: set[str], context: t.Any
|
|
552
|
+
) -> dict[str, t.Any]:
|
|
553
|
+
filtered_status: dict[str, t.Any] = {"timestamp": time.time()}
|
|
584
554
|
|
|
585
555
|
if "services" in requested:
|
|
586
556
|
filtered_status["services"] = _get_services_status()
|
|
@@ -595,12 +565,11 @@ def _build_filtered_status(requested: set[str], context: t.Any) -> dict:
|
|
|
595
565
|
|
|
596
566
|
|
|
597
567
|
def _register_filtered_status_tool(mcp_app: t.Any) -> None:
|
|
598
|
-
@mcp_app.tool()
|
|
568
|
+
@mcp_app.tool() # type: ignore[misc]
|
|
599
569
|
async def get_filtered_status(components: str = "all") -> str:
|
|
600
570
|
client_id = "mcp_client"
|
|
601
571
|
|
|
602
572
|
try:
|
|
603
|
-
# Security validation with component filter data
|
|
604
573
|
await validate_status_request(
|
|
605
574
|
client_id, "get_filtered_status", {"components": components}
|
|
606
575
|
)
|
|
@@ -612,12 +581,10 @@ def _register_filtered_status_tool(mcp_app: t.Any) -> None:
|
|
|
612
581
|
|
|
613
582
|
|
|
614
583
|
async def _process_filtered_status_request(client_id: str, components: str) -> str:
|
|
615
|
-
"""Process filtered status request with component validation."""
|
|
616
584
|
requested, error = _validate_status_components(components)
|
|
617
585
|
if error:
|
|
618
586
|
return _format_status_error(error)
|
|
619
587
|
|
|
620
|
-
# Use secure status operation with timeout
|
|
621
588
|
async with await secure_status_operation(
|
|
622
589
|
client_id, "get_filtered_status", timeout=20.0
|
|
623
590
|
):
|
|
@@ -625,7 +592,6 @@ async def _process_filtered_status_request(client_id: str, components: str) -> s
|
|
|
625
592
|
|
|
626
593
|
|
|
627
594
|
async def _collect_status_data(client_id: str, requested: set[str]) -> str:
|
|
628
|
-
"""Collect status data based on requested components."""
|
|
629
595
|
context = get_context()
|
|
630
596
|
|
|
631
597
|
if "all" in requested:
|
|
@@ -636,7 +602,6 @@ async def _collect_status_data(client_id: str, requested: set[str]) -> str:
|
|
|
636
602
|
if not context:
|
|
637
603
|
return _format_status_error("Server context not available")
|
|
638
604
|
|
|
639
|
-
# Use bounded operation for filtered status
|
|
640
605
|
raw_status = await execute_bounded_status_operation(
|
|
641
606
|
"filtered_status",
|
|
642
607
|
client_id,
|
|
@@ -648,8 +613,7 @@ async def _collect_status_data(client_id: str, requested: set[str]) -> str:
|
|
|
648
613
|
return _apply_secure_formatting(raw_status, context)
|
|
649
614
|
|
|
650
615
|
|
|
651
|
-
def _apply_secure_formatting(raw_status: dict, context: t.Any) -> str:
|
|
652
|
-
"""Apply secure formatting to status data."""
|
|
616
|
+
def _apply_secure_formatting(raw_status: dict[str, t.Any], context: t.Any) -> str:
|
|
653
617
|
project_root = context.config.project_path if context else None
|
|
654
618
|
secure_status = format_secure_status(
|
|
655
619
|
raw_status,
|
|
@@ -660,6 +624,5 @@ def _apply_secure_formatting(raw_status: dict, context: t.Any) -> str:
|
|
|
660
624
|
|
|
661
625
|
|
|
662
626
|
def _format_status_error(error_message: str) -> str:
|
|
663
|
-
"""Format status error response consistently."""
|
|
664
627
|
formatter = get_secure_status_formatter()
|
|
665
628
|
return json.dumps(formatter.format_error_response(error_message), indent=2)
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import typing as t
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
def _create_architectural_assessment(
|
|
4
|
+
def _create_architectural_assessment(
|
|
5
|
+
args: str, parsed_kwargs: dict[str, t.Any]
|
|
6
|
+
) -> dict[str, t.Any]:
|
|
5
7
|
assessment = {
|
|
6
8
|
"feature": parsed_kwargs.get("feature", "unknown"),
|
|
7
9
|
"complexity": parsed_kwargs.get("complexity", "medium"),
|
|
@@ -56,7 +58,7 @@ def _create_architectural_assessment(args: str, parsed_kwargs: dict) -> dict:
|
|
|
56
58
|
return assessment
|
|
57
59
|
|
|
58
60
|
|
|
59
|
-
def _create_validation_results(file_path: str) -> dict:
|
|
61
|
+
def _create_validation_results(file_path: str) -> dict[str, t.Any]:
|
|
60
62
|
validation = {
|
|
61
63
|
"file_path": file_path,
|
|
62
64
|
"validation_results": [],
|
|
@@ -95,7 +97,10 @@ def _create_validation_results(file_path: str) -> dict:
|
|
|
95
97
|
},
|
|
96
98
|
]
|
|
97
99
|
|
|
98
|
-
validation["validation_results"] =
|
|
100
|
+
validation["validation_results"] = [
|
|
101
|
+
f"{check['check']}: {check['status']} - {check['message']}"
|
|
102
|
+
for check in compliance_checks
|
|
103
|
+
]
|
|
99
104
|
|
|
100
105
|
validation["recommendations"] = [
|
|
101
106
|
"Run full crackerjack quality process: python - m crackerjack-t",
|
|
@@ -113,7 +118,7 @@ def _create_validation_results(file_path: str) -> dict:
|
|
|
113
118
|
return validation
|
|
114
119
|
|
|
115
120
|
|
|
116
|
-
def _create_pattern_suggestions(problem_context: str) -> dict:
|
|
121
|
+
def _create_pattern_suggestions(problem_context: str) -> dict[str, t.Any]:
|
|
117
122
|
pattern_suggestions = {
|
|
118
123
|
"context": problem_context,
|
|
119
124
|
"recommended_patterns": [],
|
|
@@ -168,7 +173,9 @@ def _create_pattern_suggestions(problem_context: str) -> dict:
|
|
|
168
173
|
return pattern_suggestions
|
|
169
174
|
|
|
170
175
|
|
|
171
|
-
def _add_complexity_patterns(
|
|
176
|
+
def _add_complexity_patterns(
|
|
177
|
+
pattern_suggestions: dict[str, t.Any], problem_context: str
|
|
178
|
+
) -> None:
|
|
172
179
|
if any(
|
|
173
180
|
keyword in problem_context.lower()
|
|
174
181
|
for keyword in ("complex", "refactor", "cleanup")
|
|
@@ -197,7 +204,9 @@ def _add_complexity_patterns(pattern_suggestions: dict, problem_context: str) ->
|
|
|
197
204
|
)
|
|
198
205
|
|
|
199
206
|
|
|
200
|
-
def _add_dry_patterns(
|
|
207
|
+
def _add_dry_patterns(
|
|
208
|
+
pattern_suggestions: dict[str, t.Any], problem_context: str
|
|
209
|
+
) -> None:
|
|
201
210
|
if any(
|
|
202
211
|
keyword in problem_context.lower() for keyword in ("duplicate", "repeat", "dry")
|
|
203
212
|
):
|
|
@@ -225,7 +234,9 @@ def _add_dry_patterns(pattern_suggestions: dict, problem_context: str) -> None:
|
|
|
225
234
|
)
|
|
226
235
|
|
|
227
236
|
|
|
228
|
-
def _add_performance_patterns(
|
|
237
|
+
def _add_performance_patterns(
|
|
238
|
+
pattern_suggestions: dict[str, t.Any], problem_context: str
|
|
239
|
+
) -> None:
|
|
229
240
|
if any(
|
|
230
241
|
keyword in problem_context.lower()
|
|
231
242
|
for keyword in ("slow", "performance", "optimize")
|
|
@@ -234,7 +245,7 @@ def _add_performance_patterns(pattern_suggestions: dict, problem_context: str) -
|
|
|
234
245
|
[
|
|
235
246
|
{
|
|
236
247
|
"pattern": "list_comprehension",
|
|
237
|
-
"description": "Use list comprehensions instead of manual loops",
|
|
248
|
+
"description": "Use list[t.Any] comprehensions instead of manual loops",
|
|
238
249
|
"benefits": [
|
|
239
250
|
"Better performance",
|
|
240
251
|
"More readable",
|
|
@@ -254,7 +265,9 @@ def _add_performance_patterns(pattern_suggestions: dict, problem_context: str) -
|
|
|
254
265
|
)
|
|
255
266
|
|
|
256
267
|
|
|
257
|
-
def _add_security_patterns(
|
|
268
|
+
def _add_security_patterns(
|
|
269
|
+
pattern_suggestions: dict[str, t.Any], problem_context: str
|
|
270
|
+
) -> None:
|
|
258
271
|
if any(
|
|
259
272
|
keyword in problem_context.lower() for keyword in ("security", "safe", "secure")
|
|
260
273
|
):
|
|
@@ -314,7 +327,7 @@ def _register_plan_development_tool(mcp_app: t.Any) -> None:
|
|
|
314
327
|
import json
|
|
315
328
|
|
|
316
329
|
try:
|
|
317
|
-
parsed_kwargs = json.loads(kwargs) if kwargs else {}
|
|
330
|
+
parsed_kwargs: dict[str, t.Any] = json.loads(kwargs) if kwargs else {}
|
|
318
331
|
assessment = _create_architectural_assessment(args, parsed_kwargs)
|
|
319
332
|
return json.dumps(assessment, indent=2)
|
|
320
333
|
except Exception as e:
|
|
@@ -327,7 +340,7 @@ def _register_validate_architecture_tool(mcp_app: t.Any) -> None:
|
|
|
327
340
|
import json
|
|
328
341
|
|
|
329
342
|
try:
|
|
330
|
-
parsed_kwargs = json.loads(kwargs) if kwargs else {}
|
|
343
|
+
parsed_kwargs: dict[str, t.Any] = json.loads(kwargs) if kwargs else {}
|
|
331
344
|
file_path = args or parsed_kwargs.get("file_path", "")
|
|
332
345
|
validation = _create_validation_results(file_path)
|
|
333
346
|
return json.dumps(validation, indent=2)
|
|
@@ -10,23 +10,20 @@ from crackerjack.services.input_validator import get_input_validator
|
|
|
10
10
|
def _create_progress_file(job_id: str) -> Path:
|
|
11
11
|
import tempfile
|
|
12
12
|
|
|
13
|
-
# Use secure input validation
|
|
14
13
|
job_id_result = get_input_validator().validate_job_id(job_id)
|
|
15
14
|
|
|
16
15
|
if not job_id_result.valid:
|
|
17
16
|
msg = f"Invalid job_id: {job_id_result.error_message}"
|
|
18
17
|
raise ValueError(msg)
|
|
19
18
|
|
|
20
|
-
# Use sanitized job ID
|
|
21
19
|
sanitized_job_id = job_id_result.sanitized_value
|
|
22
20
|
|
|
23
21
|
context = get_context()
|
|
24
22
|
if context:
|
|
25
23
|
return context.progress_dir / f"job-{sanitized_job_id}.json"
|
|
26
24
|
|
|
27
|
-
# Create secure temporary directory
|
|
28
25
|
progress_dir = Path(tempfile.gettempdir()) / "crackerjack-mcp-progress"
|
|
29
|
-
progress_dir.mkdir(exist_ok=True, mode=0o750)
|
|
26
|
+
progress_dir.mkdir(exist_ok=True, mode=0o750)
|
|
30
27
|
return progress_dir / f"job-{sanitized_job_id}.json"
|
|
31
28
|
|
|
32
29
|
|
|
@@ -99,10 +96,10 @@ def _notify_websocket(final_progress_data: dict[str, t.Any]) -> None:
|
|
|
99
96
|
|
|
100
97
|
def _update_progress(
|
|
101
98
|
job_id: str,
|
|
102
|
-
progress_data: dict[str, t.Any] | str = None,
|
|
99
|
+
progress_data: dict[str, t.Any] | str | None = None,
|
|
103
100
|
context: t.Any = None,
|
|
104
101
|
iteration: int = 1,
|
|
105
|
-
max_iterations: int =
|
|
102
|
+
max_iterations: int = 5,
|
|
106
103
|
overall_progress: int = 0,
|
|
107
104
|
current_stage: str = "initialization",
|
|
108
105
|
stage_progress: int = 0,
|
|
@@ -167,10 +164,10 @@ def _handle_get_job_progress(job_id: str) -> str:
|
|
|
167
164
|
|
|
168
165
|
|
|
169
166
|
async def _execute_session_action(
|
|
170
|
-
state_manager,
|
|
167
|
+
state_manager: t.Any,
|
|
171
168
|
action: str,
|
|
172
169
|
checkpoint_name: str | None,
|
|
173
|
-
context,
|
|
170
|
+
context: t.Any,
|
|
174
171
|
) -> str:
|
|
175
172
|
if action == "start":
|
|
176
173
|
state_manager.start_session()
|