20
20
from .. import generation
21
21
from ..utils import open_json_file , term_color , is_snake_case
22
22
23
+ created_files = []
24
+ created_dirs = []
23
25
24
- def init_project_builder (slug_name : Optional [str ] = None , template : Optional [str ] = None , use_wizard : bool = False ):
25
- if slug_name and not is_snake_case (slug_name ):
26
- print (term_color ("Project name must be snake case" , 'red' ))
27
- return
26
+ def rollback_actions ():
27
+ for file in created_files :
28
+ if os .path .exists (file ):
29
+ os .remove (file )
30
+ for dir in created_dirs :
31
+ if os .path .exists (dir ):
32
+ shutil .rmtree (dir )
28
33
29
- if template is not None and use_wizard :
30
- print (term_color ("Template and wizard flags cannot be used together" , 'red' ))
31
- return
32
-
33
- template_data = None
34
- if template is not None :
35
- url_start = "https://"
36
- if template [:len (url_start )] == url_start :
37
- # template is a url
38
- response = requests .get (template )
39
- if response .status_code == 200 :
40
- template_data = response .json ()
41
- else :
42
- print (term_color (f"Failed to fetch template data from { template } . Status code: { response .status_code } " , 'red' ))
43
- sys .exit (1 )
44
- else :
45
- with importlib .resources .path ('agentstack.templates.proj_templates' , f'{ template } .json' ) as template_path :
46
- if template_path is None :
47
- print (term_color (f"No such template { template } found" , 'red' ))
34
+ def init_project_builder (slug_name : Optional [str ] = None , template : Optional [str ] = None , use_wizard : bool = False ):
35
+ try :
36
+ if slug_name and not is_snake_case (slug_name ):
37
+ print (term_color ("Project name must be snake case" , 'red' ))
38
+ return
39
+
40
+ if template is not None and use_wizard :
41
+ print (term_color ("Template and wizard flags cannot be used together" , 'red' ))
42
+ return
43
+
44
+ template_data = None
45
+ if template is not None :
46
+ url_start = "https://"
47
+ if template [:len (url_start )] == url_start :
48
+ # template is a url
49
+ response = requests .get (template )
50
+ if response .status_code == 200 :
51
+ template_data = response .json ()
52
+ else :
53
+ print (term_color (f"Failed to fetch template data from { template } . Status code: { response .status_code } " , 'red' ))
48
54
sys .exit (1 )
49
- template_data = open_json_file (template_path )
50
-
51
- if template_data :
52
- project_details = {
53
- "name" : slug_name or template_data ['name' ],
54
- "version" : "0.0.1" ,
55
- "description" : template_data ['description' ],
56
- "author" : "Name <Email>" ,
57
- "license" : "MIT"
58
- }
59
- framework = template_data ['framework' ]
60
- design = {
61
- 'agents' : template_data ['agents' ],
62
- 'tasks' : template_data ['tasks' ]
63
- }
64
-
65
- tools = template_data ['tools' ]
66
-
67
- elif use_wizard :
68
- welcome_message ()
69
- project_details = ask_project_details (slug_name )
70
- welcome_message ()
71
- framework = ask_framework ()
72
- design = ask_design ()
73
- tools = ask_tools ()
74
-
75
- else :
76
- welcome_message ()
77
- project_details = {
78
- "name" : slug_name or "agentstack_project" ,
79
- "version" : "0.0.1" ,
80
- "description" : "New agentstack project" ,
81
- "author" : "Name <Email>" ,
82
- "license" : "MIT"
83
- }
84
-
85
- framework = "CrewAI" # TODO: if --no-wizard, require a framework flag
86
-
87
- design = {
88
- 'agents' : [],
89
- 'tasks' : []
90
- }
91
-
92
- tools = []
93
-
94
- log .debug (
95
- f"project_details: { project_details } "
96
- f"framework: { framework } "
97
- f"design: { design } "
98
- )
99
- insert_template (project_details , framework , design , template_data )
100
- for tool_data in tools :
101
- generation .add_tool (tool_data ['name' ], agents = tool_data ['agents' ], path = project_details ['name' ])
55
+ else :
56
+ with importlib .resources .path ('agentstack.templates.proj_templates' , f'{ template } .json' ) as template_path :
57
+ if template_path is None :
58
+ print (term_color (f"No such template { template } found" , 'red' ))
59
+ sys .exit (1 )
60
+ template_data = open_json_file (template_path )
61
+
62
+ if template_data :
63
+ project_details = {
64
+ "name" : slug_name or template_data ['name' ],
65
+ "version" : "0.0.1" ,
66
+ "description" : template_data ['description' ],
67
+ "author" : "Name <Email>" ,
68
+ "license" : "MIT"
69
+ }
70
+ framework = template_data ['framework' ]
71
+ design = {
72
+ 'agents' : template_data ['agents' ],
73
+ 'tasks' : template_data ['tasks' ]
74
+ }
75
+
76
+ tools = template_data ['tools' ]
77
+
78
+ elif use_wizard :
79
+ welcome_message ()
80
+ project_details = ask_project_details (slug_name )
81
+ welcome_message ()
82
+ framework = ask_framework ()
83
+ design = ask_design ()
84
+ tools = ask_tools ()
102
85
86
+ else :
87
+ welcome_message ()
88
+ project_details = {
89
+ "name" : slug_name or "agentstack_project" ,
90
+ "version" : "0.0.1" ,
91
+ "description" : "New agentstack project" ,
92
+ "author" : "Name <Email>" ,
93
+ "license" : "MIT"
94
+ }
95
+
96
+ framework = "CrewAI" # TODO: if --no-wizard, require a framework flag
97
+
98
+ design = {
99
+ 'agents' : [],
100
+ 'tasks' : []
101
+ }
102
+
103
+ tools = []
104
+
105
+ log .debug (
106
+ f"project_details: { project_details } "
107
+ f"framework: { framework } "
108
+ f"design: { design } "
109
+ )
110
+ insert_template (project_details , framework , design , template_data )
111
+ for tool_data in tools :
112
+ generation .add_tool (tool_data ['name' ], agents = tool_data ['agents' ], path = project_details ['name' ])
113
+ except Exception as e :
114
+ print (term_color (f"An error occurred: { e } " , 'red' ))
115
+ rollback_actions ()
116
+ sys .exit (1 )
103
117
104
118
def welcome_message ():
105
119
os .system ("cls" if os .name == "nt" else "clear" )
@@ -323,17 +337,20 @@ def insert_template(project_details: dict, framework_name: str, design: dict, te
323
337
template_path = get_package_path () / f'templates/{ framework .name } '
324
338
with open (f"{ template_path } /cookiecutter.json" , "w" ) as json_file :
325
339
json .dump (cookiecutter_data .to_dict (), json_file )
340
+ created_files .append (f"{ template_path } /cookiecutter.json" )
326
341
327
342
# copy .env.example to .env
328
343
shutil .copy (
329
344
f'{ template_path } /{ "{{cookiecutter.project_metadata.project_slug}}" } /.env.example' ,
330
345
f'{ template_path } /{ "{{cookiecutter.project_metadata.project_slug}}" } /.env' )
346
+ created_files .append (f'{ template_path } /{ "{{cookiecutter.project_metadata.project_slug}}" } /.env' )
331
347
332
348
if os .path .isdir (project_details ['name' ]):
333
349
print (term_color (f"Directory { template_path } already exists. Please check this and try again" , "red" ))
334
350
return
335
351
336
352
cookiecutter (str (template_path ), no_input = True , extra_context = None )
353
+ created_dirs .append (project_details ['name' ])
337
354
338
355
# TODO: inits a git repo in the directory the command was run in
339
356
# TODO: not where the project is generated. Fix this
@@ -378,4 +395,4 @@ def list_tools():
378
395
print (f": { tool .url if tool .url else 'AgentStack default tool' } " )
379
396
380
397
print ("\n \n ✨ Add a tool with: agentstack tools add <tool_name>" )
381
- print (" https://docs.agentstack.sh/tools/core" )
398
+ print (" https://docs.agentstack.sh/tools/core" )
0 commit comments