mirror of
https://github.com/Pythagora-io/gpt-pilot.git
synced 2026-01-09 13:17:55 -05:00
Merge pull request #1007 from Pythagora-io/lab
fixes for a few minor issues:
fix implement_changes during iteration and fix triggering I'm stuck in a loop
fix when we are getting relevant files and describing new files
add iteration index to steps and fix sending stats to extension
when sending relevant files in prompt, use both relevant and modified files
This commit is contained in:
@@ -72,12 +72,13 @@ class CodeMonkey(BaseAgent):
|
||||
attempt = 1
|
||||
feedback = None
|
||||
|
||||
iterations = self.current_state.iterations
|
||||
llm = self.get_llm()
|
||||
convo = self._get_task_convo().template(
|
||||
"implement_changes",
|
||||
file_name=file_name,
|
||||
file_content=file_content,
|
||||
instructions=task["instructions"],
|
||||
instructions=iterations[-1]["description"] if iterations else task["instructions"],
|
||||
)
|
||||
if feedback:
|
||||
convo.assistant(f"```\n{self.prev_response.data['new_content']}\n```\n").template(
|
||||
|
||||
@@ -67,20 +67,6 @@ class Developer(BaseAgent):
|
||||
if self.prev_response and self.prev_response.type == ResponseType.TASK_REVIEW_FEEDBACK:
|
||||
return await self.breakdown_current_iteration(self.prev_response.data["feedback"])
|
||||
|
||||
# If any of the files are missing metadata/descriptions, those need to be filled-in
|
||||
missing_descriptions = [file.path for file in self.current_state.files if not file.meta.get("description")]
|
||||
if missing_descriptions:
|
||||
log.debug(f"Some files are missing descriptions: {', '.join(missing_descriptions)}, reqesting analysis")
|
||||
return AgentResponse.describe_files(self)
|
||||
|
||||
log.debug(
|
||||
f"Current state files: {len(self.current_state.files)}, relevant {self.current_state.relevant_files or []}"
|
||||
)
|
||||
# Check which files are relevant to the current task
|
||||
if self.current_state.files and self.current_state.relevant_files is None:
|
||||
await self.get_relevant_files()
|
||||
return AgentResponse.done(self)
|
||||
|
||||
if not self.current_state.unfinished_tasks:
|
||||
log.warning("No unfinished tasks found, nothing to do (why am I called? is this a bug?)")
|
||||
return AgentResponse.done(self)
|
||||
@@ -133,6 +119,8 @@ class Developer(BaseAgent):
|
||||
self.current_state.current_task["description"],
|
||||
source,
|
||||
"in-progress",
|
||||
self.current_state.get_source_index(source),
|
||||
self.current_state.tasks,
|
||||
)
|
||||
llm = self.get_llm()
|
||||
# FIXME: In case of iteration, parse_task depends on the context (files, tasks, etc) set there.
|
||||
@@ -172,11 +160,18 @@ class Developer(BaseAgent):
|
||||
self.current_state.current_task["description"],
|
||||
source,
|
||||
"in-progress",
|
||||
self.current_state.get_source_index(source),
|
||||
self.current_state.tasks,
|
||||
)
|
||||
|
||||
log.debug(f"Breaking down the current task: {task['description']}")
|
||||
await self.send_message("Thinking about how to implement this task ...")
|
||||
|
||||
log.debug(f"Current state files: {len(self.current_state.files)}, relevant {self.current_state.relevant_files}")
|
||||
# Check which files are relevant to the current task
|
||||
if self.current_state.files and self.current_state.relevant_files is None:
|
||||
await self.get_relevant_files()
|
||||
|
||||
current_task_index = self.current_state.tasks.index(task)
|
||||
|
||||
llm = self.get_llm()
|
||||
@@ -236,6 +231,7 @@ class Developer(BaseAgent):
|
||||
"id": uuid4().hex,
|
||||
"completed": False,
|
||||
"source": source,
|
||||
"iteration_index": len(self.current_state.iterations),
|
||||
**step.model_dump(),
|
||||
}
|
||||
for step in response.steps
|
||||
@@ -248,6 +244,7 @@ class Developer(BaseAgent):
|
||||
"completed": False,
|
||||
"type": "review_task",
|
||||
"source": source,
|
||||
"iteration_index": len(self.current_state.iterations),
|
||||
},
|
||||
]
|
||||
log.debug(f"Next steps: {self.next_state.unfinished_steps}")
|
||||
|
||||
@@ -150,7 +150,15 @@ class Orchestrator(BaseAgent):
|
||||
# If there are any new or modified files changed outside Pythagora,
|
||||
# this is a good time to add them to the project. If any of them have
|
||||
# INPUT_REQUIRED, we'll first ask the user to provide the required input.
|
||||
return await self.import_files()
|
||||
import_files_response = await self.import_files()
|
||||
|
||||
# If any of the files are missing metadata/descriptions, those need to be filled-in
|
||||
missing_descriptions = [file.path for file in self.current_state.files if not file.meta.get("description")]
|
||||
if missing_descriptions:
|
||||
log.debug(f"Some files are missing descriptions: {', '.join(missing_descriptions)}, requesting analysis")
|
||||
return AgentResponse.describe_files(self)
|
||||
|
||||
return import_files_response
|
||||
|
||||
def create_agent(self, prev_response: Optional[AgentResponse]) -> BaseAgent:
|
||||
state = self.current_state
|
||||
@@ -291,7 +299,7 @@ class Orchestrator(BaseAgent):
|
||||
async def update_stats(self):
|
||||
if self.current_state.steps and self.current_state.current_step:
|
||||
source = self.current_state.current_step.get("source")
|
||||
source_steps = [s for s in self.current_state.steps if s.get("source") == source]
|
||||
source_steps = self.current_state.get_last_iteration_steps()
|
||||
await self.ui.send_step_progress(
|
||||
source_steps.index(self.current_state.current_step) + 1,
|
||||
len(source_steps),
|
||||
|
||||
@@ -14,12 +14,16 @@ class TaskCompleter(BaseAgent):
|
||||
self.next_state.action = f"Task #{current_task_index1} complete"
|
||||
self.next_state.complete_task()
|
||||
await self.state_manager.log_task_completed()
|
||||
tasks = self.current_state.tasks
|
||||
source = self.current_state.current_epic.get("source", "app")
|
||||
await self.ui.send_task_progress(
|
||||
self.current_state.tasks.index(self.current_state.current_task) + 1,
|
||||
len(self.current_state.tasks),
|
||||
tasks.index(self.current_state.current_task) + 1,
|
||||
len(tasks),
|
||||
self.current_state.current_task["description"],
|
||||
self.current_state.current_epic.get("source", "app"),
|
||||
source,
|
||||
"done",
|
||||
self.current_state.get_source_index(source),
|
||||
tasks,
|
||||
)
|
||||
|
||||
return AgentResponse.done(self)
|
||||
|
||||
@@ -46,7 +46,7 @@ class Troubleshooter(IterationPromptMixin, BaseAgent):
|
||||
|
||||
# Developer sets iteration as "completed" when it generates the step breakdown, so we can't
|
||||
# use "current_iteration" here
|
||||
last_iteration = self.current_state.iterations[-1] if self.current_state.iterations else None
|
||||
last_iteration = self.current_state.iterations[-1] if len(self.current_state.iterations) >= 3 else None
|
||||
|
||||
should_iterate, is_loop, user_feedback = await self.get_user_feedback(
|
||||
run_command,
|
||||
|
||||
@@ -168,8 +168,11 @@ class ProjectState(Base):
|
||||
|
||||
:return: List of tuples with file path and content.
|
||||
"""
|
||||
relevant = self.relevant_files or []
|
||||
return [file for file in self.files if file.path in relevant]
|
||||
relevant_files = self.relevant_files or []
|
||||
modified_files = self.modified_files or {}
|
||||
|
||||
all_files = set(relevant_files + list(modified_files.keys()))
|
||||
return [file for file in self.files if file.path in all_files]
|
||||
|
||||
@staticmethod
|
||||
def create_initial_state(branch: "Branch") -> "ProjectState":
|
||||
@@ -386,3 +389,29 @@ class ProjectState(Base):
|
||||
ProjectState.step_index > self.step_index,
|
||||
)
|
||||
)
|
||||
|
||||
def get_last_iteration_steps(self) -> list:
|
||||
"""
|
||||
Get the steps of the last iteration.
|
||||
|
||||
:return: A list of steps.
|
||||
"""
|
||||
return [s for s in self.steps if s.get("iteration_index") == len(self.iterations)] or self.steps
|
||||
|
||||
def get_source_index(self, source: str) -> int:
|
||||
"""
|
||||
Get the index of the source which can be one of: 'app', 'feature', 'troubleshooting', 'review'. For example,
|
||||
for feature return value would be number of current feature.
|
||||
|
||||
:param source: The source to search for.
|
||||
:return: The index of the source.
|
||||
"""
|
||||
if source in ["app", "feature"]:
|
||||
return len([epic for epic in self.epics if epic.get("source") == source])
|
||||
elif source == "troubleshooting":
|
||||
return len(self.iterations)
|
||||
elif source == "review":
|
||||
steps = self.get_last_iteration_steps()
|
||||
return len([step for step in steps if step.get("type") == "review_task"])
|
||||
|
||||
return 1
|
||||
|
||||
@@ -178,12 +178,15 @@ class StateManager:
|
||||
)
|
||||
|
||||
if self.current_state.current_epic and self.current_state.current_task and self.ui:
|
||||
source = self.current_state.current_epic.get("source", "app")
|
||||
await self.ui.send_task_progress(
|
||||
self.current_state.tasks.index(self.current_state.current_task) + 1,
|
||||
len(self.current_state.tasks),
|
||||
self.current_state.current_task["description"],
|
||||
self.current_state.current_epic.get("source", "app"),
|
||||
source,
|
||||
"in-progress",
|
||||
self.current_state.get_source_index(source),
|
||||
self.current_state.tasks,
|
||||
)
|
||||
|
||||
return self.current_state
|
||||
|
||||
@@ -169,6 +169,7 @@ class UIBase:
|
||||
source: str,
|
||||
status: str,
|
||||
source_index: int = 1,
|
||||
tasks: list[dict] = None,
|
||||
):
|
||||
"""
|
||||
Send a task progress update to the UI.
|
||||
@@ -179,6 +180,7 @@ class UIBase:
|
||||
:param source: Source of the task, one of: 'app', 'feature', 'debugger', 'troubleshooting', 'review'.
|
||||
:param status: Status of the task, can be 'in_progress' or 'done'.
|
||||
:param source_index: Index of the source.
|
||||
:param tasks: List of all tasks.
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
@@ -89,6 +89,7 @@ class PlainConsoleUI(UIBase):
|
||||
source: str,
|
||||
status: str,
|
||||
source_index: int = 1,
|
||||
tasks: list[dict] = None,
|
||||
):
|
||||
pass
|
||||
|
||||
|
||||
@@ -262,6 +262,7 @@ class IPCClientUI(UIBase):
|
||||
source: str,
|
||||
status: str,
|
||||
source_index: int = 1,
|
||||
tasks: list[dict] = None,
|
||||
):
|
||||
await self._send(
|
||||
MessageType.PROGRESS,
|
||||
@@ -273,7 +274,8 @@ class IPCClientUI(UIBase):
|
||||
"source": source,
|
||||
"status": status,
|
||||
"source_index": source_index,
|
||||
}
|
||||
},
|
||||
"all_tasks": tasks,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user