mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-04-26 09:16:21 +02:00
Merge branch 'add_deployer_tool_to_engineer' into fix/deployer_can_not_serialisze
This commit is contained in:
commit
21ddacd433
6 changed files with 92 additions and 28 deletions
|
|
@ -79,12 +79,12 @@ Note:
|
|||
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}.
|
||||
24. Follow the Sytem Design and Project Schedule if exists. Otherwise, use default template folder of Vite, React, MUI and Tailwind CSS. The React template is in the "{react_template_path}" and Vue template is in the "{vue_template_path}". If the template does not exist, use native HTML.
|
||||
25. When writing Vue/React project:
|
||||
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.
|
||||
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}}.
|
||||
25.4. After finish the project. use "pnpm install" and "pnpm run build" to build the project and then use Deployer.deploy_to_public to deploy the project to the public.
|
||||
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(),
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ from metagpt.roles.di.role_zero import RoleZero
|
|||
from metagpt.schema import UserMessage
|
||||
from metagpt.strategy.experience_retriever import ENGINEER_EXAMPLE
|
||||
from metagpt.tools.libs.cr import CodeReview
|
||||
from metagpt.tools.libs.deployer import Deployer
|
||||
from metagpt.tools.libs.git import git_create_pull
|
||||
from metagpt.tools.libs.image_getter import ImageGetter
|
||||
from metagpt.tools.libs.terminal import Terminal
|
||||
|
|
@ -33,7 +34,7 @@ class Engineer2(RoleZero):
|
|||
goal: str = "Take on game, app, and web development."
|
||||
instruction: str = ENGINEER2_INSTRUCTION
|
||||
terminal: Terminal = Field(default_factory=Terminal, exclude=True)
|
||||
|
||||
deployer: Deployer = Field(default_factory=Deployer, exclude=True)
|
||||
tools: list[str] = [
|
||||
"Plan",
|
||||
"Editor",
|
||||
|
|
@ -45,6 +46,7 @@ class Engineer2(RoleZero):
|
|||
"Engineer2",
|
||||
"CodeReview",
|
||||
"ImageGetter",
|
||||
"Deployer",
|
||||
]
|
||||
# SWE Agent parameter
|
||||
run_eval: bool = False
|
||||
|
|
@ -86,6 +88,7 @@ class Engineer2(RoleZero):
|
|||
"Terminal.run_command": self._eval_terminal_run,
|
||||
"RoleZero.ask_human": self._end,
|
||||
"RoleZero.reply_to_human": self._end,
|
||||
"Deployer.deploy_to_public": self.deployer.deploy_to_public,
|
||||
}
|
||||
)
|
||||
else:
|
||||
|
|
@ -98,6 +101,7 @@ class Engineer2(RoleZero):
|
|||
"CodeReview.review": cr.review,
|
||||
"CodeReview.fix": cr.fix,
|
||||
"Terminal.run_command": self.terminal.run_command,
|
||||
"Deployer.deploy_to_public": self.deployer.deploy_to_public,
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ class RoleZero(Role):
|
|||
tools: list[str] = [] # Use special symbol ["<all>"] to indicate use of all registered tools
|
||||
tool_recommender: Optional[ToolRecommender] = None
|
||||
tool_execution_map: Annotated[dict[str, Callable], Field(exclude=True)] = {}
|
||||
special_tool_commands: list[str] = ["Plan.finish_current_task", "end", "Bash.run", "RoleZero.ask_human"]
|
||||
special_tool_commands: list[str] = ["Plan.finish_current_task", "end", "Terminal.run_command", "RoleZero.ask_human"]
|
||||
# List of exclusive tool commands.
|
||||
# If multiple instances of these commands appear, only the first occurrence will be retained.
|
||||
exclusive_tool_commands: list[str] = [
|
||||
|
|
@ -543,7 +543,7 @@ class RoleZero(Role):
|
|||
return end_output
|
||||
return human_response
|
||||
# output from bash.run may be empty, add decorations to the output to ensure visibility.
|
||||
elif cmd["command_name"] == "Bash.run":
|
||||
elif cmd["command_name"] == "Terminal.run_command":
|
||||
tool_obj = self.tool_execution_map[cmd["command_name"]]
|
||||
tool_output = await tool_obj(**cmd["args"])
|
||||
if len(tool_output) <= 10:
|
||||
|
|
|
|||
|
|
@ -839,19 +839,27 @@ Explanation: I will first need to read the system design document and the projec
|
|||
}
|
||||
]
|
||||
```
|
||||
## example 2.1
|
||||
## example 2
|
||||
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.2
|
||||
## example 3
|
||||
User Requirement: Writing code.
|
||||
The template is :
|
||||
├── public
|
||||
├── src
|
||||
│ ├── App.jsx
|
||||
│ ├── index.css
|
||||
│ └── main.jsx
|
||||
└── vite.config.js
|
||||
|
||||
Here's 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.
|
||||
1. **Task 1**: Rewrite `App.jsx` - 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.
|
||||
If the project is a Vue or React Project, install the dependencies after finishing project. And then deploy the project to the public.
|
||||
```json
|
||||
[
|
||||
{
|
||||
|
|
@ -894,15 +902,15 @@ Here's the plan:
|
|||
"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.",
|
||||
"dependent_task_ids": [],
|
||||
"instruction": "Install the necessary dependencies, configure the project structure and deploy it to the public",
|
||||
"assignee": "Alex"
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## example 3
|
||||
## example 4
|
||||
Explanation: Take on one task, such as writing or rewriting a file. Upon completion, finish current task.
|
||||
|
||||
```json
|
||||
|
|
@ -919,8 +927,31 @@ Explanation: Take on one task, such as writing or rewriting a file. Upon complet
|
|||
}
|
||||
]
|
||||
```
|
||||
## example 5
|
||||
Explanation: The project have been completed. And this project is a Vue/React Project,so i will deploy the project to the public.
|
||||
|
||||
## example 4
|
||||
```json
|
||||
[
|
||||
{
|
||||
"command_name": "Terminal.run_command",
|
||||
"args": {
|
||||
"cmd": "pnpm install && pnpm run build"
|
||||
}
|
||||
}
|
||||
]
|
||||
## example 6
|
||||
Explanation: After install the project. I will deploy the project to the public.
|
||||
```json
|
||||
[
|
||||
{
|
||||
"command_name": "Deployer.deploy_to_public,
|
||||
"args": {
|
||||
"dist_dir": "{{project_path}}/dist"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
## example 7
|
||||
I have received a GitHub issue URL.
|
||||
I will use browser to review the detailed information of this issue in order to understand the problem.
|
||||
```json
|
||||
|
|
@ -934,7 +965,7 @@ I will use browser to review the detailed information of this issue in order to
|
|||
]
|
||||
```
|
||||
|
||||
## example 6
|
||||
## example 8
|
||||
I need to locating the `openai_api.py` file, so I will search for the `openai_api.py` file.
|
||||
```json
|
||||
[
|
||||
|
|
@ -949,7 +980,7 @@ I need to locating the `openai_api.py` file, so I will search for the `openai_ap
|
|||
|
||||
|
||||
|
||||
## example 7
|
||||
## example 9
|
||||
I have located the openai_api.py file. I want to edit this file, so I will open it first.
|
||||
```json
|
||||
[
|
||||
|
|
@ -962,7 +993,7 @@ I have located the openai_api.py file. I want to edit this file, so I will open
|
|||
]
|
||||
```
|
||||
|
||||
## example 8
|
||||
## example 10
|
||||
I have opened the openai_api.py file. However, the range of lines shown is from 001 to 100, and I want to see more. Therefore, I want to use the scroll_down command to view additional lines.
|
||||
```json
|
||||
[
|
||||
|
|
@ -973,7 +1004,7 @@ I have opened the openai_api.py file. However, the range of lines shown is from
|
|||
]
|
||||
```
|
||||
|
||||
## example 9
|
||||
## example 11
|
||||
I want to change the key bindings from (w/s) to the arrow keys (up, down). And add the space bar to pause.
|
||||
the previous file look like:
|
||||
142| while not self.is_game_over():
|
||||
|
|
@ -1000,7 +1031,7 @@ Editor tool is exclusive. If I use this tool, I cannot use any other commands in
|
|||
]
|
||||
```
|
||||
|
||||
## example 10
|
||||
## example 12
|
||||
I want to add a score variable in the initialization of the game.
|
||||
the previous file look like:
|
||||
028| if restart:
|
||||
|
|
@ -1032,7 +1063,7 @@ After executing the command, the file will be:
|
|||
033| self.location = (0,0)
|
||||
In the next turn, I will try to add another code snippet
|
||||
|
||||
## example 11
|
||||
## example 13
|
||||
|
||||
Create a pull request (Optional): Merge the changes from the new branch into the master branch.
|
||||
Thought: Now that the changes have been pushed to the remote repository, due to the user's requirement, let's create a pull request to merge the changes into the master branch.
|
||||
|
|
@ -1053,7 +1084,7 @@ Thought: Now that the changes have been pushed to the remote repository, due to
|
|||
]
|
||||
```
|
||||
|
||||
## example 12
|
||||
## example 14
|
||||
The requirement is to create a product website featuring goods such as caps, dresses, and T-shirts.
|
||||
I believe pictures would improve the site, so I will get the images first.
|
||||
```json
|
||||
|
|
|
|||
|
|
@ -1,11 +1,26 @@
|
|||
from metagpt.tools.tool_registry import register_tool
|
||||
from metagpt.utils.report import ServerReporter
|
||||
|
||||
|
||||
# An un-implemented tool reserved for deploying a local service to public
|
||||
@register_tool()
|
||||
@register_tool(
|
||||
include_functions=[
|
||||
"deploy_to_public",
|
||||
]
|
||||
)
|
||||
class Deployer:
|
||||
"""Deploy a local service to public. Used only for final deployment, you should NOT use it for development and testing."""
|
||||
|
||||
def deploy_to_public(self, local_url: str):
|
||||
ServerReporter().report(local_url, "local_url")
|
||||
async def static_server(self, src_path: str) -> str:
|
||||
"""This function will be implemented in the remote service."""
|
||||
return f"http://127.0.0.1:{8000}/index.html"
|
||||
|
||||
async def deploy_to_public(self, dist_dir: str):
|
||||
"""
|
||||
Deploy a web project to public.
|
||||
Args:
|
||||
dist_dir (str): The dist directory of the web project after run build.
|
||||
>>>
|
||||
deployer = Deployer("2048_game/dist")
|
||||
"""
|
||||
url = await self.static_server(dist_dir)
|
||||
return "The Project is deployed to: " + url + "\n Deployment successed!"
|
||||
|
|
|
|||
|
|
@ -26,6 +26,11 @@ class Terminal:
|
|||
self.stdout_queue = Queue(maxsize=1000)
|
||||
self.observer = TerminalReporter()
|
||||
self.process: Optional[asyncio.subprocess.Process] = None
|
||||
# The cmd in forbidden_terminal_commands will be replace by pass ana return the advise. example:{"cmd":"forbidden_reason/advice"}
|
||||
self.forbidden_commands = {
|
||||
"npm run dev": "Use Deployer.deploy_to_public instead.",
|
||||
"pnpm run dev": "Use Deployer.deploy_to_public instead.",
|
||||
}
|
||||
|
||||
async def _start_process(self):
|
||||
# Start a persistent shell process
|
||||
|
|
@ -60,6 +65,14 @@ class Terminal:
|
|||
if self.process is None:
|
||||
await self._start_process()
|
||||
|
||||
output = ""
|
||||
# Remove forbidden commands
|
||||
for cmd_name, reason in self.forbidden_commands.items():
|
||||
# 'true' is a pass command in linux terminal.
|
||||
if cmd_name in cmd:
|
||||
cmd = cmd.replace(cmd_name, "true")
|
||||
output += f"{cmd_name} is failed to executed. {reason}\n"
|
||||
|
||||
# Send the command
|
||||
self.process.stdin.write((cmd + self.command_terminator).encode())
|
||||
self.process.stdin.write(
|
||||
|
|
@ -68,9 +81,10 @@ class Terminal:
|
|||
await self.process.stdin.drain()
|
||||
if daemon:
|
||||
asyncio.create_task(self._read_and_process_output(cmd))
|
||||
return ""
|
||||
else:
|
||||
return await self._read_and_process_output(cmd)
|
||||
output += await self._read_and_process_output(cmd)
|
||||
|
||||
return output
|
||||
|
||||
async def execute_in_conda_env(self, cmd: str, env, daemon=False) -> str:
|
||||
"""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue