mirror of
https://github.com/OMGeeky/gpt-pilot.git
synced 2025-12-30 08:03:32 +01:00
refactor DB
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -161,4 +161,7 @@ cython_debug/
|
||||
|
||||
|
||||
# Logger
|
||||
/euclid/logger/debug.log
|
||||
/euclid/logger/debug.log
|
||||
|
||||
#dev
|
||||
/euclid/brija.py
|
||||
@@ -2,4 +2,4 @@ DB_NAME = 'euclid'
|
||||
DB_HOST = 'localhost'
|
||||
DB_PORT = '5432'
|
||||
DB_USER = 'admin'
|
||||
DB_PASSWORD = 'admin'
|
||||
DB_PASSWORD = 'admin'
|
||||
|
||||
@@ -1,167 +1,163 @@
|
||||
# database.py
|
||||
from playhouse.shortcuts import model_to_dict
|
||||
from peewee import *
|
||||
|
||||
import psycopg2
|
||||
import json
|
||||
from psycopg2 import sql
|
||||
from psycopg2.extras import RealDictCursor
|
||||
from const import db
|
||||
from logger.logger import logger
|
||||
from utils.utils import hash_data
|
||||
from database.models.components.base_models import database
|
||||
from database.models.user import User
|
||||
from database.models.app import App
|
||||
from database.models.project_description import ProjectDescription
|
||||
from database.models.user_stories import UserStories
|
||||
from database.models.user_tasks import UserTasks
|
||||
from database.models.architecture import Architecture
|
||||
from database.models.development_planning import DevelopmentPlanning
|
||||
from database.models.development_steps import DevelopmentSteps
|
||||
from database.models.environment_setup import EnvironmentSetup
|
||||
from database.models.development import Development
|
||||
|
||||
|
||||
def create_connection():
|
||||
conn = psycopg2.connect(
|
||||
host=db.DB_HOST,
|
||||
database=db.DB_NAME,
|
||||
port=db.DB_PORT,
|
||||
user=db.DB_USER,
|
||||
password=db.DB_PASSWORD,
|
||||
cursor_factory=RealDictCursor
|
||||
)
|
||||
return conn
|
||||
|
||||
|
||||
def create_tables():
|
||||
commands = (
|
||||
"""
|
||||
DROP TABLE IF EXISTS progress_steps;
|
||||
DROP TABLE IF EXISTS apps;
|
||||
DROP TABLE IF EXISTS users;
|
||||
""",
|
||||
"""
|
||||
CREATE TABLE users (
|
||||
id UUID PRIMARY KEY,
|
||||
username VARCHAR(255) NOT NULL,
|
||||
email VARCHAR(255) NOT NULL,
|
||||
password VARCHAR(255) NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
""",
|
||||
"""
|
||||
CREATE TABLE apps (
|
||||
id SERIAL PRIMARY KEY,
|
||||
user_id UUID NOT NULL,
|
||||
app_id UUID NOT NULL UNIQUE,
|
||||
app_type VARCHAR(255) NOT NULL,
|
||||
status VARCHAR(255) NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (user_id)
|
||||
REFERENCES users (id)
|
||||
ON UPDATE CASCADE ON DELETE CASCADE
|
||||
)
|
||||
""",
|
||||
"""
|
||||
CREATE TABLE progress_steps (
|
||||
id SERIAL PRIMARY KEY,
|
||||
app_id UUID NOT NULL,
|
||||
step VARCHAR(255) NOT NULL,
|
||||
data TEXT,
|
||||
completed BOOLEAN NOT NULL,
|
||||
completed_at TIMESTAMP,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (app_id)
|
||||
REFERENCES apps (app_id)
|
||||
ON UPDATE CASCADE ON DELETE CASCADE,
|
||||
UNIQUE (app_id, step)
|
||||
)
|
||||
""")
|
||||
|
||||
conn = None
|
||||
def save_user(user_id, email="email", password="password"):
|
||||
try:
|
||||
conn = create_connection()
|
||||
cur = conn.cursor()
|
||||
for command in commands:
|
||||
cur.execute(command)
|
||||
cur.close()
|
||||
conn.commit()
|
||||
except (Exception, psycopg2.DatabaseError) as error:
|
||||
print(error)
|
||||
finally:
|
||||
if conn is not None:
|
||||
conn.close()
|
||||
user = User.get(User.id == user_id)
|
||||
return user
|
||||
except DoesNotExist:
|
||||
return User.create(id=user_id, email=email, password=password)
|
||||
|
||||
|
||||
def save_app(user_id, app_id, app_type):
|
||||
conn = create_connection()
|
||||
cursor = conn.cursor()
|
||||
try:
|
||||
app = App.get(App.id == app_id)
|
||||
except DoesNotExist:
|
||||
user = save_user(user_id)
|
||||
app = App.create(id=app_id, user=user, app_type=app_type)
|
||||
|
||||
cursor.execute("SELECT * FROM users WHERE id = %s", (str(user_id),))
|
||||
if cursor.fetchone() is None:
|
||||
# If user doesn't exist, create a new user
|
||||
cursor.execute("INSERT INTO users (id, username, email, password) VALUES (%s, 'username', 'email', 'password')",
|
||||
(str(user_id),))
|
||||
|
||||
# Now save or update the app
|
||||
cursor.execute("""
|
||||
INSERT INTO apps (user_id, app_id, app_type, status)
|
||||
VALUES (%s, %s, %s, 'started')
|
||||
ON CONFLICT (app_id) DO UPDATE SET
|
||||
user_id = EXCLUDED.user_id, app_type = EXCLUDED.app_type, status = EXCLUDED.status
|
||||
RETURNING id
|
||||
""", (str(user_id), str(app_id), app_type))
|
||||
|
||||
conn.commit()
|
||||
cursor.close()
|
||||
conn.close()
|
||||
|
||||
logger.info('App saved')
|
||||
|
||||
return
|
||||
return app
|
||||
|
||||
|
||||
def save_progress(app_id, step, data):
|
||||
conn = create_connection()
|
||||
cursor = conn.cursor()
|
||||
progress_table_map = {
|
||||
'project_description': ProjectDescription,
|
||||
'user_stories': UserStories,
|
||||
'user_tasks': UserTasks,
|
||||
'architecture': Architecture,
|
||||
'development_planning': DevelopmentPlanning,
|
||||
'environment_setup': EnvironmentSetup,
|
||||
'development': Development,
|
||||
}
|
||||
|
||||
# Check if the data is a dictionary. If it is, convert it to a JSON string.
|
||||
if isinstance(data, dict):
|
||||
data = json.dumps(data)
|
||||
data['step'] = step
|
||||
|
||||
# INSERT the data, but on conflict (if the app_id and step combination already exists) UPDATE the data
|
||||
insert = sql.SQL(
|
||||
"""INSERT INTO progress_steps (app_id, step, data, completed)
|
||||
VALUES (%s, %s, %s, false)
|
||||
ON CONFLICT (app_id, step) DO UPDATE
|
||||
SET data = excluded.data, completed = excluded.completed"""
|
||||
)
|
||||
ProgressTable = progress_table_map.get(step)
|
||||
if not ProgressTable:
|
||||
raise ValueError(f"Invalid step: {step}")
|
||||
|
||||
cursor.execute(insert, (app_id, step, data))
|
||||
app = get_app(app_id)
|
||||
|
||||
conn.commit()
|
||||
cursor.close()
|
||||
conn.close()
|
||||
# Use the get_or_create method, which attempts to retrieve a record
|
||||
# or creates a new one if it does not exist.
|
||||
progress, created = ProgressTable.get_or_create(app=app, defaults=data)
|
||||
|
||||
# If the record was not created, it already existed and we should update it
|
||||
if not created:
|
||||
for key, value in data.items():
|
||||
setattr(progress, key, value)
|
||||
progress.save()
|
||||
|
||||
return progress
|
||||
|
||||
|
||||
def get_apps_by_id(app_id):
|
||||
conn = create_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute("SELECT * FROM apps WHERE app_id = %s", (str(app_id),))
|
||||
apps = cursor.fetchall()
|
||||
|
||||
cursor.close()
|
||||
conn.close()
|
||||
|
||||
return apps
|
||||
def get_app(app_id):
|
||||
try:
|
||||
app = App.get(App.id == app_id)
|
||||
return app
|
||||
except DoesNotExist:
|
||||
raise ValueError(f"No app with id: {app_id}")
|
||||
|
||||
|
||||
def get_progress_steps(app_id, step=None):
|
||||
conn = create_connection()
|
||||
cursor = conn.cursor()
|
||||
progress_table_map = {
|
||||
'project_description': ProjectDescription,
|
||||
'user_stories': UserStories,
|
||||
'user_tasks': UserTasks,
|
||||
'architecture': Architecture,
|
||||
'development_planning': DevelopmentPlanning,
|
||||
'environment_setup': EnvironmentSetup,
|
||||
'development': Development,
|
||||
}
|
||||
|
||||
if step:
|
||||
cursor.execute("SELECT * FROM progress_steps WHERE app_id = %s AND step = %s", (app_id, step))
|
||||
ProgressTable = progress_table_map.get(step)
|
||||
if not ProgressTable:
|
||||
raise ValueError(f"Invalid step: {step}")
|
||||
|
||||
try:
|
||||
progress = ProgressTable.get(ProgressTable.app_id == app_id)
|
||||
return model_to_dict(progress)
|
||||
except DoesNotExist:
|
||||
return None
|
||||
else:
|
||||
cursor.execute("SELECT * FROM progress_steps WHERE app_id = %s", (app_id,))
|
||||
steps = cursor.fetchall()
|
||||
steps = {}
|
||||
for step, ProgressTable in progress_table_map.items():
|
||||
try:
|
||||
progress = ProgressTable.get(ProgressTable.app_id == app_id)
|
||||
steps[step] = model_to_dict(progress)
|
||||
except DoesNotExist:
|
||||
steps[step] = None
|
||||
|
||||
cursor.close()
|
||||
conn.close()
|
||||
return steps
|
||||
|
||||
return steps
|
||||
|
||||
def save_development_step(app_id, messages):
|
||||
app = get_app(app_id)
|
||||
hash_id = hash_data(messages)
|
||||
try:
|
||||
dev_step = DevelopmentSteps.create(app=app, hash_id=hash_id, messages=messages)
|
||||
except IntegrityError:
|
||||
print(f"A Development Step with hash_id {hash_id} already exists.")
|
||||
return None
|
||||
return dev_step
|
||||
|
||||
|
||||
def get_development_step_by_hash_id(hash_id):
|
||||
try:
|
||||
dev_step = DevelopmentSteps.get(DevelopmentSteps.hash_id == hash_id)
|
||||
except DoesNotExist:
|
||||
print(f"No Development Step found with hash_id {hash_id}")
|
||||
return None
|
||||
return dev_step
|
||||
|
||||
|
||||
def create_tables():
|
||||
with database:
|
||||
database.create_tables([
|
||||
User,
|
||||
App,
|
||||
ProjectDescription,
|
||||
UserStories,
|
||||
UserTasks,
|
||||
Architecture,
|
||||
DevelopmentPlanning,
|
||||
DevelopmentSteps,
|
||||
EnvironmentSetup,
|
||||
Development
|
||||
])
|
||||
|
||||
|
||||
def drop_tables():
|
||||
with database:
|
||||
database.drop_tables([
|
||||
User,
|
||||
App,
|
||||
ProjectDescription,
|
||||
UserStories,
|
||||
UserTasks,
|
||||
Architecture,
|
||||
DevelopmentPlanning,
|
||||
DevelopmentSteps,
|
||||
EnvironmentSetup,
|
||||
Development
|
||||
])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
drop_tables()
|
||||
create_tables()
|
||||
|
||||
0
euclid/database/models/__init__.py
Normal file
0
euclid/database/models/__init__.py
Normal file
10
euclid/database/models/app.py
Normal file
10
euclid/database/models/app.py
Normal file
@@ -0,0 +1,10 @@
|
||||
from peewee import *
|
||||
|
||||
from database.models.components.base_models import BaseModel
|
||||
from database.models.user import User
|
||||
|
||||
|
||||
class App(BaseModel):
|
||||
user = ForeignKeyField(User, backref='apps')
|
||||
app_type = CharField()
|
||||
status = CharField(default='started')
|
||||
9
euclid/database/models/architecture.py
Normal file
9
euclid/database/models/architecture.py
Normal file
@@ -0,0 +1,9 @@
|
||||
from peewee import *
|
||||
|
||||
from database.models.components.progress_step import ProgressStep
|
||||
|
||||
|
||||
class Architecture(ProgressStep):
|
||||
architecture = TextField()
|
||||
class Meta:
|
||||
db_table = 'architecture'
|
||||
0
euclid/database/models/components/__init__.py
Normal file
0
euclid/database/models/components/__init__.py
Normal file
24
euclid/database/models/components/base_models.py
Normal file
24
euclid/database/models/components/base_models.py
Normal file
@@ -0,0 +1,24 @@
|
||||
from peewee import *
|
||||
from datetime import datetime
|
||||
from uuid import uuid4
|
||||
|
||||
from const import db
|
||||
|
||||
|
||||
# Establish connection to the database
|
||||
database = PostgresqlDatabase(
|
||||
db.DB_NAME,
|
||||
user=db.DB_USER,
|
||||
password=db.DB_PASSWORD,
|
||||
host=db.DB_HOST,
|
||||
port=db.DB_PORT
|
||||
)
|
||||
|
||||
|
||||
class BaseModel(Model):
|
||||
id = UUIDField(primary_key=True, default=uuid4)
|
||||
created_at = DateTimeField(default=datetime.now)
|
||||
updated_at = DateTimeField(default=datetime.now)
|
||||
|
||||
class Meta:
|
||||
database = database
|
||||
16
euclid/database/models/components/progress_step.py
Normal file
16
euclid/database/models/components/progress_step.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from peewee import *
|
||||
|
||||
from playhouse.postgres_ext import BinaryJSONField
|
||||
|
||||
from database.models.components.base_models import BaseModel
|
||||
from database.models.app import App
|
||||
|
||||
|
||||
class ProgressStep(BaseModel):
|
||||
app = ForeignKeyField(App, primary_key=True)
|
||||
step = CharField()
|
||||
data = BinaryJSONField(null=True)
|
||||
messages = BinaryJSONField(null=True)
|
||||
app_data = BinaryJSONField()
|
||||
completed = BooleanField(default=False)
|
||||
completed_at = DateTimeField(null=True)
|
||||
8
euclid/database/models/development.py
Normal file
8
euclid/database/models/development.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from peewee import *
|
||||
|
||||
from database.models.components.progress_step import ProgressStep
|
||||
|
||||
|
||||
class Development(ProgressStep):
|
||||
class Meta:
|
||||
db_table = 'development'
|
||||
10
euclid/database/models/development_planning.py
Normal file
10
euclid/database/models/development_planning.py
Normal file
@@ -0,0 +1,10 @@
|
||||
from peewee import *
|
||||
|
||||
from database.models.components.progress_step import ProgressStep
|
||||
|
||||
|
||||
class DevelopmentPlanning(ProgressStep):
|
||||
architecture = TextField()
|
||||
|
||||
class Meta:
|
||||
db_table = 'development_planning'
|
||||
12
euclid/database/models/development_steps.py
Normal file
12
euclid/database/models/development_steps.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from peewee import *
|
||||
|
||||
from playhouse.postgres_ext import BinaryJSONField
|
||||
|
||||
from database.models.components.base_models import BaseModel
|
||||
from database.models.app import App
|
||||
|
||||
|
||||
class DevelopmentSteps(BaseModel):
|
||||
app = ForeignKeyField(App, primary_key=True)
|
||||
hash_id = CharField(unique=True, null=False)
|
||||
messages = BinaryJSONField(null=True)
|
||||
6
euclid/database/models/environment_setup.py
Normal file
6
euclid/database/models/environment_setup.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from database.models.components.progress_step import ProgressStep
|
||||
|
||||
|
||||
class EnvironmentSetup(ProgressStep):
|
||||
class Meta:
|
||||
db_table = 'environment_setup'
|
||||
13
euclid/database/models/project_description.py
Normal file
13
euclid/database/models/project_description.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from peewee import *
|
||||
|
||||
from playhouse.postgres_ext import BinaryJSONField
|
||||
|
||||
from database.models.components.progress_step import ProgressStep
|
||||
|
||||
|
||||
class ProjectDescription(ProgressStep):
|
||||
prompt = TextField()
|
||||
summary = TextField()
|
||||
|
||||
class Meta:
|
||||
db_table = 'project_description'
|
||||
8
euclid/database/models/user.py
Normal file
8
euclid/database/models/user.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from peewee import *
|
||||
|
||||
from database.models.components.base_models import BaseModel
|
||||
|
||||
|
||||
class User(BaseModel):
|
||||
email = CharField(unique=True)
|
||||
password = CharField()
|
||||
9
euclid/database/models/user_stories.py
Normal file
9
euclid/database/models/user_stories.py
Normal file
@@ -0,0 +1,9 @@
|
||||
from peewee import *
|
||||
|
||||
from database.models.components.progress_step import ProgressStep
|
||||
|
||||
|
||||
class UserStories(ProgressStep):
|
||||
user_stories = TextField()
|
||||
class Meta:
|
||||
db_table = 'user_stories'
|
||||
9
euclid/database/models/user_tasks.py
Normal file
9
euclid/database/models/user_tasks.py
Normal file
@@ -0,0 +1,9 @@
|
||||
from peewee import *
|
||||
|
||||
from database.models.components.progress_step import ProgressStep
|
||||
|
||||
|
||||
class UserTasks(ProgressStep):
|
||||
user_tasks = TextField()
|
||||
class Meta:
|
||||
db_table = 'user_tasks'
|
||||
@@ -10,9 +10,7 @@ from steps.project_description.project_description import get_project_descriptio
|
||||
from steps.user_stories.user_stories import get_user_stories
|
||||
from steps.user_tasks.user_tasks import get_user_tasks
|
||||
from steps.architecture.architecture import get_architecture
|
||||
from steps.development.development import create_development_plan
|
||||
from steps.development.development import set_up_environment
|
||||
from steps.development.development import start_development
|
||||
from steps.development.development import create_development_plan, set_up_environment, start_development
|
||||
|
||||
|
||||
def init():
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
# user_stories.py
|
||||
import json
|
||||
from termcolor import colored
|
||||
from const.function_calls import ARCHITECTURE
|
||||
|
||||
from utils.utils import execute_step, find_role_from_step, generate_app_data
|
||||
from utils.utils import execute_step, find_role_from_step, generate_app_data, step_already_finished
|
||||
from database.database import save_progress, get_progress_steps
|
||||
from logger.logger import logger
|
||||
from prompts.prompts import get_additional_info_from_user
|
||||
@@ -15,17 +14,10 @@ def get_architecture(high_level_summary, user_stories, user_tasks, args):
|
||||
convo_architecture = AgentConvo(current_step)
|
||||
|
||||
# If this app_id already did this step, just get all data from DB and don't ask user again
|
||||
steps = get_progress_steps(args['app_id'], current_step)
|
||||
if steps and not execute_step(args['step'], current_step):
|
||||
first_step = steps[0]
|
||||
data = json.loads(first_step['data'])
|
||||
|
||||
architecture = data.get('architecture')
|
||||
|
||||
message = f"Architecture already done for this app_id: {args['app_id']}. Moving to next step..."
|
||||
print(colored(message, "green"))
|
||||
logger.info(message)
|
||||
return architecture
|
||||
step = get_progress_steps(args['app_id'], current_step)
|
||||
if step and not execute_step(args['step'], current_step):
|
||||
step_already_finished(args, step)
|
||||
return step['architecture']
|
||||
|
||||
# ARCHITECTURE
|
||||
print(colored(f"Planning project architecture...\n", "green"))
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import json
|
||||
from termcolor import colored
|
||||
from helpers.AgentConvo import AgentConvo
|
||||
|
||||
from utils.utils import execute_step, find_role_from_step, generate_app_data
|
||||
from utils.utils import execute_step, find_role_from_step, generate_app_data, step_already_finished
|
||||
from database.database import save_progress, get_progress_steps
|
||||
from logger.logger import logger
|
||||
from const.function_calls import FILTER_OS_TECHNOLOGIES, DEVELOPMENT_PLAN
|
||||
@@ -10,6 +9,7 @@ from const.code_execution import MAX_COMMAND_DEBUG_TRIES
|
||||
from utils.utils import get_os_info
|
||||
from helpers.cli import execute_command
|
||||
|
||||
|
||||
def environment_setup():
|
||||
# env_setup/specs.prompt
|
||||
# loop through returned array
|
||||
@@ -26,19 +26,21 @@ def implement_task(task):
|
||||
# development/task/step/specs.prompt
|
||||
pass
|
||||
|
||||
|
||||
def execute_command_and_check_cli_response(command, timeout, convo):
|
||||
cli_response = execute_command(command, timeout)
|
||||
response = convo.send_message('dev_ops/ran_command.prompt',
|
||||
{ 'cli_response': cli_response, 'command': command })
|
||||
{'cli_response': cli_response, 'command': command})
|
||||
return response
|
||||
|
||||
|
||||
def run_command_until_success(command, timeout, convo):
|
||||
command_executed = False
|
||||
for _ in range(MAX_COMMAND_DEBUG_TRIES):
|
||||
cli_response = execute_command(command, timeout)
|
||||
response = convo.send_message('dev_ops/ran_command.prompt',
|
||||
{'cli_response': cli_response, 'command': command})
|
||||
|
||||
{'cli_response': cli_response, 'command': command})
|
||||
|
||||
command_executed = response == 'DONE'
|
||||
if command_executed:
|
||||
break
|
||||
@@ -49,24 +51,17 @@ def run_command_until_success(command, timeout, convo):
|
||||
# TODO ask user to debug and press enter to continue
|
||||
pass
|
||||
|
||||
|
||||
def set_up_environment(technologies, args):
|
||||
current_step = 'environment_setup'
|
||||
convo_os_specific_tech = AgentConvo(current_step)
|
||||
|
||||
steps = get_progress_steps(args['app_id'], current_step)
|
||||
if steps and not execute_step(args['step'], current_step):
|
||||
first_step = steps[0]
|
||||
data = json.loads(first_step['data'])
|
||||
|
||||
app_data = data.get('app_data')
|
||||
if app_data is not None:
|
||||
args.update(app_data)
|
||||
|
||||
message = f"Environment setup is already done for this app_id: {args['app_id']}. Moving to next step..."
|
||||
print(colored(message, "green"))
|
||||
logger.info(message)
|
||||
# If this app_id already did this step, just get all data from DB and don't ask user again
|
||||
step = get_progress_steps(args['app_id'], current_step)
|
||||
if step and not execute_step(args['step'], current_step):
|
||||
step_already_finished(args, step)
|
||||
return
|
||||
|
||||
|
||||
# ENVIRONMENT SETUP
|
||||
print(colored(f"Setting up the environment...\n", "green"))
|
||||
logger.info(f"Setting up the environment...")
|
||||
@@ -77,69 +72,71 @@ def set_up_environment(technologies, args):
|
||||
|
||||
os_info = get_os_info()
|
||||
os_specific_techologies = convo_os_specific_tech.send_message('development/env_setup/specs.prompt',
|
||||
{ "os_info": os_info, "technologies": technologies }, FILTER_OS_TECHNOLOGIES)
|
||||
{"os_info": os_info, "technologies": technologies},
|
||||
FILTER_OS_TECHNOLOGIES)
|
||||
|
||||
for technology in os_specific_techologies:
|
||||
llm_response = convo_os_specific_tech.send_message('development/env_setup/install_next_technology.prompt',
|
||||
{ 'technology': technology}, {
|
||||
'definitions': [{
|
||||
'name': 'execute_command',
|
||||
'description': f'Executes a command that should check if {technology} is installed on the machine. ',
|
||||
'parameters': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'command': {
|
||||
'type': 'string',
|
||||
'description': f'Command that needs to be executed to check if {technology} is installed on the machine.',
|
||||
},
|
||||
'timeout': {
|
||||
'type': 'number',
|
||||
'description': f'Timeout in seconds for the approcimate time this command takes to finish.',
|
||||
}
|
||||
},
|
||||
'required': ['command', 'timeout'],
|
||||
},
|
||||
}],
|
||||
'functions': {
|
||||
'execute_command': execute_command_and_check_cli_response
|
||||
},
|
||||
'send_convo': True
|
||||
})
|
||||
|
||||
{'technology': technology}, {
|
||||
'definitions': [{
|
||||
'name': 'execute_command',
|
||||
'description': f'Executes a command that should check if {technology} is installed on the machine. ',
|
||||
'parameters': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'command': {
|
||||
'type': 'string',
|
||||
'description': f'Command that needs to be executed to check if {technology} is installed on the machine.',
|
||||
},
|
||||
'timeout': {
|
||||
'type': 'number',
|
||||
'description': f'Timeout in seconds for the approcimate time this command takes to finish.',
|
||||
}
|
||||
},
|
||||
'required': ['command', 'timeout'],
|
||||
},
|
||||
}],
|
||||
'functions': {
|
||||
'execute_command': execute_command_and_check_cli_response
|
||||
},
|
||||
'send_convo': True
|
||||
})
|
||||
|
||||
if not llm_response == 'DONE':
|
||||
installation_commands = convo_os_specific_tech.send_message('development/env_setup/unsuccessful_installation.prompt',
|
||||
{ 'technology': technology }, {
|
||||
'definitions': [{
|
||||
'name': 'execute_commands',
|
||||
'description': f'Executes a list of commands that should install the {technology} on the machine. ',
|
||||
'parameters': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'commands': {
|
||||
'type': 'array',
|
||||
'description': f'List of commands that need to be executed to install {technology} on the machine.',
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'command': {
|
||||
'type': 'string',
|
||||
'description': f'Command that needs to be executed as a step to install {technology} on the machine.',
|
||||
},
|
||||
'timeout': {
|
||||
'type': 'number',
|
||||
'description': f'Timeout in seconds for the approcimate time this command takes to finish.',
|
||||
installation_commands = convo_os_specific_tech.send_message(
|
||||
'development/env_setup/unsuccessful_installation.prompt',
|
||||
{'technology': technology}, {
|
||||
'definitions': [{
|
||||
'name': 'execute_commands',
|
||||
'description': f'Executes a list of commands that should install the {technology} on the machine. ',
|
||||
'parameters': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'commands': {
|
||||
'type': 'array',
|
||||
'description': f'List of commands that need to be executed to install {technology} on the machine.',
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'command': {
|
||||
'type': 'string',
|
||||
'description': f'Command that needs to be executed as a step to install {technology} on the machine.',
|
||||
},
|
||||
'timeout': {
|
||||
'type': 'number',
|
||||
'description': f'Timeout in seconds for the approcimate time this command takes to finish.',
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'required': ['commands'],
|
||||
},
|
||||
'required': ['commands'],
|
||||
},
|
||||
}],
|
||||
'functions': {
|
||||
'execute_commands': lambda commands: commands
|
||||
}
|
||||
})
|
||||
}],
|
||||
'functions': {
|
||||
'execute_commands': lambda commands: commands
|
||||
}
|
||||
})
|
||||
if installation_commands is not None:
|
||||
for cmd in installation_commands:
|
||||
run_command_until_success(cmd['command'], cmd['timeout'], convo_os_specific_tech)
|
||||
@@ -147,50 +144,45 @@ def set_up_environment(technologies, args):
|
||||
logger.info('The entire tech stack neede is installed and ready to be used.')
|
||||
|
||||
save_progress(args['app_id'], current_step, {
|
||||
"os_specific_techologies": os_specific_techologies, "newly_installed_technologies": [], "app_data": generate_app_data(args)
|
||||
"os_specific_techologies": os_specific_techologies, "newly_installed_technologies": [],
|
||||
"app_data": generate_app_data(args)
|
||||
})
|
||||
|
||||
# ENVIRONMENT SETUP END
|
||||
|
||||
|
||||
def create_development_plan(high_level_summary, user_stories, user_tasks, technologies_to_use, args):
|
||||
current_step = 'development_planning'
|
||||
convo_development_plan = AgentConvo(current_step)
|
||||
|
||||
steps = get_progress_steps(args['app_id'], current_step)
|
||||
if steps and not execute_step(args['step'], current_step):
|
||||
first_step = steps[0]
|
||||
data = json.loads(first_step['data'])
|
||||
# If this app_id already did this step, just get all data from DB and don't ask user again
|
||||
step = get_progress_steps(args['app_id'], current_step)
|
||||
if step and not execute_step(args['step'], current_step):
|
||||
step_already_finished(args, step)
|
||||
return step['development_plan']
|
||||
|
||||
app_data = data.get('app_data')
|
||||
if app_data is not None:
|
||||
args.update(app_data)
|
||||
|
||||
message = f"Plan for development is already done for this app_id: {args['app_id']}. Moving to next step..."
|
||||
print(colored(message, "green"))
|
||||
logger.info(message)
|
||||
return data.get('development_plan')
|
||||
|
||||
# DEVELOPMENT PLANNING
|
||||
print(colored(f"Starting to create the action plan for development...\n", "green"))
|
||||
logger.info(f"Starting to create the action plan for development...")
|
||||
|
||||
# TODO add clarifications
|
||||
development_plan = convo_development_plan.send_message('development/plan.prompt',
|
||||
{
|
||||
"app_summary": high_level_summary,
|
||||
"clarification": [],
|
||||
"user_stories": user_stories,
|
||||
"user_tasks": user_tasks,
|
||||
"technologies": technologies_to_use
|
||||
}, DEVELOPMENT_PLAN)
|
||||
{
|
||||
"app_summary": high_level_summary,
|
||||
"clarification": [],
|
||||
"user_stories": user_stories,
|
||||
"user_tasks": user_tasks,
|
||||
"technologies": technologies_to_use
|
||||
}, DEVELOPMENT_PLAN)
|
||||
|
||||
logger.info('Plan for development is created.')
|
||||
|
||||
save_progress(args['app_id'], current_step, {
|
||||
"development_plan": development_plan, "app_data": generate_app_data(args)
|
||||
"development_plan": development_plan,
|
||||
"app_data": generate_app_data(args)
|
||||
})
|
||||
|
||||
return development_plan
|
||||
|
||||
|
||||
def start_development(user_stories, user_tasks, technologies_to_use, args):
|
||||
pass
|
||||
pass
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
# project_description.py
|
||||
import json
|
||||
from termcolor import colored
|
||||
from helpers.AgentConvo import AgentConvo
|
||||
|
||||
from logger.logger import logger
|
||||
from database.database import save_progress, save_app, get_progress_steps
|
||||
from utils.utils import execute_step, generate_app_data
|
||||
from utils.utils import execute_step, generate_app_data, step_already_finished
|
||||
from prompts.prompts import ask_for_app_type, ask_for_main_app_definition, get_additional_info_from_openai, \
|
||||
generate_messages_from_description
|
||||
|
||||
@@ -15,20 +12,10 @@ def get_project_description(args):
|
||||
convo_project_description = AgentConvo(current_step)
|
||||
|
||||
# If this app_id already did this step, just get all data from DB and don't ask user again
|
||||
steps = get_progress_steps(args['app_id'], current_step)
|
||||
if steps and not execute_step(args['step'], current_step):
|
||||
first_step = steps[0]
|
||||
data = json.loads(first_step['data'])
|
||||
|
||||
summary = data.get('summary')
|
||||
app_data = data.get('app_data')
|
||||
args.update(app_data)
|
||||
|
||||
message = f"Project summary already done for this app_id: {args['app_id']}. Moving to next step..."
|
||||
print(colored(message, "green"))
|
||||
logger.info(message)
|
||||
|
||||
return summary, data.get('messages')
|
||||
step = get_progress_steps(args['app_id'], current_step)
|
||||
if step and not execute_step(args['step'], current_step):
|
||||
step_already_finished(args, step)
|
||||
return step['summary'], step['messages']
|
||||
|
||||
# PROJECT DESCRIPTION
|
||||
args['app_type'] = ask_for_app_type()
|
||||
@@ -45,7 +32,11 @@ def get_project_description(args):
|
||||
[f"{msg['role']}: {msg['content']}" for msg in high_level_messages])})
|
||||
|
||||
save_progress(args['app_id'], current_step,
|
||||
{"messages": high_level_messages, "summary": high_level_summary, "app_data": generate_app_data(args)
|
||||
{
|
||||
"prompt": description,
|
||||
"messages": high_level_messages,
|
||||
"summary": high_level_summary,
|
||||
"app_data": generate_app_data(args)
|
||||
})
|
||||
|
||||
return high_level_summary, high_level_messages
|
||||
|
||||
@@ -3,40 +3,30 @@ import json
|
||||
from termcolor import colored
|
||||
from helpers.AgentConvo import AgentConvo
|
||||
|
||||
from utils.utils import execute_step, find_role_from_step, generate_app_data
|
||||
from utils.utils import execute_step, find_role_from_step, generate_app_data, step_already_finished
|
||||
from database.database import save_progress, get_progress_steps
|
||||
from logger.logger import logger
|
||||
from prompts.prompts import get_additional_info_from_user
|
||||
from const.function_calls import USER_STORIES
|
||||
|
||||
|
||||
def get_user_stories(summary, args):
|
||||
def get_user_stories(prompt, args):
|
||||
current_step = 'user_stories'
|
||||
convo_user_stories = AgentConvo(current_step)
|
||||
|
||||
|
||||
# If this app_id already did this step, just get all data from DB and don't ask user again
|
||||
steps = get_progress_steps(args['app_id'], current_step)
|
||||
if steps and not execute_step(args['step'], current_step):
|
||||
first_step = steps[0]
|
||||
data = json.loads(first_step['data'])
|
||||
|
||||
user_stories = data.get('user_stories')
|
||||
app_data = data.get('app_data')
|
||||
if app_data is not None:
|
||||
args.update(app_data)
|
||||
|
||||
message = f"User stories already done for this app_id: {args['app_id']}. Moving to next step..."
|
||||
print(colored(message, "green"))
|
||||
logger.info(message)
|
||||
return user_stories, data.get('messages')
|
||||
step = get_progress_steps(args['app_id'], current_step)
|
||||
if step and not execute_step(args['step'], current_step):
|
||||
step_already_finished(args, step)
|
||||
return step['user_stories'], step['messages']
|
||||
|
||||
# USER STORIES
|
||||
print(colored(f"Generating user stories...\n", "green"))
|
||||
logger.info(f"Generating user stories...")
|
||||
|
||||
user_stories = convo_user_stories.send_message('user_stories/specs.prompt',
|
||||
{'prompt': summary, 'app_type': args['app_type']},
|
||||
USER_STORIES)
|
||||
{'prompt': prompt, 'app_type': args['app_type']},
|
||||
USER_STORIES)
|
||||
|
||||
logger.info(user_stories)
|
||||
user_stories = get_additional_info_from_user(user_stories, 'product_owner')
|
||||
@@ -44,8 +34,10 @@ def get_user_stories(summary, args):
|
||||
logger.info(f"Final user stories: {user_stories}")
|
||||
|
||||
save_progress(args['app_id'], current_step, {
|
||||
"messages": convo_user_stories.get_messages(), "user_stories": user_stories, "app_data": generate_app_data(args)
|
||||
"messages": convo_user_stories.get_messages(),
|
||||
"user_stories": user_stories,
|
||||
"app_data": generate_app_data(args)
|
||||
})
|
||||
|
||||
return user_stories, convo_user_stories
|
||||
# USER STORIES END
|
||||
# USER STORIES END
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
# user_tasks.py
|
||||
import json
|
||||
from termcolor import colored
|
||||
from helpers.AgentConvo import AgentConvo
|
||||
|
||||
from utils.utils import execute_step, find_role_from_step, generate_app_data
|
||||
from utils.utils import execute_step, find_role_from_step, generate_app_data, step_already_finished
|
||||
from database.database import save_progress, get_progress_steps
|
||||
from logger.logger import logger
|
||||
from prompts.prompts import get_additional_info_from_user
|
||||
@@ -14,19 +12,10 @@ def get_user_tasks(convo, args):
|
||||
current_step = 'user_tasks'
|
||||
|
||||
# If this app_id already did this step, just get all data from DB and don't ask user again
|
||||
steps = get_progress_steps(args['app_id'], current_step)
|
||||
if steps and not execute_step(args['step'], current_step):
|
||||
first_step = steps[0]
|
||||
data = json.loads(first_step['data'])
|
||||
|
||||
app_data = data.get('app_data')
|
||||
if app_data is not None:
|
||||
args.update(app_data)
|
||||
|
||||
message = f"User tasks already done for this app_id: {args['app_id']}. Moving to next step..."
|
||||
print(colored(message, "green"))
|
||||
logger.info(message)
|
||||
return data.get('user_tasks')
|
||||
step = get_progress_steps(args['app_id'], current_step)
|
||||
if step and not execute_step(args['step'], current_step):
|
||||
step_already_finished(args, step)
|
||||
return step['user_tasks']
|
||||
|
||||
# USER TASKS
|
||||
print(colored(f"Generating user tasks...\n", "green"))
|
||||
@@ -41,7 +30,9 @@ def get_user_tasks(convo, args):
|
||||
logger.info(f"Final user tasks: {user_tasks}")
|
||||
|
||||
save_progress(args['app_id'], current_step, {
|
||||
"messages": convo.get_messages(),"user_tasks": user_tasks, "app_data": generate_app_data(args)
|
||||
"messages": convo.get_messages(),
|
||||
"user_tasks": user_tasks,
|
||||
"app_data": generate_app_data(args)
|
||||
})
|
||||
|
||||
return user_tasks
|
||||
|
||||
@@ -5,11 +5,15 @@ import os
|
||||
import platform
|
||||
import distro
|
||||
import uuid
|
||||
import json
|
||||
import hashlib
|
||||
import re
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
from termcolor import colored
|
||||
|
||||
from const.llm import MAX_QUESTIONS, END_RESPONSE
|
||||
from const.common import ROLES, STEPS
|
||||
from logger.logger import logger
|
||||
|
||||
|
||||
def get_arguments():
|
||||
@@ -144,5 +148,18 @@ def execute_step(matching_step, current_step):
|
||||
return matching_step_index is not None and current_step_index is not None and current_step_index >= matching_step_index
|
||||
|
||||
|
||||
def step_already_finished(args, step):
|
||||
args.update(step['app_data'])
|
||||
|
||||
message = f"{capitalize_first_word_with_underscores(step['step'])} already done for this app_id: {args['app_id']}. Moving to next step..."
|
||||
print(colored(message, "green"))
|
||||
logger.info(message)
|
||||
|
||||
|
||||
def generate_app_data(args):
|
||||
return {'app_id': args['app_id'], 'app_type': args['app_type']}
|
||||
|
||||
|
||||
def hash_data(data):
|
||||
serialized_data = json.dumps(data, sort_keys=True).encode('utf-8')
|
||||
return hashlib.sha256(serialized_data).hexdigest()
|
||||
|
||||
@@ -5,6 +5,7 @@ distro==1.8.0
|
||||
idna==3.4
|
||||
Jinja2==3.1.2
|
||||
MarkupSafe==2.1.3
|
||||
peewee==3.16.2
|
||||
prompt-toolkit==3.0.39
|
||||
psycopg2==2.9.6
|
||||
python-dotenv==1.0.0
|
||||
|
||||
Reference in New Issue
Block a user