diff --git a/examples/di/software_company.py b/examples/di/software_company.py index 2a11d7981..ac9999ca9 100644 --- a/examples/di/software_company.py +++ b/examples/di/software_company.py @@ -6,12 +6,6 @@ from metagpt.roles.di.data_interpreter import DataInterpreter async def main(): - # prompt = f"""This is a software requirement:\n```text\nwrite a snake game\n```\n . - # 1. Append user requirement to project path `/Users/iorishinier/github/bak/MetaGPT/workspace/snake_game` and write a PRD.\n - # 2. Write a design to project path `/Users/iorishinier/github/bak/MetaGPT/workspace/snake_game`.\n - # Note: All required dependencies and environments have been fully installed and configured.""" - # prompt = f"""1. fix bug:\n```text\n{issue}\n````\nin project path `/Users/iorishinier/github/bak/MetaGPT/workspace/snake_game`.\n - # Note: All required dependencies and environments have been fully installed and configured.""" prompt = """ This is a software requirement: ```text diff --git a/metagpt/tools/libs/software_development.py b/metagpt/tools/libs/software_development.py index 0db899f49..59c71d492 100644 --- a/metagpt/tools/libs/software_development.py +++ b/metagpt/tools/libs/software_development.py @@ -21,21 +21,21 @@ async def write_prd(idea: str, project_path: Optional[str | Path] = None) -> Pat If it's None, a new project path will be created. Defaults to None. Returns: - Path: The path to the project directory + Path: The path to the PRD files under the project directory Example: >>> # Create a new project: >>> from metagpt.tools.libs.software_development import write_prd - >>> project_path = await write_prd("Create a new feature for the application") - >>> print(project_path) - '/path/to/project_path' + >>> prd_path = await write_prd("Create a new feature for the application") + >>> print(prd_path) + '/path/to/project_path/docs/prd/' >>> # Add user requirements to the exists project: >>> from metagpt.tools.libs.software_development import write_prd >>> project_path = '/path/to/exists_project_path' - >>> await write_prd("Create a new feature for the application", project_path=project_path) - >>> print(project_path) - '/path/to/exists_project_path' + >>> prd_path = await write_prd("Create a new feature for the application", project_path=project_path) + >>> print(prd_path = ) + '/path/to/project_path/docs/prd/' """ from metagpt.actions import UserRequirement from metagpt.context import Context @@ -48,25 +48,25 @@ async def write_prd(idea: str, project_path: Optional[str | Path] = None) -> Pat role = ProductManager(context=ctx) msg = await role.run(with_message=Message(content=idea, cause_by=UserRequirement)) await role.run(with_message=msg) - return ctx.repo.workdir + return ctx.repo.docs.prd.workdir @register_tool(tags=["software company", "Architect"]) -async def write_design(project_path: str | Path) -> Path: +async def write_design(prd_path: str | Path) -> Path: """Writes a design to the project repository, based on the PRD of the project. Args: - project_path (str|Path): The path to the project repository. + prd_path (str|Path): The path to the PRD files under the project directory. Returns: - Path: The path to the project directory + Path: The path to the system design files under the project directory. Example: >>> from metagpt.tools.libs.software_development import write_design - >>> project_path = '/path/to/project_path' # Returned by `write_prd` - >>> project_path = await write_desgin(project_path) - >>> print(project_path) - '/path/to/project_path' + >>> prd_path = '/path/to/project_path/docs/prd' # Returned by `write_prd` + >>> system_design_path = await write_desgin(prd_path) + >>> print(system_design_path) + '/path/to/project_path/docs/system_design/' """ from metagpt.actions import WritePRD @@ -74,29 +74,30 @@ async def write_design(project_path: str | Path) -> Path: from metagpt.roles import Architect ctx = Context() + project_path = Path(prd_path).parent.parent ctx.set_repo_dir(project_path) role = Architect(context=ctx) await role.run(with_message=Message(content="", cause_by=WritePRD)) - return project_path + return ctx.repo.docs.system_design.workdir @register_tool(tags=["software company", "Architect"]) -async def write_project_plan(project_path: str | Path) -> Path: +async def write_project_plan(system_design_path: str | Path) -> Path: """Writes a project plan to the project repository, based on the design of the project. Args: - project_path (str|Path): The path to the project repository. + system_design_path (str|Path): The path to the system design files under the project directory. Returns: - Path: The path to the project directory + Path: The path to task files under the project directory. Example: >>> from metagpt.tools.libs.software_development import write_project_plan - >>> project_path = '/path/to/project_path' # Returned by `write_prd` - >>> project_path = await write_project_plan(project_path) - >>> print(project_path) - '/path/to/project_path' + >>> system_design_path = '/path/to/project_path/docs/system_design/' # Returned by `write_design` + >>> task_path = await write_project_plan(system_design_path) + >>> print(task_path) + '/path/to/project_path/docs/task' """ from metagpt.actions import WriteDesign @@ -104,38 +105,39 @@ async def write_project_plan(project_path: str | Path) -> Path: from metagpt.roles import ProjectManager ctx = Context() + project_path = Path(system_design_path).parent.parent ctx.set_repo_dir(project_path) role = ProjectManager(context=ctx) await role.run(with_message=Message(content="", cause_by=WriteDesign)) - return project_path + return ctx.repo.docs.task.workdir @register_tool(tags=["software company", "Engineer"]) -async def write_codes(project_path: str | Path, inc: bool = False) -> Path: +async def write_codes(task_path: str | Path, inc: bool = False) -> Path: """Writes codes to the project repository, based on the project plan of the project. Args: - project_path (str|Path): The path to the project repository. + task_path (str|Path): The path to task files under the project directory. inc (bool, optional): Whether to write incremental codes. Defaults to False. Returns: - Path: The path to the project directory + Path: The path to the source code files under the project directory. Example: # Write codes to a new project >>> from metagpt.tools.libs.software_development import write_codes - >>> project_path = '/path/to/project_path' # Returned by `write_prd` - >>> project_path = await write_codes(project_path) - >>> print(project_path) - '/path/to/project_path' + >>> task_path = '/path/to/project_path/docs/task' # Returned by `write_project_plan` + >>> src_path = await write_codes(task_path) + >>> print(src_path) + '/path/to/project_path/src/' # Write increment codes to the exists project >>> from metagpt.tools.libs.software_development import write_codes - >>> project_path = '/path/to/project_path' # Returned by `write_prd` - >>> project_path = await write_codes(project_path, inc=True) - >>> print(project_path) - '/path/to/project_path' + >>> task_path = '/path/to/project_path/docs/task' # Returned by `write_prd` + >>> src_path = await write_codes(task_path, inc=True) + >>> print(src_path) + '/path/to/project_path/src/' """ from metagpt.actions import WriteTasks from metagpt.context import Context @@ -143,6 +145,7 @@ async def write_codes(project_path: str | Path, inc: bool = False) -> Path: ctx = Context() ctx.config.inc = inc + project_path = Path(task_path).parent.parent ctx.set_repo_dir(project_path) role = Engineer(context=ctx) @@ -150,25 +153,25 @@ async def write_codes(project_path: str | Path, inc: bool = False) -> Path: me = {any_to_str(role), role.name} while me.intersection(msg.send_to): msg = await role.run(with_message=msg) - return project_path + return ctx.repo.srcs.workdir @register_tool(tags=["software company", "QaEngineer"]) -async def run_qa_test(project_path: str | Path) -> Path: +async def run_qa_test(src_path: str | Path) -> Path: """Run QA test on the project repository. Args: - project_path (str|Path): The path to the project repository. + src_path (str|Path): The path to the source code files under the project directory. Returns: - Path: The path to the project directory + Path: The path to the unit tests under the project directory Example: >>> from metagpt.tools.libs.software_development import run_qa_test - >>> project_path = '/path/to/project_path' # Returned by `write_codes` - >>> project_path = await run_qa_test(project_path) - >>> print(project_path) - '/path/to/project_path' + >>> src_path = '/path/to/project_path/src/' # Returned by `write_codes` + >>> test_path = await run_qa_test(src_path) + >>> print(test_path) + '/path/to/project_path/tests' """ from metagpt.actions.summarize_code import SummarizeCode from metagpt.context import Context @@ -176,6 +179,7 @@ async def run_qa_test(project_path: str | Path) -> Path: from metagpt.roles import QaEngineer ctx = Context() + project_path = Path(src_path).parent ctx.set_repo_dir(project_path) ctx.src_workspace = ctx.git_repo.workdir / ctx.git_repo.workdir.name @@ -188,7 +192,7 @@ async def run_qa_test(project_path: str | Path) -> Path: while not env.is_idle: await env.run() - return project_path + return ctx.repo.tests.workdir @register_tool(tags=["software company", "Engineer"]) @@ -197,7 +201,7 @@ async def fix_bug(project_path: str | Path, issue: str) -> Path: Args: project_path (str|Path): The path to the project repository. - + issue (str): Description of the bug or issue. Returns: Path: The path to the project directory @@ -205,7 +209,7 @@ async def fix_bug(project_path: str | Path, issue: str) -> Path: Example: >>> from metagpt.tools.libs.software_development import fix_bug >>> project_path = '/path/to/project_path' # Returned by `write_codes` - >>> issue = 'The exception description about the issue' + >>> issue = 'Exception: exception about ...; Bug: bug about ...; Issue: issue about ...' >>> project_path = await fix_bug(project_path=project_path, issue=issue) >>> print(project_path) '/path/to/project_path'