Skip to content

Commit 958479f

Browse files
committed
add logs for all agents and actions
1 parent 47dcbe2 commit 958479f

13 files changed

+77
-26
lines changed

pilot/database/database.py

+20-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def get_created_apps_with_steps():
6868

6969
for dev_step in app['development_steps']:
7070
# Filter out unwanted keys first
71-
filtered_step = {k: v for k, v in dev_step.items() if k in {'id', 'created_at', 'prompt_path'}}
71+
filtered_step = {k: v for k, v in dev_step.items() if k in {'id', 'prompt_path'}}
7272

7373
if 'breakdown' in filtered_step['prompt_path']:
7474
filtered_step['name'] = f"Task {task_counter}"
@@ -94,6 +94,13 @@ def get_created_apps_with_steps():
9494
# Update the dev_step in the list
9595
new_development_steps.append(filtered_step)
9696

97+
last_step = get_last_development_step(app['id'])
98+
if last_step:
99+
new_development_steps.append({
100+
'id': last_step['id'],
101+
'prompt_path': last_step['prompt_path'],
102+
'name': 'Latest Step',
103+
})
97104
app['development_steps'] = new_development_steps
98105

99106
return apps
@@ -116,6 +123,18 @@ def get_all_app_development_steps(app_id, last_step=None, loading_steps_only=Fal
116123
return [model_to_dict(dev_step) for dev_step in query]
117124

118125

126+
def get_last_development_step(app_id, last_step=None):
127+
last_dev_step_query = DevelopmentSteps.select().where(DevelopmentSteps.app == app_id)
128+
if last_step is not None:
129+
last_dev_step_query = last_dev_step_query.where(DevelopmentSteps.id <= last_step)
130+
131+
# Order by ID in descending order to get the last step and fetch the first result
132+
last_dev_step = last_dev_step_query.order_by(DevelopmentSteps.id.desc()).first()
133+
134+
# If a step is found, convert it to a dictionary, otherwise return None
135+
return model_to_dict(last_dev_step) if last_dev_step else None
136+
137+
119138
def save_user(user_id, email, password):
120139
try:
121140
user = User.get(User.id == user_id)

pilot/helpers/AgentConvo.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,8 @@ def log_message(self, content):
238238
if self.log_to_user:
239239
if self.agent.project.checkpoints['last_development_step'] is not None:
240240
dev_step_msg = f'\nDev step {str(self.agent.project.checkpoints["last_development_step"]["id"])}\n'
241-
print(color_yellow_bold(dev_step_msg), end='')
241+
if not self.agent.project.check_ipc():
242+
print(color_yellow_bold(dev_step_msg), end='')
242243
logger.info(dev_step_msg)
243244
print(f"\n{content}\n", type='local')
244245
logger.info(f"{print_msg}: {content}\n")

pilot/helpers/Debugger.py

+1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ def debug(self, convo, command=None, user_input=None, issue_description=None, is
6666
user_input = answer
6767
self.agent.project.current_task.add_user_input_to_debugging_task(user_input)
6868

69+
print('', type='verbose', category='agent:debugger')
6970
llm_response = convo.send_message('dev_ops/debug.prompt',
7071
{
7172
'command': command['command'] if command is not None else None,

pilot/helpers/Project.py

+11-3
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,6 @@ def __init__(
102102
self.tasks_to_load = []
103103
self.features_to_load = []
104104
self.dev_steps_to_load = []
105-
if self.continuing_project:
106-
self.setup_loading()
107105
# end loading of project
108106

109107
def set_root_path(self, root_path: str):
@@ -167,9 +165,13 @@ def start(self):
167165
if not test_api_access(self):
168166
return False
169167

168+
if self.continuing_project:
169+
self.setup_loading()
170+
170171
self.project_manager = ProductOwner(self)
171172
self.spec_writer = SpecWriter(self)
172173

174+
print('', type='verbose', category='agent:product-owner')
173175
self.project_manager.get_project_description(self.spec_writer)
174176
self.project_manager.get_user_stories()
175177
# self.user_tasks = self.project_manager.get_user_tasks()
@@ -183,6 +185,7 @@ def start(self):
183185
self.developer.set_up_environment()
184186
self.technical_writer = TechnicalWriter(self)
185187

188+
print('', type='verbose', category='agent:tech-lead')
186189
self.tech_lead = TechLead(self)
187190
self.tech_lead.create_development_plan()
188191

@@ -210,13 +213,15 @@ def finish(self):
210213

211214
self.previous_features = get_features_by_app_id(self.args['app_id'])
212215
if not self.skip_steps:
216+
print('', type='verbose', category='pythagora')
213217
feature_description = ask_user(self, "Project is finished! Do you want to add any features or changes? "
214218
"If yes, describe it here and if no, just press ENTER",
215219
require_some_input=False)
216220

217221
if feature_description == '':
218222
return
219223

224+
print('', type='verbose', category='agent:tech-lead')
220225
self.tech_lead.create_feature_plan(feature_description)
221226

222227
# loading of features
@@ -248,6 +253,7 @@ def finish(self):
248253

249254
self.current_feature = feature_description
250255
self.developer.start_coding('feature')
256+
print('', type='verbose', category='agent:tech-lead')
251257
self.tech_lead.create_feature_summary(feature_description)
252258

253259
def get_directory_tree(self, with_descriptions=False):
@@ -544,7 +550,9 @@ def delete_all_steps_except_current_branch(self):
544550
delete_unconnected_steps_from(self.checkpoints['last_command_run'], 'previous_step')
545551
delete_unconnected_steps_from(self.checkpoints['last_user_input'], 'previous_step')
546552

547-
def ask_for_human_intervention(self, message, description=None, cbs={}, convo=None, is_root_task=False, add_loop_button=False):
553+
def ask_for_human_intervention(self, message, description=None, cbs={}, convo=None, is_root_task=False,
554+
add_loop_button=False, category='human-intervention'):
555+
print('', type='verbose', category=category)
548556
answer = ''
549557
question = color_yellow_bold(message)
550558

pilot/helpers/agents/Developer.py

+19-8
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ def __init__(self, project):
4545
self.debugger = Debugger(self)
4646

4747
def start_coding(self, task_source):
48+
print('', type='verbose', category='agent:developer')
4849
if not self.project.finished:
4950
self.project.current_step = 'coding'
5051
update_app_status(self.project.args['app_id'], self.project.current_step)
@@ -67,6 +68,7 @@ def start_coding(self, task_source):
6768
if current_progress_percent > threshold and threshold not in documented_thresholds:
6869
if not self.project.skip_steps:
6970
self.project.technical_writer.document_project(current_progress_percent)
71+
print('', type='verbose', category='agent:developer')
7072
documented_thresholds.add(threshold)
7173

7274
if self.project.tasks_to_load:
@@ -101,14 +103,14 @@ def start_coding(self, task_source):
101103
update_app_status(self.project.args['app_id'], self.project.current_step)
102104
message = 'The app is DONE!!! Yay...you can use it now.\n'
103105
logger.info(message)
104-
print(color_green_bold(message))
106+
print(color_green_bold(message), category='success')
105107
if not self.project.skip_steps:
106108
telemetry.set("end_result", "success:initial-project")
107109
telemetry.send()
108110
else:
109111
message = 'Feature complete!\n'
110112
logger.info(message)
111-
print(color_green_bold(message))
113+
print(color_green_bold(message), category='success')
112114
if not self.project.skip_steps:
113115
telemetry.set("end_result", "success:feature")
114116
telemetry.send()
@@ -121,7 +123,7 @@ def implement_task(self, i, task_source, development_task=None):
121123
:param task_source: The source of the task, one of: 'app', 'feature', 'debugger', 'iteration'.
122124
:param development_task: The task to implement.
123125
"""
124-
print(color_green_bold(f'Implementing task #{i + 1}: ') + color_green(f' {development_task["description"]}\n'))
126+
print(color_green_bold(f'Implementing task #{i + 1}: ') + color_green(f' {development_task["description"]}\n'), category='agent:developer')
125127
self.project.dot_pilot_gpt.chat_log_folder(i + 1)
126128

127129
convo_dev_task = AgentConvo(self)
@@ -495,6 +497,13 @@ def execute_task(self, convo, task_steps, test_command=None, reset_convo=True,
495497
"""
496498
function_uuid = str(uuid.uuid4())
497499
convo.save_branch(function_uuid)
500+
agent_map = {
501+
'app': 'agent:developer',
502+
'feature': 'agent:developer',
503+
'debugger': 'agent:debugger',
504+
'troubleshooting': 'agent:troubleshooter',
505+
'review': 'agent:reviewer',
506+
}
498507

499508
for (i, step) in enumerate(task_steps):
500509
print_step_progress(i+1, len(task_steps), step, task_source)
@@ -525,20 +534,19 @@ def execute_task(self, convo, task_steps, test_command=None, reset_convo=True,
525534
convo.load_branch(function_uuid)
526535

527536
if step['type'] == 'command':
528-
print('', type='verbose', category='command run')
529537
result = self.step_command_run(convo, task_steps, i, success_with_cli_response=need_to_see_output)
530538
# if need_to_see_output and 'cli_response' in result:
531539
# result['user_input'] = result['cli_response']
532540

533541
elif step['type'] in ['save_file', 'modify_file', 'code_change']:
534-
print('', type='verbose', category='save file')
542+
print('', type='verbose', category='agent:code-monkey')
535543
result = self.step_save_file(convo, step, i, test_after_code_changes)
536544

537545
elif step['type'] == 'delete_file':
538546
result = self.step_delete_file(convo, step, i, test_after_code_changes)
539547

540548
elif step['type'] == 'human_intervention':
541-
print('', type='verbose', category='human intervention')
549+
print('', type='verbose', category='human-intervention')
542550
result = self.step_human_intervention(convo, task_steps, i)
543551

544552
# TODO background_command - if we run commands in background we should have way to kill processes
@@ -547,7 +555,7 @@ def execute_task(self, convo, task_steps, test_command=None, reset_convo=True,
547555
# terminate_named_process(step['kill_process'])
548556
# result = {'success': True}
549557

550-
print('', type='verbose', category='agent:developer')
558+
print('', type='verbose', category=agent_map[task_source])
551559
logger.info(' step result: %s', result)
552560

553561
if (not result['success']) or (need_to_see_output and result.get("user_input") != "SKIP"):
@@ -628,7 +636,8 @@ def continue_development(self, iteration_convo, last_branch_name, continue_descr
628636
return_cli_response=True, is_root_task=True)},
629637
convo=iteration_convo,
630638
is_root_task=True,
631-
add_loop_button=iteration_count > 3)
639+
add_loop_button=iteration_count > 3,
640+
category='human-test')
632641

633642
logger.info('response: %s', response)
634643
self.review_count = 0
@@ -638,6 +647,7 @@ def continue_development(self, iteration_convo, last_branch_name, continue_descr
638647
return {"success": True, "user_input": user_feedback}
639648

640649
if user_feedback is not None:
650+
print('', type='verbose', category='agent:troubleshooter')
641651
user_feedback = self.bug_report_generator(user_feedback)
642652
stuck_in_loop = user_feedback.startswith(STUCK_IN_LOOP)
643653
if stuck_in_loop:
@@ -761,6 +771,7 @@ def review_task(self):
761771
Review all task changes and refactor big files.
762772
:return: bool - True if the task changes passed review, False if not
763773
"""
774+
print('', type='verbose', category='agent:reviewer')
764775
self.review_count += 1
765776
review_result = self.review_code_changes()
766777
refactoring_done = self.refactor_code()

pilot/helpers/agents/ProductOwner.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def __init__(self, project):
2323
def get_project_description(self, spec_writer):
2424
print(json.dumps({
2525
"project_stage": "project_description"
26-
}), type='info')
26+
}), type='info', category='agent:product-owner')
2727

2828
self.project.app = get_app(self.project.args['app_id'], error_if_not_found=False)
2929

pilot/helpers/agents/TechnicalWriter.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@ def __init__(self, project):
1212

1313
def document_project(self, percent):
1414
files = self.project.get_all_coded_files()
15-
print(f'{color_green_bold("CONGRATULATIONS!!!")}')
15+
print(f'{color_green_bold("CONGRATULATIONS!!!")}', category='success')
1616
print(f'You reached {color_green(str(percent) + "%")} of your project generation!\n\n')
1717
print('For now, you have created:\n')
1818
print(f'{color_green(len(files))} files\n')
1919
print(f'{color_green(count_lines_of_code(files))} lines of code\n\n')
2020
print('Before continuing, GPT Pilot will create some documentation for the project...\n')
21+
print('', type='verbose', category='agent:tech-writer')
2122
self.create_license()
2223
self.create_readme()
2324
self.create_api_documentation()

pilot/helpers/cli.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ def execute_command(project, command, timeout=None, success_message=None, comman
194194
If `cli_response` not None: 'was interrupted by user', 'timed out' or `None` - caller should send `cli_response` to LLM
195195
exit_code (int): The exit code of the process.
196196
"""
197+
print('', type='verbose', category='exec-command')
197198
project.finish_loading()
198199
if timeout is not None:
199200
if timeout < 0:
@@ -216,7 +217,6 @@ def execute_command(project, command, timeout=None, success_message=None, comman
216217
logger.info('--------- EXECUTE COMMAND ---------- : %s', question)
217218
answer = ask_user(project, question, False, hint='If yes, just press ENTER. Otherwise, type "no" but it will be processed as successfully executed.')
218219
# TODO can we use .confirm(question, default='yes').ask() https://questionary.readthedocs.io/en/stable/pages/types.html#confirmation
219-
print('answer: ' + answer)
220220
if answer.lower() in NEGATIVE_ANSWERS:
221221
return None, 'SKIP', None
222222
elif answer.lower() not in AFFIRMATIVE_ANSWERS:

pilot/main.py

+1
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ def init():
126126
print('Exit', type='exit')
127127

128128
except Exception as err:
129+
print('', type='verbose', category='error')
129130
print(color_red('---------- GPT PILOT EXITING WITH ERROR ----------'))
130131
traceback.print_exc()
131132
print(color_red('--------------------------------------------------'))

pilot/prompts/prompts.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def ask_for_main_app_definition(project):
5555
def ask_user(project, question: str, require_some_input=True, hint: str = None, ignore_user_input_count: bool = False):
5656
while True:
5757
if hint is not None:
58-
print(color_white_bold(hint) + '\n', type='hint')
58+
print(color_white_bold(hint) + '\n')
5959
project.finish_loading()
6060
answer = styled_text(project, question, hint=hint, ignore_user_input_count=ignore_user_input_count)
6161

pilot/utils/custom_print.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import builtins
22
from helpers.ipc import IPCClient
33
from const.ipc import MESSAGE_TYPE, LOCAL_IGNORE_MESSAGE_TYPES
4+
from utils.print import remove_ansi_codes
45

56

67
def get_custom_print(args):
@@ -19,7 +20,7 @@ def print_to_external_process(*args, **kwargs):
1920
ipc_client_instance.send({
2021
'type': MESSAGE_TYPE[kwargs['type']],
2122
'category': kwargs['category'] if 'category' in kwargs else '',
22-
'content': message,
23+
'content': remove_ansi_codes(message),
2324
})
2425
if kwargs['type'] == MESSAGE_TYPE['user_input_request']:
2526
return ipc_client_instance.listen()

pilot/utils/print.py

+13
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import re
2+
3+
14
def print_task_progress(index, num_of_tasks, description, task_source, status):
25
"""
36
Print task progress in extension.
@@ -36,3 +39,13 @@ def print_step_progress(index, num_of_steps, step, task_source):
3639
'step': step,
3740
'source': task_source,
3841
}}, type='progress')
42+
43+
44+
def remove_ansi_codes(s: str) -> str:
45+
ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
46+
# Check if the input is a string
47+
if isinstance(s, str):
48+
return ansi_escape.sub('', s)
49+
else:
50+
# If the input is not a string, return the input as is
51+
return s

pilot/utils/questionary.py

+3-8
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
import platform
22
import questionary
3-
import re
43
import sys
54
from database.database import save_user_input
65
from utils.style import style_config
7-
8-
9-
def remove_ansi_codes(s: str) -> str:
10-
ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
11-
return ansi_escape.sub('', s)
6+
from utils.print import remove_ansi_codes
127

138

149
def styled_select(*args, **kwargs):
@@ -29,7 +24,6 @@ def styled_text(project, question, ignore_user_input_count=False, style=None, hi
2924

3025
if project is not None and project.check_ipc():
3126
response = print(question, type='user_input_request')
32-
print(response)
3327
else:
3428
used_style = style if style is not None else style_config.get_style()
3529
question = remove_ansi_codes(question) # Colorama and questionary are not compatible and styling doesn't work
@@ -39,7 +33,8 @@ def styled_text(project, question, ignore_user_input_count=False, style=None, hi
3933
if not ignore_user_input_count:
4034
save_user_input(project, question, response, hint)
4135

42-
print('\n\n', end='')
36+
if project is not None and not project.check_ipc():
37+
print('\n\n', end='')
4338
return response
4439

4540

0 commit comments

Comments
 (0)