mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-06-11 15:15:18 +02:00
include more plan status in thinking, add row num for editor
This commit is contained in:
parent
819c00a55a
commit
27157e33a0
3 changed files with 58 additions and 49 deletions
|
|
@ -22,7 +22,8 @@ If plan is created, you should track the progress and update the plan accordingl
|
|||
Pay close attention to new user message, review the conversation history, use reply_to_human to respond to new user requirement.
|
||||
Note:
|
||||
1. If you keeping encountering errors, unexpected situation, or you are not sure of proceeding, use ask_human to ask for help.
|
||||
2. Each time you finish a task, use reply_to_human to report your progress.
|
||||
2. Carefully review your progress at the current task, if your actions so far has not fulfilled the task instruction, you should continue with current task. Otherwise, finish current task.
|
||||
3. Each time you finish a task, use reply_to_human to report your progress.
|
||||
Pay close attention to the Example provided, you can reuse the example for your current situation if it fits.
|
||||
|
||||
You may use any of the available commands to create a plan or update the plan. You may output mutiple commands, they will be executed sequentially.
|
||||
|
|
|
|||
|
|
@ -73,9 +73,9 @@ class DataAnalyst(DataInterpreter):
|
|||
# TODO: implement experience retrieval in multi-round setting
|
||||
|
||||
plan_status = self.planner.plan.model_dump(include=["goal", "tasks"])
|
||||
for task in plan_status["tasks"]:
|
||||
task.pop("code")
|
||||
task.pop("result")
|
||||
# for task in plan_status["tasks"]:
|
||||
# task.pop("code")
|
||||
# task.pop("result")
|
||||
prompt = CMD_PROMPT.format(
|
||||
plan_status=plan_status,
|
||||
example=example,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import os
|
|||
import shutil
|
||||
import subprocess
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import BaseModel
|
||||
|
||||
from metagpt.tools.tool_registry import register_tool
|
||||
from metagpt.utils.report import EditorReporter
|
||||
|
|
@ -13,12 +13,6 @@ class FileBlock(BaseModel):
|
|||
|
||||
file_path: str
|
||||
block_content: str
|
||||
block_start_line: int
|
||||
block_end_line: int
|
||||
symbol: str = Field(default="", description="The symbol of interest in the block, empty if not applicable.")
|
||||
symbol_start_line: int = Field(
|
||||
default=-1, description="The line number of the symbol in the file, -1 if not applicable"
|
||||
)
|
||||
|
||||
|
||||
@register_tool()
|
||||
|
|
@ -34,13 +28,19 @@ class Editor:
|
|||
f.write(content)
|
||||
self.resource.report(path, "path")
|
||||
|
||||
def read(self, path: str) -> str:
|
||||
def read(self, path: str) -> FileBlock:
|
||||
"""Read the whole content of a file."""
|
||||
with open(path, "r") as f:
|
||||
self.resource.report(path, "path")
|
||||
return f.read()
|
||||
lines = f.readlines()
|
||||
lines_with_num = [f"{i + 1:03}|{line}" for i, line in enumerate(lines)]
|
||||
result = FileBlock(
|
||||
file_path=path,
|
||||
block_content="".join(lines_with_num),
|
||||
)
|
||||
return result
|
||||
|
||||
def search_content(self, symbol: str, root_path: str = ".", window: int = 20) -> FileBlock:
|
||||
def search_content(self, symbol: str, root_path: str = ".", window: int = 50) -> FileBlock:
|
||||
"""
|
||||
Search symbol in all files under root_path, return the context of symbol with window size
|
||||
Useful for locating class or function in a large codebase. Example symbol can be "def some_function", "class SomeClass", etc.
|
||||
|
|
@ -48,7 +48,7 @@ class Editor:
|
|||
|
||||
Args:
|
||||
symbol (str): The symbol to search.
|
||||
root_path (str, optional): The root path to search in. If not provided, search in the current directory. Defaults to ".".
|
||||
root_path (str, optional): The root path to search in, the path can be a folder or a file. If not provided, search in the current directory. Defaults to ".".
|
||||
window (int, optional): The window size to return. Defaults to 20.
|
||||
|
||||
Returns:
|
||||
|
|
@ -56,42 +56,50 @@ class Editor:
|
|||
class FileBlock(BaseModel):
|
||||
file_path: str
|
||||
block_content: str
|
||||
block_start_line: int
|
||||
block_end_line: int
|
||||
symbol: str = Field(default="", description="The symbol of interest in the block, empty if not applicable.")
|
||||
symbol_start_line: int = Field(default=-1, description="The line number of the symbol in the file, -1 if not applicable")
|
||||
"""
|
||||
if not os.path.exists(root_path):
|
||||
print(f"Currently at {os.getcwd()}. Path {root_path} does not exist.")
|
||||
return None
|
||||
not_found_msg = (
|
||||
"symbol not found, you may try searching another one, or break down your search term to search a part of it"
|
||||
)
|
||||
if os.path.isfile(root_path):
|
||||
result = self._search_content_in_file(symbol, root_path, window)
|
||||
if not result:
|
||||
print(not_found_msg)
|
||||
return result
|
||||
for root, _, files in os.walk(root_path or "."):
|
||||
for file in files:
|
||||
file_path = os.path.join(root, file)
|
||||
if not file.endswith(".py"):
|
||||
continue
|
||||
with open(file_path, "r", encoding="utf-8") as f:
|
||||
try:
|
||||
lines = f.readlines()
|
||||
except Exception:
|
||||
continue
|
||||
for i, line in enumerate(lines):
|
||||
if symbol in line:
|
||||
start = max(i - window, 0)
|
||||
end = min(i + window, len(lines) - 1)
|
||||
block_content = "".join(lines[start : end + 1])
|
||||
result = FileBlock(
|
||||
file_path=file_path,
|
||||
block_content=block_content,
|
||||
block_start_line=start + 1,
|
||||
block_end_line=end + 1,
|
||||
symbol=symbol,
|
||||
symbol_start_line=i + 1,
|
||||
)
|
||||
self.resource.report(result.file_path, "path")
|
||||
return result
|
||||
print(
|
||||
"symbol not found, you may try searching another one, or break down your search term to search a part of it"
|
||||
)
|
||||
result = self._search_content_in_file(symbol, file_path, window)
|
||||
if result:
|
||||
# FIXME: This returns the first found result, not all results.
|
||||
return result
|
||||
print(not_found_msg)
|
||||
return None
|
||||
|
||||
def _search_content_in_file(self, symbol: str, file_path: str, window: int = 50) -> FileBlock:
|
||||
print("search in", file_path)
|
||||
if not file_path.endswith(".py"):
|
||||
return None
|
||||
with open(file_path, "r", encoding="utf-8") as f:
|
||||
try:
|
||||
lines = f.readlines()
|
||||
except Exception:
|
||||
return None
|
||||
for i, line in enumerate(lines):
|
||||
if symbol in line:
|
||||
start = max(i - window, 0)
|
||||
end = min(i + window, len(lines) - 1)
|
||||
for row_num in range(start, end + 1):
|
||||
lines[row_num] = f"{(row_num + 1):03}|{lines[row_num]}"
|
||||
block_content = "".join(lines[start : end + 1])
|
||||
result = FileBlock(
|
||||
file_path=file_path,
|
||||
block_content=block_content,
|
||||
)
|
||||
self.resource.report(result.file_path, "path")
|
||||
return result
|
||||
return None
|
||||
|
||||
def write_content(self, file_path: str, start_line: int, end_line: int, new_block_content: str = "") -> str:
|
||||
|
|
@ -100,12 +108,13 @@ class Editor:
|
|||
1. If the new block content is empty, the original block will be deleted.
|
||||
2. If the new block content is not empty and end_line < start_line (e.g. set end_line = -1) the new block content will be inserted at start_line.
|
||||
3. If the new block content is not empty and end_line >= start_line, the original block from start_line to end_line (both inclusively) will be replaced by the new block content.
|
||||
This function can sometimes be used given a FileBlock upstream. Think carefully if you want to use block_start_line or symbol_start_line in the FileBlock as your start_line input. Your new_block_content will be placed at the start_line.
|
||||
This function can sometimes be used given a FileBlock upstream. You should carefully review its row number. Determine the start_line and end_line based on the row number of the FileBlock.
|
||||
The file content from start_line to end_line will be replaced by your new_block_content. DON'T replace more than you intend to.
|
||||
|
||||
Args:
|
||||
file_path (str): The file path to write the new block content.
|
||||
start_line (int): start line of the original block to be updated.
|
||||
end_line (int): end line of the original block to be updated.
|
||||
start_line (int): start line of the original block to be updated (inclusive).
|
||||
end_line (int): end line of the original block to be updated (inclusive).
|
||||
new_block_content (str): The new block content to write.
|
||||
|
||||
Returns:
|
||||
|
|
@ -130,8 +139,6 @@ class Editor:
|
|||
new_file_block = FileBlock(
|
||||
file_path=file_path,
|
||||
block_content=new_block_content,
|
||||
block_start_line=start_line,
|
||||
block_end_line=-1 if end_line < start_line else start_line + new_block_content.count("\n"),
|
||||
)
|
||||
self.resource.report(new_file_block.file_path, "path")
|
||||
|
||||
|
|
@ -143,6 +150,7 @@ class Editor:
|
|||
os.remove(temp_file_path)
|
||||
|
||||
def _write_content(self, file_path: str, start_line: int, end_line: int, new_block_content: str = ""):
|
||||
"""start_line and end_line are both 1-based indices and inclusive."""
|
||||
with open(file_path, "r") as file:
|
||||
lines = file.readlines()
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue