add Deployer tool

This commit is contained in:
黄伟韬 2024-10-11 18:31:33 +08:00
parent 67e491d97a
commit b81c00a44d
5 changed files with 73 additions and 13 deletions

View file

@ -83,8 +83,8 @@ Note:
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.
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(),

View file

@ -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)
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,
}
)

View file

@ -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,10 @@ 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":
if "npm run dev" in cmd["args"]:
command_output = "command run failed! Pleae use Delopyer to deploy your project after build."
tool_obj = self.tool_execution_map[cmd["command_name"]]
tool_output = await tool_obj(**cmd["args"])
if len(tool_output) <= 10:

View file

@ -845,13 +845,21 @@ Explanation: This is a project that needs to be implemented using Vue.js. Theref
## example 2.2
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,8 +902,8 @@ 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"
}
}
@ -919,6 +927,29 @@ Explanation: Take on one task, such as writing or rewriting a file. Upon complet
}
]
```
## example 3.2
Explanation: The project have been completed. And this project is a Vue/React Project,so i will deploy the project to the public.
```json
[
{
"command_name": "Terminal.run_command",
"args": {
"cmd": "pnpm install && pnpm run build"
}
}
]
## example 3.3
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 4
I have received a GitHub issue URL.

View file

@ -1,11 +1,33 @@
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."""
# app = aiohttp.web.Application()
# app.router.add_static('/', src_path, show_index=True)
# runner = aiohttp.web.AppRunner(app)
# await runner.setup()
# site = aiohttp.web.TCPSite(runner, "127.0.0.1", 0)
# await site.start()
# port = site._server.sockets[0].getsockname()[1]
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!"