-
Notifications
You must be signed in to change notification settings - Fork 19
feat: Implement Smart Cleanup and Disk Space Optimizer (#125) #295
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
aa17f57
bdfcccf
95215f7
dff2092
f7a5653
dc4143e
6ba1715
618e075
219b9e6
e010296
446f660
2ce6a4d
7660b3a
e30dc8e
28d8de7
ce9e51d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -38,8 +38,9 @@ | |
| validate_installation_id, | ||
| ValidationError | ||
| ) | ||
| # Import the new Notification Manager | ||
| # Import Notification Manager | ||
| from cortex.notification_manager import NotificationManager | ||
| from cortex.optimizer import CleanupOptimizer | ||
|
|
||
|
|
||
| class CortexCLI: | ||
|
|
@@ -112,10 +113,9 @@ | |
| sys.stdout.write('\r\033[K') | ||
| sys.stdout.flush() | ||
|
|
||
| # --- New Notification Method --- | ||
| # --- Notification Method --- | ||
| def notify(self, args): | ||
| """Handle notification commands""" | ||
| # Addressing CodeRabbit feedback: Handle missing subcommand gracefully | ||
| if not args.notify_action: | ||
| self._print_error("Please specify a subcommand (config/enable/disable/dnd/send)") | ||
| return 1 | ||
|
|
@@ -132,24 +132,21 @@ | |
|
|
||
| elif args.notify_action == 'enable': | ||
| mgr.config["enabled"] = True | ||
| # Addressing CodeRabbit feedback: Ideally should use a public method instead of private _save_config, | ||
| # but keeping as is for a simple fix (or adding a save method to NotificationManager would be best). | ||
| mgr._save_config() | ||
| mgr.save_config() | ||
| self._print_success("Notifications enabled") | ||
| return 0 | ||
|
|
||
| elif args.notify_action == 'disable': | ||
| mgr.config["enabled"] = False | ||
| mgr._save_config() | ||
| cx_print("Notifications disabled (Critical alerts will still show)", "warning") | ||
| mgr.save_config() | ||
| self._print_success("Notifications disabled (Critical alerts will still show)") | ||
| return 0 | ||
|
|
||
| elif args.notify_action == 'dnd': | ||
| if not args.start or not args.end: | ||
| self._print_error("Please provide start and end times (HH:MM)") | ||
| return 1 | ||
|
|
||
| # Addressing CodeRabbit feedback: Add time format validation | ||
| try: | ||
| datetime.strptime(args.start, "%H:%M") | ||
| datetime.strptime(args.end, "%H:%M") | ||
|
|
@@ -159,7 +156,7 @@ | |
|
|
||
| mgr.config["dnd_start"] = args.start | ||
| mgr.config["dnd_end"] = args.end | ||
| mgr._save_config() | ||
| mgr.save_config() | ||
| self._print_success(f"DND Window updated: {args.start} - {args.end}") | ||
| return 0 | ||
|
|
||
|
|
@@ -174,7 +171,99 @@ | |
| else: | ||
| self._print_error("Unknown notify command") | ||
| return 1 | ||
| # ------------------------------- | ||
|
|
||
|
|
||
| def cleanup(self, args): | ||
| """Run system cleanup optimization""" | ||
| optimizer = CleanupOptimizer() | ||
|
|
||
| if args.cleanup_action == 'scan': | ||
| return self._cleanup_scan(optimizer) | ||
|
|
||
| elif args.cleanup_action == 'run': | ||
| return self._cleanup_run(args, optimizer) | ||
|
|
||
| else: | ||
| self._print_error("Unknown cleanup action") | ||
| return 1 | ||
|
|
||
| def _cleanup_scan(self, optimizer): | ||
|
Check failure on line 190 in cortex/cli.py
|
||
| self._print_status("🔍", "Scanning for cleanup opportunities...") | ||
| opportunities = optimizer.scan() | ||
|
|
||
| if not opportunities: | ||
| self._print_success("No cleanup opportunities found! system is clean.") | ||
| return 0 | ||
|
|
||
| total_bytes = sum(o.size_bytes for o in opportunities) | ||
| total_mb = total_bytes / (1024 * 1024) | ||
|
|
||
| console.print() | ||
| cx_header(f"Cleanup Scan Results ({total_mb:.1f} MB Reclaimable)") | ||
|
|
||
| from rich.table import Table | ||
| table = Table(box=None) | ||
| table.add_column("Type", style="cyan") | ||
| table.add_column("Description") | ||
| table.add_column("Size", justify="right", style="green") | ||
|
|
||
| for opp in opportunities: | ||
| size_mb = opp.size_bytes / (1024 * 1024) | ||
| table.add_row( | ||
| opp.type.replace('_', ' ').title(), | ||
| opp.description, | ||
| f"{size_mb:.1f} MB" | ||
| ) | ||
|
|
||
| console.print(table) | ||
| console.print() | ||
| console.print("[dim]Run 'cortex cleanup run' to clean these items.[/dim]") | ||
| return 0 | ||
|
|
||
| def _cleanup_run(self, args, optimizer): | ||
| safe_mode = not args.force | ||
|
|
||
| self._print_status("🔍", "Preparing cleanup plan...") | ||
| commands = optimizer.get_cleanup_plan() | ||
|
|
||
| if not commands: | ||
| self._print_success("Nothing to clean!") | ||
| return 0 | ||
|
|
||
| console.print("[bold]Proposed Cleanup Operations:[/bold]") | ||
| for i, cmd in enumerate(commands, 1): | ||
| console.print(f" {i}. {cmd}") | ||
|
|
||
| if getattr(args, 'dry_run', False): | ||
| console.print("\n[dim](Dry run mode - no changes made)[/dim]") | ||
| return 0 | ||
|
|
||
| if not args.yes: | ||
| if not safe_mode: | ||
| console.print("\n[bold red]WARNING: Running in FORCE mode (no backups)[/bold red]") | ||
|
|
||
| confirm = input("\nProceed with cleanup? (y/n): ") | ||
| if confirm.lower() != 'y': | ||
| print("Operation cancelled.") | ||
| return 0 | ||
|
|
||
| # Use InstallationCoordinator for execution | ||
| def progress_callback(current, total, step): | ||
| print(f"[{current}/{total}] {step.description}") | ||
|
|
||
| coordinator = InstallationCoordinator( | ||
| commands=commands, | ||
| descriptions=[f"Cleanup Step {i+1}" for i in range(len(commands))], | ||
| progress_callback=progress_callback | ||
| ) | ||
|
|
||
| result = coordinator.execute() | ||
| if result.success: | ||
| self._print_success("Cleanup completed successfully!") | ||
| return 0 | ||
| else: | ||
| self._print_error("Cleanup encountered errors.") | ||
| return 1 | ||
|
|
||
|
Comment on lines
+176
to
267
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add type hints for new CLI entrypoints (per guidelines). 🧰 Tools🪛 GitHub Check: SonarCloud Code Analysis[failure] 190-190: Refactor this method to not always return the same value. 🤖 Prompt for AI Agents |
||
| def install(self, software: str, execute: bool = False, dry_run: bool = False): | ||
| # Validate input first | ||
|
|
@@ -543,7 +632,7 @@ | |
| table.add_row("install <pkg>", "Install software") | ||
| table.add_row("history", "View history") | ||
| table.add_row("rollback <id>", "Undo installation") | ||
| table.add_row("notify", "Manage desktop notifications") # Added this line | ||
| table.add_row("notify", "Manage desktop notifications") | ||
|
|
||
| console.print(table) | ||
| console.print() | ||
|
|
@@ -598,7 +687,7 @@ | |
| edit_pref_parser.add_argument('key', nargs='?') | ||
| edit_pref_parser.add_argument('value', nargs='?') | ||
|
|
||
| # --- New Notify Command --- | ||
| # --- Notify Command --- | ||
| notify_parser = subparsers.add_parser('notify', help='Manage desktop notifications') | ||
| notify_subs = notify_parser.add_subparsers(dest='notify_action', help='Notify actions') | ||
|
|
||
|
|
@@ -615,6 +704,19 @@ | |
| send_parser.add_argument('--title', default='Cortex Notification') | ||
| send_parser.add_argument('--level', choices=['low', 'normal', 'critical'], default='normal') | ||
| send_parser.add_argument('--actions', nargs='*', help='Action buttons') | ||
|
|
||
|
|
||
| # --- Cleanup Command --- | ||
| cleanup_parser = subparsers.add_parser('cleanup', help='Optimize disk space') | ||
| cleanup_subs = cleanup_parser.add_subparsers(dest='cleanup_action', help='Cleanup actions') | ||
|
|
||
| cleanup_subs.add_parser('scan', help='Scan for cleanable items') | ||
|
|
||
| run_parser = cleanup_subs.add_parser('run', help='Execute cleanup') | ||
| run_parser.add_argument('--safe', action='store_true', default=True, help='Run safely (with backups)') | ||
| run_parser.add_argument('--force', action='store_true', help='Force cleanup (no backups)') | ||
| run_parser.add_argument('--yes', '-y', action='store_true', help='Skip confirmation') | ||
| run_parser.add_argument('--dry-run', action='store_true', help='Show proposed changes without executing') | ||
| # -------------------------- | ||
|
|
||
| args = parser.parse_args() | ||
|
|
@@ -642,9 +744,12 @@ | |
| return cli.check_pref(key=args.key) | ||
| elif args.command == 'edit-pref': | ||
| return cli.edit_pref(action=args.action, key=args.key, value=args.value) | ||
| # Handle the new notify command | ||
| elif args.command == 'notify': | ||
| return cli.notify(args) | ||
| # Handle new command | ||
|
|
||
| elif args.command == 'cleanup': | ||
| return cli.cleanup(args) | ||
| else: | ||
| parser.print_help() | ||
| return 1 | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: cortexlinux/cortex
Length of output: 77
🏁 Script executed:
Repository: cortexlinux/cortex
Length of output: 81
🏁 Script executed:
Repository: cortexlinux/cortex
Length of output: 1751
🏁 Script executed:
Repository: cortexlinux/cortex
Length of output: 3040
🏁 Script executed:
Repository: cortexlinux/cortex
Length of output: 83
🏁 Script executed:
Repository: cortexlinux/cortex
Length of output: 87
🏁 Script executed:
Repository: cortexlinux/cortex
Length of output: 10005
🏁 Script executed:
Repository: cortexlinux/cortex
Length of output: 85
🏁 Script executed:
Repository: cortexlinux/cortex
Length of output: 89
🏁 Script executed:
grep -n "class InstallationCoordinator\|def execute" ./cortex/coordinator.pyRepository: cortexlinux/cortex
Length of output: 144
🏁 Script executed:
Repository: cortexlinux/cortex
Length of output: 2462
🏁 Script executed:
Repository: cortexlinux/cortex
Length of output: 3819
🏁 Script executed:
grep -n "_rollback\|def.*backup" ./cortex/coordinator.pyRepository: cortexlinux/cortex
Length of output: 625
🏁 Script executed:
Repository: cortexlinux/cortex
Length of output: 953
🏁 Script executed:
Repository: cortexlinux/cortex
Length of output: 562
🏁 Script executed:
Repository: cortexlinux/cortex
Length of output: 44
safe_modeonly affects messaging; ensure it controls actual backup/undo behavior.The variable is set but never passed to
optimizer.get_cleanup_plan()orInstallationCoordinator, and the warning message on line 243 claims "no backups" in force mode, yet no backup logic is invoked in this execution flow. Either passsafe_modeto enable the coordinator'senable_rollbackparameter when in safe mode, or implement explicit backup creation before cleanup commands execute.🤖 Prompt for AI Agents