-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcli_sync.py
More file actions
125 lines (110 loc) · 4.06 KB
/
cli_sync.py
File metadata and controls
125 lines (110 loc) · 4.06 KB
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
import argparse
import queue
import sys
from pathlib import Path
# [Created] by LLM model | 2025-11-13_01
"""
CLI wrapper for headless operation of the sync engine.
Usage:
python cli_sync.py folder1 folder2 [folder3 ...]
This script:
- Loads configuration via load_config()
- Validates provided folders contain a .roo directory
- Creates a SyncEngine with a Queue for events
- Runs a synchronous sync via engine.run_sync(folders)
- Prints basic progress events from the event queue to stdout
"""
from utils_sync.sync_core import SyncEngine
from utils_sync.config_sync import load_config
from utils_sync.file_path_utils import has_roo_dir
from utils_sync.progress_events import EventType, ProgressEvent
def _print_event(event: ProgressEvent) -> None:
"""Print a concise, human-readable representation of a ProgressEvent."""
et = event.event_type
if et == EventType.SCAN_START:
print(f"[SCAN_START] {event.folder} - {event.message}")
elif et == EventType.SCAN_FILE:
print(f"[SCAN_FILE] {event.folder}: {event.file_path}")
elif et == EventType.COPY:
print(f"[COPY] {event.file_path} - {event.message}")
elif et == EventType.SKIP:
print(f"[SKIP] {event.file_path} - {event.message}")
elif et == EventType.ERROR:
print(f"[ERROR] {event.message}")
elif et == EventType.COMPLETE:
print(f"[COMPLETE] {event.message}")
else:
# Generic fallback
print(f"[{et}] {event.message}")
def run_cli_sync(folders):
# [Created-or-Modified] by LLM model | 2025-11-13_01
"""
Run a synchronous CLI-based sync operation.
Args:
folders: iterable of folder paths (str or Path)
"""
# Normalize folder paths to Path objects
folders = [Path(f) for f in folders]
# Load configuration
config = load_config(args.config)
# Validate number of folders
if len(folders) < 2:
print("Error: At least two folders must be provided for sync.", file=sys.stderr)
sys.exit(1)
# Ensure each folder has a .roo directory (create if missing)
created = []
for f in folders:
try:
if not has_roo_dir(f):
# create .roo directory for new projects
from utils_sync import file_path_utils
file_path_utils.ensure_roo_dir(f)
created.append(str(f))
except Exception as exc:
print(f"Error: Could not ensure .roo subdirectory in {f}: {exc}", file=sys.stderr)
sys.exit(1)
if created:
print("Created missing .roo directories in:\n" + "\n".join(created))
# Create event queue and engine
event_queue = queue.Queue()
engine = SyncEngine(config, event_queue)
# Run synchronous sync operation
try:
engine.run_sync(folders)
except AttributeError:
# In case SyncEngine exposes only scan/plan/execute, try the sequence
try:
file_index = engine.scan_folders(folders)
actions = engine.plan_actions(file_index, scanned_folders=folders)
engine.execute_actions(actions)
except Exception as e:
print(f"Sync failed: {e}", file=sys.stderr)
sys.exit(2)
except Exception as e:
print(f"Sync failed: {e}", file=sys.stderr)
sys.exit(2)
# After run_sync completes, drain and print remaining events
while not event_queue.empty():
event = event_queue.get()
try:
_print_event(event)
except Exception:
# Best-effort printing
print(f"[EVENT] {getattr(event, 'message', repr(event))}")
def _parse_args():
p = argparse.ArgumentParser(
description="Headless CLI wrapper for the AgentAutoFlow sync engine."
)
p.add_argument(
"folders",
nargs="+",
help="Folders to synchronize (must contain a .roo subdirectory)"
)
p.add_argument(
"--config",
help="Path to config file (optional, defaults to config.txt or AgentAutoFlow_CONFIG env var)"
)
return p.parse_args()
if __name__ == "__main__":
args = _parse_args()
run_cli_sync(args.folders)