""" Resume Command for Skill Seekers Allows users to resume interrupted scraping jobs from saved progress. """ import argparse import sys from .config_manager import get_config_manager def list_resumable_jobs(): """List all resumable jobs with details.""" config = get_config_manager() jobs = config.list_resumable_jobs() if not jobs: print("\n๐Ÿ“ฆ No resumable jobs found.\n") print("Jobs are automatically saved when:") print(" โ€ข You interrupt a scraping operation (Ctrl+C)") print(" โ€ข A rate limit is reached") print(" โ€ข An error occurs during scraping\n") return print(f"\n๐Ÿ“ฆ Resumable Jobs ({len(jobs)} available):\n") for idx, job in enumerate(jobs, 1): job_id = job["job_id"] started = job.get("started_at", "Unknown") command = job.get("command", "Unknown") progress = job.get("progress", {}) last_updated = job.get("last_updated", "Unknown") print(f"{idx}. Job ID: {job_id}") print(f" Started: {started}") print(f" Command: {command}") if progress: phase = progress.get("phase", "Unknown") files_processed = progress.get("files_processed", 0) files_total = progress.get("files_total", 0) print(f" Progress: {phase}") if files_total > 0: percentage = (files_processed / files_total) * 100 print(f" Files: {files_processed}/{files_total} ({percentage:.1f}%)") print(f" Last updated: {last_updated}") print() print("To resume a job:") print(" $ skill-seekers resume \n") def resume_job(job_id: str): """Resume a specific job.""" config = get_config_manager() print(f"\n๐Ÿ”„ Resuming job: {job_id}\n") # Load progress progress = config.load_progress(job_id) if not progress: print(f"โŒ Job '{job_id}' not found or cannot be resumed.\n") print("Use 'skill-seekers resume --list' to see available jobs.\n") return 1 if not progress.get("can_resume", False): print(f"โŒ Job '{job_id}' is not marked as resumable.\n") return 1 # Extract job details command = progress.get("command", "") _job_config = progress.get("config", {}) checkpoint = progress.get("progress", {}).get("last_checkpoint") print(f"Original command: {command}") print(f"Last checkpoint: {checkpoint or 'Unknown'}") print() # Reconstruct command if "github" in command: print("๐Ÿ“Œ Resuming GitHub scraping...") print("โš ๏ธ Note: GitHub resume feature not yet implemented") print(" You can re-run the original command - it will use cached data where available.\n") print(f" Command: {command}\n") return 1 elif "scrape" in command: print("๐Ÿ“Œ Resuming documentation scraping...") print("โš ๏ธ Note: Documentation scraping resume feature not yet implemented") print(" You can re-run the original command - it will use cached data where available.\n") print(f" Command: {command}\n") return 1 elif "unified" in command: print("๐Ÿ“Œ Resuming unified scraping...") print("โš ๏ธ Note: Unified scraping resume feature not yet implemented") print(" You can re-run the original command - it will use cached data where available.\n") print(f" Command: {command}\n") return 1 else: print("โŒ Unknown job type. Cannot resume.\n") return 1 def clean_old_jobs(): """Clean up old progress files.""" config = get_config_manager() print("\n๐Ÿงน Cleaning up old progress files...\n") jobs_before = len(config.list_resumable_jobs()) config.cleanup_old_progress() jobs_after = len(config.list_resumable_jobs()) deleted = jobs_before - jobs_after if deleted > 0: print(f"โœ… Deleted {deleted} old job(s)") else: print("โœ… No old jobs to clean up") if jobs_after > 0: print(f"๐Ÿ“ฆ {jobs_after} job(s) remaining\n") else: print() def main(): """Main entry point for resume command.""" parser = argparse.ArgumentParser(description="Resume interrupted Skill Seekers jobs") parser.add_argument("job_id", nargs="?", help="Job ID to resume") parser.add_argument("--list", action="store_true", help="List all resumable jobs") parser.add_argument("--clean", action="store_true", help="Clean up old progress files") args = parser.parse_args() # Handle options if args.list: list_resumable_jobs() return 0 if args.clean: clean_old_jobs() return 0 if not args.job_id: print("\nโŒ Error: Job ID required or use --list to see available jobs\n") parser.print_help() return 1 return resume_job(args.job_id) if __name__ == "__main__": sys.exit(main())