diff --git a/metagpt/actions/project_management.py b/metagpt/actions/project_management.py index abfea7f10..1ce94cd99 100644 --- a/metagpt/actions/project_management.py +++ b/metagpt/actions/project_management.py @@ -180,7 +180,7 @@ class WriteTasks(Action): ) -> str: context = to_markdown_code_block(user_requirement) if design_filename: - design_filename = rectify_pathname(path=design_filename, default_filename="system_design.json") + design_filename = rectify_pathname(path=design_filename, default_filename="system_design.md") content = await aread(filename=design_filename) context += to_markdown_code_block(content) diff --git a/metagpt/actions/project_management_an.py b/metagpt/actions/project_management_an.py index 78f17653b..cca51a94b 100644 --- a/metagpt/actions/project_management_an.py +++ b/metagpt/actions/project_management_an.py @@ -28,7 +28,8 @@ LOGIC_ANALYSIS = ActionNode( expected_type=List[List[str]], instruction="Provide a list of files with the classes/methods/functions to be implemented, " "including dependency analysis and imports." - "Ensure consistency between System Design and Logic Analysis; the files must match exactly.", + "Ensure consistency between System Design and Logic Analysis; the files must match exactly. " + "If the file is written in Vue or React, use Tailwind CSS for styling.", example=[ ["game.py", "Contains Game class and ... functions"], ["main.py", "Contains main function, from game import Game"], diff --git a/metagpt/actions/write_prd_an.py b/metagpt/actions/write_prd_an.py index 574dcef89..81e16bcfa 100644 --- a/metagpt/actions/write_prd_an.py +++ b/metagpt/actions/write_prd_an.py @@ -19,8 +19,8 @@ LANGUAGE = ActionNode( PROGRAMMING_LANGUAGE = ActionNode( key="Programming Language", expected_type=str, - instruction="Mainstream programming language. If not specified in the requirements, use native HTML", - example="native HTML", + instruction="Mainstream programming language. If not specified in the requirements, use Vite, React, MUI, Tailwind CSS.", + example="Vite, React, MUI, Tailwind CSS", ) ORIGINAL_REQUIREMENTS = ActionNode( diff --git a/metagpt/prompts/di/architect.py b/metagpt/prompts/di/architect.py new file mode 100644 index 000000000..ed0c2b7d1 --- /dev/null +++ b/metagpt/prompts/di/architect.py @@ -0,0 +1,83 @@ +from metagpt.const import REACT_TEMPLATE_PATH, VUE_TEMPLATE_PATH + +SYSTEM_DESIGN_EXAMPLE = """ +```markdown +## Implementation approach": + +We will ... + +## File list + +- a.js +- b.py +- c.css +- d.html + +## Data structures and interfaces: + + +classDiagram + class Main { + <> + +main() str + } + class SearchEngine { + +search(query: str) str + } + class Index { + +create_index(data: dict) + +query_index(query: str) list + } + class Ranking { + +rank_results(results: list) list +} + +## Program call flow: + + +sequenceDiagram + participant M as Main + participant SE as SearchEngine + participant I as Index + participant R as Ranking + participant S as Summary + participant KB as KnowledgeBase + M->>SE: search(query) + SE->>I: query_index(query) + I->>KB: fetch_data(query) + KB-->>I: return data + + +## Anything UNCLEAR + +Clarification needed on third-party API integration, ... + +``` +""" + +ARCHITECT_INSTRUCTION = """ +You are an architect. Your task is to design a software system that meets the requirements. + +Note: +1. If Product Requirement Document is provided, read the document and use it as the requirement. +2. When the requirement use Vite, React/Vue, MUI, and Tailwind CSS to build a web application, list the files in the template before writing system design. Use "cd /{{template_path}} && tree -f". This must be a single response without other commands. +3. React template is in {react_template_path} and Vue template is in {vue_template_path}. +4. The system design must adhere to the following rules: +4.1 Chapter in the system design should include: +Required Python packages: Provide required Python packages in requirements.txt format. The response language should correspond to the context and requirements. +Required Other language third-party packages: List down the required packages for languages other than Python. +Logic Analysis: Provide a list of files with the classes/methods/functions to be implemented, including dependency analysis and imports.Ensure consistency between System Design and Logic Analysis; the files must match exactly. +Task list: Break down the tasks into a list of filenames, prioritized by dependency order. +Full API spec : escribe all APIs using OpenAPI 3.0 spec that may be used by both frontend and backend. If front-end and back-end communication is not required, leave it blank. +Shared Knowledge: Detail any shared knowledge, like common utility functions or configuration variables. +Anything UNCLEA: Mention any unclear aspects in the project management context and try to clarify them. + +4.2 System Design Format example: +{system_design_example} + +5. Use Editor.write to write the system design in markdown format. The path must be "/absolute/path/to/{{project_name}}/docs/system_design.md". Use command_name "end" when the system design is finished. +""".format( + system_design_example=SYSTEM_DESIGN_EXAMPLE, + vue_template_path=VUE_TEMPLATE_PATH.absolute(), + react_template_path=REACT_TEMPLATE_PATH.absolute(), +) diff --git a/metagpt/prompts/di/engineer2.py b/metagpt/prompts/di/engineer2.py index 1c39444de..74b41b750 100644 --- a/metagpt/prompts/di/engineer2.py +++ b/metagpt/prompts/di/engineer2.py @@ -46,7 +46,7 @@ Note: 23. When create unit tests for a code file, use Editor.read() to read the code file before planing. And create one plan to writing the unit test for the whole file. 24. the priority to select technical stack: Describe in Sytem Design and Project Schedule > Vite, React, MUI and Tailwind CSS > native HTML 24.1. The React template is in the "{react_template_path}" and Vue template is in the "{vue_template_path}". -25. If no programmming language is specified, use Vue/React project. Do the following steps: +25. If no programming language is specified or specifies use Vite, Vue/React, MUI, and Tailwind CSS, follow these steps: 25.1. Create the project folder first. Use cmd " mkdir -p {{project_name}} " 25.2. Copy a Vue/React template to your project folder, move into it and list the file in it. Use cmd "cp -r {{template_folder}}/* {{workspace}}/{{project_name}}/ && cd {{workspace}}/{{project_name}} && pwd && tree -f". This must be a single response without other commands. 25.3. User Editor.read to read the content of files in the src and read the index.html in the project root before making a plan. diff --git a/metagpt/roles/architect.py b/metagpt/roles/architect.py index b990808b3..4b54f2c26 100644 --- a/metagpt/roles/architect.py +++ b/metagpt/roles/architect.py @@ -5,18 +5,11 @@ @Author : alexanderwu @File : architect.py """ -from metagpt.actions import WritePRD -from metagpt.actions.design_api import WriteDesign +from pydantic import Field + +from metagpt.prompts.di.architect import ARCHITECT_INSTRUCTION from metagpt.roles.di.role_zero import RoleZero -from metagpt.utils.common import tool2name - -ARCHITECT_INSTRUCTION = """ -Use WriteDesign tool to write a system design document if a system design is required; - -Note: -1. When you think, just analyze which tool you should use, and then provide your answer. And your output should contain firstly, secondly, ... -2. The automated tools at your disposal will generate a document that perfectly meets your requirements. There is no need to do it manually. -""" +from metagpt.tools.libs.terminal import Terminal class Architect(RoleZero): @@ -37,13 +30,12 @@ class Architect(RoleZero): "make sure the architecture is simple enough and use appropriate open source " "libraries. Use same language as user requirement" ) - + terminal: Terminal = Field(default_factory=Terminal, exclude=True) instruction: str = ARCHITECT_INSTRUCTION - max_react_loop: int = 1 # FIXME: Read and edit files requires more steps, consider later tools: list[str] = [ - "Editor:write,read,write_content,similarity_search", + "Editor:write,read,similarity_search", "RoleZero", - "WriteDesign", + "Terminal:run_command", ] def __init__(self, **kwargs) -> None: @@ -51,17 +43,6 @@ class Architect(RoleZero): # NOTE: The following init setting will only be effective when self.use_fixed_sop is changed to True self.enable_memory = False - # Initialize actions specific to the Architect role - self.set_actions([WriteDesign]) - - # Set events or actions the Architect should watch or be aware of - self._watch({WritePRD}) def _update_tool_execution(self): - write_design = WriteDesign() - self.tool_execution_map.update(tool2name(WriteDesign, ["run"], write_design.run)) - self.tool_execution_map.update( - { - "run": write_design.run, # alias - } - ) + self.tool_execution_map.update({"Terminal.run_command": self.terminal.run_command}) diff --git a/metagpt/roles/di/role_zero.py b/metagpt/roles/di/role_zero.py index 4614de0f3..551034f2c 100644 --- a/metagpt/roles/di/role_zero.py +++ b/metagpt/roles/di/role_zero.py @@ -537,7 +537,7 @@ class RoleZero(Role): command_output = await self._end() elif cmd["command_name"] == "RoleZero.ask_human": human_response = await self.ask_human(**cmd["args"]) - if "stop" in human_response.lower(): + if human_response.strip().lower() in ["", "stop"]: human_response += "The user has asked me to stop because I have encountered a problem." self.rc.memory.add(UserMessage(content=human_response, cause_by=RunCommand)) end_output = "\nCommand end executed:" diff --git a/metagpt/roles/project_manager.py b/metagpt/roles/project_manager.py index d64fb90a1..cb0ead9de 100644 --- a/metagpt/roles/project_manager.py +++ b/metagpt/roles/project_manager.py @@ -31,7 +31,7 @@ class ProjectManager(RoleZero): instruction: str = """Use WriteTasks tool to write a project task list""" max_react_loop: int = 1 # FIXME: Read and edit files requires more steps, consider later - tools: list[str] = ["Editor:write,read,write_content,similarity_search", "RoleZero", "WriteTasks"] + tools: list[str] = ["Editor:write,read,similarity_search", "RoleZero", "WriteTasks"] def __init__(self, **kwargs) -> None: super().__init__(**kwargs) diff --git a/metagpt/strategy/experience_retriever.py b/metagpt/strategy/experience_retriever.py index 003bcd90c..aa094effb 100644 --- a/metagpt/strategy/experience_retriever.py +++ b/metagpt/strategy/experience_retriever.py @@ -479,7 +479,7 @@ Explanation: The requirement is about software development. Assign each tasks to "args": { "task_id": "1", "dependent_task_ids": [], - "instruction": "Use native HTML for the program. And create a product requirement document (PRD) outlining the features, user interface. ", + "instruction": "Use Vite, React, MUI, Tailwind CSS for the program. And create a product requirement document (PRD) outlining the features, user interface. ", "assignee": "Alice" } }, @@ -488,7 +488,7 @@ Explanation: The requirement is about software development. Assign each tasks to "args": { "task_id": "2", "dependent_task_ids": ["1"], - "instruction": "Use native HTML for the program. Design the software architecture for the CLI snake game, including the data flow.", + "instruction": "Use Vite, React, MUI, Tailwind CSS for the program. Design the software architecture for the CLI snake game, including the data flow.", "assignee": "Bob" } }, @@ -506,14 +506,14 @@ Explanation: The requirement is about software development. Assign each tasks to "args": { "task_id": "4", "dependent_task_ids": ["3"], - "instruction": "Use native HTML for the program. Implement the core game logic for the CLI snake game, including snake movement, food generation, and score tracking.", + "instruction": "Use Vite, React, MUI, Tailwind CSS for the program. Implement the core game logic for the CLI snake game, including snake movement, food generation, and score tracking.", "assignee": "Alex" } }, { "command_name": "TeamLeader.publish_message", "args": { - "content": "Use native HTML for the program. Create a cli snake game.", + "content": "Use Vite, React, MUI, Tailwind CSS for the program. Create a cli snake game.", "send_to": "Alice" } }, diff --git a/metagpt/tools/libs/terminal.py b/metagpt/tools/libs/terminal.py index 48f012e9f..9f3545052 100644 --- a/metagpt/tools/libs/terminal.py +++ b/metagpt/tools/libs/terminal.py @@ -6,7 +6,7 @@ from asyncio.subprocess import PIPE, STDOUT from typing import Optional from metagpt.config2 import Config -from metagpt.const import SWE_SETUP_PATH +from metagpt.const import DEFAULT_WORKSPACE_ROOT, SWE_SETUP_PATH from metagpt.logs import logger from metagpt.tools.tool_registry import register_tool from metagpt.utils.report import END_MARKER_VALUE, TerminalReporter @@ -37,7 +37,13 @@ class Terminal: async def _start_process(self): # Start a persistent shell process self.process = await asyncio.create_subprocess_exec( - *self.shell_command, stdin=PIPE, stdout=PIPE, stderr=STDOUT, executable="bash", env=os.environ.copy() + *self.shell_command, + stdin=PIPE, + stdout=PIPE, + stderr=STDOUT, + executable="bash", + env=os.environ.copy(), + cwd=DEFAULT_WORKSPACE_ROOT.absolute(), ) await self._check_state()