File size: 5,303 Bytes
14f6b4f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#!/usr/bin/env python3

import asyncio
import argparse
import logging
import os
import sys
from integration_orchestrator import RepairOrchestrator
from repair_loop_engine import RepairLoopEngine, LoopConfig
from auto_repair_executor import AutoRepairExecutor
from rollback_manager import RollbackManager
from data_models import SpaceInfo, SpaceStatus
from datetime import datetime


def setup_logging(level: str = "INFO"):
    logging.basicConfig(
        level=getattr(logging, level.upper()),
        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
        handlers=[
            logging.StreamHandler(sys.stdout),
            logging.FileHandler('hf_repair_system.log')
        ]
    )


async def start_monitoring(spaces: list, config: LoopConfig):
    logger = logging.getLogger(__name__)
    
    hf_client = None
    repair_executor = AutoRepairExecutor(hf_client, repo_path=".")
    rollback_manager = RollbackManager()
    loop_engine = RepairLoopEngine(repair_executor, config)
    orchestrator = RepairOrchestrator(hf_client)
    orchestrator.set_components(repair_executor, loop_engine, rollback_manager)
    
    for space_id in spaces:
        space_info = SpaceInfo(
            space_id=space_id,
            name=space_id.split('/')[-1],
            repository_url=f"https://huggingface.co/spaces/{space_id}",
            current_status=SpaceStatus.RUNNING,
            last_updated=datetime.now()
        )
        loop_engine.add_space(space_info)
        logger.info(f"Added monitoring for Space: {space_id}")
    
    await orchestrator.start_monitoring()
    logger.info("Repair system monitoring started")
    
    try:
        while True:
            await asyncio.sleep(60)
            stats = orchestrator.get_orchestrator_stats()
            logger.info(f"System stats: {stats}")
    except KeyboardInterrupt:
        logger.info("Received interrupt signal")
    finally:
        await orchestrator.stop_monitoring()
        logger.info("Repair system monitoring stopped")


async def repair_single_space(space_id: str, dry_run: bool = False):
    logger = logging.getLogger(__name__)
    hf_client = None
    orchestrator = RepairOrchestrator(hf_client)
    
    logger.info(f"Starting repair for Space: {space_id}")
    
    if dry_run:
        logger.info("DRY RUN: Would analyze and plan repair, but not execute")
        return
    
    logger.info("Repair functionality requires full system setup")


def validate_spaces(spaces: list) -> bool:
    for space_id in spaces:
        if '/' not in space_id or len(space_id.split('/')) != 2:
            print(f"Invalid Space ID format: {space_id}")
            print("Expected format: username/space-name")
            return False
    return True


def main():
    parser = argparse.ArgumentParser(
        description="HuggingFace Spaces 自动修复系统",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="示例:\n  # 监控模式\n  python start_system.py --monitor user/space1 user/space2\n  \n  # 修复单个 Space\n  python start_system.py --repair user/space1\n  \n  # 试运行\n  python start_system.py --repair user/space1 --dry-run"
    )
    
    mode_group = parser.add_mutually_exclusive_group(required=True)
    mode_group.add_argument('--monitor', nargs='+', metavar='SPACE', help='监控指定的 Spaces')
    mode_group.add_argument('--repair', metavar='SPACE', help='修复指定的 Space')
    
    parser.add_argument('--max-attempts', type=int, default=5, help='最大修复尝试次数')
    parser.add_argument('--timeout', type=int, default=60, help='超时时间(分钟)')
    parser.add_argument('--check-interval', type=int, default=60, help='检查间隔(秒)')
    parser.add_argument('--max-concurrent', type=int, default=3, help='最大并发修复数')
    parser.add_argument('--log-level', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR'], default='INFO', help='日志级别')
    parser.add_argument('--dry-run', action='store_true', help='试运行模式')
    parser.add_argument('--version', action='version', version='%(prog)s 1.0.0')
    
    args = parser.parse_args()
    
    setup_logging(args.log_level)
    logger = logging.getLogger(__name__)
    
    if not os.getenv('HF_TOKEN') and not args.dry_run:
        logger.error("HF_TOKEN environment variable is required")
        sys.exit(1)
    
    try:
        if args.monitor:
            if not validate_spaces(args.monitor):
                sys.exit(1)
            
            config = LoopConfig(
                max_iterations=args.max_attempts,
                timeout_minutes=args.timeout,
                check_interval_seconds=args.check_interval,
                max_concurrent_repairs=args.max_concurrent
            )
            
            logger.info(f"Starting monitoring for {len(args.monitor)} spaces")
            asyncio.run(start_monitoring(args.monitor, config))
            
        elif args.repair:
            if not validate_spaces([args.repair]):
                sys.exit(1)
            
            asyncio.run(repair_single_space(args.repair, args.dry_run))
    
    except KeyboardInterrupt:
        sys.exit(0)
    except Exception as e:
        logger.error(f"Fatal error: {e}")
        sys.exit(1)


if __name__ == "__main__":
    main()