Merge branch 'feature/create_react_project' into 'mgx_ops'

Create React/Vue project

See merge request pub/MetaGPT!391
This commit is contained in:
林义章 2024-10-11 04:09:15 +00:00
commit c95a925b19
7 changed files with 72 additions and 37 deletions

View file

@ -13,7 +13,7 @@ from metagpt.utils.mermaid import MMC1, MMC2
IMPLEMENTATION_APPROACH = ActionNode(
key="Implementation approach",
expected_type=str,
instruction="Analyze the difficult points of the requirements, select the appropriate open-source framework",
instruction="Analyze the difficult points of the requirements, select the appropriate open-source framework.",
example="We will ...",
)

View file

@ -71,6 +71,11 @@ SKILL_DIRECTORY = SOURCE_ROOT / "skills"
TOOL_SCHEMA_PATH = METAGPT_ROOT / "metagpt/tools/schemas"
TOOL_LIBS_PATH = METAGPT_ROOT / "metagpt/tools/libs"
# TEMPLATE PATH
TEMPLATE_FOLDER_PATH = METAGPT_ROOT / "template"
VUE_TEMPLATE_PATH = TEMPLATE_FOLDER_PATH / "vue_template"
REACT_TEMPLATE_PATH = TEMPLATE_FOLDER_PATH / "react_template"
# REAL CONSTS
MEM_TTL = 24 * 30 * 3600

View file

@ -1,3 +1,4 @@
from metagpt.const import REACT_TEMPLATE_PATH, VUE_TEMPLATE_PATH
from metagpt.prompts.di.role_zero import ROLE_INSTRUCTION
EXTRA_INSTRUCTION = """
@ -7,7 +8,6 @@ The special interface consists of a file editor that shows you 100 lines of a fi
You can use terminal commands (e.g., cat, ls, cd) by calling Terminal.run_command.
You should carefully observe the behavior and results of the previous action, and avoid triggering repeated errors.
In addition to the terminal, I also provide additional tools.
@ -69,20 +69,27 @@ Note:
11.1 Do not use Editor.insert_content_at_line or Editor.edit_file_by_replace more than once per command list.
12. If you choose Editor.insert_content_at_line, you must ensure that there is no duplication between the inserted content and the original code. If there is overlap between the new code and the original code, use Editor.edit_file_by_replace instead.
13. If you choose Editor.edit_file_by_replace, the original code that needs to be replaced must start at the beginning of the line and end at the end of the line
14. When not specified, you should write files in a folder named "src". If you know the project path, then write in a "src" folder under the project path.
14. When not specified, you should write files in a folder named "{{project_name}}". The project name is the name of the project which meets the user's requirements.
15. When provided system design or project schedule, you MUST read them first before making a plan, then adhere to them in your implementation, especially in the programming language, package, or framework. You MUST implement all code files prescribed in the system design or project schedule. You can create a plan first with each task corresponding to implementing one code file.
16. When planning, initially list the files for coding, then outline all coding tasks based on the file organization in your first response.
17. If you plan to read a file, do not include other plans in the same response.
18. Write only one code file each time and provide its full implementation.
19. When the requirement is simple, you don't need to create a plan, just do it right away.
20. If the code exists, use the Editor tool's open and edit commands to modify it. Since it is not a new code, do not use write_new_code.
21. When using the editor, pay attention to the editor's current directory. When you use editor tools, the paths must be either absolute or relative to the editor's current directory.
22. The default programming languages are Native HTML.
23. When planning, consider whether images are needed. If you are developing a showcase website, start by using ImageGetter.get_image to obtain the necessary images.
24. When planning, merge multiple tasks that operate on the same file into a single task. For example, create one task for writing unit tests for all functions in a class. Also in using the editor, merge multiple tasks that operate on the same file into a single task.
25. 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.
"""
20. When using the editor, pay attention to current directory. When you use editor tools, the paths must be either absolute or relative to the editor's current directory.
21. When planning, consider whether images are needed. If you are developing a showcase website, start by using ImageGetter.get_image to obtain the necessary images.
22. When planning, merge multiple tasks that operate on the same file into a single task. For example, create one task for writing unit tests for all functions in a class. Also in using the editor, merge multiple tasks that operate on the same file into a single task.
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. Follow the Sytem Design and Project Schedule if exists. Otherwise, use default template folder of Vite, React, MUI and Tailwind CSS. If the template does not exist, use native HTML.
25. When writing Vue/React project: The Vue template is in the {vue_template_path}, the React template is in the {react_template_path}.
25.1. Create the project folder first. Use cmd " mkdir -p {{project_name}} "
25.2. Copy a Vue/React template to your project and view all files. This must be a single respond. Use cmd "cp -r {{template_folder}}/* {{workspace}}/{{project_name}}/ && cd {{workspace}}/{{project_name}} && pwd && tree -f".
25.3. Read the content of each file and use the write_new_code command to rewrite the code. Be sure you are in the {{project_name}}. Reorganize the file structure to match the project template if it differs from the system design.
25.4. After finish the project. use "npm install" and "npm run build" to build the project.
26. Engineer2.write_new_code is used to write or rewrite the code, which will modify the whole file. Editor.edit_file_by_replace is used to edit a small part of the file.
""".format(
vue_template_path=VUE_TEMPLATE_PATH.absolute(),
react_template_path=REACT_TEMPLATE_PATH.absolute(),
)
CURRENT_STATE = """
The current editor state is:
(Current directory: {current_directory})
@ -113,10 +120,11 @@ WRITE_CODE_PROMPT = """
{file_description}
# Instruction
Your task is to write the {file_name} according to the User Requirement.
Your task is to write the {file_name} according to the User Requirement. You must ensure the code is complete, correct, and bug-free.
# Output
While some concise thoughts are helpful, code is absolutely required. Always output one and only one code block in your response. Output code in the following format:
While some concise thoughts are helpful, code is absolutely required. Always output one and only one code block in your response. DO NOT leave any TODO or placeholder.
Output code in the following format:
```
your code
```

View file

@ -104,12 +104,6 @@ class Engineer2(RoleZero):
def _retrieve_experience(self) -> str:
return ENGINEER_EXAMPLE
async def _run_special_command(self, cmd) -> str:
"""command requiring special check or parsing."""
# finish current task before end.
command_output = await super()._run_special_command(cmd)
return command_output
async def write_new_code(self, path: str, file_description: str = "") -> str:
"""Write a new code file.
@ -117,6 +111,8 @@ class Engineer2(RoleZero):
path (str): The absolute path of the file to be created.
file_description (optional, str): "Brief description and important notes of the file content, must be very concise and can be empty. Defaults to "".
"""
# If the path is not absolute, try to fix it with the editor's working directory.
path = self.editor._try_fix_path(path)
plan_status, _ = self._get_plan_status()
prompt = WRITE_CODE_PROMPT.format(
user_requirement=self.planner.plan.goal,

View file

@ -839,19 +839,19 @@ Explanation: I will first need to read the system design document and the projec
}
]
```
## example 2.1
User Requirement: Implement the core game project in Vue/React framework.
Explanation: This is a project that needs to be implemented using Vue.js. Therefore, I need to copy the Vue/React template to the project folder first.
## example 2
Consider this example only after you have obtained the content of system design and project schedule documents.
Suppose the system design and project schedule prescribes three files index.html, style.css, script.js, to follow the design and schedule, I will create a plan consisting of three tasks, each corresponding to the creation of one of the required files: `index.html`, `style.css`, and `script.js`.
## example 2.2
User Requirement: Writing code.
Here's the plan:
[Optional] 0. **Task 0**: Obtain images before coding.
1. **Task 1**: Create `index.html` - This file will contain the HTML structure necessary for the game's UI.
2. **Task 2**: Create `style.css` - This file will define the CSS styles to make the game visually appealing and responsive.
3. **Task 3**: Create `script.js` - This file will contain the Pure JavaScript code for the game logic and UI interactions.
Let's start by appending the first task to the plan.
[Optional] Read the original file in the template if they exist.
[Optional] Obtain images before coding.
1. **Task 1**: Rewrite `App.vue` - This file will contain the Vue structure necessary for the game's UI, the game logic and UI interactions.
2. **Task 2**: Rewrite `style.css` - This file will define the CSS styles to make the game visually appealing and responsive. Default use tailwindcss.
3. **Task 3**: Rewrite `main.js` - This file is the main entry of Vue project, including the main Vue instance, global styles, and the router.
[Optional] Install the dependencies after finishing project.
```json
[
{
@ -859,7 +859,7 @@ Let's start by appending the first task to the plan.
"args": {
"task_id": "1",
"dependent_task_ids": [],
"instruction": "Create the index.html file with the basic HTML structure for the 2048 game.",
"instruction": "Read the original file in the template if they exist.",
"assignee": "Alex"
}
},
@ -867,8 +867,8 @@ Let's start by appending the first task to the plan.
"command_name": "Plan.append_task",
"args": {
"task_id": "2",
"dependent_task_ids": ["1"],
"instruction": "Create the style.css file with the necessary CSS to style the 2048 game.",
"dependent_task_ids": [],
"instruction": "Create the App.vue file with the game's UI, the game logic and UI interactions, the style will implemented in the global style file using Tailwind CSS.",
"assignee": "Alex"
}
},
@ -876,8 +876,26 @@ Let's start by appending the first task to the plan.
"command_name": "Plan.append_task",
"args": {
"task_id": "3",
"dependent_task_ids": ["1", "2"],
"instruction": "Create the script.js file containing the Pure JavaScript logic for the 2048 game.",
"dependent_task_ids": ["2"],
"instruction": "Create the style.css file with Tailwind CSS for the 2048 Game.",
"assignee": "Alex"
}
},
{
"command_name": "Plan.append_task",
"args": {
"task_id": "4",
"dependent_task_ids": ["2","3"],
"instruction": "Create the main.js, which will include the main Vue instance, global styles, and the router.",
"assignee": "Alex"
}
},
{
"command_name": "Plan.append_task",
"args": {
"task_id": "5",
"dependent_task_ids": ["2","3","4"],
"instruction": "Install the necessary dependencies and configure the project structure.",
"assignee": "Alex"
}
}
@ -885,7 +903,7 @@ Let's start by appending the first task to the plan.
```
## example 3
Explanation: Take on one task, such as writing a file. Upon completion, finish current task
Explanation: Take on one task, such as writing or rewriting a file. Upon completion, finish current task.
```json
[

View file

@ -116,6 +116,9 @@ class Editor(BaseModel):
def write(self, path: str, content: str):
"""Write the whole content to a file. When used, make sure content arg contains the full content of the file."""
path = self._try_fix_path(path)
if "\n" not in content and "\\n" in content:
# A very raw rule to correct the content: If 'content' lacks actual newlines ('\n') but includes '\\n', consider
# replacing them with '\n' to potentially correct mistaken representations of newline characters.
@ -130,6 +133,9 @@ class Editor(BaseModel):
async def read(self, path: str) -> FileBlock:
"""Read the whole content of a file. Using absolute paths as the argument for specifying the file location."""
path = self._try_fix_path(path)
error = FileBlock(
file_path=str(path),
block_content="The file is too large to read. Use `Editor.similarity_search` to read the file instead.",

View file

@ -5,7 +5,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
@ -33,6 +33,8 @@ class Terminal:
*self.shell_command, stdin=PIPE, stdout=PIPE, stderr=STDOUT, executable="bash", env=os.environ.copy()
)
await self._check_state()
# Goto the default directory
await self.run_command(f"cd {DEFAULT_WORKSPACE_ROOT.absolute()}")
async def _check_state(self):
"""