Merge pull request #678 from Pythagora-io/development

Development
This commit is contained in:
LeonOstrez
2024-02-23 14:49:30 -08:00
committed by GitHub
30 changed files with 380 additions and 78 deletions

View File

@@ -3,3 +3,4 @@ MAX_RECURSION_LAYER = 3
MIN_COMMAND_RUN_TIME = 2000 # 2sec
MAX_COMMAND_RUN_TIME = 60000 # 1min
MAX_COMMAND_OUTPUT_LENGTH = 50000
MAX_QUESTIONS_FOR_BUG_REPORT = 5

View File

@@ -49,3 +49,32 @@ IGNORE_PATHS = DEFAULT_IGNORE_PATHS + [
]
IGNORE_SIZE_THRESHOLD = 50000 # 50K+ files are ignored by default
PROMPT_DATA_TO_IGNORE = {'directory_tree', 'name'}
EXAMPLE_PROJECT_DESCRIPTION = (
"A simple webchat application in node/express using MongoDB. "
"Use Bootstrap and jQuery on the frontend, for a simple, clean UI. "
"Use socket.io for real-time communication between backend and frontend.\n\n"
"Visiting http://localhost:3000/, users must first log in or create an account using "
"a username and a password (no email required).\n\n"
"Once authenticated, on the home screen users see list of active chat rooms and a button to create a new chat. "
"They can either click a link to one of the chat rooms which redirects them to `/<chat-id>/` "
"or click the button to create a new chat. Creating a new chat should ask for the chat name, "
"and then create a new chat with that name (which doesn't need to be unique), and a unique chat id. "
"The user should then be redirected to the chat page.\n\n"
"Chat page should have the chat name as the title. There's no possibility to edit chat name. "
"Below that, show previous messages in the chat (these should get loaded from the database "
"whenever the user visits the page so the user sees previous conversation in that chat - "
"no pagination, entire history should be loaded). "
"User has a text field and a button 'send' to send the message "
"(pressing enter in the text field should also send the message). "
"There's also a button to change user's nickname (default is equal to username, "
"there's no need to store the nickname in the user's profile).\n\n"
"Sent messages should be immediately shown to other participants in the same chat (use socket.io), "
"and stored in the database (forever - no message expiry). "
"All messages are text-only: no image upload, no embedding, no special markup in the messages. "
"There's no message size limit. Also, there's no need to notify/alert user of new messages, or keep track of unread messages.\n\n"
"All channels are available to all authenticated users, there are no private messages. "
"Anonymous users can't see or join any chat rooms, the can only log in or create an account. "
"No moderation, filtering or any admin functionality is required. Keep everything else as simple as possible."
)

View File

@@ -476,7 +476,7 @@ GET_DOCUMENTATION_FILE = {
REVIEW_CHANGES = {
'definitions': [{
'name': 'review_diff',
'description': 'Review a unified diff and select hunks to apply.',
'description': 'Review a unified diff and select hunks to apply or rework.',
'parameters': {
"type": "object",
"properties": {
@@ -491,12 +491,12 @@ REVIEW_CHANGES = {
},
"reason": {
"type": "string",
"desciprion": "Reason for applying or ignoring this hunk."
"description": "Reason for applying or ignoring this hunk, or for asking for it to be reworked."
},
"decision": {
"type": "string",
"enum": ["apply", "ignore"],
"description": "Whether to apply this hunk (if it's a valid change) or ignore it."
"enum": ["apply", "ignore", "rework"],
"description": "Whether to apply this hunk (if it's a valid change with no problems), rework (a valid change but does something incorrectly), or ignore it (unwanted change)."
}
},
"required": ["number", "reason", "decision"],
@@ -512,3 +512,40 @@ REVIEW_CHANGES = {
}
}],
}
GET_BUG_REPORT_MISSING_DATA = {
'definitions': [{
'name': 'bug_report_missing_data',
'description': 'Review bug report and identify missing data. List questions that need to be answered to proceed with the bug fix. If no additional questions are needed missing_data should be an empty array.',
'parameters': {
"type": "object",
"properties": {
"reasoning": {
"type": "string",
"description": "Reasoning for asking these questions or for not asking any questions."
},
"missing_data": {
"type": "array",
"items": {
"type": "object",
"properties": {
"category": {
"type": "string",
"enum": ["general", "frontend", "backend", "database", "devops", "other"],
"description": "Category of the question."
},
"question": {
"type": "string",
"description": "Very clear question that needs to be answered to have good bug report.",
},
},
"required": ["category", "question"],
"additionalProperties": False
},
}
},
"required": ["reasoning", "missing_data"],
"additionalProperties": False
}
}],
}

View File

@@ -19,6 +19,7 @@ MESSAGE_TYPE = {
LOCAL_IGNORE_MESSAGE_TYPES = [
'info',
'project_folder_name',
'run_command',
'button',
'buttons-only',
'exit',

View File

@@ -10,7 +10,7 @@ from const.messages import CHECK_AND_CONTINUE, AFFIRMATIVE_ANSWERS, NEGATIVE_ANS
from utils.style import color_yellow_bold, color_cyan, color_white_bold, color_red_bold
from const.common import STEPS
from database.database import delete_unconnected_steps_from, delete_all_app_development_data, \
get_all_app_development_steps, delete_all_subsequent_steps
get_all_app_development_steps, delete_all_subsequent_steps, get_features_by_app_id
from const.ipc import MESSAGE_TYPE
from prompts.prompts import ask_user
from helpers.exceptions import TokenLimitError, GracefulExit
@@ -88,6 +88,8 @@ class Project:
self.package_dependencies = []
self.project_template = None
self.development_plan = None
self.previous_features = None
self.current_feature = None
self.dot_pilot_gpt = DotGptPilot(log_chat_completions=True)
if os.getenv("AUTOFIX_FILE_PATHS", "").lower() in ["true", "1", "yes"]:
@@ -203,6 +205,8 @@ class Project:
feature_description = ''
if not self.features_to_load:
self.finish_loading()
self.previous_features = get_features_by_app_id(self.args['app_id'])
if not self.skip_steps:
feature_description = ask_user(self, "Project is finished! Do you want to add any features or changes? "
"If yes, describe it here and if no, just press ENTER",
@@ -240,6 +244,7 @@ class Project:
feature_description = current_feature['prompt_data']['feature_description']
self.features_to_load = []
self.current_feature = feature_description
self.developer.start_coding()
self.tech_lead.create_feature_summary(feature_description)

View File

@@ -8,6 +8,7 @@ from helpers.AgentConvo import AgentConvo
from helpers.Agent import Agent
from helpers.files import get_file_contents
from const.function_calls import GET_FILE_TO_MODIFY, REVIEW_CHANGES
from logger.logger import logger
from utils.exit import trace_code_event
from utils.telemetry import telemetry
@@ -97,13 +98,25 @@ class CodeMonkey(Agent):
files,
)
# Review the changes and only apply changes that are useful/approved
if content and content != file_content:
content = self.review_change(convo, code_change_description, file_name, file_content, content)
for i in range(MAX_REVIEW_RETRIES):
if not content or content == file_content:
# There are no changes or there was problem talking with the LLM, we're done here
break
content, rework_feedback = self.review_change(convo, code_change_description, file_name, file_content, content)
if not rework_feedback:
# No rework needed, we're done here
break
content = convo.send_message('development/review_feedback.prompt', {
"content": content,
"original_content": file_content,
"rework_feedback": rework_feedback,
})
if content:
content = self.remove_backticks(content)
# If we have changes, update the file
# TODO: if we *don't* have changes, we might want to retry the whole process (eg. have the reviewer
# explicitly reject the whole PR and use that as feedback in implement_changes.prompt)
if content and content != file_content:
if not self.project.skip_steps:
delta_lines = len(content.splitlines()) - len(file_content.splitlines())
@@ -143,12 +156,22 @@ class CodeMonkey(Agent):
"file_name": file_name,
"files": files,
})
convo.remove_last_x_messages(2)
return self.remove_backticks(llm_response)
@staticmethod
def remove_backticks(content: str) -> str:
"""
Remove optional backticks from the beginning and end of the content.
:param content: content to remove backticks from
:return: content without backticks
"""
start_pattern = re.compile(r"^\s*```([a-z0-9]+)?\n")
end_pattern = re.compile(r"\n```\s*$")
llm_response = start_pattern.sub("", llm_response)
llm_response = end_pattern.sub("", llm_response)
convo.remove_last_x_messages(2)
return llm_response
content = start_pattern.sub("", content)
content = end_pattern.sub("", content)
return content
def identify_file_to_change(self, code_changes_description: str, files: list[dict]) -> str:
"""
@@ -172,7 +195,7 @@ class CodeMonkey(Agent):
file_name: str,
old_content: str,
new_content: str
) -> str:
) -> tuple[str, str]:
"""
Review changes that were applied to the file.
@@ -184,7 +207,7 @@ class CodeMonkey(Agent):
:param file_name: name of the file being modified
:param old_content: old file content
:param new_content: new file content (with proposed changes)
:return: file content update with approved changes
:return: tuple with file content update with approved changes, and review feedback
Diff hunk explanation: https://www.gnu.org/software/diffutils/manual/html_node/Hunks.html
"""
@@ -200,20 +223,25 @@ class CodeMonkey(Agent):
messages_to_remove = 2
for i in range(MAX_REVIEW_RETRIES):
reasons = {}
ids_to_apply = set()
ids_to_ignore = set()
ids_to_rework = set()
for hunk in llm_response.get("hunks", []):
reasons[hunk["number"] - 1] = hunk["reason"]
if hunk.get("decision", "").lower() == "apply":
ids_to_apply.add(hunk["number"] - 1)
elif hunk.get("decision", "").lower() == "ignore":
ids_to_ignore.add(hunk["number"] - 1)
elif hunk.get("decision", "").lower() == "rework":
ids_to_rework.add(hunk["number"] - 1)
n_hunks = len(hunks)
n_review_hunks = len(ids_to_apply | ids_to_ignore)
n_review_hunks = len(reasons)
if n_review_hunks == n_hunks:
break
elif n_review_hunks < n_hunks:
error = "Not all hunks have been reviewed. Please review all hunks and add 'apply' or 'ignore' decision for each."
error = "Not all hunks have been reviewed. Please review all hunks and add 'apply', 'ignore' or 'rework' decision for each."
elif n_review_hunks > n_hunks:
error = f"Your review contains more hunks ({n_review_hunks}) than in the original diff ({n_hunks}). Note that one hunk may have multiple changed lines."
@@ -235,23 +263,37 @@ class CodeMonkey(Agent):
hunks_to_apply = [ h for i, h in enumerate(hunks) if i in ids_to_apply ]
diff_log = f"--- {file_name}\n+++ {file_name}\n" + "\n".join(hunks_to_apply)
hunks_to_rework = [ (i, h) for i, h in enumerate(hunks) if i in ids_to_rework ]
review_log = "\n\n".join([
f"## Change\n```{hunk}```\nReviewer feedback:\n{reasons[i]}" for (i, hunk) in hunks_to_rework
]) + "\n\nReview notes:\n" + llm_response["review_notes"]
if len(hunks_to_apply) == len(hunks):
print("Applying entire change")
return new_content
logger.info(f"Applying entire change to {file_name}")
return new_content, None
elif len(hunks_to_apply) == 0:
print("Reviewer has doubts, but applying all proposed changes anyway")
trace_code_event(
"modify-file-review-reject-all",
{
"file": file_name,
"original": old_content,
"diff": f"--- {file_name}\n+++ {file_name}\n" + "\n".join(hunks),
}
)
return new_content
if hunks_to_rework:
print(f"Requesting rework for {len(hunks_to_rework)} changes with reason: {llm_response['review_notes']}")
logger.info(f"Requesting rework for {len(hunks_to_rework)} changes to {file_name} (0 hunks to apply)")
return old_content, review_log
else:
# If everything can be safely ignored, it's probably because the files already implement the changes
# from previous tasks (which can happen often). Insisting on a change here is likely to cause problems.
print(f"Rejecting entire change with reason: {llm_response['review_notes']}")
logger.info(f"Rejecting entire change to {file_name} with reason: {llm_response['review_notes']}")
return old_content, None
print("Applying code change:\n" + diff_log)
logger.info(f"Applying code change to {file_name}:\n{diff_log}")
new_content = self.apply_diff(file_name, old_content, hunks_to_apply, new_content)
if hunks_to_rework:
print(f"Requesting rework for {len(hunks_to_rework)} changes with reason: {llm_response['review_notes']}")
logger.info(f"Requesting further rework for {len(hunks_to_rework)} changes to {file_name}")
return new_content, review_log
else:
print("Applying code change:\n" + diff_log)
return self.apply_diff(file_name, old_content, hunks_to_apply, new_content)
return new_content, None
@staticmethod
def get_diff_hunks(file_name: str, old_content: str, new_content: str) -> list[str]:

View File

@@ -15,7 +15,7 @@ from utils.style import (
color_white_bold
)
from helpers.exceptions import TokenLimitError
from const.code_execution import MAX_COMMAND_DEBUG_TRIES
from const.code_execution import MAX_COMMAND_DEBUG_TRIES, MAX_QUESTIONS_FOR_BUG_REPORT
from helpers.exceptions import TooDeepRecursionError
from helpers.Debugger import Debugger
from utils.questionary import styled_text
@@ -26,7 +26,8 @@ from helpers.Agent import Agent
from helpers.AgentConvo import AgentConvo
from utils.utils import should_execute_step, array_of_objects_to_string, generate_app_data
from helpers.cli import run_command_until_success, execute_command_and_check_cli_response
from const.function_calls import EXECUTE_COMMANDS, GET_TEST_TYPE, IMPLEMENT_TASK, COMMAND_TO_RUN, ALTERNATIVE_SOLUTIONS
from const.function_calls import (EXECUTE_COMMANDS, GET_TEST_TYPE, IMPLEMENT_TASK, COMMAND_TO_RUN,
ALTERNATIVE_SOLUTIONS, GET_BUG_REPORT_MISSING_DATA)
from database.database import save_progress, get_progress_steps, update_app_status
from utils.telemetry import telemetry
from prompts.prompts import ask_user
@@ -134,7 +135,9 @@ class Developer(Agent):
"files": self.project.get_all_coded_files(),
"architecture": self.project.architecture,
"technologies": self.project.system_dependencies + self.project.package_dependencies,
"task_type": 'feature' if self.project.finished else 'app'
"task_type": 'feature' if self.project.finished else 'app',
"previous_features": self.project.previous_features,
"current_feature": self.project.current_feature,
})
instructions_prefix = " ".join(instructions.split()[:5])
@@ -602,6 +605,7 @@ class Developer(Agent):
return {"success": True, "user_input": user_feedback}
if user_feedback is not None:
user_feedback = self.bug_report_generator(user_feedback)
stuck_in_loop = user_feedback.startswith(STUCK_IN_LOOP)
if stuck_in_loop:
# Remove the STUCK_IN_LOOP prefix from the user feedback
@@ -639,7 +643,9 @@ class Developer(Agent):
"next_solution_to_try": next_solution_to_try,
"alternative_solutions_to_current_issue": alternative_solutions_to_current_issue,
"tried_alternative_solutions_to_current_issue": tried_alternative_solutions_to_current_issue,
"iteration_count": iteration_count
"iteration_count": iteration_count,
"previous_features": self.project.previous_features,
"current_feature": self.project.current_feature,
})
llm_solutions.append({
@@ -660,6 +666,61 @@ class Developer(Agent):
task_steps = llm_response['tasks']
self.execute_task(iteration_convo, task_steps, is_root_task=True)
def bug_report_generator(self, user_feedback):
"""
Generate a bug report from the user feedback.
:param user_feedback: The user feedback.
:return: The bug report.
"""
bug_report_convo = AgentConvo(self)
function_uuid = str(uuid.uuid4())
bug_report_convo.save_branch(function_uuid)
questions_and_answers = []
while True:
llm_response = bug_report_convo.send_message('development/bug_report.prompt', {
"user_feedback": user_feedback,
"app_summary": self.project.project_description,
"files": self.project.get_all_coded_files(),
"questions_and_answers": questions_and_answers,
}, GET_BUG_REPORT_MISSING_DATA)
missing_data = llm_response['missing_data']
if len(missing_data) == 0:
break
length_before = len(questions_and_answers)
for missing_data_item in missing_data:
if self.project.check_ipc():
print(missing_data_item['question'], type='verbose')
print('continue/skip question', type='button')
if self.run_command:
print(self.run_command, type='run_command')
answer = ask_user(self.project, missing_data_item['question'], require_some_input=False)
if answer.lower() == 'skip question' or answer.lower() == '' or answer.lower() == 'continue':
continue
questions_and_answers.append({
"question": missing_data_item['question'],
"answer": answer
})
# if user skips all questions or if we got more than 4 answers, we don't want to get stuck in infinite loop
if length_before == len(questions_and_answers) or len(questions_and_answers) >= MAX_QUESTIONS_FOR_BUG_REPORT:
break
bug_report_convo.load_branch(function_uuid)
if len(questions_and_answers):
bug_report_summary_convo = AgentConvo(self)
user_feedback = bug_report_summary_convo.send_message('development/bug_report_summary.prompt', {
"app_summary": self.project.project_description,
"user_feedback": user_feedback,
"questions_and_answers": questions_and_answers,
})
return user_feedback
def review_task(self):
"""
Review all task changes and refactor big files.
@@ -700,6 +761,8 @@ class Developer(Agent):
"user_input": self.user_feedback,
"modified_files": self.modified_files,
"files_at_start_of_task": files_at_start_of_task,
"previous_features": self.project.previous_features,
"current_feature": self.project.current_feature,
})
instructions_prefix = " ".join(review.split()[:5])
@@ -867,6 +930,8 @@ class Developer(Agent):
"user_input": user_feedback,
"previous_solutions": previous_solutions,
"tried_alternative_solutions_to_current_issue": tried_alternative_solutions_to_current_issue,
"previous_features": self.project.previous_features,
"current_feature": self.project.current_feature,
}, ALTERNATIVE_SOLUTIONS)
next_solution_to_try_index = self.ask_user_for_next_solution(response['alternative_solutions'])

View File

@@ -9,6 +9,7 @@ from utils.files import setup_workspace
from prompts.prompts import ask_for_app_type, ask_for_main_app_definition, ask_user
from const.llm import END_RESPONSE
from const.messages import MAX_PROJECT_NAME_LENGTH
from const.common import EXAMPLE_PROJECT_DESCRIPTION
PROJECT_DESCRIPTION_STEP = 'project_description'
USER_STORIES_STEP = 'user_stories'
@@ -39,31 +40,41 @@ class ProductOwner(Agent):
# PROJECT DESCRIPTION
self.project.current_step = PROJECT_DESCRIPTION_STEP
is_example_project = False
if 'app_type' not in self.project.args:
self.project.args['app_type'] = ask_for_app_type()
if 'name' not in self.project.args:
while True:
question = 'What is the project name?'
print(question, type='ipc')
print('start an example project', type='button')
project_name = ask_user(self.project, question)
if len(project_name) <= MAX_PROJECT_NAME_LENGTH:
break
else:
print(f"Hold your horses cowboy! Please, give project NAME with max {MAX_PROJECT_NAME_LENGTH} characters.")
if project_name.lower() == 'start an example project':
is_example_project = True
project_name = 'Example Project'
self.project.args['name'] = clean_filename(project_name)
self.project.app = save_app(self.project)
self.project.set_root_path(setup_workspace(self.project.args))
print(color_green_bold(
"GPT Pilot currently works best for web app projects using Node, Express and MongoDB. "
"You can use it with other technologies, but you may run into problems "
"(eg. React might not work as expected).\n"
))
self.project.main_prompt = ask_for_main_app_definition(self.project)
if is_example_project:
print(EXAMPLE_PROJECT_DESCRIPTION)
self.project.main_prompt = EXAMPLE_PROJECT_DESCRIPTION
else:
print(color_green_bold(
"GPT Pilot currently works best for web app projects using Node, Express and MongoDB. "
"You can use it with other technologies, but you may run into problems "
"(eg. React might not work as expected).\n"
))
self.project.main_prompt = ask_for_main_app_definition(self.project)
print(json.dumps({'open_project': {
#'uri': 'file:///' + self.project.root_path.replace('\\', '/'),

View File

@@ -62,7 +62,6 @@ class TechLead(Agent):
def create_feature_plan(self, feature_description):
self.save_dev_steps = True
self.convo_feature_plan = AgentConvo(self)
previous_features = get_features_by_app_id(self.project.args['app_id'])
llm_response = self.convo_feature_plan.send_message('development/feature_plan.prompt',
{
@@ -74,9 +73,8 @@ class TechLead(Agent):
"architecture": self.project.architecture,
"technologies": self.project.system_dependencies + self.project.package_dependencies,
"directory_tree": self.project.get_directory_tree(True),
"development_tasks": self.project.development_plan,
"files": self.project.get_all_coded_files(),
"previous_features": previous_features,
"previous_features": self.project.previous_features,
"feature_description": feature_description,
"task_type": 'feature',
}, DEVELOPMENT_PLAN)

View File

@@ -38,6 +38,8 @@ class TechnicalWriter(Agent):
"user_tasks": self.project.user_tasks,
"directory_tree": self.project.get_directory_tree(True),
"files": self.project.get_all_coded_files(),
"previous_features": self.project.previous_features,
"current_feature": self.project.current_feature,
}, GET_DOCUMENTATION_FILE)
self.project.save_file(llm_response)

View File

@@ -5,6 +5,7 @@ If the project requirements call out for specific technology, use that. Otherwis
Here are the details for the new project:
-----------------------------
{{ project_details }}
{{ features_list }}
-----------------------------
Based on these details, think step by step to design the architecture for the project and choose technologies to use in building it.

View File

@@ -0,0 +1,13 @@
{% if previous_features %}
Here is the list of features that were previously implemented on top of initial high level description of "{{ name }}":
```
{% for feature in previous_features %}
- {{ loop.index }}. {{ feature['summary'] }}
{% endfor %}
```
{% endif %}{% if current_feature %}Here is the feature that you are implementing right now:
```
{{ current_feature }}
```
{% endif %}

View File

@@ -0,0 +1,40 @@
Here is description of app that you are working on:
```
{{ app_summary }}
```
{{ files_list }}
Client wrote this feedback:
```
{{ user_feedback }}
```
{% if questions_and_answers|length > 0 %}
Here are questions and answers that you already asked the client:
```{% for row in questions_and_answers %}
Q: {{ row.question }}
A: {{ row.answer }}
{% endfor %}
```{% endif %}
Your job is to identify if feedback is good enough for you to solve the problem. If not, what information you need to solve the problem. Ask for any information that you need to solve the problem.
If you have enough information don't ask any questions.
When thinking of questions, consider the following:
- After getting answers to your questions, you must be able to solve the problem.
- Category on which you need more information ("general", "frontend", "backend", "database", "devops", "other")
- Client is not very technical person but understands basics. It is crucial that your questions can be answered without looking into code or knowing codebase. Do not ask how something is implemented, how code works or for code snippets.
- Make sure to cover all categories that you need to solve the problem.
- Ask only specific information that you need to solve the problem.
- Ask clear, short and concise questions.
- Ask only crucial questions. Do not ask for information that you do not need to solve the problem.
- Ask least amount of questions to get the most information.
- Ask least amount of questions to solve the problem.
Here are some examples of good questions:
"Are there any logs in browser?"
"Can you provide logs from server?"
"What is the error message?"
"What is the expected behavior?"
"What is the actual behavior?"
"What is the stack trace?"

View File

@@ -0,0 +1,28 @@
You are working on this app:
```
{{ app_summary }}
```
User came to you with this bug report:
```
{{ user_feedback }}
```
You didn't have enough information to start working on it, so you asked the user to provide more details.
Here are questions and answers that you asked the user:
```{% for row in questions_and_answers %}
Q: {{ row.question }}
A: {{ row.answer }}
{% endfor %}
```
Your job is now to write issue explanation that will be sent to developer, strictly following these rules:
- If there are some logs you MUST copy all logs in whole! Do not omit any logs! This is also true for code snippets or stack traces!
- Explanation must be very clear and factual, keep it as short as possible.
- When writing explanation of the issue, it is good to cover all categories that you have information on. If you don't have information about one category, then don't mention it. Here are categories: "general", "frontend", "backend", "database", "devops", "other".
- Omit all information that turns out to be irrelevant for this issue (e.g. after asking additional questions it turns out that first user message is not relevant then you should ignore it)
- Write issue explanation as if you are talking directly to developer (in first person). Do not mention "user", talk as if you found the the issue.
- Do not use any subjective thoughts, just facts.
- Write only issue explanation. Do not write any recap, summary or ideas how to solve the problem at the end. Do not write introduction at the start (e.g. "Issue Explanation for Developer:").
- Do not write any new code, only if something is provided by user.
- Have in mind that developer is smart and he will understand everything as long as you provide all information that you have and that is needed to fix this issue.
- Have in mind that issue might not be related to your current development task.

View File

@@ -1,19 +1,7 @@
You are working in a software development agency and a project manager and software architect approach you telling you that you're assigned to add new feature to an existing project. You are working on a {{ app_type }} called "{{ name }}" and you need to create a detailed development plan so that developers can start developing the new feature.
{{ project_details }}
Here are development tasks that specify what was already coded:
```
{{ development_tasks }}
```
{% if previous_features and previous_features|length > 0 %}
After those tasks, new features were added to {{ app_type }} ""{{ name }}"". Here is a list of all features that are already implemented:
{% for feature in previous_features %}
- {{ loop.index }}. {{ feature['summary'] }}
{% endfor %}
{% endif %}
{{ features_list }}
Here is directory tree that shows current folder structure of project:
```
{{ directory_tree }}

View File

@@ -4,7 +4,7 @@ Here is a high level description of "{{ name }}":
```
{{ app_summary }}
```
{{ features_list }}
Project architecture:
{{ architecture }}

View File

@@ -10,7 +10,10 @@ the full contents of the updated file, without skipping over any content
```
------------------------end_of_format---------------------------
**IMPORTANT**:If the instructions have comments like `// ..add code here...` or `# placeholder for code`, instead of copying the comment, interpret the instructions and output the relevant code.
**IMPORTANT**: Your reply MUST NOT omit any code in the new implementation or substitute anything with comments like `// .. rest of the code goes here ..` or `# insert existing code here`, because I will overwrite the existing file with the content you provide. Output ONLY the content for this file, without additional explanation, suggestions or notes. Your output MUST start with ``` and MUST end with ``` and include only the complete file contents.
**IMPORTANT**: If the user must configure something manually, mark the line that needs user configuration with `INPUT_REQUIRED {input_description}` comment, where `input_description` is a description of what needs to be added here by the user. Use appropriate syntax for comments in the file you're saving (for example `// INPUT_REQUIRED {input_description}` in JavaScript). If the file type doesn't support comments (eg JSON), don't add any.
**IMPORTANT**: For hardcoded configuration values that the user needs to change, mark the line that needs user configuration with `INPUT_REQUIRED {config_description}` comment, where `config_description` is a description of the value that needs to be set by the user. Use appropriate syntax for comments in the file you're saving (for example `// INPUT_REQUIRED {config_description}` in JavaScript). NEVER ask the user to write code or provide implementation, even if the instructions suggest it! If the file type doesn't support comments (eg JSON), don't add any.
{{ logs_and_error_handling }}

View File

@@ -4,7 +4,7 @@ Here is a high level description of "{{ name }}":
```
{{ app_summary }}
```
{{ features_list }}
Project architecture:
{{ architecture }}

View File

@@ -4,7 +4,7 @@ Each step can be either:
* `command` - command to run (must be able to run on a {{ os }} machine, assume current working directory is project root folder)
* `save_file` - create or update ONE file
* `human_intervention` - if you need the human to do something, use this type of step and explain in details what you want the human to do. NEVER use `human_intervention` for testing, as testing will be done separately by a dedicated QA after all the steps are done.
* `human_intervention` - if you need the human to do something, use this type of step and explain in details what you want the human to do. NEVER use `human_intervention` for testing, as testing will be done separately by a dedicated QA after all the steps are done. Also you MUST NOT use `human_intervention` to ask the human to write or review code.
**IMPORTANT**: In `code_change_description` field of `save_file` step, you must provide empty string. If multiple changes are required for same file, you must provide single `save_file` step for each file.

View File

@@ -1,7 +1,7 @@
You are working in a software development agency and a project manager and software architect approach you telling you that you're assigned to work on a new project. You are working on a {{ app_type }} called "{{ name }}" and you need to create a detailed development plan so that developers can start developing the app.
{{ project_details }}
{{ features_list }}
{% if files %}The developers have already used a project scaffolding tool that creates the initial boilerplate for the project:
{{ existing_summary }}

View File

@@ -15,11 +15,16 @@ Here is the diff of the changes:
As you can see, there {% if hunks|length == 1 %}is only one hunk in this diff, and it{% else %}are {{hunks|length}} hunks in this diff, and each{% endif %} starts with the `@@` header line.
Think carefully about the instructions and review the proposed changes. For each hunk of change, provide a detailed rationale, and decide whether it should be applied or should be ignored (for example if it is a code deletion or change that wasn't asked for). Finally, if the changes miss something that was in the instructions, mention that. Keep in mind you're just reviewing one file, `{{ file_name }}`. You don't need to consider if other files are created, dependent packages installed, etc. Focus only on reviewing the changes in this file based on the instructions in the previous message.
Think carefully about the instructions and review the proposed changes. For each hunk of change, provide a detailed rationale, and decide whether it should be:
* applied - if the change is correct
* ignored - for example if it is a code deletion or change that wasn't asked for
* reworked - if the change does something correctly but also makes a serious mistake, in which case both applying and ignoring the entire hunk would be incorrect
Note that the developer may add, modify or delete logging (including `gpt_pilot_debugging_log`) or error handling that's not explicitly asked for, but is a part of good development practice. Unless these logging and error handling additions break something, you should not ignore those changes. Base your decision only on functional changes - comments or logging are less important.
Finally, if the changes miss something that was in the instructions, mention that. Keep in mind you're just reviewing one file, `{{ file_name }}`. You don't need to consider if other files are created, dependent packages installed, etc. Focus only on reviewing the changes in this file based on the instructions in the previous message.
Here is an example output if 3 of 4 hunks in the change should be applied and one of them should be ignored, and no other changes are needed:
Note that the developer may add, modify or delete logging (including `gpt_pilot_debugging_log`) or error handling that's not explicitly asked for, but is a part of good development practice. Unless these logging and error handling additions break something, your decision to apply, ignore or rework the hunk should not be based on this. Base your decision only on functional changes - comments or logging are less important. Importantly, don't ask for a rework just because of logging or error handling changes. Also, take into account this is a junior developer and while the approach they take may not be the best practice, if it's not *wrong*, let it pass. Ask for rework only if the change is clearly bad and would break something.
Here is an example output if 2 of 4 hunks in the change should be applied, one of them should be ignored, one should be reworked, and no other changes are needed:
```
{
"hunks": [
@@ -35,13 +40,13 @@ Here is an example output if 3 of 4 hunks in the change should be applied and on
},
{
"number": 3,
"reason": "This hunk accidentally deletes important code",
"reason": "This hunk accidentally deletes important code without any useful change",
"decision": "ignore"
},
{
"number": 4,
"reason": "Explanation why the fourth hunk should be included in the change",
"decision": "apply"
"reason": "This hunk does something correctly but also does something really wrong. It would be incorrect to either apply or ignore it fully, so it should be reworked.",
"decision": "rework"
},
],
"review_notes": "General review notes, if something is missing from the change you can comment about it here"

View File

@@ -0,0 +1,17 @@
Your changes have been reviewed.
{% if content != original_content %}
THe reviewer approved and applied some of your changes, but requested you rework the others.
Here's the file with the approved changes already applied:
```
{{ content }}
```
Here's the reviewer's feedback:
{% else %}
The reviewer requested that you rework your changes, here's the feedback:
{% endif %}
{{ rework_feedback }}
Based on this feedback and the original instructions, think carefully, make the correct changes, and output the entire file again. Remember, Output ONLY the content for this file, without additional explanation, suggestions or notes. Your output MUST start with ``` and MUST end with ``` and include only the complete file contents.

View File

@@ -4,7 +4,7 @@ Here is a high level description of "{{ name }}":
```
{{ app_summary }}
```
{{ features_list }}
Development process of this app was split into smaller tasks. Here is the list of all tasks:
```{% for task in tasks %}
{{ loop.index }}. {{ task['description'] }}
@@ -50,14 +50,15 @@ Now I will show you how those files looked before this task implementation start
You have to review this task implementation. You are known to be very strict with your reviews and very good at noticing bugs but you don't mind minor changes like refactoring, adding or removing logs and so on. You think twice through all information given before giving any conclusions.
Each task goes through multiple reviews and you have to focus only on your part of review.
Your goal is to check:
In this review, your goal is to check:
1. If there are some functionalities that were removed but are still needed.
2. If new files or functions are created but never called or used.
3. If there is some "dead code" that should be removed.
4. If there is some duplicate code resulting from refactoring or moving code into separate classes or files.
If everything is ok respond only with "DONE" and nothing else. Do NOT respond with thoughts, reasoning, explanations or anything similar if everything is ok, respond just with "DONE".
If you find any of these 3 mistakes describe shortly what has to be changed.
If you find any of these 4 mistakes, describe in detail what has to be changed.
{{ execution_order }}

View File

@@ -1,7 +1,7 @@
You are working on a {{ app_type }} called "{{ name }}" and you need to write code for the entire {{ task_type }} based on the tasks that the tech lead gives you. So that you understand better what you're working on, you're given other specs for "{{ name }}" as well.
{{ project_details }}
{{ features_list }}
{{ files_list }}
We've broken the development of this {{ task_type }} down to these tasks:

View File

@@ -1,7 +1,7 @@
You are working on a {{ app_type }} called "{{ name }}" and you need to create a detailed documentation for current state of project. Your first task is to create README.md file.
{{ project_details }}
{{ features_list }}
{{ files_list }}
DO NOT specify commands to create any folders or files, they will be created automatically - just specify the relative path to file that needs to be written.

View File

@@ -1,5 +1,6 @@
import os
from typing import TYPE_CHECKING, Optional
from uuid import uuid4
from utils.style import color_green_bold
from logger.logger import logger
@@ -51,6 +52,7 @@ def apply_project_template(
{
"project_name": project_name,
"project_description": project_description,
"random_secret": uuid4().hex,
},
)

View File

@@ -0,0 +1,8 @@
# Port to listen on (example: 3000)
PORT=3000
# MongoDB database URL (example: mongodb://localhost/dbname)
DATABASE_URL=mongodb://localhost/myDb # INPUT_REQUIRED {insert your MongoDB url here}
# Session secret string (must be unique to your server)
SESSION_SECRET={{ random_secret }}

View File

@@ -36,7 +36,7 @@ mongoose
process.exit(1);
});
// Session configuration with connect-mongo
// Session configuration with connect-mongo
app.use(
session({
secret: process.env.SESSION_SECRET,
@@ -54,13 +54,15 @@ app.on("error", (error) => {
// Logging session creation and destruction
app.use((req, res, next) => {
const sess = req.session;
// Make session available to all views
res.locals.session = sess;
if (!sess.views) {
sess.views = 1;
console.log("Session created at: ", new Date().toISOString());
} else {
sess.views++;
console.log(
`Session accessed again at: ${new Date().toISOString()}, Views: ${sess.views}`,
`Session accessed again at: ${new Date().toISOString()}, Views: ${sess.views}, User ID: ${sess.userId || '(unauthenticated)'}`,
);
}
next();

View File

@@ -1,6 +1,6 @@
<head>
<meta charset="UTF-8">
<title>A3 Time Tracker</title>
<title>{{ project_name }}</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
<link rel="stylesheet" href="/css/style.css">
</head>

View File

@@ -9,9 +9,12 @@
<a class="nav-link" href="/">Home</a>
</li>
<li class="nav-item">
<% if (session && session.userId) { %>
<a class="nav-link" href="/auth/logout">Logout</a>
<% } else { %>
<a class="nav-link" href="/auth/login">Login</a>
<% } %>
</li>
</ul>
</div>
</nav>