feat: Integrate NO_COLOR support and replace existing color functions

- Implement NO_COLOR environment variable adherence to disable colored output.
- Replace existing output color functions with the new `color_text`.
This commit is contained in:
Umpire2018
2023-10-10 15:55:47 +08:00
parent a296d0d971
commit 5143568857
18 changed files with 129 additions and 137 deletions

View File

@@ -166,6 +166,8 @@ Erase all development steps previously done and continue working on an existing
python main.py app_id=<ID_OF_THE_APP> skip_until_dev_step=0 python main.py app_id=<ID_OF_THE_APP> skip_until_dev_step=0
``` ```
## `--no-color`
Disable terminal color output
## `delete_unrelated_steps` ## `delete_unrelated_steps`

View File

@@ -23,3 +23,6 @@ DB_HOST=
DB_PORT= DB_PORT=
DB_USER= DB_USER=
DB_PASSWORD= DB_PASSWORD=
# Terminal has color or not
NO_COLOR=

View File

@@ -1,6 +1,6 @@
from playhouse.shortcuts import model_to_dict from playhouse.shortcuts import model_to_dict
from peewee import * from peewee import *
from utils.style import yellow, red from utils.style import color_text, ColorName
from functools import reduce from functools import reduce
import operator import operator
import psycopg2 import psycopg2
@@ -267,7 +267,7 @@ def hash_and_save_step(Model, app_id, unique_data_fields, data_fields, message):
.execute()) .execute())
record = Model.get_by_id(inserted_id) record = Model.get_by_id(inserted_id)
logger.debug(yellow(f"{message} with id {record.id}")) logger.debug(color_text(f"{message} with id {record.id}", ColorName.YELLOW))
except IntegrityError as e: except IntegrityError as e:
logger.warn(f"A record with data {unique_data_fields} already exists for {Model.__name__}.") logger.warn(f"A record with data {unique_data_fields} already exists for {Model.__name__}.")
return None return None
@@ -373,7 +373,7 @@ def delete_all_subsequent_steps(project):
def delete_subsequent_steps(Model, app, step): def delete_subsequent_steps(Model, app, step):
logger.info(red(f"Deleting subsequent {Model.__name__} steps after {step.id if step is not None else None}")) logger.info(color_text(f"Deleting subsequent {Model.__name__} steps after {step.id if step is not None else None}", ColorName.RED))
subsequent_steps = Model.select().where( subsequent_steps = Model.select().where(
(Model.app == app) & (Model.previous_step == (step.id if step is not None else None))) (Model.app == app) & (Model.previous_step == (step.id if step is not None else None)))
for subsequent_step in subsequent_steps: for subsequent_step in subsequent_steps:
@@ -410,7 +410,7 @@ def delete_unconnected_steps_from(step, previous_step_field_name):
).order_by(DevelopmentSteps.id.desc()) ).order_by(DevelopmentSteps.id.desc())
for unconnected_step in unconnected_steps: for unconnected_step in unconnected_steps:
print(red(f"Deleting unconnected {step.__class__.__name__} step {unconnected_step.id}")) print(color_text(f"Deleting unconnected {step.__class__.__name__} step {unconnected_step.id}", ColorName.RED))
unconnected_step.delete_instance() unconnected_step.delete_instance()

View File

@@ -1,7 +1,7 @@
import re import re
import subprocess import subprocess
import uuid import uuid
from utils.style import yellow, yellow_bold from utils.style import color_text, ColorName
from database.database import get_saved_development_step, save_development_step, delete_all_subsequent_steps from database.database import get_saved_development_step, save_development_step, delete_all_subsequent_steps
from helpers.exceptions.TokenLimitError import TokenLimitError from helpers.exceptions.TokenLimitError import TokenLimitError
@@ -55,7 +55,7 @@ class AgentConvo:
development_step = get_saved_development_step(self.agent.project) development_step = get_saved_development_step(self.agent.project)
if development_step is not None and self.agent.project.skip_steps: if development_step is not None and self.agent.project.skip_steps:
# if we do, use it # if we do, use it
print(yellow(f'Restoring development step with id {development_step.id}')) print(color_text(f'Restoring development step with id {development_step.id}', ColorName.YELLOW))
self.agent.project.checkpoints['last_development_step'] = development_step self.agent.project.checkpoints['last_development_step'] = development_step
self.agent.project.restore_files(development_step.id) self.agent.project.restore_files(development_step.id)
response = development_step.llm_response response = development_step.llm_response
@@ -131,7 +131,8 @@ class AgentConvo:
# Continue conversation until GPT response equals END_RESPONSE # Continue conversation until GPT response equals END_RESPONSE
while response != END_RESPONSE: while response != END_RESPONSE:
user_message = ask_user(self.agent.project, response, user_message = ask_user(self.agent.project, response,
hint=yellow("Do you want to add anything else? If not, ") + yellow_bold('just press ENTER.'), hint=color_text("Do you want to add anything else? If not, ", ColorName.YELLOW)
+ color_text('just press ENTER.', ColorName.YELLOW, bold=True),
require_some_input=False) require_some_input=False)
if user_message == "": if user_message == "":
@@ -191,7 +192,9 @@ class AgentConvo:
print_msg = capitalize_first_word_with_underscores(self.high_level_step) print_msg = capitalize_first_word_with_underscores(self.high_level_step)
if self.log_to_user: if self.log_to_user:
if self.agent.project.checkpoints['last_development_step'] is not None: if self.agent.project.checkpoints['last_development_step'] is not None:
print(yellow("\nDev step ") + yellow_bold(str(self.agent.project.checkpoints['last_development_step'])) + '\n', end='') print(color_text("\nDev step ")
+ color_text(str(self.agent.project.checkpoints['last_development_step']),
ColorName.YELLOW, bold=True) + '\n', end='')
print(f"\n{content}\n", type='local') print(f"\n{content}\n", type='local')
logger.info(f"{print_msg}: {content}\n") logger.info(f"{print_msg}: {content}\n")

View File

@@ -1,7 +1,7 @@
import json import json
import os import os
from typing import Tuple from typing import Tuple
from utils.style import yellow_bold, cyan, white_bold from utils.style import color_text, ColorName
from const.common import IGNORE_FOLDERS, STEPS from const.common import IGNORE_FOLDERS, STEPS
from database.database import delete_unconnected_steps_from, delete_all_app_development_data from database.database import delete_unconnected_steps_from, delete_all_app_development_data
from const.ipc import MESSAGE_TYPE from const.ipc import MESSAGE_TYPE
@@ -300,7 +300,7 @@ class Project:
development_step, created = DevelopmentSteps.get_or_create(id=development_step_id) development_step, created = DevelopmentSteps.get_or_create(id=development_step_id)
for file in files: for file in files:
print(cyan(f'Saving file {(file["path"])}/{file["name"]}')) print(color_text(f'Saving file {(file["path"])}/{file["name"]}', ColorName.CYAN))
# TODO this can be optimized so we don't go to the db each time # TODO this can be optimized so we don't go to the db each time
file_in_db, created = File.get_or_create( file_in_db, created = File.get_or_create(
app=self.app, app=self.app,
@@ -333,10 +333,11 @@ class Project:
def ask_for_human_intervention(self, message, description=None, cbs={}, convo=None, is_root_task=False): def ask_for_human_intervention(self, message, description=None, cbs={}, convo=None, is_root_task=False):
answer = '' answer = ''
question = yellow_bold(message) question = color_text(message, ColorName.YELLOW, bold=True)
if description is not None: if description is not None:
question += '\n' + '-' * 100 + '\n' + white_bold(description) + '\n' + '-' * 100 + '\n' question += ('\n' + '-' * 100 + '\n' + color_text(description, ColorName.WHITE, bold=True)
+ '\n' + '-' * 100 + '\n')
reset_branch_id = None if convo is None else convo.save_branch() reset_branch_id = None if convo is None else convo.save_branch()

View File

@@ -1,7 +1,7 @@
from utils.utils import step_already_finished from utils.utils import step_already_finished
from helpers.Agent import Agent from helpers.Agent import Agent
import json import json
from utils.style import green_bold from utils.style import color_text, ColorName
from const.function_calls import ARCHITECTURE from const.function_calls import ARCHITECTURE
from utils.utils import should_execute_step, find_role_from_step, generate_app_data from utils.utils import should_execute_step, find_role_from_step, generate_app_data
@@ -28,7 +28,7 @@ class Architect(Agent):
return step['architecture'] return step['architecture']
# ARCHITECTURE # ARCHITECTURE
print(green_bold(f"Planning project architecture...\n")) print(color_text(f"Planning project architecture...\n", ColorName.GREEN, bold=True))
logger.info(f"Planning project architecture...") logger.info(f"Planning project architecture...")
self.convo_architecture = AgentConvo(self) self.convo_architecture = AgentConvo(self)

View File

@@ -1,5 +1,5 @@
import uuid import uuid
from utils.style import green, red, green_bold, yellow_bold, red_bold, blue_bold, white_bold from utils.style import color_text, ColorName
from helpers.exceptions.TokenLimitError import TokenLimitError from helpers.exceptions.TokenLimitError import TokenLimitError
from const.code_execution import MAX_COMMAND_DEBUG_TRIES from const.code_execution import MAX_COMMAND_DEBUG_TRIES
from helpers.exceptions.TooDeepRecursionError import TooDeepRecursionError from helpers.exceptions.TooDeepRecursionError import TooDeepRecursionError
@@ -33,7 +33,7 @@ class Developer(Agent):
self.project.skip_steps = False if ('skip_until_dev_step' in self.project.args and self.project.args['skip_until_dev_step'] == '0') else True self.project.skip_steps = False if ('skip_until_dev_step' in self.project.args and self.project.args['skip_until_dev_step'] == '0') else True
# DEVELOPMENT # DEVELOPMENT
print(green_bold(f"🚀 Now for the actual development...\n")) print(color_text(f"🚀 Now for the actual development...\n", ColorName.GREEN, bold=True))
logger.info(f"Starting to create the actual code...") logger.info(f"Starting to create the actual code...")
for i, dev_task in enumerate(self.project.development_plan): for i, dev_task in enumerate(self.project.development_plan):
@@ -44,7 +44,8 @@ class Developer(Agent):
logger.info('The app is DONE!!! Yay...you can use it now.') logger.info('The app is DONE!!! Yay...you can use it now.')
def implement_task(self, i, development_task=None): def implement_task(self, i, development_task=None):
print(green_bold(f'Implementing task #{i + 1}: ') + green(f' {development_task["description"]}\n')) print(color_text(f'Implementing task #{i + 1}: ')
+ color_text(f' {development_task["description"]}\n', ColorName.GREEN, bold=True))
convo_dev_task = AgentConvo(self) convo_dev_task = AgentConvo(self)
task_description = convo_dev_task.send_message('development/task/breakdown.prompt', { task_description = convo_dev_task.send_message('development/task/breakdown.prompt', {
@@ -115,7 +116,7 @@ class Developer(Agent):
while True: while True:
human_intervention_description = step['human_intervention_description'] + \ human_intervention_description = step['human_intervention_description'] + \
yellow_bold('\n\nIf you want to run the app, just type "r" and press ENTER and that will run `' + self.run_command + '`') \ color_text('\n\nIf you want to run the app, just type "r" and press ENTER and that will run `' + self.run_command + '`', ColorName.YELLOW, bold=True) \
if self.run_command is not None else step['human_intervention_description'] if self.run_command is not None else step['human_intervention_description']
response = self.project.ask_for_human_intervention('I need human intervention:', response = self.project.ask_for_human_intervention('I need human intervention:',
human_intervention_description, human_intervention_description,
@@ -148,9 +149,9 @@ class Developer(Agent):
cli_response, llm_response = execute_command_and_check_cli_response(test_command['command'], test_command['timeout'], convo) cli_response, llm_response = execute_command_and_check_cli_response(test_command['command'], test_command['timeout'], convo)
logger.info('After running command llm_response: ' + llm_response) logger.info('After running command llm_response: ' + llm_response)
if llm_response == 'NEEDS_DEBUGGING': if llm_response == 'NEEDS_DEBUGGING':
print(red(f'Got incorrect CLI response:')) print(color_text(f'Got incorrect CLI response:', ColorName.RED))
print(cli_response) print(cli_response)
print(red('-------------------')) print(color_text('-------------------', ColorName.RED))
return { "success": llm_response == 'DONE', "cli_response": cli_response, "llm_response": llm_response } return { "success": llm_response == 'DONE', "cli_response": cli_response, "llm_response": llm_response }
@@ -183,8 +184,8 @@ class Developer(Agent):
if step_implementation_try >= MAX_COMMAND_DEBUG_TRIES: if step_implementation_try >= MAX_COMMAND_DEBUG_TRIES:
self.dev_help_needed(step) self.dev_help_needed(step)
print(red_bold(f'\n--------- LLM Reached Token Limit ----------')) print(color_text(f'\n--------- LLM Reached Token Limit ----------', ColorName.RED, bold=True))
print(red_bold(f'Can I retry implementing the entire development step?')) print(color_text(f'Can I retry implementing the entire development step?', ColorName.RED, bold=True))
answer = '' answer = ''
while answer != 'y': while answer != 'y':
@@ -202,9 +203,9 @@ class Developer(Agent):
def dev_help_needed(self, step): def dev_help_needed(self, step):
if step['type'] == 'command': if step['type'] == 'command':
help_description = (red_bold(f'I tried running the following command but it doesn\'t seem to work:\n\n') + help_description = (color_text(f'I tried running the following command but it doesn\'t seem to work:\n\n', ColorName.RED, bold=True) +
white_bold(step['command']['command']) + color_text(step['command']['command'], ColorName.WHITE, bold=True) +
red_bold(f'\n\nCan you please make it work?')) color_text(f'\n\nCan you please make it work?', ColorName.RED, bold=True))
elif step['type'] == 'code_change': elif step['type'] == 'code_change':
help_description = step['code_change_description'] help_description = step['code_change_description']
elif step['type'] == 'human_intervention': elif step['type'] == 'human_intervention':
@@ -223,9 +224,11 @@ class Developer(Agent):
answer = '' answer = ''
while answer != 'continue': while answer != 'continue':
print(red_bold(f'\n----------------------------- I need your help ------------------------------')) print(color_text(f'\n----------------------------- I need your help ------------------------------',
ColorName.RED, bold=True))
print(extract_substring(str(help_description))) print(extract_substring(str(help_description)))
print(red_bold(f'\n-----------------------------------------------------------------------------')) print(color_text(f'\n-----------------------------------------------------------------------------',
ColorName.RED, bold=True))
answer = styled_text( answer = styled_text(
self.project, self.project,
'Once you\'re done, type "continue"?' 'Once you\'re done, type "continue"?'
@@ -291,11 +294,12 @@ class Developer(Agent):
while True: while True:
logger.info('Continue development: %s', last_branch_name) logger.info('Continue development: %s', last_branch_name)
iteration_convo.load_branch(last_branch_name) iteration_convo.load_branch(last_branch_name)
user_description = ('Here is a description of what should be working: \n\n' + blue_bold(continue_description) + '\n') \ user_description = ('Here is a description of what should be working: \n\n' + color_text(continue_description
+ '\n', ColorName.BLUE, bold=True)) \
if continue_description != '' else '' if continue_description != '' else ''
user_description = 'Can you check if the app works please? ' + user_description + \ user_description = 'Can you check if the app works please? ' + user_description + \
'\nIf you want to run the app, ' + \ '\nIf you want to run the app, ' + \
yellow_bold('just type "r" and press ENTER and that will run `' + self.run_command + '`') color_text('just type "r" and press ENTER and that will run `' + self.run_command + '`', ColorName.YELLOW, bold=True)
# continue_description = '' # continue_description = ''
# TODO: Wait for a specific string in the output or timeout? # TODO: Wait for a specific string in the output or timeout?
response = self.project.ask_for_human_intervention( response = self.project.ask_for_human_intervention(
@@ -355,7 +359,7 @@ class Developer(Agent):
}) })
return return
# ENVIRONMENT SETUP # ENVIRONMENT SETUP
print(green(f"Setting up the environment...\n")) print(color_text(f"Setting up the environment...\n", ColorName.GREEN))
logger.info(f"Setting up the environment...") logger.info(f"Setting up the environment...")
os_info = get_os_info() os_info = get_os_info()

View File

@@ -1,5 +1,5 @@
import json import json
from utils.style import green_bold from utils.style import color_text, ColorName
from helpers.AgentConvo import AgentConvo from helpers.AgentConvo import AgentConvo
from helpers.Agent import Agent from helpers.Agent import Agent
from logger.logger import logger from logger.logger import logger
@@ -55,7 +55,7 @@ class ProductOwner(Agent):
self.project, self.project,
generate_messages_from_description(main_prompt, self.project.args['app_type'], self.project.args['name'])) generate_messages_from_description(main_prompt, self.project.args['app_type'], self.project.args['name']))
print(green_bold('Project Summary:\n')) print(color_text('Project Summary:\n', ColorName.GREEN, bold=True))
convo_project_description = AgentConvo(self) convo_project_description = AgentConvo(self)
high_level_summary = convo_project_description.send_message('utils/summary.prompt', high_level_summary = convo_project_description.send_message('utils/summary.prompt',
{'conversation': '\n'.join( {'conversation': '\n'.join(
@@ -87,7 +87,7 @@ class ProductOwner(Agent):
# USER STORIES # USER STORIES
msg = f"User Stories:\n" msg = f"User Stories:\n"
print(green_bold(msg)) print(color_text(msg, ColorName.GREEN, bold=True))
logger.info(msg) logger.info(msg)
self.project.user_stories = self.convo_user_stories.continuous_conversation('user_stories/specs.prompt', { self.project.user_stories = self.convo_user_stories.continuous_conversation('user_stories/specs.prompt', {
@@ -121,7 +121,7 @@ class ProductOwner(Agent):
# USER TASKS # USER TASKS
msg = f"User Tasks:\n" msg = f"User Tasks:\n"
print(green_bold(msg)) print(color_text(msg, ColorName.GREEN, bold=True))
logger.info(msg) logger.info(msg)
self.project.user_tasks = self.convo_user_stories.continuous_conversation('user_stories/user_tasks.prompt', self.project.user_tasks = self.convo_user_stories.continuous_conversation('user_stories/user_tasks.prompt',

View File

@@ -1,7 +1,7 @@
from utils.utils import step_already_finished from utils.utils import step_already_finished
from helpers.Agent import Agent from helpers.Agent import Agent
import json import json
from utils.style import green_bold from utils.style import color_text, ColorName
from const.function_calls import DEV_STEPS from const.function_calls import DEV_STEPS
from helpers.cli import build_directory_tree from helpers.cli import build_directory_tree
from helpers.AgentConvo import AgentConvo from helpers.AgentConvo import AgentConvo
@@ -32,7 +32,7 @@ class TechLead(Agent):
return step['development_plan'] return step['development_plan']
# DEVELOPMENT PLANNING # DEVELOPMENT PLANNING
print(green_bold(f"Starting to create the action plan for development...\n")) print(color_text(f"Starting to create the action plan for development...\n", ColorName.GREEN, bold=True))
logger.info(f"Starting to create the action plan for development...") logger.info(f"Starting to create the action plan for development...")
# TODO add clarifications # TODO add clarifications

View File

@@ -8,7 +8,7 @@ import platform
from typing import Dict, Union from typing import Dict, Union
from logger.logger import logger from logger.logger import logger
from utils.style import yellow, green, red, yellow_bold, white_bold from utils.style import color_text, ColorName
from database.database import get_saved_command_run, save_command_run from database.database import get_saved_command_run, save_command_run
from helpers.exceptions.TooDeepRecursionError import TooDeepRecursionError from helpers.exceptions.TooDeepRecursionError import TooDeepRecursionError
from helpers.exceptions.TokenLimitError import TokenLimitError from helpers.exceptions.TokenLimitError import TokenLimitError
@@ -133,8 +133,8 @@ def execute_command(project, command, timeout=None, process_name: str = None, fo
timeout = min(max(timeout, MIN_COMMAND_RUN_TIME), MAX_COMMAND_RUN_TIME) timeout = min(max(timeout, MIN_COMMAND_RUN_TIME), MAX_COMMAND_RUN_TIME)
if not force: if not force:
print(yellow_bold(f'\n--------- EXECUTE COMMAND ----------')) print(color_text(f'\n--------- EXECUTE COMMAND ----------', ColorName.YELLOW, bold=True))
question = f'Can I execute the command: `{yellow_bold(command)}`' question = f'Can I execute the command: `{color_text(command, ColorName.YELLOW, bold=True)}`'
if timeout is not None: if timeout is not None:
question += f' with {timeout}ms timeout?' question += f' with {timeout}ms timeout?'
else: else:
@@ -162,7 +162,8 @@ def execute_command(project, command, timeout=None, process_name: str = None, fo
if command_run is not None and project.skip_steps: if command_run is not None and project.skip_steps:
# if we do, use it # if we do, use it
project.checkpoints['last_command_run'] = command_run project.checkpoints['last_command_run'] = command_run
print(yellow(f'Restoring command run response id {command_run.id}:\n```\n{command_run.cli_response}```')) print(color_text(f'Restoring command run response id {command_run.id}:\n```\n{command_run.cli_response}```',
ColorName.YELLOW))
return command_run.cli_response, None, None return command_run.cli_response, None, None
return_value = None return_value = None
@@ -191,7 +192,8 @@ def execute_command(project, command, timeout=None, process_name: str = None, fo
elapsed_time = time.time() - start_time elapsed_time = time.time() - start_time
if timeout is not None: if timeout is not None:
# TODO: print to IPC using a different message type so VS Code can ignore it or update the previous value # TODO: print to IPC using a different message type so VS Code can ignore it or update the previous value
print(white_bold(f'\rt: {round(elapsed_time * 1000)}ms : '), end='', flush=True) print(color_text(f'\rt: {round(elapsed_time * 1000)}ms : ', ColorName.WHITE, bold=True),
end='', flush=True,)
# Check if process has finished # Check if process has finished
if process.poll() is not None: if process.poll() is not None:
@@ -200,7 +202,7 @@ def execute_command(project, command, timeout=None, process_name: str = None, fo
while not q.empty(): while not q.empty():
output_line = q.get_nowait() output_line = q.get_nowait()
if output_line not in output: if output_line not in output:
print(green('CLI OUTPUT:') + output_line, end='') print(color_text('CLI OUTPUT:', ColorName.GREEN) + output_line, end='', )
logger.info('CLI OUTPUT: ' + output_line) logger.info('CLI OUTPUT: ' + output_line)
output += output_line output += output_line
break break
@@ -218,7 +220,7 @@ def execute_command(project, command, timeout=None, process_name: str = None, fo
if line: if line:
output += line output += line
print(green('CLI OUTPUT:') + line, end='') print(color_text('CLI OUTPUT:', ColorName.GREEN) + line, end='')
logger.info('CLI OUTPUT: ' + line) logger.info('CLI OUTPUT: ' + line)
# Read stderr # Read stderr
@@ -229,7 +231,7 @@ def execute_command(project, command, timeout=None, process_name: str = None, fo
if stderr_line: if stderr_line:
stderr_output += stderr_line stderr_output += stderr_line
print(red('CLI ERROR:') + stderr_line, end='') # Print with different color for distinction print(color_text('CLI ERROR:', ColorName.RED) + stderr_line, end='') # Print with different color for distinction
logger.error('CLI ERROR: ' + stderr_line) logger.error('CLI ERROR: ' + stderr_line)
if process_name is not None: if process_name is not None:
@@ -373,9 +375,9 @@ def run_command_until_success(convo, command,
if response != 'DONE': if response != 'DONE':
# 'NEEDS_DEBUGGING' # 'NEEDS_DEBUGGING'
print(red(f'Got incorrect CLI response:')) print(color_text(f'Got incorrect CLI response:', ColorName.RED))
print(cli_response) print(cli_response)
print(red('-------------------')) print(color_text('-------------------', ColorName.RED))
reset_branch_id = convo.save_branch() reset_branch_id = convo.save_branch()
while True: while True:

View File

@@ -1,4 +1,4 @@
from utils.style import green from utils.style import color_text, ColorName
import os import os
@@ -11,7 +11,7 @@ def update_file(path, new_content):
# Write content to the file # Write content to the file
with open(path, 'w') as file: with open(path, 'w') as file:
file.write(new_content) file.write(new_content)
print(green(f"Updated file {path}")) print(color_text(f"Updated file {path}", ColorName.GREEN))
def get_files_content(directory, ignore=[]): def get_files_content(directory, ignore=[]):
return_array = [] return_array = []

View File

@@ -8,7 +8,7 @@ import traceback
from dotenv import load_dotenv from dotenv import load_dotenv
load_dotenv() load_dotenv()
from utils.style import red from utils.style import color_text, ColorName
from utils.custom_print import get_custom_print from utils.custom_print import get_custom_print
from helpers.Project import Project from helpers.Project import Project
from utils.arguments import get_arguments from utils.arguments import get_arguments
@@ -53,9 +53,9 @@ if __name__ == "__main__":
except KeyboardInterrupt: except KeyboardInterrupt:
exit_gpt_pilot() exit_gpt_pilot()
except Exception as e: except Exception as e:
print(red('---------- GPT PILOT EXITING WITH ERROR ----------')) print(color_text('---------- GPT PILOT EXITING WITH ERROR ----------', ColorName.RED))
traceback.print_exc() traceback.print_exc()
print(red('--------------------------------------------------')) print(color_text('--------------------------------------------------', ColorName.RED))
exit_gpt_pilot(False) exit_gpt_pilot(False)
finally: finally:
sys.exit(0) sys.exit(0)

View File

@@ -1,5 +1,5 @@
# prompts/prompts.py # prompts/prompts.py
from utils.style import yellow from utils.style import color_text, ColorName
from const import common from const import common
from const.llm import MAX_QUESTIONS, END_RESPONSE from const.llm import MAX_QUESTIONS, END_RESPONSE
from utils.llm_connection import create_gpt_chat_completion from utils.llm_connection import create_gpt_chat_completion
@@ -52,7 +52,7 @@ def ask_for_main_app_definition(project):
def ask_user(project, question: str, require_some_input=True, hint: str = None): def ask_user(project, question: str, require_some_input=True, hint: str = None):
while True: while True:
if hint is not None: if hint is not None:
print(yellow(hint), type='hint') print(color_text(hint, ColorName.YELLOW), type='hint')
answer = styled_text(project, question) answer = styled_text(project, question)
logger.info('Q: %s', question) logger.info('Q: %s', question)
@@ -126,7 +126,8 @@ def get_additional_info_from_user(project, messages, role):
while True: while True:
if isinstance(message, dict) and 'text' in message: if isinstance(message, dict) and 'text' in message:
message = message['text'] message = message['text']
print(yellow(f"Please check this message and say what needs to be changed. If everything is ok just press ENTER",)) print(color_text(f"Please check this message and say what needs to be changed. If everything is ok just press ENTER",
ColorName.YELLOW))
answer = ask_user(project, message, require_some_input=False) answer = ask_user(project, message, require_some_input=False)
if answer.lower() == '': if answer.lower() == '':
break break

View File

@@ -5,7 +5,7 @@ import sys
import uuid import uuid
from getpass import getuser from getpass import getuser
from database.database import get_app, get_app_by_user_workspace from database.database import get_app, get_app_by_user_workspace
from utils.style import green_bold from utils.style import color_text, ColorName
from utils.utils import should_execute_step from utils.utils import should_execute_step
@@ -25,6 +25,9 @@ def get_arguments():
else: else:
arguments[arg] = True arguments[arg] = True
if '--no-color' in args:
os.environ["NO_COLOR"] = True
if 'user_id' not in arguments: if 'user_id' not in arguments:
arguments['user_id'] = username_to_uuid(getuser()) arguments['user_id'] = username_to_uuid(getuser())
@@ -46,18 +49,22 @@ def get_arguments():
if 'step' not in arguments or ('step' in arguments and not should_execute_step(arguments['step'], app.status)): if 'step' not in arguments or ('step' in arguments and not should_execute_step(arguments['step'], app.status)):
arguments['step'] = app.status arguments['step'] = app.status
print(green_bold('\n------------------ LOADING PROJECT ----------------------')) print(color_text('\n------------------ LOADING PROJECT ----------------------',
print(green_bold(f'{app.name} (app_id={arguments["app_id"]})')) ColorName.GREEN, bold=True))
print(green_bold('--------------------------------------------------------------\n')) print(color_text(f'{app.name} (app_id={arguments["app_id"]})', ColorName.GREEN, bold=True))
print(color_text('--------------------------------------------------------------\n',
ColorName.GREEN, bold=True))
except ValueError as e: except ValueError as e:
print(e) print(e)
exit(1) exit(1)
else: else:
arguments['app_id'] = str(uuid.uuid4()) arguments['app_id'] = str(uuid.uuid4())
print(green_bold('\n------------------ STARTING NEW PROJECT ----------------------')) print(color_text('\n------------------ STARTING NEW PROJECT ----------------------',
ColorName.GREEN, bold=True))
print("If you wish to continue with this project in future run:") print("If you wish to continue with this project in future run:")
print(green_bold(f'python {sys.argv[0]} app_id={arguments["app_id"]}')) print(color_text(f'python {sys.argv[0]} app_id={arguments["app_id"]}', ColorName.GREEN, bold=True))
print(green_bold('--------------------------------------------------------------\n')) print(color_text('--------------------------------------------------------------\n',
ColorName.GREEN, bold=True))
if 'email' not in arguments: if 'email' not in arguments:
arguments['email'] = get_email() arguments['email'] = get_email()
@@ -68,6 +75,7 @@ def get_arguments():
if 'step' not in arguments: if 'step' not in arguments:
arguments['step'] = None arguments['step'] = None
return arguments return arguments

View File

@@ -8,7 +8,7 @@ import tiktoken
from prompt_toolkit.styles import Style from prompt_toolkit.styles import Style
from jsonschema import validate, ValidationError from jsonschema import validate, ValidationError
from utils.style import red from utils.style import color_text, ColorName
from typing import List from typing import List
from const.llm import MIN_TOKENS_FOR_GPT_RESPONSE, MAX_GPT_MODEL_TOKENS from const.llm import MIN_TOKENS_FOR_GPT_RESPONSE, MAX_GPT_MODEL_TOKENS
from logger.logger import logger, logging from logger.logger import logger, logging
@@ -217,7 +217,7 @@ def retry_on_exception(func):
time.sleep(wait_duration) time.sleep(wait_duration)
continue continue
print(red(f'There was a problem with request to openai API:')) print(color_text(f'There was a problem with request to openai API:', ColorName.RED))
# spinner_stop(spinner) # spinner_stop(spinner)
print(err_str) print(err_str)
logger.error(f'There was a problem with request to openai API: {err_str}') logger.error(f'There was a problem with request to openai API: {err_str}')
@@ -284,8 +284,8 @@ def stream_gpt_completion(data, req_type, project):
delete_last_n_lines(lines_printed) delete_last_n_lines(lines_printed)
return result_data return result_data
# spinner = spinner_start(yellow("Waiting for OpenAI API response...")) # spinner = spinner_start(color_text("Waiting for OpenAI API response...", ColorName.YELLOW))
# print(yellow("Stream response from OpenAI:")) # print(color_text("Stream response from OpenAI:", ColorName.YELLOW))
# Configure for the selected ENDPOINT # Configure for the selected ENDPOINT
model = os.getenv('MODEL_NAME', 'gpt-4') model = os.getenv('MODEL_NAME', 'gpt-4')

View File

@@ -1,6 +1,6 @@
from prompt_toolkit.styles import Style from prompt_toolkit.styles import Style
import questionary import questionary
from utils.style import yellow_bold from utils.style import color_text, ColorName
import re import re
from database.database import save_user_input, get_saved_user_input from database.database import save_user_input, get_saved_user_input
@@ -30,8 +30,8 @@ def styled_text(project, question, ignore_user_input_count=False, style=None):
if user_input is not None and user_input.user_input is not None and project.skip_steps: if user_input is not None and user_input.user_input is not None and project.skip_steps:
# if we do, use it # if we do, use it
project.checkpoints['last_user_input'] = user_input project.checkpoints['last_user_input'] = user_input
print(yellow_bold(f'Restoring user input id {user_input.id}: '), end='') print(color_text(f'Restoring user input id {user_input.id}: ', ColorName.YELLOW, bold=True), end='')
print(yellow_bold(f'{user_input.user_input}')) print(color_text(f'{user_input.user_input}', ColorName.YELLOW, bold=True))
return user_input.user_input return user_input.user_input
if project.ipc_client_instance is None or project.ipc_client_instance.client is None: if project.ipc_client_instance is None or project.ipc_client_instance.client is None:

View File

@@ -1,86 +1,55 @@
from colorama import Fore, Style, init import os
from enum import Enum
init()
def red(text):
return f'{Fore.RED}{text}{Style.RESET_ALL}'
def red_bold(text):
return f'{Fore.RED}{Style.BRIGHT}{text}{Style.RESET_ALL}'
def yellow(text):
return f'{Fore.YELLOW}{text}{Style.RESET_ALL}'
def yellow_bold(text):
return f'{Fore.YELLOW}{Style.BRIGHT}{text}{Style.RESET_ALL}'
def green(text):
return f'{Fore.GREEN}{text}{Style.RESET_ALL}'
def green_bold(text):
return f'{Fore.GREEN}{Style.BRIGHT}{text}{Style.RESET_ALL}'
def blue(text):
return f'{Fore.BLUE}{text}{Style.RESET_ALL}'
def blue_bold(text):
return f'{Fore.BLUE}{Style.BRIGHT}{text}{Style.RESET_ALL}'
def cyan(text):
return f'{Fore.CYAN}{text}{Style.RESET_ALL}'
def white(text):
return f'{Fore.WHITE}{text}{Style.RESET_ALL}'
def white_bold(text):
return f'{Fore.WHITE}{Style.BRIGHT}{text}{Style.RESET_ALL}'
from colorama import Fore, Style, init from colorama import Fore, Style, init
init(autoreset=True) init(autoreset=True)
COLORS = {
"red": Fore.RED, class ColorName(Enum):
"green": Fore.GREEN, BLACK = Fore.BLACK
"yellow": Fore.YELLOW, RED = Fore.RED
"blue": Fore.BLUE, GREEN = Fore.GREEN
"cyan": Fore.CYAN, YELLOW = Fore.YELLOW
"white": Fore.WHITE, BLUE = Fore.BLUE
} CYAN = Fore.CYAN
WHITE = Fore.WHITE
def color_text(text: str, color_name: str, bold: bool = False, enable_formatting: bool = True) -> str: class Config:
# Use environment variable or default value for NO_COLOR
NO_COLOR = os.environ.get("NO_COLOR", False)
def color_text(text: str, color_name: ColorName, bold: bool = False) -> str:
""" """
Returns text with a specified color and optional style. Returns text with a specified color and optional style.
Args: Args:
text (str): The text to colorize. text (str): The text to colorize.
color_name (str): The color of the text. Should be a key in the COLORS dictionary. color_name (ColorName): The color of the text. Should be a member of the ColorName enum.
bold (bool, optional): If True, the text will be displayed in bold. Defaults to False. bold (bool, optional): If True, the text will be displayed in bold. Defaults to False.
enable_formatting (bool, optional): If True, ANSI codes will be applied. Defaults to True.
Returns: Returns:
str: The text with applied color and optional style. str: The text with applied color and optional style.
Example:
>>> color_text("Hello, World!", "red", True, enable_formatting=False)
'Hello, World!'
""" """
if not enable_formatting: # If NO_COLOR is True, return unmodified text
if Config.NO_COLOR:
return text return text
color = COLORS.get(color_name, Fore.WHITE) # Default color is white # Use the color value from the enum
color = color_name.value
# Apply BRIGHT style if bold is True, otherwise use an empty string
style = Style.BRIGHT if bold else "" style = Style.BRIGHT if bold else ""
# Return the formatted text
return f'{color}{style}{text}' return f'{color}{style}{text}'
# Example usage:
if __name__ == "__main__":
print(color_text("This is black text", ColorName.BLACK))
print(color_text("This is red text", ColorName.RED))
print(color_text("This is green text", ColorName.GREEN, bold=True))
print(color_text("This is yellow text", ColorName.YELLOW))
print(color_text("This is blue text", ColorName.BLUE, bold=True))
print(color_text("This is cyan text", ColorName.CYAN))
print(color_text("This is white text", ColorName.WHITE, bold=True))

View File

@@ -9,8 +9,7 @@ import json
import hashlib import hashlib
import re import re
from jinja2 import Environment, FileSystemLoader from jinja2 import Environment, FileSystemLoader
from .style import green from .style import color_text, ColorName
from const.llm import MAX_QUESTIONS, END_RESPONSE from const.llm import MAX_QUESTIONS, END_RESPONSE
from const.common import ROLES, STEPS from const.common import ROLES, STEPS
from logger.logger import logger from logger.logger import logger
@@ -114,7 +113,7 @@ def get_os_info():
"Node": platform.node(), "Node": platform.node(),
"Release": platform.release(), "Release": platform.release(),
} }
# TODO deprecated linux_distribution
if os_info["OS"] == "Linux": if os_info["OS"] == "Linux":
os_info["Distribution"] = ' '.join(distro.linux_distribution(full_distribution_name=True)) os_info["Distribution"] = ' '.join(distro.linux_distribution(full_distribution_name=True))
elif os_info["OS"] == "Windows": elif os_info["OS"] == "Windows":
@@ -142,7 +141,7 @@ def step_already_finished(args, step):
args.update(step['app_data']) args.update(step['app_data'])
message = f"{capitalize_first_word_with_underscores(step['step'])}" message = f"{capitalize_first_word_with_underscores(step['step'])}"
print(green(message)) print(color_text(message, ColorName.GREEN))
logger.info(message) logger.info(message)