main
py 139 lines 4.69 KB
Raw
1 import os
2 import json
3 from helpers import files
4 from helpers import subagents, extension
5 from helpers import yaml as yaml_helper
6 from helpers.print_style import PrintStyle
7
8
9 def startup_migration() -> None:
10 migrate_user_data()
11 convert_agents_json_yaml()
12
13 extension.call_extensions_sync("startup_migration", None)
14
15
16
17 def migrate_user_data() -> None:
18 """
19 Migrate user data from /tmp and other locations to /usr.
20 """
21
22 # --- Migrate Directories -------------------------------------------------------
23 # Move directories from tmp/ or other source locations to usr/
24
25 _move_dir("tmp/chats", "usr/chats")
26 _move_dir("tmp/scheduler", "usr/scheduler", overwrite=True)
27 _move_dir("tmp/uploads", "usr/uploads")
28 _move_dir("tmp/upload", "usr/upload")
29 _move_dir("tmp/downloads", "usr/downloads")
30 _move_dir("tmp/email", "usr/email")
31 _move_dir("knowledge/custom", "usr/knowledge", overwrite=True)
32
33 # --- Migrate Files -------------------------------------------------------------
34 # Move specific configuration files to usr/
35
36 _move_file("tmp/settings.json", "usr/settings.json")
37 _move_file("tmp/secrets.env", "usr/secrets.env")
38 _move_file(".env", "usr/.env", overwrite=True)
39
40 # --- Special Migration Cases ---------------------------------------------------
41
42 # Migrate Memory
43 _migrate_memory()
44
45 # Flatten default directories (knowledge/default -> knowledge/, etc.)
46 # We use _merge_dir_contents because we want to move the *contents* of default/
47 # into the parent directory, not move the default directory itself.
48 _merge_dir_contents("knowledge/default", "knowledge")
49
50 # --- Cleanup -------------------------------------------------------------------
51
52 # Remove obsolete directories after migration
53 _cleanup_obsolete()
54
55
56 def convert_agents_json_yaml() -> None:
57 for root in subagents.get_agents_roots():
58 rel_root = files.deabsolute_path(root)
59 for subdir in files.get_subdirectories(rel_root):
60 agent_yaml = os.path.join(rel_root, subdir, "agent.yaml")
61 if files.exists(agent_yaml):
62 continue
63
64 agent_json = os.path.join(rel_root, subdir, "agent.json")
65 if not files.exists(agent_json):
66 continue
67
68 try:
69 agent_obj = json.loads(files.read_file(agent_json))
70 files.write_file(agent_yaml, yaml_helper.dumps(agent_obj))
71 except Exception as e:
72 PrintStyle.error(f"Failed to convert {agent_json} to YAML", e)
73 continue
74
75 # --- Helper Functions ----------------------------------------------------------
76
77 def _move_dir(src: str, dst: str, overwrite: bool = False) -> None:
78 """
79 Move a directory from src to dst if src exists and dst does not.
80 """
81 if files.exists(src) and (not files.exists(dst) or overwrite):
82 PrintStyle().print(f"Migrating {src} to {dst}...")
83 if overwrite and files.exists(dst):
84 files.delete_dir(dst)
85 files.move_dir(src, dst)
86
87 def _move_file(src: str, dst: str, overwrite: bool = False) -> None:
88 """
89 Move a file from src to dst if src exists and dst does not.
90 """
91 if files.exists(src) and (not files.exists(dst) or overwrite):
92 PrintStyle().print(f"Migrating {src} to {dst}...")
93 files.move_file(src, dst)
94
95 def _migrate_memory(base_path: str = "memory") -> None:
96 """
97 Migrate memory subdirectories.
98 """
99 subdirs = files.get_subdirectories(base_path)
100 for subdir in subdirs:
101 if subdir == "embeddings":
102 # Special case: Embeddings
103 _move_dir("memory/embeddings", "tmp/memory/embeddings")
104 else:
105 # Move other memory items to usr/memory
106 dst = f"usr/memory/{subdir}"
107 _move_dir(f"memory/{subdir}", dst)
108
109 def _merge_dir_contents(src_parent: str, dst_parent: str) -> None:
110 """
111 Moves all items from src_parent to dst_parent.
112 Useful for flattening structures like 'knowledge/default/*' -> 'knowledge/*'.
113 """
114 if not files.exists(src_parent):
115 return
116
117 entries = files.list_files(src_parent)
118 for entry in entries:
119 src = f"{src_parent}/{entry}"
120 dst = f"{dst_parent}/{entry}"
121 abs_src = files.get_abs_path(src)
122 if os.path.isdir(abs_src):
123 _move_dir(src, dst)
124 elif os.path.isfile(abs_src):
125 _move_file(src, dst)
126
127 def _cleanup_obsolete() -> None:
128 """
129 Remove directories that are no longer needed.
130 """
131 to_remove = [
132 "knowledge/default",
133 "memory",
134 "logs",
135 ]
136 for path in to_remove:
137 if files.exists(path):
138 PrintStyle().print(f"Removing {path}...")
139 files.delete_dir(path)