1515from cookiecutter .main import cookiecutter
1616from dotenv import load_dotenv
1717import subprocess
18+ from packaging .metadata import Metadata
1819
1920from .agentstack_data import (
2021 FrameworkData ,
2526from agentstack .logger import log
2627from agentstack .utils import get_package_path
2728from agentstack .tools import get_all_tools
28- from agentstack .generation .files import ConfigFile
29+ from agentstack .generation .files import ConfigFile , ProjectFile
2930from agentstack import frameworks
3031from agentstack import packaging
3132from agentstack import generation
32- from agentstack .utils import open_json_file , term_color , is_snake_case
33+ from agentstack .agents import get_all_agents
34+ from agentstack .tasks import get_all_tasks
35+ from agentstack .utils import open_json_file , term_color , is_snake_case , get_framework
3336from agentstack .update import AGENTSTACK_PACKAGE
3437from agentstack .proj_templates import TemplateConfig
3538
@@ -62,13 +65,13 @@ def init_project_builder(
6265 try :
6366 template_data = TemplateConfig .from_url (template )
6467 except Exception as e :
65- print (term_color (f"Failed to fetch template data from { template } " , 'red' ))
68+ print (term_color (f"Failed to fetch template data from { template } . \n { e } " , 'red' ))
6669 sys .exit (1 )
6770 else :
6871 try :
6972 template_data = TemplateConfig .from_template_name (template )
7073 except Exception as e :
71- print (term_color (f"Failed to load template { template } " , 'red' ))
74+ print (term_color (f"Failed to load template { template } . \n { e } " , 'red' ))
7275 sys .exit (1 )
7376
7477 if template_data :
@@ -81,11 +84,11 @@ def init_project_builder(
8184 }
8285 framework = template_data .framework
8386 design = {
84- 'agents' : template_data .agents ,
85- 'tasks' : template_data .tasks ,
87+ 'agents' : [ agent . model_dump () for agent in template_data .agents ] ,
88+ 'tasks' : [ task . model_dump () for task in template_data .tasks ] ,
8689 'inputs' : template_data .inputs ,
8790 }
88- tools = template_data .tools
91+ tools = [ tools . model_dump () for tools in template_data .tools ]
8992
9093 elif use_wizard :
9194 welcome_message ()
@@ -465,3 +468,85 @@ def list_tools():
465468
466469 print ("\n \n ✨ Add a tool with: agentstack tools add <tool_name>" )
467470 print (" https://docs.agentstack.sh/tools/core" )
471+
472+
473+ def export_template (output_filename : str , path : str = '' ):
474+ """
475+ Export the current project as a template.
476+ """
477+ _path = Path (path )
478+ framework = get_framework (_path )
479+
480+ try :
481+ metadata = ProjectFile (_path )
482+ except Exception as e :
483+ print (term_color (f"Failed to load project metadata: { e } " , 'red' ))
484+ sys .exit (1 )
485+
486+ # Read all the agents from the project's agents.yaml file
487+ agents : list [TemplateConfig .Agent ] = []
488+ for agent in get_all_agents (_path ):
489+ agents .append (
490+ TemplateConfig .Agent (
491+ name = agent .name ,
492+ role = agent .role ,
493+ goal = agent .goal ,
494+ backstory = agent .backstory ,
495+ model = agent .llm , # TODO consistent naming (llm -> model)
496+ )
497+ )
498+
499+ # Read all the tasks from the project's tasks.yaml file
500+ tasks : list [TemplateConfig .Task ] = []
501+ for task in get_all_tasks (_path ):
502+ tasks .append (
503+ TemplateConfig .Task (
504+ name = task .name ,
505+ description = task .description ,
506+ expected_output = task .expected_output ,
507+ agent = task .agent ,
508+ )
509+ )
510+
511+ # Export all of the configured tools from the project
512+ tools_agents : dict [str , list [str ]] = {}
513+ for agent_name in frameworks .get_agent_names (framework , _path ):
514+ for tool_name in frameworks .get_agent_tool_names (framework , agent_name , _path ):
515+ if not tool_name :
516+ continue
517+ if tool_name not in tools_agents :
518+ tools_agents [tool_name ] = []
519+ tools_agents [tool_name ].append (agent_name )
520+
521+ tools : list [TemplateConfig .Tool ] = []
522+ for tool_name , agent_names in tools_agents .items ():
523+ tools .append (
524+ TemplateConfig .Tool (
525+ name = tool_name ,
526+ agents = agent_names ,
527+ )
528+ )
529+
530+ inputs : list [str ] = []
531+ # TODO extract inputs from project
532+ # for input in frameworks.get_input_names():
533+ # inputs.append(input)
534+
535+ template = TemplateConfig (
536+ template_version = 1 ,
537+ name = metadata .project_name ,
538+ description = metadata .project_description ,
539+ framework = framework ,
540+ method = "sequential" , # TODO this needs to be stored in the project somewhere
541+ agents = agents ,
542+ tasks = tasks ,
543+ tools = tools ,
544+ inputs = inputs ,
545+ )
546+
547+ try :
548+ template .write_to_file (_path / output_filename )
549+ print (term_color (f"Template saved to: { _path / output_filename } " , 'green' ))
550+ except Exception as e :
551+ print (term_color (f"Failed to write template to file: { e } " , 'red' ))
552+ sys .exit (1 )
0 commit comments