#!/usr/bin/env python3
"""
Main CLI for multi-agent SaaS repository builder
Usage: python repo_builder.py <command> [options]
"""
import asyncio
import argparse
from pathlib import Path
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_agentchat.conditions import TextMentionTermination
from autogen_ext.models.openai import OpenAIChatCompletionClient
import os
from dotenv import load_dotenv
load_dotenv()
class RepoBuilder:
def __init__(self, spec_file: str, output_dir: str):
self.spec_file = Path(spec_file)
self.output_dir = Path(output_dir)
self.model_client = OpenAIChatCompletionClient(
model="gpt-4o",
api_key=os.getenv("OPENAI_API_KEY")
)
self.agents = self._create_agents()
def _create_agents(self):
"""Create specialized agent team"""
return {
"pm": AssistantAgent(
name="product_manager",
model_client=self.model_client,
system_message="You are a Product Manager..."
),
"architect": AssistantAgent(
name="architect",
model_client=self.model_client,
system_message="You are a System Architect..."
),
"backend": AssistantAgent(
name="backend_engineer",
model_client=self.model_client,
system_message="You are a Backend Engineer..."
),
"frontend": AssistantAgent(
name="frontend_engineer",
model_client=self.model_client,
system_message="You are a Frontend Engineer..."
),
"qa": AssistantAgent(
name="qa_engineer",
model_client=self.model_client,
system_message="You are a QA Engineer..."
),
"devops": AssistantAgent(
name="devops_engineer",
model_client=self.model_client,
system_message="You are a DevOps Engineer..."
)
}
async def init_project(self):
"""Initialize new project from requirements"""
spec_content = self.spec_file.read_text()
team = RoundRobinGroupChat(
list(self.agents.values()),
termination_condition=TextMentionTermination("INITIALIZATION_COMPLETE")
)
task = f"""Create a new SaaS application based on these requirements:
{spec_content}
Output structure:
1. Project architecture document
2. Backend scaffolding (API routes, models, services)
3. Frontend scaffolding (components, pages, state management)
4. Database schema and migrations
5. Test suites
6. Documentation (README, API docs)
7. Deployment configuration
INITIALIZATION_COMPLETE when all files are generated."""
result = await team.run(task=task)
self._save_results(result)
return result
async def update_feature(self, target_agents: list, description: str):
"""Update specific feature with targeted agents"""
spec_content = self.spec_file.read_text()
# Select only required agents
selected_agents = [self.agents[name] for name in target_agents]
team = RoundRobinGroupChat(
selected_agents,
termination_condition=TextMentionTermination("UPDATE_COMPLETE")
)
task = f"""Update the following feature:
{description}
Current requirements: {spec_content}
Only modify files related to this feature. Preserve all other code.
UPDATE_COMPLETE when changes are implemented and tested."""
result = await team.run(task=task)
self._save_results(result)
return result
def _save_results(self, result):
"""Save agent outputs and summaries"""
# Implementation: parse result.messages and write to files
pass
def main():
parser = argparse.ArgumentParser(description="Multi-agent SaaS repository builder")
subparsers = parser.add_subparsers(dest="command", help="Commands")
# init command
init_parser = subparsers.add_parser("init", help="Initialize new project")
init_parser.add_argument("--spec", required=True, help="Requirements document")
init_parser.add_argument("--output", required=True, help="Output directory")
# update command
update_parser = subparsers.add_parser("update", help="Update existing project")
update_parser.add_argument("--spec", required=True, help="Updated requirements")
update_parser.add_argument("--target", help="Target agents (comma-separated)")
update_parser.add_argument("--full", action="store_true", help="Full system update")
# feature command
feature_parser = subparsers.add_parser("feature", help="Add new feature")
feature_parser.add_argument("action", choices=["add", "remove", "modify"])
feature_parser.add_argument("--name", required=True, help="Feature name")
feature_parser.add_argument("--agents", help="Required agents (comma-separated)")
args = parser.parse_args()
builder = RepoBuilder(args.spec, args.output)
if args.command == "init":
asyncio.run(builder.init_project())
elif args.command == "update":
target_agents = args.target.split(",") if args.target else list(builder.agents.keys())
asyncio.run(builder.update_feature(target_agents, "Update from spec"))
print("✓ Operation completed successfully")
if __name__ == "__main__":
main()
# Make executable
chmod +x repo_builder.py