mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-05-27 14:25:20 +02:00
merge main to dev
This commit is contained in:
commit
76d4451fc6
28 changed files with 1479 additions and 55 deletions
|
|
@ -20,17 +20,27 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
from collections import defaultdict
|
||||
from pathlib import Path
|
||||
from typing import Set
|
||||
from typing import Literal, Set
|
||||
|
||||
from metagpt.actions import Action, WriteCode, WriteCodeReview, WriteTasks
|
||||
from metagpt.actions.fix_bug import FixBug
|
||||
from metagpt.actions.project_management_an import REFINED_TASK_LIST, TASK_LIST
|
||||
from metagpt.actions.summarize_code import SummarizeCode
|
||||
from metagpt.const import SYSTEM_DESIGN_FILE_REPO, TASK_FILE_REPO
|
||||
from metagpt.actions.write_code_plan_and_change_an import WriteCodePlanAndChange
|
||||
from metagpt.const import (
|
||||
CODE_PLAN_AND_CHANGE_FILE_REPO,
|
||||
CODE_PLAN_AND_CHANGE_FILENAME,
|
||||
REQUIREMENT_FILENAME,
|
||||
SYSTEM_DESIGN_FILE_REPO,
|
||||
TASK_FILE_REPO,
|
||||
)
|
||||
from metagpt.logs import logger
|
||||
from metagpt.roles import Role
|
||||
from metagpt.schema import (
|
||||
CodePlanAndChangeContext,
|
||||
CodeSummarizeContext,
|
||||
CodingContext,
|
||||
Document,
|
||||
|
|
@ -80,7 +90,7 @@ class Engineer(Role):
|
|||
super().__init__(**kwargs)
|
||||
|
||||
self.set_actions([WriteCode])
|
||||
self._watch([WriteTasks, SummarizeCode, WriteCode, WriteCodeReview, FixBug])
|
||||
self._watch([WriteTasks, SummarizeCode, WriteCode, WriteCodeReview, FixBug, WriteCodePlanAndChange])
|
||||
self.code_todos = []
|
||||
self.summarize_todos = []
|
||||
self.next_todo_action = any_to_name(WriteCode)
|
||||
|
|
@ -88,9 +98,9 @@ class Engineer(Role):
|
|||
@staticmethod
|
||||
def _parse_tasks(task_msg: Document) -> list[str]:
|
||||
m = json.loads(task_msg.content)
|
||||
return m.get("Task list")
|
||||
return m.get(TASK_LIST.key) or m.get(REFINED_TASK_LIST.key)
|
||||
|
||||
async def _act_sp_with_cr(self, review=False) -> Set[str]:
|
||||
async def _act_sp_with_cr(self, review=False, mode: Literal["normal", "incremental"] = "normal") -> Set[str]:
|
||||
changed_files = set()
|
||||
for todo in self.code_todos:
|
||||
"""
|
||||
|
|
@ -106,9 +116,13 @@ class Engineer(Role):
|
|||
action = WriteCodeReview(i_context=coding_context, context=self.context, llm=self.llm)
|
||||
self._init_action(action)
|
||||
coding_context = await action.run()
|
||||
|
||||
dependencies = {coding_context.design_doc.root_relative_path, coding_context.task_doc.root_relative_path}
|
||||
if mode == "incremental":
|
||||
dependencies.add(os.path.join(CODE_PLAN_AND_CHANGE_FILE_REPO, CODE_PLAN_AND_CHANGE_FILENAME))
|
||||
await self.project_repo.srcs.save(
|
||||
filename=coding_context.filename,
|
||||
dependencies={coding_context.design_doc.root_relative_path, coding_context.task_doc.root_relative_path},
|
||||
dependencies=dependencies,
|
||||
content=coding_context.code_doc.content,
|
||||
)
|
||||
msg = Message(
|
||||
|
|
@ -128,6 +142,9 @@ class Engineer(Role):
|
|||
"""Determines the mode of action based on whether code review is used."""
|
||||
if self.rc.todo is None:
|
||||
return None
|
||||
if isinstance(self.rc.todo, WriteCodePlanAndChange):
|
||||
self.next_todo_action = any_to_name(WriteCode)
|
||||
return await self._act_code_plan_and_change()
|
||||
if isinstance(self.rc.todo, WriteCode):
|
||||
self.next_todo_action = any_to_name(SummarizeCode)
|
||||
return await self._act_write_code()
|
||||
|
|
@ -187,6 +204,36 @@ class Engineer(Role):
|
|||
content=json.dumps(tasks), role=self.profile, cause_by=SummarizeCode, send_to=self, sent_from=self
|
||||
)
|
||||
|
||||
async def _act_code_plan_and_change(self):
|
||||
"""Write code plan and change that guides subsequent WriteCode and WriteCodeReview"""
|
||||
logger.info("Writing code plan and change..")
|
||||
node = await self.rc.todo.run()
|
||||
code_plan_and_change = node.instruct_content.model_dump_json()
|
||||
dependencies = {
|
||||
self.rc.todo.i_context.requirement_doc.filename,
|
||||
self.rc.todo.i_context.prd_docs[0].filename,
|
||||
self.rc.todo.i_context.design_docs[0].filename,
|
||||
self.rc.todo.i_context.tasks_docs[0].filename,
|
||||
}
|
||||
|
||||
code_plan_and_change_filename = os.path.join(CODE_PLAN_AND_CHANGE_FILE_REPO, CODE_PLAN_AND_CHANGE_FILENAME)
|
||||
await self.project_repo.resources.code_plan_and_change.save(
|
||||
filename=code_plan_and_change_filename, content=code_plan_and_change, dependencies=dependencies
|
||||
)
|
||||
await self.project_repo.docs.code_plan_and_change.save(
|
||||
filename=Path(code_plan_and_change_filename).with_suffix(".md").name,
|
||||
content=node.content,
|
||||
dependencies=dependencies,
|
||||
)
|
||||
|
||||
return Message(
|
||||
content=code_plan_and_change,
|
||||
role=self.profile,
|
||||
cause_by=WriteCodePlanAndChange,
|
||||
send_to=self,
|
||||
sent_from=self,
|
||||
)
|
||||
|
||||
async def _is_pass(self, summary) -> (str, str):
|
||||
rsp = await self.llm.aask(msg=IS_PASS_PROMPT.format(context=summary), stream=False)
|
||||
logger.info(rsp)
|
||||
|
|
@ -197,11 +244,16 @@ class Engineer(Role):
|
|||
async def _think(self) -> Action | None:
|
||||
if not self.src_workspace:
|
||||
self.src_workspace = self.git_repo.workdir / self.git_repo.workdir.name
|
||||
write_code_filters = any_to_str_set([WriteTasks, SummarizeCode, FixBug])
|
||||
write_plan_and_change_filters = any_to_str_set([WriteTasks])
|
||||
write_code_filters = any_to_str_set([WriteTasks, WriteCodePlanAndChange, SummarizeCode, FixBug])
|
||||
summarize_code_filters = any_to_str_set([WriteCode, WriteCodeReview])
|
||||
if not self.rc.news:
|
||||
return None
|
||||
msg = self.rc.news[0]
|
||||
if self.config.inc and msg.cause_by in write_plan_and_change_filters:
|
||||
logger.debug(f"TODO WriteCodePlanAndChange:{msg.model_dump_json()}")
|
||||
await self._new_code_plan_and_change_action()
|
||||
return self.rc.todo
|
||||
if msg.cause_by in write_code_filters:
|
||||
logger.debug(f"TODO WriteCode:{msg.model_dump_json()}")
|
||||
await self._new_code_actions(bug_fix=msg.cause_by == any_to_str(FixBug))
|
||||
|
|
@ -296,6 +348,21 @@ class Engineer(Role):
|
|||
if self.summarize_todos:
|
||||
self.set_todo(self.summarize_todos[0])
|
||||
|
||||
async def _new_code_plan_and_change_action(self):
|
||||
"""Create a WriteCodePlanAndChange action for subsequent to-do actions."""
|
||||
requirement_doc = await self.project_repo.docs.requirement.get(REQUIREMENT_FILENAME)
|
||||
prd_docs = await self.project_repo.docs.prd.get_all()
|
||||
design_docs = await self.project_repo.docs.system_design.get_all()
|
||||
task_docs = await self.project_repo.docs.task.get_all()
|
||||
|
||||
code_plan_and_change_context = CodePlanAndChangeContext(
|
||||
requirement_doc=requirement_doc,
|
||||
prd_docs=prd_docs,
|
||||
design_docs=design_docs,
|
||||
task_docs=task_docs,
|
||||
)
|
||||
self.rc.todo = WriteCodePlanAndChange(i_context=code_plan_and_change_context, llm=self.llm)
|
||||
|
||||
@property
|
||||
def todo(self) -> str:
|
||||
"""AgentStore uses this attribute to display to the user what actions the current role should take."""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue