crackerjack 0.18.2__py3-none-any.whl → 0.45.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (533) hide show
  1. crackerjack/README.md +19 -0
  2. crackerjack/__init__.py +96 -2
  3. crackerjack/__main__.py +637 -138
  4. crackerjack/adapters/README.md +18 -0
  5. crackerjack/adapters/__init__.py +39 -0
  6. crackerjack/adapters/_output_paths.py +167 -0
  7. crackerjack/adapters/_qa_adapter_base.py +309 -0
  8. crackerjack/adapters/_tool_adapter_base.py +706 -0
  9. crackerjack/adapters/ai/README.md +65 -0
  10. crackerjack/adapters/ai/__init__.py +5 -0
  11. crackerjack/adapters/ai/claude.py +853 -0
  12. crackerjack/adapters/complexity/README.md +53 -0
  13. crackerjack/adapters/complexity/__init__.py +10 -0
  14. crackerjack/adapters/complexity/complexipy.py +641 -0
  15. crackerjack/adapters/dependency/__init__.py +22 -0
  16. crackerjack/adapters/dependency/pip_audit.py +418 -0
  17. crackerjack/adapters/format/README.md +72 -0
  18. crackerjack/adapters/format/__init__.py +11 -0
  19. crackerjack/adapters/format/mdformat.py +313 -0
  20. crackerjack/adapters/format/ruff.py +516 -0
  21. crackerjack/adapters/lint/README.md +47 -0
  22. crackerjack/adapters/lint/__init__.py +11 -0
  23. crackerjack/adapters/lint/codespell.py +273 -0
  24. crackerjack/adapters/lsp/README.md +49 -0
  25. crackerjack/adapters/lsp/__init__.py +27 -0
  26. crackerjack/adapters/lsp/_base.py +194 -0
  27. crackerjack/adapters/lsp/_client.py +358 -0
  28. crackerjack/adapters/lsp/_manager.py +193 -0
  29. crackerjack/adapters/lsp/skylos.py +283 -0
  30. crackerjack/adapters/lsp/zuban.py +557 -0
  31. crackerjack/adapters/refactor/README.md +59 -0
  32. crackerjack/adapters/refactor/__init__.py +12 -0
  33. crackerjack/adapters/refactor/creosote.py +318 -0
  34. crackerjack/adapters/refactor/refurb.py +406 -0
  35. crackerjack/adapters/refactor/skylos.py +494 -0
  36. crackerjack/adapters/sast/README.md +132 -0
  37. crackerjack/adapters/sast/__init__.py +32 -0
  38. crackerjack/adapters/sast/_base.py +201 -0
  39. crackerjack/adapters/sast/bandit.py +423 -0
  40. crackerjack/adapters/sast/pyscn.py +405 -0
  41. crackerjack/adapters/sast/semgrep.py +241 -0
  42. crackerjack/adapters/security/README.md +111 -0
  43. crackerjack/adapters/security/__init__.py +17 -0
  44. crackerjack/adapters/security/gitleaks.py +339 -0
  45. crackerjack/adapters/type/README.md +52 -0
  46. crackerjack/adapters/type/__init__.py +12 -0
  47. crackerjack/adapters/type/pyrefly.py +402 -0
  48. crackerjack/adapters/type/ty.py +402 -0
  49. crackerjack/adapters/type/zuban.py +522 -0
  50. crackerjack/adapters/utility/README.md +51 -0
  51. crackerjack/adapters/utility/__init__.py +10 -0
  52. crackerjack/adapters/utility/checks.py +884 -0
  53. crackerjack/agents/README.md +264 -0
  54. crackerjack/agents/__init__.py +66 -0
  55. crackerjack/agents/architect_agent.py +238 -0
  56. crackerjack/agents/base.py +167 -0
  57. crackerjack/agents/claude_code_bridge.py +641 -0
  58. crackerjack/agents/coordinator.py +600 -0
  59. crackerjack/agents/documentation_agent.py +520 -0
  60. crackerjack/agents/dry_agent.py +585 -0
  61. crackerjack/agents/enhanced_coordinator.py +279 -0
  62. crackerjack/agents/enhanced_proactive_agent.py +185 -0
  63. crackerjack/agents/error_middleware.py +53 -0
  64. crackerjack/agents/formatting_agent.py +230 -0
  65. crackerjack/agents/helpers/__init__.py +9 -0
  66. crackerjack/agents/helpers/performance/__init__.py +22 -0
  67. crackerjack/agents/helpers/performance/performance_ast_analyzer.py +357 -0
  68. crackerjack/agents/helpers/performance/performance_pattern_detector.py +909 -0
  69. crackerjack/agents/helpers/performance/performance_recommender.py +572 -0
  70. crackerjack/agents/helpers/refactoring/__init__.py +22 -0
  71. crackerjack/agents/helpers/refactoring/code_transformer.py +536 -0
  72. crackerjack/agents/helpers/refactoring/complexity_analyzer.py +344 -0
  73. crackerjack/agents/helpers/refactoring/dead_code_detector.py +437 -0
  74. crackerjack/agents/helpers/test_creation/__init__.py +19 -0
  75. crackerjack/agents/helpers/test_creation/test_ast_analyzer.py +216 -0
  76. crackerjack/agents/helpers/test_creation/test_coverage_analyzer.py +643 -0
  77. crackerjack/agents/helpers/test_creation/test_template_generator.py +1031 -0
  78. crackerjack/agents/import_optimization_agent.py +1181 -0
  79. crackerjack/agents/performance_agent.py +325 -0
  80. crackerjack/agents/performance_helpers.py +205 -0
  81. crackerjack/agents/proactive_agent.py +55 -0
  82. crackerjack/agents/refactoring_agent.py +511 -0
  83. crackerjack/agents/refactoring_helpers.py +247 -0
  84. crackerjack/agents/security_agent.py +793 -0
  85. crackerjack/agents/semantic_agent.py +479 -0
  86. crackerjack/agents/semantic_helpers.py +356 -0
  87. crackerjack/agents/test_creation_agent.py +570 -0
  88. crackerjack/agents/test_specialist_agent.py +526 -0
  89. crackerjack/agents/tracker.py +110 -0
  90. crackerjack/api.py +647 -0
  91. crackerjack/cli/README.md +394 -0
  92. crackerjack/cli/__init__.py +24 -0
  93. crackerjack/cli/cache_handlers.py +209 -0
  94. crackerjack/cli/cache_handlers_enhanced.py +680 -0
  95. crackerjack/cli/facade.py +162 -0
  96. crackerjack/cli/formatting.py +13 -0
  97. crackerjack/cli/handlers/__init__.py +85 -0
  98. crackerjack/cli/handlers/advanced.py +103 -0
  99. crackerjack/cli/handlers/ai_features.py +62 -0
  100. crackerjack/cli/handlers/analytics.py +479 -0
  101. crackerjack/cli/handlers/changelog.py +271 -0
  102. crackerjack/cli/handlers/config_handlers.py +16 -0
  103. crackerjack/cli/handlers/coverage.py +84 -0
  104. crackerjack/cli/handlers/documentation.py +280 -0
  105. crackerjack/cli/handlers/main_handlers.py +497 -0
  106. crackerjack/cli/handlers/monitoring.py +371 -0
  107. crackerjack/cli/handlers.py +700 -0
  108. crackerjack/cli/interactive.py +488 -0
  109. crackerjack/cli/options.py +1216 -0
  110. crackerjack/cli/semantic_handlers.py +292 -0
  111. crackerjack/cli/utils.py +19 -0
  112. crackerjack/cli/version.py +19 -0
  113. crackerjack/code_cleaner.py +1307 -0
  114. crackerjack/config/README.md +472 -0
  115. crackerjack/config/__init__.py +275 -0
  116. crackerjack/config/global_lock_config.py +207 -0
  117. crackerjack/config/hooks.py +390 -0
  118. crackerjack/config/loader.py +239 -0
  119. crackerjack/config/settings.py +141 -0
  120. crackerjack/config/tool_commands.py +331 -0
  121. crackerjack/core/README.md +393 -0
  122. crackerjack/core/__init__.py +0 -0
  123. crackerjack/core/async_workflow_orchestrator.py +738 -0
  124. crackerjack/core/autofix_coordinator.py +282 -0
  125. crackerjack/core/container.py +105 -0
  126. crackerjack/core/enhanced_container.py +583 -0
  127. crackerjack/core/file_lifecycle.py +472 -0
  128. crackerjack/core/performance.py +244 -0
  129. crackerjack/core/performance_monitor.py +357 -0
  130. crackerjack/core/phase_coordinator.py +1227 -0
  131. crackerjack/core/proactive_workflow.py +267 -0
  132. crackerjack/core/resource_manager.py +425 -0
  133. crackerjack/core/retry.py +275 -0
  134. crackerjack/core/service_watchdog.py +601 -0
  135. crackerjack/core/session_coordinator.py +239 -0
  136. crackerjack/core/timeout_manager.py +563 -0
  137. crackerjack/core/websocket_lifecycle.py +410 -0
  138. crackerjack/core/workflow/__init__.py +21 -0
  139. crackerjack/core/workflow/workflow_ai_coordinator.py +863 -0
  140. crackerjack/core/workflow/workflow_event_orchestrator.py +1107 -0
  141. crackerjack/core/workflow/workflow_issue_parser.py +714 -0
  142. crackerjack/core/workflow/workflow_phase_executor.py +1158 -0
  143. crackerjack/core/workflow/workflow_security_gates.py +400 -0
  144. crackerjack/core/workflow_orchestrator.py +2243 -0
  145. crackerjack/data/README.md +11 -0
  146. crackerjack/data/__init__.py +8 -0
  147. crackerjack/data/models.py +79 -0
  148. crackerjack/data/repository.py +210 -0
  149. crackerjack/decorators/README.md +180 -0
  150. crackerjack/decorators/__init__.py +35 -0
  151. crackerjack/decorators/error_handling.py +649 -0
  152. crackerjack/decorators/error_handling_decorators.py +334 -0
  153. crackerjack/decorators/helpers.py +58 -0
  154. crackerjack/decorators/patterns.py +281 -0
  155. crackerjack/decorators/utils.py +58 -0
  156. crackerjack/docs/INDEX.md +11 -0
  157. crackerjack/docs/README.md +11 -0
  158. crackerjack/docs/generated/api/API_REFERENCE.md +10895 -0
  159. crackerjack/docs/generated/api/CLI_REFERENCE.md +109 -0
  160. crackerjack/docs/generated/api/CROSS_REFERENCES.md +1755 -0
  161. crackerjack/docs/generated/api/PROTOCOLS.md +3 -0
  162. crackerjack/docs/generated/api/SERVICES.md +1252 -0
  163. crackerjack/documentation/README.md +11 -0
  164. crackerjack/documentation/__init__.py +31 -0
  165. crackerjack/documentation/ai_templates.py +756 -0
  166. crackerjack/documentation/dual_output_generator.py +767 -0
  167. crackerjack/documentation/mkdocs_integration.py +518 -0
  168. crackerjack/documentation/reference_generator.py +1065 -0
  169. crackerjack/dynamic_config.py +678 -0
  170. crackerjack/errors.py +378 -0
  171. crackerjack/events/README.md +11 -0
  172. crackerjack/events/__init__.py +16 -0
  173. crackerjack/events/telemetry.py +175 -0
  174. crackerjack/events/workflow_bus.py +346 -0
  175. crackerjack/exceptions/README.md +301 -0
  176. crackerjack/exceptions/__init__.py +5 -0
  177. crackerjack/exceptions/config.py +4 -0
  178. crackerjack/exceptions/tool_execution_error.py +245 -0
  179. crackerjack/executors/README.md +591 -0
  180. crackerjack/executors/__init__.py +13 -0
  181. crackerjack/executors/async_hook_executor.py +938 -0
  182. crackerjack/executors/cached_hook_executor.py +316 -0
  183. crackerjack/executors/hook_executor.py +1295 -0
  184. crackerjack/executors/hook_lock_manager.py +708 -0
  185. crackerjack/executors/individual_hook_executor.py +739 -0
  186. crackerjack/executors/lsp_aware_hook_executor.py +349 -0
  187. crackerjack/executors/progress_hook_executor.py +282 -0
  188. crackerjack/executors/tool_proxy.py +433 -0
  189. crackerjack/hooks/README.md +485 -0
  190. crackerjack/hooks/lsp_hook.py +93 -0
  191. crackerjack/intelligence/README.md +557 -0
  192. crackerjack/intelligence/__init__.py +37 -0
  193. crackerjack/intelligence/adaptive_learning.py +693 -0
  194. crackerjack/intelligence/agent_orchestrator.py +485 -0
  195. crackerjack/intelligence/agent_registry.py +377 -0
  196. crackerjack/intelligence/agent_selector.py +439 -0
  197. crackerjack/intelligence/integration.py +250 -0
  198. crackerjack/interactive.py +719 -0
  199. crackerjack/managers/README.md +369 -0
  200. crackerjack/managers/__init__.py +11 -0
  201. crackerjack/managers/async_hook_manager.py +135 -0
  202. crackerjack/managers/hook_manager.py +585 -0
  203. crackerjack/managers/publish_manager.py +631 -0
  204. crackerjack/managers/test_command_builder.py +391 -0
  205. crackerjack/managers/test_executor.py +474 -0
  206. crackerjack/managers/test_manager.py +1357 -0
  207. crackerjack/managers/test_progress.py +187 -0
  208. crackerjack/mcp/README.md +374 -0
  209. crackerjack/mcp/__init__.py +0 -0
  210. crackerjack/mcp/cache.py +352 -0
  211. crackerjack/mcp/client_runner.py +121 -0
  212. crackerjack/mcp/context.py +802 -0
  213. crackerjack/mcp/dashboard.py +657 -0
  214. crackerjack/mcp/enhanced_progress_monitor.py +493 -0
  215. crackerjack/mcp/file_monitor.py +394 -0
  216. crackerjack/mcp/progress_components.py +607 -0
  217. crackerjack/mcp/progress_monitor.py +1016 -0
  218. crackerjack/mcp/rate_limiter.py +336 -0
  219. crackerjack/mcp/server.py +24 -0
  220. crackerjack/mcp/server_core.py +526 -0
  221. crackerjack/mcp/service_watchdog.py +505 -0
  222. crackerjack/mcp/state.py +407 -0
  223. crackerjack/mcp/task_manager.py +259 -0
  224. crackerjack/mcp/tools/README.md +27 -0
  225. crackerjack/mcp/tools/__init__.py +19 -0
  226. crackerjack/mcp/tools/core_tools.py +469 -0
  227. crackerjack/mcp/tools/error_analyzer.py +283 -0
  228. crackerjack/mcp/tools/execution_tools.py +384 -0
  229. crackerjack/mcp/tools/intelligence_tool_registry.py +46 -0
  230. crackerjack/mcp/tools/intelligence_tools.py +264 -0
  231. crackerjack/mcp/tools/monitoring_tools.py +628 -0
  232. crackerjack/mcp/tools/proactive_tools.py +367 -0
  233. crackerjack/mcp/tools/progress_tools.py +222 -0
  234. crackerjack/mcp/tools/semantic_tools.py +584 -0
  235. crackerjack/mcp/tools/utility_tools.py +358 -0
  236. crackerjack/mcp/tools/workflow_executor.py +699 -0
  237. crackerjack/mcp/websocket/README.md +31 -0
  238. crackerjack/mcp/websocket/__init__.py +14 -0
  239. crackerjack/mcp/websocket/app.py +54 -0
  240. crackerjack/mcp/websocket/endpoints.py +492 -0
  241. crackerjack/mcp/websocket/event_bridge.py +188 -0
  242. crackerjack/mcp/websocket/jobs.py +406 -0
  243. crackerjack/mcp/websocket/monitoring/__init__.py +25 -0
  244. crackerjack/mcp/websocket/monitoring/api/__init__.py +19 -0
  245. crackerjack/mcp/websocket/monitoring/api/dependencies.py +141 -0
  246. crackerjack/mcp/websocket/monitoring/api/heatmap.py +154 -0
  247. crackerjack/mcp/websocket/monitoring/api/intelligence.py +199 -0
  248. crackerjack/mcp/websocket/monitoring/api/metrics.py +203 -0
  249. crackerjack/mcp/websocket/monitoring/api/telemetry.py +101 -0
  250. crackerjack/mcp/websocket/monitoring/dashboard.py +18 -0
  251. crackerjack/mcp/websocket/monitoring/factory.py +109 -0
  252. crackerjack/mcp/websocket/monitoring/filters.py +10 -0
  253. crackerjack/mcp/websocket/monitoring/metrics.py +64 -0
  254. crackerjack/mcp/websocket/monitoring/models.py +90 -0
  255. crackerjack/mcp/websocket/monitoring/utils.py +171 -0
  256. crackerjack/mcp/websocket/monitoring/websocket_manager.py +78 -0
  257. crackerjack/mcp/websocket/monitoring/websockets/__init__.py +17 -0
  258. crackerjack/mcp/websocket/monitoring/websockets/dependencies.py +126 -0
  259. crackerjack/mcp/websocket/monitoring/websockets/heatmap.py +176 -0
  260. crackerjack/mcp/websocket/monitoring/websockets/intelligence.py +291 -0
  261. crackerjack/mcp/websocket/monitoring/websockets/metrics.py +291 -0
  262. crackerjack/mcp/websocket/monitoring_endpoints.py +21 -0
  263. crackerjack/mcp/websocket/server.py +174 -0
  264. crackerjack/mcp/websocket/websocket_handler.py +276 -0
  265. crackerjack/mcp/websocket_server.py +10 -0
  266. crackerjack/models/README.md +308 -0
  267. crackerjack/models/__init__.py +40 -0
  268. crackerjack/models/config.py +730 -0
  269. crackerjack/models/config_adapter.py +265 -0
  270. crackerjack/models/protocols.py +1535 -0
  271. crackerjack/models/pydantic_models.py +320 -0
  272. crackerjack/models/qa_config.py +145 -0
  273. crackerjack/models/qa_results.py +134 -0
  274. crackerjack/models/resource_protocols.py +299 -0
  275. crackerjack/models/results.py +35 -0
  276. crackerjack/models/semantic_models.py +258 -0
  277. crackerjack/models/task.py +173 -0
  278. crackerjack/models/test_models.py +60 -0
  279. crackerjack/monitoring/README.md +11 -0
  280. crackerjack/monitoring/__init__.py +0 -0
  281. crackerjack/monitoring/ai_agent_watchdog.py +405 -0
  282. crackerjack/monitoring/metrics_collector.py +427 -0
  283. crackerjack/monitoring/regression_prevention.py +580 -0
  284. crackerjack/monitoring/websocket_server.py +406 -0
  285. crackerjack/orchestration/README.md +340 -0
  286. crackerjack/orchestration/__init__.py +43 -0
  287. crackerjack/orchestration/advanced_orchestrator.py +894 -0
  288. crackerjack/orchestration/cache/README.md +312 -0
  289. crackerjack/orchestration/cache/__init__.py +37 -0
  290. crackerjack/orchestration/cache/memory_cache.py +338 -0
  291. crackerjack/orchestration/cache/tool_proxy_cache.py +340 -0
  292. crackerjack/orchestration/config.py +297 -0
  293. crackerjack/orchestration/coverage_improvement.py +180 -0
  294. crackerjack/orchestration/execution_strategies.py +361 -0
  295. crackerjack/orchestration/hook_orchestrator.py +1398 -0
  296. crackerjack/orchestration/strategies/README.md +401 -0
  297. crackerjack/orchestration/strategies/__init__.py +39 -0
  298. crackerjack/orchestration/strategies/adaptive_strategy.py +630 -0
  299. crackerjack/orchestration/strategies/parallel_strategy.py +237 -0
  300. crackerjack/orchestration/strategies/sequential_strategy.py +299 -0
  301. crackerjack/orchestration/test_progress_streamer.py +647 -0
  302. crackerjack/plugins/README.md +11 -0
  303. crackerjack/plugins/__init__.py +15 -0
  304. crackerjack/plugins/base.py +200 -0
  305. crackerjack/plugins/hooks.py +254 -0
  306. crackerjack/plugins/loader.py +335 -0
  307. crackerjack/plugins/managers.py +264 -0
  308. crackerjack/py313.py +191 -0
  309. crackerjack/security/README.md +11 -0
  310. crackerjack/security/__init__.py +0 -0
  311. crackerjack/security/audit.py +197 -0
  312. crackerjack/services/README.md +374 -0
  313. crackerjack/services/__init__.py +9 -0
  314. crackerjack/services/ai/README.md +295 -0
  315. crackerjack/services/ai/__init__.py +7 -0
  316. crackerjack/services/ai/advanced_optimizer.py +878 -0
  317. crackerjack/services/ai/contextual_ai_assistant.py +542 -0
  318. crackerjack/services/ai/embeddings.py +444 -0
  319. crackerjack/services/ai/intelligent_commit.py +328 -0
  320. crackerjack/services/ai/predictive_analytics.py +510 -0
  321. crackerjack/services/anomaly_detector.py +392 -0
  322. crackerjack/services/api_extractor.py +617 -0
  323. crackerjack/services/backup_service.py +467 -0
  324. crackerjack/services/bounded_status_operations.py +530 -0
  325. crackerjack/services/cache.py +369 -0
  326. crackerjack/services/changelog_automation.py +399 -0
  327. crackerjack/services/command_execution_service.py +305 -0
  328. crackerjack/services/config_integrity.py +132 -0
  329. crackerjack/services/config_merge.py +546 -0
  330. crackerjack/services/config_service.py +198 -0
  331. crackerjack/services/config_template.py +493 -0
  332. crackerjack/services/coverage_badge_service.py +173 -0
  333. crackerjack/services/coverage_ratchet.py +381 -0
  334. crackerjack/services/debug.py +733 -0
  335. crackerjack/services/dependency_analyzer.py +460 -0
  336. crackerjack/services/dependency_monitor.py +622 -0
  337. crackerjack/services/documentation_generator.py +493 -0
  338. crackerjack/services/documentation_service.py +704 -0
  339. crackerjack/services/enhanced_filesystem.py +497 -0
  340. crackerjack/services/enterprise_optimizer.py +865 -0
  341. crackerjack/services/error_pattern_analyzer.py +676 -0
  342. crackerjack/services/file_filter.py +221 -0
  343. crackerjack/services/file_hasher.py +149 -0
  344. crackerjack/services/file_io_service.py +361 -0
  345. crackerjack/services/file_modifier.py +615 -0
  346. crackerjack/services/filesystem.py +381 -0
  347. crackerjack/services/git.py +422 -0
  348. crackerjack/services/health_metrics.py +615 -0
  349. crackerjack/services/heatmap_generator.py +744 -0
  350. crackerjack/services/incremental_executor.py +380 -0
  351. crackerjack/services/initialization.py +823 -0
  352. crackerjack/services/input_validator.py +668 -0
  353. crackerjack/services/intelligent_commit.py +327 -0
  354. crackerjack/services/log_manager.py +289 -0
  355. crackerjack/services/logging.py +228 -0
  356. crackerjack/services/lsp_client.py +628 -0
  357. crackerjack/services/memory_optimizer.py +414 -0
  358. crackerjack/services/metrics.py +587 -0
  359. crackerjack/services/monitoring/README.md +30 -0
  360. crackerjack/services/monitoring/__init__.py +9 -0
  361. crackerjack/services/monitoring/dependency_monitor.py +678 -0
  362. crackerjack/services/monitoring/error_pattern_analyzer.py +676 -0
  363. crackerjack/services/monitoring/health_metrics.py +716 -0
  364. crackerjack/services/monitoring/metrics.py +587 -0
  365. crackerjack/services/monitoring/performance_benchmarks.py +410 -0
  366. crackerjack/services/monitoring/performance_cache.py +388 -0
  367. crackerjack/services/monitoring/performance_monitor.py +569 -0
  368. crackerjack/services/parallel_executor.py +527 -0
  369. crackerjack/services/pattern_cache.py +333 -0
  370. crackerjack/services/pattern_detector.py +478 -0
  371. crackerjack/services/patterns/__init__.py +142 -0
  372. crackerjack/services/patterns/agents.py +107 -0
  373. crackerjack/services/patterns/code/__init__.py +15 -0
  374. crackerjack/services/patterns/code/detection.py +118 -0
  375. crackerjack/services/patterns/code/imports.py +107 -0
  376. crackerjack/services/patterns/code/paths.py +159 -0
  377. crackerjack/services/patterns/code/performance.py +119 -0
  378. crackerjack/services/patterns/code/replacement.py +36 -0
  379. crackerjack/services/patterns/core.py +212 -0
  380. crackerjack/services/patterns/documentation/__init__.py +14 -0
  381. crackerjack/services/patterns/documentation/badges_markdown.py +96 -0
  382. crackerjack/services/patterns/documentation/comments_blocks.py +83 -0
  383. crackerjack/services/patterns/documentation/docstrings.py +89 -0
  384. crackerjack/services/patterns/formatting.py +226 -0
  385. crackerjack/services/patterns/operations.py +339 -0
  386. crackerjack/services/patterns/security/__init__.py +23 -0
  387. crackerjack/services/patterns/security/code_injection.py +122 -0
  388. crackerjack/services/patterns/security/credentials.py +190 -0
  389. crackerjack/services/patterns/security/path_traversal.py +221 -0
  390. crackerjack/services/patterns/security/unsafe_operations.py +216 -0
  391. crackerjack/services/patterns/templates.py +62 -0
  392. crackerjack/services/patterns/testing/__init__.py +18 -0
  393. crackerjack/services/patterns/testing/error_patterns.py +107 -0
  394. crackerjack/services/patterns/testing/pytest_output.py +126 -0
  395. crackerjack/services/patterns/tool_output/__init__.py +16 -0
  396. crackerjack/services/patterns/tool_output/bandit.py +72 -0
  397. crackerjack/services/patterns/tool_output/other.py +97 -0
  398. crackerjack/services/patterns/tool_output/pyright.py +67 -0
  399. crackerjack/services/patterns/tool_output/ruff.py +44 -0
  400. crackerjack/services/patterns/url_sanitization.py +114 -0
  401. crackerjack/services/patterns/utilities.py +42 -0
  402. crackerjack/services/patterns/utils.py +339 -0
  403. crackerjack/services/patterns/validation.py +46 -0
  404. crackerjack/services/patterns/versioning.py +62 -0
  405. crackerjack/services/predictive_analytics.py +523 -0
  406. crackerjack/services/profiler.py +280 -0
  407. crackerjack/services/quality/README.md +415 -0
  408. crackerjack/services/quality/__init__.py +11 -0
  409. crackerjack/services/quality/anomaly_detector.py +392 -0
  410. crackerjack/services/quality/pattern_cache.py +333 -0
  411. crackerjack/services/quality/pattern_detector.py +479 -0
  412. crackerjack/services/quality/qa_orchestrator.py +491 -0
  413. crackerjack/services/quality/quality_baseline.py +395 -0
  414. crackerjack/services/quality/quality_baseline_enhanced.py +649 -0
  415. crackerjack/services/quality/quality_intelligence.py +949 -0
  416. crackerjack/services/regex_patterns.py +58 -0
  417. crackerjack/services/regex_utils.py +483 -0
  418. crackerjack/services/secure_path_utils.py +524 -0
  419. crackerjack/services/secure_status_formatter.py +450 -0
  420. crackerjack/services/secure_subprocess.py +635 -0
  421. crackerjack/services/security.py +239 -0
  422. crackerjack/services/security_logger.py +495 -0
  423. crackerjack/services/server_manager.py +411 -0
  424. crackerjack/services/smart_scheduling.py +167 -0
  425. crackerjack/services/status_authentication.py +460 -0
  426. crackerjack/services/status_security_manager.py +315 -0
  427. crackerjack/services/terminal_utils.py +0 -0
  428. crackerjack/services/thread_safe_status_collector.py +441 -0
  429. crackerjack/services/tool_filter.py +368 -0
  430. crackerjack/services/tool_version_service.py +43 -0
  431. crackerjack/services/unified_config.py +115 -0
  432. crackerjack/services/validation_rate_limiter.py +220 -0
  433. crackerjack/services/vector_store.py +689 -0
  434. crackerjack/services/version_analyzer.py +461 -0
  435. crackerjack/services/version_checker.py +223 -0
  436. crackerjack/services/websocket_resource_limiter.py +438 -0
  437. crackerjack/services/zuban_lsp_service.py +391 -0
  438. crackerjack/slash_commands/README.md +11 -0
  439. crackerjack/slash_commands/__init__.py +59 -0
  440. crackerjack/slash_commands/init.md +112 -0
  441. crackerjack/slash_commands/run.md +197 -0
  442. crackerjack/slash_commands/status.md +127 -0
  443. crackerjack/tools/README.md +11 -0
  444. crackerjack/tools/__init__.py +30 -0
  445. crackerjack/tools/_git_utils.py +105 -0
  446. crackerjack/tools/check_added_large_files.py +139 -0
  447. crackerjack/tools/check_ast.py +105 -0
  448. crackerjack/tools/check_json.py +103 -0
  449. crackerjack/tools/check_jsonschema.py +297 -0
  450. crackerjack/tools/check_toml.py +103 -0
  451. crackerjack/tools/check_yaml.py +110 -0
  452. crackerjack/tools/codespell_wrapper.py +72 -0
  453. crackerjack/tools/end_of_file_fixer.py +202 -0
  454. crackerjack/tools/format_json.py +128 -0
  455. crackerjack/tools/mdformat_wrapper.py +114 -0
  456. crackerjack/tools/trailing_whitespace.py +198 -0
  457. crackerjack/tools/validate_input_validator_patterns.py +236 -0
  458. crackerjack/tools/validate_regex_patterns.py +188 -0
  459. crackerjack/ui/README.md +11 -0
  460. crackerjack/ui/__init__.py +1 -0
  461. crackerjack/ui/dashboard_renderer.py +28 -0
  462. crackerjack/ui/templates/README.md +11 -0
  463. crackerjack/utils/console_utils.py +13 -0
  464. crackerjack/utils/dependency_guard.py +230 -0
  465. crackerjack/utils/retry_utils.py +275 -0
  466. crackerjack/workflows/README.md +590 -0
  467. crackerjack/workflows/__init__.py +46 -0
  468. crackerjack/workflows/actions.py +811 -0
  469. crackerjack/workflows/auto_fix.py +444 -0
  470. crackerjack/workflows/container_builder.py +499 -0
  471. crackerjack/workflows/definitions.py +443 -0
  472. crackerjack/workflows/engine.py +177 -0
  473. crackerjack/workflows/event_bridge.py +242 -0
  474. crackerjack-0.45.2.dist-info/METADATA +1678 -0
  475. crackerjack-0.45.2.dist-info/RECORD +478 -0
  476. {crackerjack-0.18.2.dist-info → crackerjack-0.45.2.dist-info}/WHEEL +1 -1
  477. crackerjack-0.45.2.dist-info/entry_points.txt +2 -0
  478. crackerjack/.gitignore +0 -14
  479. crackerjack/.libcst.codemod.yaml +0 -18
  480. crackerjack/.pdm.toml +0 -1
  481. crackerjack/.pre-commit-config.yaml +0 -91
  482. crackerjack/.pytest_cache/.gitignore +0 -2
  483. crackerjack/.pytest_cache/CACHEDIR.TAG +0 -4
  484. crackerjack/.pytest_cache/README.md +0 -8
  485. crackerjack/.pytest_cache/v/cache/nodeids +0 -1
  486. crackerjack/.pytest_cache/v/cache/stepwise +0 -1
  487. crackerjack/.ruff_cache/.gitignore +0 -1
  488. crackerjack/.ruff_cache/0.1.11/3256171999636029978 +0 -0
  489. crackerjack/.ruff_cache/0.1.14/602324811142551221 +0 -0
  490. crackerjack/.ruff_cache/0.1.4/10355199064880463147 +0 -0
  491. crackerjack/.ruff_cache/0.1.6/15140459877605758699 +0 -0
  492. crackerjack/.ruff_cache/0.1.7/1790508110482614856 +0 -0
  493. crackerjack/.ruff_cache/0.1.9/17041001205004563469 +0 -0
  494. crackerjack/.ruff_cache/0.11.2/4070660268492669020 +0 -0
  495. crackerjack/.ruff_cache/0.11.3/9818742842212983150 +0 -0
  496. crackerjack/.ruff_cache/0.11.4/9818742842212983150 +0 -0
  497. crackerjack/.ruff_cache/0.11.6/3557596832929915217 +0 -0
  498. crackerjack/.ruff_cache/0.11.7/10386934055395314831 +0 -0
  499. crackerjack/.ruff_cache/0.11.7/3557596832929915217 +0 -0
  500. crackerjack/.ruff_cache/0.11.8/530407680854991027 +0 -0
  501. crackerjack/.ruff_cache/0.2.0/10047773857155985907 +0 -0
  502. crackerjack/.ruff_cache/0.2.1/8522267973936635051 +0 -0
  503. crackerjack/.ruff_cache/0.2.2/18053836298936336950 +0 -0
  504. crackerjack/.ruff_cache/0.3.0/12548816621480535786 +0 -0
  505. crackerjack/.ruff_cache/0.3.3/11081883392474770722 +0 -0
  506. crackerjack/.ruff_cache/0.3.4/676973378459347183 +0 -0
  507. crackerjack/.ruff_cache/0.3.5/16311176246009842383 +0 -0
  508. crackerjack/.ruff_cache/0.5.7/1493622539551733492 +0 -0
  509. crackerjack/.ruff_cache/0.5.7/6231957614044513175 +0 -0
  510. crackerjack/.ruff_cache/0.5.7/9932762556785938009 +0 -0
  511. crackerjack/.ruff_cache/0.6.0/11982804814124138945 +0 -0
  512. crackerjack/.ruff_cache/0.6.0/12055761203849489982 +0 -0
  513. crackerjack/.ruff_cache/0.6.2/1206147804896221174 +0 -0
  514. crackerjack/.ruff_cache/0.6.4/1206147804896221174 +0 -0
  515. crackerjack/.ruff_cache/0.6.5/1206147804896221174 +0 -0
  516. crackerjack/.ruff_cache/0.6.7/3657366982708166874 +0 -0
  517. crackerjack/.ruff_cache/0.6.9/285614542852677309 +0 -0
  518. crackerjack/.ruff_cache/0.7.1/1024065805990144819 +0 -0
  519. crackerjack/.ruff_cache/0.7.1/285614542852677309 +0 -0
  520. crackerjack/.ruff_cache/0.7.3/16061516852537040135 +0 -0
  521. crackerjack/.ruff_cache/0.8.4/16354268377385700367 +0 -0
  522. crackerjack/.ruff_cache/0.9.10/12813592349865671909 +0 -0
  523. crackerjack/.ruff_cache/0.9.10/923908772239632759 +0 -0
  524. crackerjack/.ruff_cache/0.9.3/13948373885254993391 +0 -0
  525. crackerjack/.ruff_cache/0.9.9/12813592349865671909 +0 -0
  526. crackerjack/.ruff_cache/0.9.9/8843823720003377982 +0 -0
  527. crackerjack/.ruff_cache/CACHEDIR.TAG +0 -1
  528. crackerjack/crackerjack.py +0 -855
  529. crackerjack/pyproject.toml +0 -214
  530. crackerjack-0.18.2.dist-info/METADATA +0 -420
  531. crackerjack-0.18.2.dist-info/RECORD +0 -59
  532. crackerjack-0.18.2.dist-info/entry_points.txt +0 -4
  533. {crackerjack-0.18.2.dist-info → crackerjack-0.45.2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,657 @@
1
+ import time
2
+ import typing as t
3
+ from collections import deque
4
+ from datetime import datetime
5
+ from pathlib import Path
6
+ from typing import TYPE_CHECKING, Any
7
+
8
+ import aiohttp
9
+ from rich.text import Text
10
+ from textual.app import App, ComposeResult
11
+ from textual.containers import (
12
+ Container,
13
+ Horizontal,
14
+ )
15
+ from textual.reactive import reactive
16
+ from textual.widgets import (
17
+ Button,
18
+ DataTable,
19
+ Footer,
20
+ Header,
21
+ Log,
22
+ Static,
23
+ TabbedContent,
24
+ TabPane,
25
+ )
26
+
27
+ from crackerjack.services import server_manager
28
+
29
+ from .progress_components import JobDataCollector, TerminalRestorer
30
+
31
+ if TYPE_CHECKING:
32
+ from textual.timer import Timer
33
+
34
+
35
+ class MetricCard(Static):
36
+ DEFAULT_CSS = """
37
+ MetricCard {
38
+ width: 1fr;
39
+ height: 4;
40
+ border: solid $primary;
41
+ padding: 0 1;
42
+ margin: 0 1;
43
+ }
44
+
45
+ MetricCard.critical {
46
+ border: solid $error;
47
+ color: $error;
48
+ }
49
+
50
+ MetricCard.warning {
51
+ border: solid $warning;
52
+ color: $warning;
53
+ }
54
+
55
+ MetricCard.success {
56
+ border: solid $success;
57
+ color: $success;
58
+ }
59
+
60
+ MetricCard.info {
61
+ border: solid $info;
62
+ color: $info;
63
+ }
64
+ """
65
+
66
+ value = reactive(" --")
67
+ label = reactive("Metric")
68
+ trend = reactive("")
69
+ status = reactive("")
70
+
71
+ def __init__(
72
+ self,
73
+ label: str,
74
+ value: str = " --",
75
+ trend: str = "",
76
+ status: str = "",
77
+ **kwargs: t.Any,
78
+ ) -> None:
79
+ super().__init__(**kwargs)
80
+ self.label = label
81
+ self.value = value
82
+ self.trend = trend
83
+ self.status = status
84
+
85
+ def render(self) -> Text:
86
+ text = Text()
87
+ text.append(f"{self.label}\n", style="dim")
88
+ text.append(str(self.value), style="bold")
89
+ if self.trend:
90
+ text.append(f" {self.trend}", style="green" if "↑" in self.trend else "red")
91
+ return text
92
+
93
+ def update_metric(self, value: str, trend: str = "", status: str = "") -> None:
94
+ self.value = value
95
+ self.trend = trend
96
+ self.status = status
97
+
98
+ self.remove_class("critical", "warning", "success", "info")
99
+ if status:
100
+ self.add_class(status)
101
+
102
+
103
+ class SystemOverviewWidget(Static):
104
+ DEFAULT_CSS = """
105
+ SystemOverviewWidget {
106
+ height: 8;
107
+ border: solid $primary;
108
+ margin: 1;
109
+ }
110
+ """
111
+
112
+ def compose(self) -> ComposeResult:
113
+ with Container(id="system_overview"):
114
+ with Horizontal(classes="metrics_row"):
115
+ yield MetricCard("CPU", "0 % ", id="cpu_metric")
116
+ yield MetricCard("Memory", "0MB", id="memory_metric")
117
+ yield MetricCard("Active Jobs", "0", id="jobs_metric")
118
+ yield MetricCard("Queue Depth", "0", id="queue_metric")
119
+
120
+ with Horizontal(classes="status_row"):
121
+ yield MetricCard("MCP Server", "Stopped", id="mcp_status")
122
+ yield MetricCard("WebSocket", "Stopped", id="websocket_status")
123
+ yield MetricCard("AI Agent", "Idle", id="agent_status")
124
+ yield MetricCard("Last Run", "Never", id="last_run")
125
+
126
+
127
+ class JobsTableWidget(Static):
128
+ DEFAULT_CSS = """
129
+ JobsTableWidget {
130
+ height: 1fr;
131
+ border: solid $primary;
132
+ margin: 1;
133
+ }
134
+ """
135
+
136
+ def compose(self) -> ComposeResult:
137
+ with Container():
138
+ yield DataTable(id="jobs_table")
139
+
140
+ def on_mount(self) -> None:
141
+ table = self.query_one("#jobs_table", DataTable)
142
+ table.add_columns(
143
+ "Job ID",
144
+ "Status",
145
+ "Stage",
146
+ "Progress",
147
+ "Started",
148
+ "Duration",
149
+ "Issues",
150
+ )
151
+ table.zebra_stripes = True
152
+ table.show_header = True
153
+
154
+
155
+ class LogViewWidget(Static):
156
+ DEFAULT_CSS = """
157
+ LogViewWidget {
158
+ height: 1fr;
159
+ border: solid $primary;
160
+ margin: 1;
161
+ }
162
+ """
163
+
164
+ def compose(self) -> ComposeResult:
165
+ with Container():
166
+ with Horizontal(id="log_controls"):
167
+ yield Button("Clear", id="clear_logs")
168
+ yield Button("Pause", id="pause_logs")
169
+ yield Button("Export", id="export_logs")
170
+ yield Log(id="log_display")
171
+
172
+
173
+ class AIAgentWidget(Static):
174
+ DEFAULT_CSS = """
175
+ AIAgentWidget {
176
+ height: 12;
177
+ border: solid $primary;
178
+ margin: 1;
179
+ }
180
+ """
181
+
182
+ def compose(self) -> ComposeResult:
183
+ with Container():
184
+ with Horizontal(classes="agent_metrics"):
185
+ yield MetricCard("Active Agents", "0", id="active_agents")
186
+ yield MetricCard("Issues Fixed", "0", "↑", id="issues_fixed")
187
+ yield MetricCard("Avg Confidence", "0 % ", id="avg_confidence")
188
+ yield MetricCard("Cache Hits", "0", id="cache_hits")
189
+
190
+ yield DataTable(id="agents_table")
191
+
192
+ def on_mount(self) -> None:
193
+ table = self.query_one("#agents_table", DataTable)
194
+ table.add_columns("Agent", "Type", "Status", "Confidence", "Fixed", "Runtime")
195
+ table.zebra_stripes = True
196
+ table.show_header = True
197
+
198
+
199
+ class PerformanceWidget(Static):
200
+ DEFAULT_CSS = """
201
+ PerformanceWidget {
202
+ height: 10;
203
+ border: solid $primary;
204
+ margin: 1;
205
+ }
206
+ """
207
+
208
+ def __init__(self, **kwargs: t.Any) -> None:
209
+ super().__init__(**kwargs)
210
+ self.cpu_history: deque[float] = deque(maxlen=50)
211
+ self.memory_history: deque[float] = deque(maxlen=50)
212
+ self.job_history: deque[int] = deque(maxlen=50)
213
+
214
+ def compose(self) -> ComposeResult:
215
+ with Container():
216
+ with Horizontal():
217
+ yield MetricCard("Avg Job Time", "0s", id="avg_job_time")
218
+ yield MetricCard("Success Rate", "100 % ", id="success_rate")
219
+ yield MetricCard("Error Rate", "0 % ", id="error_rate")
220
+ yield MetricCard("Throughput", "0 j / h", id="throughput")
221
+
222
+ yield Static(id="performance_chart")
223
+
224
+ def update_performance_data(self, cpu: float, memory: float, jobs: int) -> None:
225
+ self.cpu_history.append(cpu)
226
+ self.memory_history.append(memory)
227
+ self.job_history.append(jobs)
228
+
229
+ self._render_performance_chart()
230
+
231
+ def _render_performance_chart(self) -> None:
232
+ if not self.cpu_history:
233
+ return
234
+
235
+ max_cpu = max(self.cpu_history) if self.cpu_history else 1
236
+ max_mem = max(self.memory_history) if self.memory_history else 1
237
+
238
+ cpu_line = "".join(self._get_bar_char(val, max_cpu) for val in self.cpu_history)
239
+ mem_line = "".join(
240
+ self._get_bar_char(val, max_mem) for val in self.memory_history
241
+ )
242
+
243
+ chart_text = f"CPU: {cpu_line}\nMEM: {mem_line}"
244
+
245
+ chart = self.query_one("#performance_chart", Static)
246
+ chart.update(chart_text)
247
+
248
+ def _get_bar_char(self, value: float, max_value: float) -> str:
249
+ if max_value == 0:
250
+ return "▁"
251
+ ratio = value / max_value
252
+ if ratio >= 0.875:
253
+ return "█"
254
+ if ratio >= 0.75:
255
+ return "▇"
256
+ if ratio >= 0.625:
257
+ return "▆"
258
+ if ratio >= 0.5:
259
+ return "▅"
260
+ if ratio >= 0.375:
261
+ return "▄"
262
+ if ratio >= 0.25:
263
+ return "▃"
264
+ if ratio >= 0.125:
265
+ return "▂"
266
+ return "▁"
267
+
268
+
269
+ class CrackerjackDashboard(App):
270
+ TITLE = "Crackerjack Dashboard"
271
+ SUB_TITLE = "Comprehensive Project Monitoring"
272
+
273
+ CSS_PATH = None
274
+
275
+ BINDINGS = [
276
+ ("q", "quit", "Quit"),
277
+ ("r", "refresh", "Refresh"),
278
+ ("c", "clear_logs", "Clear Logs"),
279
+ ("p", "pause_logs", "Pause / Resume Logs"),
280
+ ("s", "toggle_servers", "Start / Stop Servers"),
281
+ ("d", "toggle_debug", "Debug Mode"),
282
+ ]
283
+
284
+ DEFAULT_CSS = """
285
+ Screen {
286
+ layout: vertical;
287
+ }
288
+
289
+ Header {
290
+ dock: top;
291
+ height: 3;
292
+ }
293
+
294
+ Footer {
295
+ dock: bottom;
296
+ height: 1;
297
+ }
298
+
299
+ .metrics_row {
300
+ height: 4;
301
+ margin: 0 1;
302
+ }
303
+
304
+ .status_row {
305
+ height: 4;
306
+ margin: 0 1;
307
+ }
308
+ """
309
+
310
+ def __init__(
311
+ self,
312
+ progress_dir: Path | None = None,
313
+ websocket_url: str | None = None,
314
+ **kwargs: t.Any,
315
+ ) -> None:
316
+ super().__init__(**kwargs)
317
+
318
+ # Use defaults if not provided
319
+ self.progress_dir = progress_dir or Path.cwd() / ".crackerjack" / "progress"
320
+ self.websocket_url = websocket_url or "ws://localhost:8675"
321
+
322
+ self.job_collector = JobDataCollector(self.progress_dir, self.websocket_url)
323
+ self.terminal_restorer = TerminalRestorer()
324
+
325
+ self.is_paused = False
326
+ self.debug_mode = False
327
+ self.last_refresh = time.time()
328
+
329
+ self.jobs_data: dict[str, Any] = {}
330
+ self.logs_buffer: list[str] = []
331
+ self.performance_data = {
332
+ "cpu": 0.0,
333
+ "memory": 0.0,
334
+ "jobs": 0,
335
+ "success_rate": 100.0,
336
+ }
337
+
338
+ self.update_timer: Timer | None = None
339
+
340
+ def compose(self) -> ComposeResult:
341
+ yield Header()
342
+
343
+ with TabbedContent(id="main_tabs"):
344
+ with TabPane("Overview", id="overview_tab"):
345
+ yield SystemOverviewWidget(id="system_overview")
346
+ yield JobsTableWidget(id="jobs_widget")
347
+
348
+ with TabPane("AI Agents", id="agents_tab"):
349
+ yield AIAgentWidget(id="ai_agent_widget")
350
+
351
+ with TabPane("Performance", id="performance_tab"):
352
+ yield PerformanceWidget(id="performance_widget")
353
+
354
+ with TabPane("Logs", id="logs_tab"):
355
+ yield LogViewWidget(id="log_widget")
356
+
357
+ yield Footer()
358
+
359
+ def on_mount(self) -> None:
360
+ self.log("Crackerjack Dashboard starting...")
361
+
362
+ # Schedule periodic updates using a callback pattern instead of set_interval with async method
363
+ self.call_later(self._setup_periodic_updates)
364
+
365
+ self.call_later(self.initial_setup)
366
+
367
+ def _setup_periodic_updates(self) -> None:
368
+ """Setup the periodic update callbacks."""
369
+ # self.call_later(self.update_dashboard) # Commented out due to Textual typing issue
370
+ # Schedule the next update
371
+ self.set_timer(2.0, self._setup_periodic_updates)
372
+
373
+ async def initial_setup(self) -> None:
374
+ try:
375
+ await self._check_server_status()
376
+
377
+ await self._load_jobs_data()
378
+
379
+ # self.call_later(self.update_dashboard) # Commented out due to Textual typing issue
380
+
381
+ self.log("Dashboard initialized successfully")
382
+
383
+ except Exception as e:
384
+ self.log(f"Error during initial setup: {e}")
385
+
386
+ # @work(exclusive=True) # Commented out due to typing issues
387
+ async def update_dashboard(self) -> None:
388
+ if self.is_paused:
389
+ return
390
+
391
+ try:
392
+ current_time = time.time()
393
+
394
+ await self._update_system_metrics()
395
+
396
+ await self._update_jobs_data()
397
+
398
+ await self._update_agent_status()
399
+
400
+ await self._update_performance_metrics()
401
+
402
+ await self._update_logs()
403
+
404
+ self.last_refresh = current_time
405
+
406
+ except Exception as e:
407
+ self.log(f"Error updating dashboard: {e}")
408
+
409
+ async def _check_server_status(self) -> None:
410
+ try:
411
+ mcp_processes = server_manager.find_mcp_server_processes()
412
+ mcp_running = len(mcp_processes) > 0
413
+ mcp_metric = self.query_one("#mcp_status", MetricCard)
414
+ mcp_metric.update_metric(
415
+ "Running" if mcp_running else "Stopped",
416
+ status="success" if mcp_running else "critical",
417
+ )
418
+
419
+ ws_running = await self._check_websocket_server()
420
+ ws_metric = self.query_one("#websocket_status", MetricCard)
421
+ ws_metric.update_metric(
422
+ "Running" if ws_running else "Stopped",
423
+ status="success" if ws_running else "critical",
424
+ )
425
+
426
+ except Exception as e:
427
+ self.log(f"Error checking server status: {e}")
428
+
429
+ async def _check_websocket_server(self) -> bool:
430
+ try:
431
+ timeout = aiohttp.ClientTimeout(total=5.0)
432
+ async with aiohttp.ClientSession(timeout=timeout) as session:
433
+ async with session.get("http://localhost:8675/") as response:
434
+ return response.status == 200
435
+ except Exception:
436
+ return False
437
+
438
+ async def _update_system_metrics(self) -> None:
439
+ try:
440
+ import psutil
441
+
442
+ cpu_percent = psutil.cpu_percent(interval=None)
443
+ memory = psutil.virtual_memory()
444
+ memory_mb = memory.used / (1024 * 1024)
445
+
446
+ cpu_metric = self.query_one("#cpu_metric", MetricCard)
447
+ memory_metric = self.query_one("#memory_metric", MetricCard)
448
+
449
+ cpu_metric.update_metric(f"{cpu_percent: .1f} % ")
450
+ memory_metric.update_metric(f"{memory_mb}MB")
451
+
452
+ self.performance_data["cpu"] = cpu_percent
453
+ self.performance_data["memory"] = memory_mb
454
+
455
+ except ImportError:
456
+ pass
457
+ except Exception as e:
458
+ self.log(f"Error updating system metrics: {e}")
459
+
460
+ async def _load_jobs_data(self) -> None:
461
+ try:
462
+ if await self._check_websocket_server():
463
+ jobs_data = await self._fetch_jobs_from_websocket()
464
+ if jobs_data:
465
+ self.jobs_data.update(jobs_data)
466
+
467
+ file_jobs = await self._collect_jobs_from_filesystem()
468
+ if file_jobs:
469
+ self.jobs_data.update(file_jobs)
470
+
471
+ except Exception as e:
472
+ self.log(f"Error loading jobs data: {e}")
473
+
474
+ async def _fetch_jobs_from_websocket(self) -> dict[str, Any]:
475
+ try:
476
+ timeout = aiohttp.ClientTimeout(total=10.0)
477
+ async with aiohttp.ClientSession(timeout=timeout) as session:
478
+ async with session.get(
479
+ "http: / / localhost: 8675 / api / jobs"
480
+ ) as response:
481
+ if response.status == 200:
482
+ json_result = await response.json()
483
+ return t.cast(dict[str, t.Any], json_result)
484
+ return {}
485
+ except Exception as e:
486
+ self.log(f"Error fetching WebSocket jobs: {e}")
487
+ return {}
488
+
489
+ async def _collect_jobs_from_filesystem(self) -> dict[str, Any]:
490
+ try:
491
+ jobs: dict[str, Any] = {}
492
+
493
+ import tempfile
494
+
495
+ temp_dir = Path(tempfile.gettempdir())
496
+ debug_files = temp_dir.glob("crackerjack - debug-*.log")
497
+ for debug_file in debug_files:
498
+ try:
499
+ if debug_file.stat().st_mtime > (time.time() - 3600):
500
+ debug_file.read_text()
501
+ job_id = debug_file.stem.replace("crackerjack-debug -", "")
502
+ jobs[job_id] = {
503
+ "id": job_id,
504
+ "status": "completed",
505
+ "log_file": str(debug_file),
506
+ "timestamp": debug_file.stat().st_mtime,
507
+ }
508
+ except Exception as e:
509
+ self.log(f"Could not process debug file {debug_file}: {e}")
510
+ continue
511
+
512
+ return jobs
513
+
514
+ except Exception as e:
515
+ self.log(f"Error collecting filesystem jobs: {e}")
516
+ return {}
517
+
518
+ async def _update_jobs_data(self) -> None:
519
+ try:
520
+ table = self.query_one("#jobs_table", DataTable)
521
+ table.clear()
522
+
523
+ active_count = len(
524
+ [j for j in self.jobs_data.values() if j.get("status") != "completed"],
525
+ )
526
+ jobs_metric = self.query_one("#jobs_metric", MetricCard)
527
+ jobs_metric.update_metric(str(active_count))
528
+
529
+ for job_id, job_data in sorted(
530
+ self.jobs_data.items(),
531
+ key=lambda x: x[1].get("timestamp", 0),
532
+ reverse=True,
533
+ ):
534
+ status = job_data.get("status", "unknown")
535
+ stage = job_data.get("current_stage", "N / A")
536
+ progress = job_data.get("progress", 0)
537
+ started = datetime.fromtimestamp(job_data.get("timestamp", 0)).strftime(
538
+ "% H: % M: % S",
539
+ )
540
+ duration = self._format_duration(job_data.get("duration", 0))
541
+ issues = job_data.get("issues_found", 0)
542
+
543
+ table.add_row(
544
+ job_id[:8],
545
+ status.title(),
546
+ stage,
547
+ f"{progress} % ",
548
+ started,
549
+ duration,
550
+ str(issues),
551
+ )
552
+
553
+ except Exception as e:
554
+ self.log(f"Error updating jobs data: {e}")
555
+
556
+ async def _update_agent_status(self) -> None:
557
+ try:
558
+ agents_table = self.query_one("#agents_table", DataTable)
559
+ agents_table.clear()
560
+
561
+ active_agents_metric = self.query_one("#active_agents", MetricCard)
562
+ issues_fixed_metric = self.query_one("#issues_fixed", MetricCard)
563
+ avg_confidence_metric = self.query_one("#avg_confidence", MetricCard)
564
+ cache_hits_metric = self.query_one("#cache_hits", MetricCard)
565
+
566
+ active_agents_metric.update_metric("0")
567
+ issues_fixed_metric.update_metric("0")
568
+ avg_confidence_metric.update_metric("0 % ")
569
+ cache_hits_metric.update_metric("0")
570
+
571
+ except Exception as e:
572
+ self.log(f"Error updating agent status: {e}")
573
+
574
+ async def _update_performance_metrics(self) -> None:
575
+ try:
576
+ performance_widget = self.query_one(
577
+ "#performance_widget",
578
+ PerformanceWidget,
579
+ )
580
+
581
+ cpu = self.performance_data.get("cpu", 0)
582
+ memory = self.performance_data.get("memory", 0)
583
+ jobs = len(self.jobs_data)
584
+
585
+ performance_widget.update_performance_data(cpu, memory, jobs)
586
+
587
+ avg_job_time = self.query_one("#avg_job_time", MetricCard)
588
+ success_rate = self.query_one("#success_rate", MetricCard)
589
+
590
+ avg_job_time.update_metric("0s")
591
+ success_rate.update_metric("100 % ")
592
+
593
+ except Exception as e:
594
+ self.log(f"Error updating performance metrics: {e}")
595
+
596
+ async def _update_logs(self) -> None:
597
+ try:
598
+ log_display = self.query_one("#log_display", Log)
599
+
600
+ current_time = datetime.now().strftime("% H: % M: % S")
601
+ if len(self.logs_buffer) % 10 == 0:
602
+ log_display.write_line(f"[{current_time}] Dashboard refresh completed")
603
+
604
+ except Exception as e:
605
+ self.log(f"Error updating logs: {e}")
606
+
607
+ def _format_duration(self, seconds: float) -> str:
608
+ if seconds < 60:
609
+ return f"{seconds: .1f}s"
610
+ if seconds < 3600:
611
+ minutes = seconds / 60
612
+ return f"{minutes: .1f}m"
613
+ hours = seconds / 3600
614
+ return f"{hours: .1f}h"
615
+
616
+ def action_refresh(self) -> None:
617
+ # Schedule the async update_dashboard method to be called later
618
+ # self.call_later(self.update_dashboard) # Commented out due to Textual typing issue
619
+ self.log("Manual refresh triggered")
620
+
621
+ def action_clear_logs(self) -> None:
622
+ try:
623
+ log_display = self.query_one("#log_display", Log)
624
+ log_display.clear()
625
+ self.logs_buffer.clear()
626
+ self.log("Logs cleared")
627
+ except Exception as e:
628
+ self.log(f"Error clearing logs: {e}")
629
+
630
+ def action_pause_logs(self) -> None:
631
+ self.is_paused = not self.is_paused
632
+ status = "paused" if self.is_paused else "resumed"
633
+ self.log(f"Dashboard updates {status}")
634
+
635
+ def action_toggle_servers(self) -> None:
636
+ self.log("Server toggle not implemented yet")
637
+
638
+ def action_toggle_debug(self) -> None:
639
+ self.debug_mode = not self.debug_mode
640
+ self.log(f"Debug mode {'enabled' if self.debug_mode else 'disabled'}")
641
+
642
+ async def on_exit(self) -> None:
643
+ if self.update_timer:
644
+ self.update_timer.stop()
645
+
646
+ self.terminal_restorer.restore_terminal()
647
+
648
+ self.log("Dashboard shutting down...")
649
+
650
+
651
+ def run_dashboard() -> None:
652
+ app = CrackerjackDashboard()
653
+ app.run()
654
+
655
+
656
+ if __name__ == "__main__":
657
+ run_dashboard()