mcli-framework 7.12.0__py3-none-any.whl → 7.12.3__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 mcli-framework might be problematic. Click here for more details.

Files changed (216) hide show
  1. mcli/app/__init__.py +0 -2
  2. mcli/app/commands_cmd.py +19 -23
  3. mcli/app/completion_helpers.py +5 -5
  4. mcli/app/init_cmd.py +10 -10
  5. mcli/app/lock_cmd.py +82 -27
  6. mcli/app/main.py +4 -50
  7. mcli/app/model/model.py +5 -10
  8. mcli/app/store_cmd.py +8 -8
  9. mcli/app/video/__init__.py +0 -2
  10. mcli/app/video/video.py +1 -14
  11. mcli/chat/chat.py +90 -108
  12. mcli/chat/command_rag.py +0 -4
  13. mcli/chat/enhanced_chat.py +32 -41
  14. mcli/chat/system_controller.py +37 -37
  15. mcli/chat/system_integration.py +4 -5
  16. mcli/cli.py +2 -3
  17. mcli/lib/api/api.py +4 -9
  18. mcli/lib/api/daemon_client.py +19 -20
  19. mcli/lib/api/daemon_client_local.py +1 -3
  20. mcli/lib/api/daemon_decorator.py +6 -6
  21. mcli/lib/api/mcli_decorators.py +4 -8
  22. mcli/lib/auth/__init__.py +0 -1
  23. mcli/lib/auth/auth.py +4 -5
  24. mcli/lib/auth/mcli_manager.py +7 -12
  25. mcli/lib/auth/token_util.py +5 -5
  26. mcli/lib/config/__init__.py +29 -1
  27. mcli/lib/config/config.py +0 -1
  28. mcli/lib/custom_commands.py +1 -1
  29. mcli/lib/discovery/command_discovery.py +15 -15
  30. mcli/lib/erd/erd.py +7 -7
  31. mcli/lib/files/files.py +1 -1
  32. mcli/lib/fs/__init__.py +31 -1
  33. mcli/lib/fs/fs.py +12 -13
  34. mcli/lib/lib.py +0 -1
  35. mcli/lib/logger/logger.py +7 -10
  36. mcli/lib/performance/optimizer.py +25 -27
  37. mcli/lib/performance/rust_bridge.py +22 -27
  38. mcli/lib/performance/uvloop_config.py +0 -1
  39. mcli/lib/pickles/__init__.py +0 -1
  40. mcli/lib/pickles/pickles.py +0 -2
  41. mcli/lib/secrets/commands.py +0 -2
  42. mcli/lib/secrets/manager.py +0 -1
  43. mcli/lib/secrets/repl.py +2 -3
  44. mcli/lib/secrets/store.py +1 -2
  45. mcli/lib/services/data_pipeline.py +34 -34
  46. mcli/lib/services/lsh_client.py +38 -40
  47. mcli/lib/shell/shell.py +2 -2
  48. mcli/lib/toml/__init__.py +0 -1
  49. mcli/lib/ui/styling.py +0 -1
  50. mcli/lib/ui/visual_effects.py +33 -41
  51. mcli/lib/watcher/watcher.py +0 -1
  52. mcli/ml/__init__.py +1 -1
  53. mcli/ml/api/__init__.py +1 -1
  54. mcli/ml/api/app.py +8 -9
  55. mcli/ml/api/middleware.py +10 -10
  56. mcli/ml/api/routers/__init__.py +1 -1
  57. mcli/ml/api/routers/admin_router.py +3 -3
  58. mcli/ml/api/routers/auth_router.py +17 -18
  59. mcli/ml/api/routers/backtest_router.py +2 -2
  60. mcli/ml/api/routers/data_router.py +2 -2
  61. mcli/ml/api/routers/model_router.py +14 -15
  62. mcli/ml/api/routers/monitoring_router.py +2 -2
  63. mcli/ml/api/routers/portfolio_router.py +2 -2
  64. mcli/ml/api/routers/prediction_router.py +10 -9
  65. mcli/ml/api/routers/trade_router.py +2 -2
  66. mcli/ml/api/routers/websocket_router.py +6 -7
  67. mcli/ml/api/schemas.py +2 -2
  68. mcli/ml/auth/__init__.py +1 -1
  69. mcli/ml/auth/auth_manager.py +22 -23
  70. mcli/ml/auth/models.py +17 -17
  71. mcli/ml/auth/permissions.py +17 -17
  72. mcli/ml/backtesting/__init__.py +1 -1
  73. mcli/ml/backtesting/backtest_engine.py +31 -35
  74. mcli/ml/backtesting/performance_metrics.py +12 -14
  75. mcli/ml/backtesting/run.py +1 -2
  76. mcli/ml/cache.py +35 -36
  77. mcli/ml/cli/__init__.py +1 -1
  78. mcli/ml/cli/main.py +21 -24
  79. mcli/ml/config/__init__.py +1 -1
  80. mcli/ml/config/settings.py +28 -29
  81. mcli/ml/configs/__init__.py +1 -1
  82. mcli/ml/configs/dvc_config.py +14 -15
  83. mcli/ml/configs/mlflow_config.py +12 -13
  84. mcli/ml/configs/mlops_manager.py +19 -21
  85. mcli/ml/dashboard/__init__.py +4 -4
  86. mcli/ml/dashboard/app.py +20 -30
  87. mcli/ml/dashboard/app_supabase.py +16 -19
  88. mcli/ml/dashboard/app_training.py +11 -14
  89. mcli/ml/dashboard/cli.py +2 -2
  90. mcli/ml/dashboard/common.py +2 -3
  91. mcli/ml/dashboard/components/__init__.py +1 -1
  92. mcli/ml/dashboard/components/charts.py +13 -11
  93. mcli/ml/dashboard/components/metrics.py +7 -7
  94. mcli/ml/dashboard/components/tables.py +12 -9
  95. mcli/ml/dashboard/overview.py +2 -2
  96. mcli/ml/dashboard/pages/__init__.py +1 -1
  97. mcli/ml/dashboard/pages/cicd.py +15 -18
  98. mcli/ml/dashboard/pages/debug_dependencies.py +7 -7
  99. mcli/ml/dashboard/pages/monte_carlo_predictions.py +11 -18
  100. mcli/ml/dashboard/pages/predictions_enhanced.py +24 -32
  101. mcli/ml/dashboard/pages/scrapers_and_logs.py +22 -24
  102. mcli/ml/dashboard/pages/test_portfolio.py +3 -6
  103. mcli/ml/dashboard/pages/trading.py +16 -18
  104. mcli/ml/dashboard/pages/workflows.py +20 -30
  105. mcli/ml/dashboard/utils.py +9 -9
  106. mcli/ml/dashboard/warning_suppression.py +3 -3
  107. mcli/ml/data_ingestion/__init__.py +1 -1
  108. mcli/ml/data_ingestion/api_connectors.py +41 -46
  109. mcli/ml/data_ingestion/data_pipeline.py +36 -46
  110. mcli/ml/data_ingestion/stream_processor.py +43 -46
  111. mcli/ml/database/__init__.py +1 -1
  112. mcli/ml/database/migrations/env.py +2 -2
  113. mcli/ml/database/models.py +22 -24
  114. mcli/ml/database/session.py +14 -14
  115. mcli/ml/experimentation/__init__.py +1 -1
  116. mcli/ml/experimentation/ab_testing.py +45 -46
  117. mcli/ml/features/__init__.py +1 -1
  118. mcli/ml/features/ensemble_features.py +22 -27
  119. mcli/ml/features/recommendation_engine.py +30 -30
  120. mcli/ml/features/stock_features.py +29 -32
  121. mcli/ml/features/test_feature_engineering.py +10 -11
  122. mcli/ml/logging.py +4 -4
  123. mcli/ml/mlops/__init__.py +1 -1
  124. mcli/ml/mlops/data_versioning.py +29 -30
  125. mcli/ml/mlops/experiment_tracker.py +24 -24
  126. mcli/ml/mlops/model_serving.py +31 -34
  127. mcli/ml/mlops/pipeline_orchestrator.py +27 -35
  128. mcli/ml/models/__init__.py +5 -6
  129. mcli/ml/models/base_models.py +23 -23
  130. mcli/ml/models/ensemble_models.py +31 -31
  131. mcli/ml/models/recommendation_models.py +18 -19
  132. mcli/ml/models/test_models.py +14 -16
  133. mcli/ml/monitoring/__init__.py +1 -1
  134. mcli/ml/monitoring/drift_detection.py +32 -36
  135. mcli/ml/monitoring/metrics.py +2 -2
  136. mcli/ml/optimization/__init__.py +1 -1
  137. mcli/ml/optimization/optimize.py +1 -2
  138. mcli/ml/optimization/portfolio_optimizer.py +30 -32
  139. mcli/ml/predictions/__init__.py +1 -1
  140. mcli/ml/preprocessing/__init__.py +1 -1
  141. mcli/ml/preprocessing/data_cleaners.py +22 -23
  142. mcli/ml/preprocessing/feature_extractors.py +23 -26
  143. mcli/ml/preprocessing/ml_pipeline.py +23 -23
  144. mcli/ml/preprocessing/test_preprocessing.py +7 -8
  145. mcli/ml/scripts/populate_sample_data.py +0 -4
  146. mcli/ml/serving/serve.py +1 -2
  147. mcli/ml/tasks.py +17 -17
  148. mcli/ml/tests/test_integration.py +29 -30
  149. mcli/ml/tests/test_training_dashboard.py +21 -21
  150. mcli/ml/trading/__init__.py +1 -1
  151. mcli/ml/trading/migrations.py +5 -5
  152. mcli/ml/trading/models.py +21 -23
  153. mcli/ml/trading/paper_trading.py +16 -13
  154. mcli/ml/trading/risk_management.py +17 -18
  155. mcli/ml/trading/trading_service.py +25 -28
  156. mcli/ml/training/__init__.py +1 -1
  157. mcli/ml/training/train.py +0 -1
  158. mcli/public/oi/oi.py +1 -2
  159. mcli/self/completion_cmd.py +6 -10
  160. mcli/self/logs_cmd.py +19 -24
  161. mcli/self/migrate_cmd.py +22 -20
  162. mcli/self/redis_cmd.py +10 -11
  163. mcli/self/self_cmd.py +62 -18
  164. mcli/self/store_cmd.py +10 -12
  165. mcli/self/visual_cmd.py +9 -14
  166. mcli/self/zsh_cmd.py +2 -4
  167. mcli/workflow/daemon/async_command_database.py +23 -24
  168. mcli/workflow/daemon/async_process_manager.py +27 -29
  169. mcli/workflow/daemon/client.py +27 -33
  170. mcli/workflow/daemon/daemon.py +32 -36
  171. mcli/workflow/daemon/enhanced_daemon.py +24 -33
  172. mcli/workflow/daemon/process_cli.py +11 -12
  173. mcli/workflow/daemon/process_manager.py +23 -26
  174. mcli/workflow/daemon/test_daemon.py +4 -5
  175. mcli/workflow/dashboard/dashboard_cmd.py +0 -1
  176. mcli/workflow/doc_convert.py +15 -17
  177. mcli/workflow/gcloud/__init__.py +0 -1
  178. mcli/workflow/gcloud/gcloud.py +11 -8
  179. mcli/workflow/git_commit/ai_service.py +14 -15
  180. mcli/workflow/lsh_integration.py +9 -11
  181. mcli/workflow/model_service/client.py +26 -31
  182. mcli/workflow/model_service/download_and_run_efficient_models.py +10 -14
  183. mcli/workflow/model_service/lightweight_embedder.py +25 -35
  184. mcli/workflow/model_service/lightweight_model_server.py +26 -32
  185. mcli/workflow/model_service/lightweight_test.py +7 -10
  186. mcli/workflow/model_service/model_service.py +80 -91
  187. mcli/workflow/model_service/ollama_efficient_runner.py +14 -18
  188. mcli/workflow/model_service/openai_adapter.py +23 -23
  189. mcli/workflow/model_service/pdf_processor.py +21 -26
  190. mcli/workflow/model_service/test_efficient_runner.py +12 -16
  191. mcli/workflow/model_service/test_example.py +11 -13
  192. mcli/workflow/model_service/test_integration.py +3 -5
  193. mcli/workflow/model_service/test_new_features.py +7 -8
  194. mcli/workflow/notebook/converter.py +1 -1
  195. mcli/workflow/notebook/notebook_cmd.py +5 -6
  196. mcli/workflow/notebook/schema.py +0 -1
  197. mcli/workflow/notebook/validator.py +7 -3
  198. mcli/workflow/openai/openai.py +1 -2
  199. mcli/workflow/registry/registry.py +4 -1
  200. mcli/workflow/repo/repo.py +6 -7
  201. mcli/workflow/scheduler/cron_parser.py +16 -19
  202. mcli/workflow/scheduler/job.py +10 -10
  203. mcli/workflow/scheduler/monitor.py +15 -15
  204. mcli/workflow/scheduler/persistence.py +17 -18
  205. mcli/workflow/scheduler/scheduler.py +37 -38
  206. mcli/workflow/secrets/__init__.py +1 -1
  207. mcli/workflow/sync/test_cmd.py +0 -1
  208. mcli/workflow/wakatime/__init__.py +5 -9
  209. mcli/workflow/wakatime/wakatime.py +1 -2
  210. {mcli_framework-7.12.0.dist-info → mcli_framework-7.12.3.dist-info}/METADATA +1 -1
  211. mcli_framework-7.12.3.dist-info/RECORD +279 -0
  212. mcli_framework-7.12.0.dist-info/RECORD +0 -279
  213. {mcli_framework-7.12.0.dist-info → mcli_framework-7.12.3.dist-info}/WHEEL +0 -0
  214. {mcli_framework-7.12.0.dist-info → mcli_framework-7.12.3.dist-info}/entry_points.txt +0 -0
  215. {mcli_framework-7.12.0.dist-info → mcli_framework-7.12.3.dist-info}/licenses/LICENSE +0 -0
  216. {mcli_framework-7.12.0.dist-info → mcli_framework-7.12.3.dist-info}/top_level.txt +0 -0
mcli/chat/chat.py CHANGED
@@ -1,5 +1,5 @@
1
- import os
2
- import readline
1
+ import re
2
+ from pathlib import Path
3
3
  from typing import Dict, List, Optional
4
4
 
5
5
  import requests
@@ -51,7 +51,7 @@ logger = get_logger(__name__)
51
51
  # Fallbacks if not set in config.toml
52
52
  LLM_PROVIDER = config.get("provider", "local")
53
53
  MODEL_NAME = config.get("model", "prajjwal1/bert-tiny") # Default to lightweight model
54
- OPENAI_API_KEY = config.get("openai_api_key", None)
54
+ OPENAI_API_KEY = config.get("openai_api_key")
55
55
  OLLAMA_BASE_URL = config.get(
56
56
  "ollama_base_url", "http://localhost:8080"
57
57
  ) # Default to lightweight server
@@ -79,7 +79,7 @@ I'm designed to be your digital assistant that keeps things running smoothly."""
79
79
 
80
80
 
81
81
  class ChatClient:
82
- """Interactive chat client for MCLI command management"""
82
+ """Interactive chat client for MCLI command management."""
83
83
 
84
84
  def __init__(self, use_remote: bool = False, model_override: str = None):
85
85
  self.daemon = get_daemon_client()
@@ -92,7 +92,7 @@ class ChatClient:
92
92
  self._load_scheduled_jobs()
93
93
 
94
94
  def _configure_model_settings(self):
95
- """Configure model settings based on remote/local preferences"""
95
+ """Configure model settings based on remote/local preferences."""
96
96
  global LLM_PROVIDER, MODEL_NAME, OLLAMA_BASE_URL
97
97
 
98
98
  if not self.use_remote:
@@ -115,7 +115,7 @@ class ChatClient:
115
115
  # Keep existing provider settings from config
116
116
 
117
117
  def _ensure_lightweight_model_server(self):
118
- """Ensure the lightweight model server is running"""
118
+ """Ensure the lightweight model server is running."""
119
119
  import time
120
120
 
121
121
  import requests
@@ -139,10 +139,10 @@ class ChatClient:
139
139
  f"[yellow]Model {MODEL_NAME} not loaded, will auto-load on first use[/yellow]"
140
140
  )
141
141
  return # Server will auto-load model when needed
142
- except:
142
+ except Exception:
143
143
  # If we can't check models, assume server will handle it
144
144
  return
145
- except:
145
+ except Exception:
146
146
  pass
147
147
 
148
148
  # Try to start the server automatically
@@ -173,7 +173,7 @@ class ChatClient:
173
173
 
174
174
  # Wait longer for server to start and verify it's working
175
175
  max_retries = 10
176
- for i in range(max_retries):
176
+ for _i in range(max_retries):
177
177
  time.sleep(1)
178
178
  try:
179
179
  response = requests.get(f"{OLLAMA_BASE_URL}/health", timeout=1)
@@ -182,10 +182,10 @@ class ChatClient:
182
182
  f"[green]✅ Lightweight model server started with {model_name}[/green]"
183
183
  )
184
184
  return
185
- except:
185
+ except Exception:
186
186
  pass
187
187
 
188
- console.print(f"[yellow]⚠️ Server started but health check failed[/yellow]")
188
+ console.print("[yellow]⚠️ Server started but health check failed[/yellow]")
189
189
  console.print("Falling back to remote models...")
190
190
  self.use_remote = True
191
191
  else:
@@ -199,7 +199,7 @@ class ChatClient:
199
199
  self.use_remote = True
200
200
 
201
201
  def start_interactive_session(self):
202
- """Start the chat interface"""
202
+ """Start the chat interface."""
203
203
  console.print("[bold green]MCLI Personal Assistant[/bold green] (type 'exit' to quit)")
204
204
 
205
205
  # Show current configuration
@@ -250,7 +250,7 @@ class ChatClient:
250
250
  console.print(f"[red]Error:[/red] {str(e)}")
251
251
 
252
252
  def process_input(self, user_input: str):
253
- """Process user input and generate response"""
253
+ """Process user input and generate response."""
254
254
  self.history.append({"user": user_input})
255
255
 
256
256
  # Check for commands list request
@@ -383,7 +383,6 @@ class ChatClient:
383
383
  return "hello"
384
384
 
385
385
  # Try to extract command name using common patterns
386
- import re
387
386
 
388
387
  patterns = [
389
388
  r"(?:call|execute|run)\s+(?:the\s+)?([a-zA-Z0-9\-_]+)(?:\s+command)?",
@@ -413,11 +412,11 @@ class ChatClient:
413
412
  # For the hello command, we need to call it appropriately
414
413
  if command.name == "hello" and command.full_name.startswith("self."):
415
414
  # This is the hello command from self module - call with default argument
416
- result = command.callback("World")
417
- console.print(f"[green]✅ Command executed successfully[/green]")
415
+ command.callback("World")
416
+ console.print("[green]✅ Command executed successfully[/green]")
418
417
  else:
419
- result = command.callback()
420
- console.print(f"[green]✅ Command executed successfully[/green]")
418
+ command.callback()
419
+ console.print("[green]✅ Command executed successfully[/green]")
421
420
  else:
422
421
  console.print("[yellow]Command found but has no callback[/yellow]")
423
422
  except Exception as e:
@@ -430,16 +429,16 @@ class ChatClient:
430
429
  console.print(f"[red]Error finding command:[/red] {e}")
431
430
 
432
431
  def handle_command_queries(self, query: str):
433
- """Handle command-related queries using existing command registry"""
432
+ """Handle command-related queries using existing command registry."""
434
433
  try:
435
434
  # Always fetch all commands (active and inactive)
436
435
  result = self.daemon.list_commands(all=True)
437
436
  if isinstance(result, dict):
438
- commands = result.get("commands", [])
437
+ result.get("commands", [])
439
438
  elif isinstance(result, list):
440
- commands = result
439
+ pass
441
440
  else:
442
- commands = []
441
+ pass
443
442
  except Exception as e:
444
443
  logger.debug(
445
444
  f"Could not fetch commands from daemon: {e}. Falling back to LLM-only mode."
@@ -466,7 +465,7 @@ class ChatClient:
466
465
  self.generate_llm_response(query)
467
466
 
468
467
  def list_commands(self, commands: List[Dict] = None):
469
- """List available commands"""
468
+ """List available commands."""
470
469
  if commands is None:
471
470
  # Use discovery system to get all commands
472
471
  try:
@@ -505,7 +504,7 @@ class ChatClient:
505
504
  console.print("[dim]Use 'mcli commands list' to see all commands[/dim]")
506
505
 
507
506
  def search_commands(self, query: str, commands: List[Dict] = None):
508
- """Search commands based on query"""
507
+ """Search commands based on query."""
509
508
  search_term = query.lower().replace("search", "").replace("find", "").strip()
510
509
 
511
510
  if commands is None:
@@ -548,7 +547,7 @@ class ChatClient:
548
547
  console.print(f"[dim]... and {len(results) - 10} more results[/dim]")
549
548
 
550
549
  def handle_commands_list(self):
551
- """Handle 'commands' command to list available functions"""
550
+ """Handle 'commands' command to list available functions."""
552
551
  try:
553
552
  # Get commands from daemon
554
553
  if hasattr(self.daemon, "list_commands"):
@@ -560,7 +559,7 @@ class ChatClient:
560
559
 
561
560
  console.print(f"[bold green]Available Commands ({len(commands)}):[/bold green]")
562
561
 
563
- for i, cmd in enumerate(commands[:20]): # Show first 20 commands
562
+ for _i, cmd in enumerate(commands[:20]): # Show first 20 commands
564
563
  name = cmd.get("name", "Unknown")
565
564
  description = cmd.get("description", cmd.get("help", "No description"))
566
565
 
@@ -597,7 +596,7 @@ class ChatClient:
597
596
  console.print("• [cyan]start/stop <id>[/cyan] - Control process lifecycle")
598
597
 
599
598
  def handle_process_list(self):
600
- """Handle 'ps' command to list running processes"""
599
+ """Handle 'ps' command to list running processes."""
601
600
  try:
602
601
  import requests
603
602
 
@@ -627,7 +626,7 @@ class ChatClient:
627
626
  console.print(f"[red]Error connecting to daemon: {e}[/red]")
628
627
 
629
628
  def handle_process_logs(self, process_id: str):
630
- """Handle 'logs' command to show process logs"""
629
+ """Handle 'logs' command to show process logs."""
631
630
  try:
632
631
  import requests
633
632
 
@@ -651,7 +650,7 @@ class ChatClient:
651
650
  console.print(f"[red]Error connecting to daemon: {e}[/red]")
652
651
 
653
652
  def handle_process_inspect(self, process_id: str):
654
- """Handle 'inspect' command to show detailed process info"""
653
+ """Handle 'inspect' command to show detailed process info."""
655
654
  try:
656
655
  import requests
657
656
 
@@ -682,7 +681,7 @@ class ChatClient:
682
681
  console.print(f"[red]Error connecting to daemon: {e}[/red]")
683
682
 
684
683
  def handle_process_stop(self, process_id: str):
685
- """Handle 'stop' command to stop a process"""
684
+ """Handle 'stop' command to stop a process."""
686
685
  try:
687
686
  import requests
688
687
 
@@ -699,7 +698,7 @@ class ChatClient:
699
698
  console.print(f"[red]Error connecting to daemon: {e}[/red]")
700
699
 
701
700
  def handle_process_start(self, process_id: str):
702
- """Handle 'start' command to start a process"""
701
+ """Handle 'start' command to start a process."""
703
702
  try:
704
703
  import requests
705
704
 
@@ -716,7 +715,7 @@ class ChatClient:
716
715
  console.print(f"[red]Error connecting to daemon: {e}[/red]")
717
716
 
718
717
  def handle_containerized_run(self, command: str, args: List[str]):
719
- """Handle 'run' command to execute in a containerized process"""
718
+ """Handle 'run' command to execute in a containerized process."""
720
719
  try:
721
720
  import requests
722
721
 
@@ -755,7 +754,7 @@ class ChatClient:
755
754
  )
756
755
  console.print("Use 'logs <id>' to view output or 'ps' to see status")
757
756
  else:
758
- console.print(f"[red]Failed to start containerized command[/red]")
757
+ console.print("[red]Failed to start containerized command[/red]")
759
758
  return
760
759
  except Exception:
761
760
  pass # Fall through to shell command execution
@@ -773,13 +772,13 @@ class ChatClient:
773
772
  )
774
773
  console.print("Use 'logs <id>' to view output or 'ps' to see status")
775
774
  else:
776
- console.print(f"[red]Failed to start containerized process[/red]")
775
+ console.print("[red]Failed to start containerized process[/red]")
777
776
 
778
777
  except Exception as e:
779
778
  console.print(f"[red]Error connecting to daemon: {e}[/red]")
780
779
 
781
780
  def _ensure_daemon_running(self):
782
- """Ensure the API daemon is running, start it if not"""
781
+ """Ensure the API daemon is running, start it if not."""
783
782
  try:
784
783
  if not self.daemon.is_running():
785
784
  console.print("[yellow]Starting MCLI daemon...[/yellow]")
@@ -813,7 +812,7 @@ class ChatClient:
813
812
  console.print("[yellow]Try starting manually: mcli workflow api-daemon start[/yellow]")
814
813
 
815
814
  def _pull_model_if_needed(self, model_name: str):
816
- """Pull the model from Ollama if it doesn't exist locally"""
815
+ """Pull the model from Ollama if it doesn't exist locally."""
817
816
  try:
818
817
  console.print(
819
818
  f"[yellow]Downloading model '{model_name}'. This may take a few minutes...[/yellow]"
@@ -844,7 +843,7 @@ class ChatClient:
844
843
  console.print(f"[red]❌ Error downloading model '{model_name}': {e}[/red]")
845
844
 
846
845
  def generate_llm_response(self, query: str):
847
- """Generate response using LLM integration"""
846
+ """Generate response using LLM integration."""
848
847
  try:
849
848
  # Try to get all commands, including inactive
850
849
  try:
@@ -858,7 +857,7 @@ class ChatClient:
858
857
  except Exception:
859
858
  commands = []
860
859
 
861
- command_context = (
860
+ _command_context = ( # noqa: F841
862
861
  "\n".join(
863
862
  f"Command: {cmd['name']}\nDescription: {cmd.get('description', '')}\nTags: {', '.join(cmd.get('tags', []))}\nStatus: {'INACTIVE' if not cmd.get('is_active', True) else 'ACTIVE'}"
864
863
  for cmd in commands
@@ -883,7 +882,7 @@ class ChatClient:
883
882
  )
884
883
 
885
884
  if is_creation_request:
886
- prompt = f"""{SYSTEM_PROMPT}
885
+ prompt = """{SYSTEM_PROMPT}
887
886
 
888
887
  IMPORTANT CONTEXT:
889
888
  - Available MCLI Commands: {command_context}
@@ -903,7 +902,7 @@ This is a command creation request. You must:
903
902
 
904
903
  NEVER suggest commands that don't exist. ALWAYS create new code for missing functionality."""
905
904
  else:
906
- prompt = f"""{SYSTEM_PROMPT}
905
+ prompt = """{SYSTEM_PROMPT}
907
906
 
908
907
  AVAILABLE MCLI COMMANDS:
909
908
  {command_context}
@@ -954,7 +953,6 @@ Respond naturally and helpfully, considering both MCLI commands and system contr
954
953
  content = response.get("response", "")
955
954
 
956
955
  # Clean up response like we do for OpenAI
957
- import re
958
956
 
959
957
  split_patterns = [
960
958
  r"\n2\.",
@@ -994,7 +992,6 @@ Respond naturally and helpfully, considering both MCLI commands and system contr
994
992
  },
995
993
  )
996
994
  content = response.get("response", "")
997
- import re
998
995
 
999
996
  split_patterns = [
1000
997
  r"\n2\.",
@@ -1034,7 +1031,6 @@ Respond naturally and helpfully, considering both MCLI commands and system contr
1034
1031
  },
1035
1032
  )
1036
1033
  content = response.get("response", "")
1037
- import re
1038
1034
 
1039
1035
  split_patterns = [
1040
1036
  r"\n2\.",
@@ -1059,7 +1055,7 @@ Respond naturally and helpfully, considering both MCLI commands and system contr
1059
1055
  else:
1060
1056
  raise Exception(f"Ollama API error: {e}")
1061
1057
 
1062
- except (requests.exceptions.ConnectionError, ollama.RequestError if OLLAMA_AVAILABLE else Exception): # type: ignore
1058
+ except (requests.exceptions.ConnectionError, ollama.RequestError if OLLAMA_AVAILABLE else Exception): # type: ignore # noqa: B030
1063
1059
  console.print(
1064
1060
  "[red]Could not connect to Ollama. Please ensure Ollama is running:[/red]"
1065
1061
  )
@@ -1072,7 +1068,7 @@ Respond naturally and helpfully, considering both MCLI commands and system contr
1072
1068
  "[yellow]Request timed out. The model might be processing a complex query.[/yellow]"
1073
1069
  )
1074
1070
  return
1075
- except Exception as api_exc:
1071
+ except Exception:
1076
1072
  raise
1077
1073
 
1078
1074
  elif LLM_PROVIDER == "openai":
@@ -1093,7 +1089,6 @@ Respond naturally and helpfully, considering both MCLI commands and system contr
1093
1089
  # Only print the first section (natural language answer) before any markdown/code block
1094
1090
  content = response.choices[0].message.content
1095
1091
  # Split on '```' or '2.' or 'Relevant commands' to avoid printing command/code blocks
1096
- import re
1097
1092
 
1098
1093
  # Try to split on numbered sections or code block
1099
1094
  split_patterns = [
@@ -1110,13 +1105,13 @@ Respond naturally and helpfully, considering both MCLI commands and system contr
1110
1105
  split_idx = min(split_idx, m.start())
1111
1106
  main_answer = content[:split_idx].strip()
1112
1107
  return console.print(main_answer)
1113
- except Exception as api_exc:
1108
+ except Exception:
1114
1109
  raise
1115
1110
 
1116
1111
  elif LLM_PROVIDER == "anthropic":
1117
1112
  from anthropic import Anthropic
1118
1113
 
1119
- api_key = config.get("anthropic_api_key", None)
1114
+ api_key = config.get("anthropic_api_key")
1120
1115
  client = Anthropic(api_key=api_key)
1121
1116
  try:
1122
1117
  response = client.messages.create(
@@ -1127,7 +1122,7 @@ Respond naturally and helpfully, considering both MCLI commands and system contr
1127
1122
  messages=[{"role": "user", "content": query}],
1128
1123
  )
1129
1124
  return console.print(response.content)
1130
- except Exception as api_exc:
1125
+ except Exception:
1131
1126
  raise
1132
1127
 
1133
1128
  else:
@@ -1158,9 +1153,7 @@ Respond naturally and helpfully, considering both MCLI commands and system contr
1158
1153
  r"\bhelp\s+me\s+create", # "help me create"
1159
1154
  ]
1160
1155
 
1161
- import re
1162
-
1163
- for pattern in creation_patterns:
1156
+ for pattern in creation_patterns: # noqa: SIM110
1164
1157
  if re.search(pattern, lower_input):
1165
1158
  return True
1166
1159
 
@@ -1208,7 +1201,6 @@ Respond naturally and helpfully, considering both MCLI commands and system contr
1208
1201
 
1209
1202
  def validate_and_correct_response(self, response_text: str, available_commands: list) -> str:
1210
1203
  """Validate AI response and correct any hallucinated commands."""
1211
- import re
1212
1204
 
1213
1205
  # Extract command names from available commands
1214
1206
  real_commands = set()
@@ -1276,9 +1268,6 @@ Respond naturally and helpfully, considering both MCLI commands and system contr
1276
1268
 
1277
1269
  def _create_complete_command(self, user_input: str):
1278
1270
  """Create a complete working command with full automation."""
1279
- import os
1280
- import re
1281
- from pathlib import Path
1282
1271
 
1283
1272
  console.print("[bold blue]🤖 Starting automated command creation...[/bold blue]")
1284
1273
  console.print()
@@ -1336,7 +1325,7 @@ Respond naturally and helpfully, considering both MCLI commands and system contr
1336
1325
  except Exception:
1337
1326
  commands = []
1338
1327
 
1339
- command_context = (
1328
+ _command_context = ( # noqa: F841
1340
1329
  "\n".join(
1341
1330
  f"Command: {cmd['name']}\nDescription: {cmd.get('description', '')}"
1342
1331
  for cmd in commands
@@ -1345,7 +1334,7 @@ Respond naturally and helpfully, considering both MCLI commands and system contr
1345
1334
  else "(No command context available)"
1346
1335
  )
1347
1336
 
1348
- prompt = f"""You are creating a complete MCLI command. Generate ONLY the Python code with this exact structure:
1337
+ prompt = """You are creating a complete MCLI command. Generate ONLY the Python code with this exact structure:
1349
1338
 
1350
1339
  COMMAND_NAME: [single word command name]
1351
1340
  FILENAME: [snake_case_filename.py]
@@ -1389,7 +1378,6 @@ Generate a working command that implements the requested functionality. Use prop
1389
1378
 
1390
1379
  def _parse_command_response(self, response: str) -> dict:
1391
1380
  """Parse AI response to extract command information."""
1392
- import re
1393
1381
 
1394
1382
  # Extract command name
1395
1383
  name_match = re.search(r"COMMAND_NAME:\s*([a-zA-Z_][a-zA-Z0-9_-]*)", response)
@@ -1422,7 +1410,6 @@ Generate a working command that implements the requested functionality. Use prop
1422
1410
 
1423
1411
  def _create_command_file(self, command_info: dict) -> str:
1424
1412
  """Create the command file in the appropriate directory."""
1425
- from pathlib import Path
1426
1413
 
1427
1414
  # Choose directory based on command type
1428
1415
  base_dir = Path(__file__).parent.parent.parent # mcli src directory
@@ -1457,7 +1444,7 @@ Generate a working command that implements the requested functionality. Use prop
1457
1444
  return False
1458
1445
 
1459
1446
  def is_system_control_request(self, user_input: str) -> bool:
1460
- """Check if user input is requesting system control functionality"""
1447
+ """Check if user input is requesting system control functionality."""
1461
1448
  lower_input = user_input.lower()
1462
1449
 
1463
1450
  # System control keywords
@@ -1547,9 +1534,7 @@ Generate a working command that implements the requested functionality. Use prop
1547
1534
  r"\bclear\s+(cache|system)", # "clear cache" or "clear system"
1548
1535
  ]
1549
1536
 
1550
- import re
1551
-
1552
- for pattern in system_patterns:
1537
+ for pattern in system_patterns: # noqa: SIM110
1553
1538
  if re.search(pattern, lower_input):
1554
1539
  return True
1555
1540
 
@@ -1557,7 +1542,7 @@ Generate a working command that implements the requested functionality. Use prop
1557
1542
  return any(keyword in lower_input for keyword in system_keywords)
1558
1543
 
1559
1544
  def handle_system_control(self, user_input: str):
1560
- """Handle system control requests with intelligent reasoning and suggestions"""
1545
+ """Handle system control requests with intelligent reasoning and suggestions."""
1561
1546
  try:
1562
1547
  console.print("[dim]🤖 Processing system control request...[/dim]")
1563
1548
 
@@ -1609,7 +1594,7 @@ Generate a working command that implements the requested functionality. Use prop
1609
1594
  console.print(" • 'Close TextEdit'")
1610
1595
 
1611
1596
  def _provide_intelligent_suggestions(self, user_input: str, result: dict):
1612
- """Provide intelligent suggestions based on system control results"""
1597
+ """Provide intelligent suggestions based on system control results."""
1613
1598
  try:
1614
1599
  lower_input = user_input.lower()
1615
1600
  data = result.get("data", {})
@@ -1630,12 +1615,12 @@ Generate a working command that implements the requested functionality. Use prop
1630
1615
  elif "time" in lower_input:
1631
1616
  self._suggest_time_actions(data)
1632
1617
 
1633
- except Exception as e:
1618
+ except Exception:
1634
1619
  # Don't let suggestion errors break the main flow
1635
1620
  pass
1636
1621
 
1637
1622
  def _suggest_disk_cleanup(self, disk_data: dict):
1638
- """Suggest disk cleanup actions based on usage"""
1623
+ """Suggest disk cleanup actions based on usage."""
1639
1624
  if not disk_data:
1640
1625
  return
1641
1626
 
@@ -1671,7 +1656,7 @@ Generate a working command that implements the requested functionality. Use prop
1671
1656
  console.print(f" {suggestion}")
1672
1657
 
1673
1658
  def _suggest_memory_optimization(self, memory_data: dict):
1674
- """Suggest memory optimization actions"""
1659
+ """Suggest memory optimization actions."""
1675
1660
  if not memory_data:
1676
1661
  return
1677
1662
 
@@ -1696,7 +1681,7 @@ Generate a working command that implements the requested functionality. Use prop
1696
1681
  console.print(f" {suggestion}")
1697
1682
 
1698
1683
  def _suggest_system_actions(self, system_data: dict):
1699
- """Suggest system-related actions"""
1684
+ """Suggest system-related actions."""
1700
1685
  if not system_data:
1701
1686
  return
1702
1687
 
@@ -1734,7 +1719,7 @@ Generate a working command that implements the requested functionality. Use prop
1734
1719
  console.print(f" {suggestion}")
1735
1720
 
1736
1721
  def _suggest_time_actions(self, time_data: dict):
1737
- """Suggest time-related actions"""
1722
+ """Suggest time-related actions."""
1738
1723
  if not time_data:
1739
1724
  return
1740
1725
 
@@ -1756,7 +1741,7 @@ Generate a working command that implements the requested functionality. Use prop
1756
1741
  elif 17 < hour < 22: # Evening
1757
1742
  suggestions.append("🌆 Good evening! Wrapping up for the day?")
1758
1743
 
1759
- except:
1744
+ except Exception:
1760
1745
  pass
1761
1746
 
1762
1747
  suggestions.append("I can also help you schedule tasks with the workflow system!")
@@ -1767,7 +1752,7 @@ Generate a working command that implements the requested functionality. Use prop
1767
1752
  console.print(f" {suggestion}")
1768
1753
 
1769
1754
  def _is_system_help_request(self, query: str) -> bool:
1770
- """Detect if this is a request for system help or cleanup"""
1755
+ """Detect if this is a request for system help or cleanup."""
1771
1756
  lower_query = query.lower()
1772
1757
 
1773
1758
  help_patterns = [
@@ -1788,16 +1773,14 @@ Generate a working command that implements the requested functionality. Use prop
1788
1773
  r"help me.*clean",
1789
1774
  ]
1790
1775
 
1791
- import re
1792
-
1793
- for pattern in help_patterns:
1776
+ for pattern in help_patterns: # noqa: SIM110
1794
1777
  if re.search(pattern, lower_query):
1795
1778
  return True
1796
1779
 
1797
1780
  return False
1798
1781
 
1799
1782
  def _handle_system_help_request(self, query: str):
1800
- """Handle requests for system help and cleanup"""
1783
+ """Handle requests for system help and cleanup."""
1801
1784
  lower_query = query.lower()
1802
1785
 
1803
1786
  console.print("[dim]🤖 I can definitely help you with system cleanup![/dim]")
@@ -1846,7 +1829,7 @@ Generate a working command that implements the requested functionality. Use prop
1846
1829
  )
1847
1830
 
1848
1831
  def _load_scheduled_jobs(self):
1849
- """Load and start monitoring existing scheduled jobs"""
1832
+ """Load and start monitoring existing scheduled jobs."""
1850
1833
  try:
1851
1834
  # Lazy import to avoid circular dependencies
1852
1835
  from mcli.workflow.scheduler.job import JobStatus
@@ -1863,12 +1846,12 @@ Generate a working command that implements the requested functionality. Use prop
1863
1846
  if active_count > 0:
1864
1847
  console.print(f"[dim]📅 {active_count} scheduled jobs loaded[/dim]")
1865
1848
 
1866
- except Exception as e:
1849
+ except Exception:
1867
1850
  # Silently handle import/loading errors at startup
1868
1851
  pass
1869
1852
 
1870
1853
  def _is_job_management_request(self, query: str) -> bool:
1871
- """Detect if this is a job/schedule management request"""
1854
+ """Detect if this is a job/schedule management request."""
1872
1855
  lower_query = query.lower()
1873
1856
 
1874
1857
  job_patterns = [
@@ -1901,16 +1884,14 @@ Generate a working command that implements the requested functionality. Use prop
1901
1884
  r".*completion.*",
1902
1885
  ]
1903
1886
 
1904
- import re
1905
-
1906
- for pattern in job_patterns:
1887
+ for pattern in job_patterns: # noqa: SIM110
1907
1888
  if re.search(pattern, lower_query):
1908
1889
  return True
1909
1890
 
1910
1891
  return False
1911
1892
 
1912
1893
  def _handle_job_management(self, query: str):
1913
- """Handle job scheduling and management requests"""
1894
+ """Handle job scheduling and management requests."""
1914
1895
  lower_query = query.lower()
1915
1896
 
1916
1897
  console.print("[dim]🤖 Processing job management request...[/dim]")
@@ -1982,12 +1963,13 @@ Generate a working command that implements the requested functionality. Use prop
1982
1963
  console.print(f"[red]❌ Error handling job request: {e}[/red]")
1983
1964
 
1984
1965
  def _show_agent_status(self):
1985
- """Show comprehensive agent status including jobs, system state, and context"""
1966
+ """Show comprehensive agent status including jobs, system state, and context."""
1986
1967
  console.print("\n[bold cyan]🤖 Personal Assistant Status Report[/bold cyan]")
1987
1968
 
1988
1969
  # Jobs and schedules
1989
1970
  try:
1990
- from mcli.workflow.scheduler.job import JobStatus, ScheduledJob
1971
+ from mcli.workflow.scheduler.job import JobStatus
1972
+ from mcli.workflow.scheduler.job import ScheduledJob as Job
1991
1973
  from mcli.workflow.scheduler.persistence import JobStorage
1992
1974
 
1993
1975
  job_storage = JobStorage()
@@ -2024,13 +2006,13 @@ Generate a working command that implements the requested functionality. Use prop
2024
2006
  elif status == JobStatus.FAILED.value:
2025
2007
  failed_jobs.append(job_dict)
2026
2008
 
2027
- except Exception as e:
2009
+ except Exception:
2028
2010
  jobs = []
2029
2011
  active_jobs = []
2030
2012
  completed_jobs = []
2031
2013
  failed_jobs = []
2032
2014
 
2033
- console.print(f"\n[green]📅 Scheduled Jobs:[/green]")
2015
+ console.print("\n[green]📅 Scheduled Jobs:[/green]")
2034
2016
  if active_jobs:
2035
2017
  for job_data in active_jobs[:5]: # Show first 5
2036
2018
  try:
@@ -2053,7 +2035,7 @@ Generate a working command that implements the requested functionality. Use prop
2053
2035
 
2054
2036
  # Recent activity
2055
2037
  if completed_jobs or failed_jobs:
2056
- console.print(f"\n[blue]📊 Recent Activity:[/blue]")
2038
+ console.print("\n[blue]📊 Recent Activity:[/blue]")
2057
2039
  if completed_jobs:
2058
2040
  console.print(f" ✅ {len(completed_jobs)} completed jobs")
2059
2041
  if failed_jobs:
@@ -2067,7 +2049,7 @@ Generate a working command that implements the requested functionality. Use prop
2067
2049
  memory_result = system_controller.get_memory_usage()
2068
2050
  disk_result = system_controller.get_disk_usage()
2069
2051
 
2070
- console.print(f"\n[yellow]💻 System Context:[/yellow]")
2052
+ console.print("\n[yellow]💻 System Context:[/yellow]")
2071
2053
 
2072
2054
  if memory_result.get("success"):
2073
2055
  mem_data = memory_result["data"]["virtual_memory"]
@@ -2086,10 +2068,10 @@ Generate a working command that implements the requested functionality. Use prop
2086
2068
  )
2087
2069
 
2088
2070
  except Exception:
2089
- console.print(f"\n[yellow]💻 System Context: Unable to get current status[/yellow]")
2071
+ console.print("\n[yellow]💻 System Context: Unable to get current status[/yellow]")
2090
2072
 
2091
2073
  # Agent capabilities reminder
2092
- console.print(f"\n[magenta]🛠️ I can help you with:[/magenta]")
2074
+ console.print("\n[magenta]🛠️ I can help you with:[/magenta]")
2093
2075
  console.print(" • System monitoring and cleanup")
2094
2076
  console.print(" • Application control and automation")
2095
2077
  console.print(" • Scheduled tasks and reminders")
@@ -2101,7 +2083,7 @@ Generate a working command that implements the requested functionality. Use prop
2101
2083
  )
2102
2084
 
2103
2085
  def _handle_job_scheduling(self, query: str):
2104
- """Handle requests to schedule new jobs"""
2086
+ """Handle requests to schedule new jobs."""
2105
2087
  console.print("[green]📅 Let me help you schedule that task![/green]")
2106
2088
 
2107
2089
  # For now, provide guidance on scheduling
@@ -2124,9 +2106,10 @@ Generate a working command that implements the requested functionality. Use prop
2124
2106
  )
2125
2107
 
2126
2108
  def _handle_job_cancellation(self, query: str):
2127
- """Handle requests to cancel jobs"""
2109
+ """Handle requests to cancel jobs."""
2128
2110
  try:
2129
2111
  from mcli.workflow.scheduler.job import JobStatus
2112
+ from mcli.workflow.scheduler.job import ScheduledJob as Job
2130
2113
  from mcli.workflow.scheduler.persistence import JobStorage
2131
2114
 
2132
2115
  job_storage = JobStorage()
@@ -2156,7 +2139,7 @@ Generate a working command that implements the requested functionality. Use prop
2156
2139
  console.print("\n[dim]To cancel a specific job, use: 'cancel job [name]'[/dim]")
2157
2140
 
2158
2141
  def _show_startup_status(self):
2159
- """Show proactive status update when assistant starts"""
2142
+ """Show proactive status update when assistant starts."""
2160
2143
  try:
2161
2144
  # Quick system check
2162
2145
  from mcli.chat.system_controller import system_controller
@@ -2215,11 +2198,11 @@ Generate a working command that implements the requested functionality. Use prop
2215
2198
  else:
2216
2199
  console.print("\n[green]🤖 All systems running smoothly![/green]")
2217
2200
 
2218
- except Exception as e:
2219
- console.print(f"\n[green]🤖 All systems running smoothly![/green]")
2201
+ except Exception:
2202
+ console.print("\n[green]🤖 All systems running smoothly![/green]")
2220
2203
 
2221
2204
  def _handle_cron_test(self, query: str):
2222
- """Handle cron test execution requests"""
2205
+ """Handle cron test execution requests."""
2223
2206
  console.print("[green]🕒 Running MCLI Cron Validation Test...[/green]")
2224
2207
 
2225
2208
  try:
@@ -2247,7 +2230,7 @@ Generate a working command that implements the requested functionality. Use prop
2247
2230
  # Show successful output
2248
2231
  console.print(result.stdout)
2249
2232
  else:
2250
- console.print(f"[red]❌ Cron test failed:[/red]")
2233
+ console.print("[red]❌ Cron test failed:[/red]")
2251
2234
  console.print(result.stderr if result.stderr else result.stdout)
2252
2235
 
2253
2236
  except subprocess.TimeoutExpired:
@@ -2258,7 +2241,7 @@ Generate a working command that implements the requested functionality. Use prop
2258
2241
  console.print(" mcli cron-test --quick --verbose")
2259
2242
 
2260
2243
  def _show_failed_jobs(self):
2261
- """Show detailed information about failed jobs"""
2244
+ """Show detailed information about failed jobs."""
2262
2245
  console.print("[red]❌ Analyzing Failed Jobs...[/red]")
2263
2246
 
2264
2247
  try:
@@ -2304,7 +2287,7 @@ Generate a working command that implements the requested functionality. Use prop
2304
2287
  console.print(f"\n[dim]... and {len(failed_jobs) - 10} more failed jobs[/dim]")
2305
2288
 
2306
2289
  # Show helpful actions
2307
- console.print(f"\n[cyan]💡 Recommended Actions:[/cyan]")
2290
+ console.print("\n[cyan]💡 Recommended Actions:[/cyan]")
2308
2291
  console.print("• Check job commands and file paths")
2309
2292
  console.print("• Verify system permissions")
2310
2293
  console.print("• Review error messages above")
@@ -2314,11 +2297,10 @@ Generate a working command that implements the requested functionality. Use prop
2314
2297
  console.print(f"[red]❌ Failed to analyze jobs: {e}[/red]")
2315
2298
 
2316
2299
  def _show_job_completion_details(self):
2317
- """Show comprehensive job completion analysis"""
2300
+ """Show comprehensive job completion analysis."""
2318
2301
  console.print("[blue]📊 Job Completion Analysis...[/blue]")
2319
2302
 
2320
2303
  try:
2321
- from datetime import datetime, timedelta
2322
2304
 
2323
2305
  from mcli.workflow.scheduler.job import JobStatus
2324
2306
  from mcli.workflow.scheduler.persistence import JobStorage
@@ -2348,7 +2330,7 @@ Generate a working command that implements the requested functionality. Use prop
2348
2330
  pending_jobs.append(job)
2349
2331
 
2350
2332
  # Status summary
2351
- console.print(f"\n[green]📈 Job Status Summary:[/green]")
2333
+ console.print("\n[green]📈 Job Status Summary:[/green]")
2352
2334
  console.print(f" ✅ Completed: {len(completed_jobs)}")
2353
2335
  console.print(f" 🔄 Running: {len(running_jobs)}")
2354
2336
  console.print(f" ❌ Failed: {len(failed_jobs)}")
@@ -2361,7 +2343,7 @@ Generate a working command that implements the requested functionality. Use prop
2361
2343
 
2362
2344
  if total_runs > 0:
2363
2345
  success_rate = total_successes / total_runs * 100
2364
- console.print(f"\n[cyan]⚡ Performance Metrics:[/cyan]")
2346
+ console.print("\n[cyan]⚡ Performance Metrics:[/cyan]")
2365
2347
  console.print(f" Total Executions: {total_runs}")
2366
2348
  console.print(f" Success Rate: {success_rate:.1f}%")
2367
2349
  console.print(f" Successful: {total_successes}")
@@ -2375,7 +2357,7 @@ Generate a working command that implements the requested functionality. Use prop
2375
2357
  )[:5]
2376
2358
 
2377
2359
  if recent_completed:
2378
- console.print(f"\n[green]🎯 Recent Completions:[/green]")
2360
+ console.print("\n[green]🎯 Recent Completions:[/green]")
2379
2361
  for job in recent_completed:
2380
2362
  runtime = (
2381
2363
  f" ({job.runtime_seconds:.2f}s)"
@@ -2391,12 +2373,12 @@ Generate a working command that implements the requested functionality. Use prop
2391
2373
  job_types[job_type] = job_types.get(job_type, 0) + 1
2392
2374
 
2393
2375
  if job_types:
2394
- console.print(f"\n[blue]📋 Job Types:[/blue]")
2376
+ console.print("\n[blue]📋 Job Types:[/blue]")
2395
2377
  for job_type, count in sorted(job_types.items()):
2396
2378
  console.print(f" {job_type}: {count} jobs")
2397
2379
 
2398
2380
  # Helpful commands
2399
- console.print(f"\n[yellow]🔧 Available Commands:[/yellow]")
2381
+ console.print("\n[yellow]🔧 Available Commands:[/yellow]")
2400
2382
  console.print("• 'show failed jobs' - Analyze job failures")
2401
2383
  console.print("• 'run cron test' - Validate cron system")
2402
2384
  console.print("• 'cancel job <name>' - Remove specific job")