Merge branch 'main' of github.com:Pythagora-io/copilot

This commit is contained in:
Zvonimir Sabljic
2023-08-09 13:58:16 +02:00
10 changed files with 107 additions and 70 deletions

View File

@@ -29,10 +29,11 @@ def save_user(user_id, email, password):
return user
except DoesNotExist:
try:
return User.create(id=user_id, email=email, password=password)
except IntegrityError as e:
existing_user = User.get(User.email == email)
return existing_user
except DoesNotExist:
return User.create(id=user_id, email=email, password=password)
def get_user(user_id=None, email=None):
@@ -55,12 +56,27 @@ def get_user(user_id=None, email=None):
def save_app(args):
try:
app = App.get(App.id == args['app_id'])
for key, value in args.items():
if key != 'app_id' and value is not None:
setattr(app, key, value)
app.save()
except DoesNotExist:
try:
user = get_user(user_id=args['user_id'])
except ValueError:
user = save_user(args['user_id'], args['email'], args['password'])
app = App.create(id=args['app_id'], user=user, app_type=args['app_type'], name=args['name'])
if args.get('user_id') is not None:
try:
user = get_user(user_id=args['user_id'])
except ValueError:
user = save_user(args['user_id'], args['email'], args['password'])
args['user_id'] = user.id
args['email'] = user.email
else:
user = None
app = App.create(
id=args['app_id'],
user=user,
app_type=args.get('app_type'),
name=args.get('name')
)
return app

View File

@@ -6,6 +6,6 @@ from database.models.user import User
class App(BaseModel):
user = ForeignKeyField(User, backref='apps')
app_type = CharField()
name = CharField()
app_type = CharField(null=True)
name = CharField(null=True)
status = CharField(default='started')

View File

@@ -37,9 +37,6 @@ class Project:
self.root_path = ''
# self.restore_files({dev_step_id_to_start_from})
if 'app_id' in args:
self.app = get_app(args['app_id'])
if current_step is not None:
self.current_step = current_step
if name is not None:
@@ -57,7 +54,7 @@ class Project:
def start(self):
self.project_manager = ProductOwner(self)
self.high_level_summary = self.project_manager.get_project_description()
self.project_manager.get_project_description()
self.user_stories = self.project_manager.get_user_stories()
self.user_tasks = self.project_manager.get_user_tasks()

View File

@@ -16,6 +16,7 @@ class ProductOwner(Agent):
super().__init__('product_owner', project)
def get_project_description(self):
self.project.app = save_app(self.project.args)
self.project.current_step = 'project_description'
convo_project_description = AgentConvo(self)
@@ -23,18 +24,19 @@ class ProductOwner(Agent):
step = get_progress_steps(self.project.args['app_id'], self.project.current_step)
if step and not execute_step(self.project.args['step'], self.project.current_step):
step_already_finished(self.project.args, step)
self.project_description = step['summary']
return step['summary']
self.project.project_description = step['summary']
self.project.project_description_messages = step['messages']
return
# PROJECT DESCRIPTION
self.project.args['app_type'] = ask_for_app_type()
self.project.args['name'] = clean_filename(ask_user('What is the project name?'))
self.project.args['name'] = clean_filename(ask_user(self.project, 'What is the project name?'))
setup_workspace(self.project.root_path, self.project.args['name'])
save_app(self.project.args)
self.project.app = save_app(self.project.args)
main_prompt = ask_for_main_app_definition(self, project)
main_prompt = ask_for_main_app_definition(self.project)
high_level_messages = get_additional_info_from_openai(
self.project,
@@ -51,8 +53,9 @@ class ProductOwner(Agent):
"app_data": generate_app_data(self.project.args)
})
self.project_description = high_level_summary
return high_level_summary
self.project.project_description = high_level_summary
self.project.project_description_messages = high_level_messages
return
# PROJECT DESCRIPTION END
@@ -74,7 +77,8 @@ class ProductOwner(Agent):
self.project.user_stories = self.convo_user_stories.continuous_conversation('user_stories/specs.prompt', {
'name': self.project.args['name'],
'prompt': self.project_description,
'prompt': self.project.project_description,
'clarifications': self.project.project_description_messages,
'app_type': self.project.args['app_type'],
'END_RESPONSE': END_RESPONSE
})

View File

@@ -4,9 +4,10 @@ from __future__ import print_function, unicode_literals
from dotenv import load_dotenv
from helpers.Project import Project
from utils.utils import get_arguments
from utils.arguments import get_arguments
from logger.logger import logger
def init():
load_dotenv()

View File

@@ -1,9 +1,9 @@
I want you to create the application (let's call it "{{ name }}") that can be described like this:
I want you to create the {{ app_type }} (let's call it "{{ name }}") that can be described like this:
```
{{ prompt }}
```
I'm going to show you an overview of tasks that you need to do to lead the process of creating this app and for each task, I will tell you an example of how would you solve this task for the example app.
I'm going to show you an overview of tasks that you need to do to lead the process of creating this {{ app_type }} and for each task, I will tell you an example of how would you solve this task for the example app.
Example app description: `Create a script that finds Youtube channels with the word "test" inside the channel name`.
Here is an overview of the tasks that you need to do:
@@ -12,13 +12,13 @@ Here is an overview of the tasks that you need to do:
- `do you want to enable user to be able to specify different word to search for in channel name?`
- `do you want to save the results in a CSV file on the disk?`
2. Break down user stories. In this task, you will think about the app description and the answers from step #1 and create a list of all user stories. A user story is a description of how a user can interact with the app. In the example description, user stories could be:
2. Break down user stories. In this task, you will think about the {{ app_type }} description and the answers from step #1 and create a list of all user stories. A user story is a description of how a user can interact with the {{ app_type }}. In the example description, user stories could be:
- `user will run the script from the CLI`
- `user will get the list of all channels in a CSV file`
3. Break down user tasks. In this task, you will think about the app description, answers from step #1 and the user stories from the step #2 and create a list of user tasks that a user needs to do to interact with the app. In the example description, user tasks could be:
3. Break down user tasks. In this task, you will think about the {{ app_type }} description, answers from step #1 and the user stories from the step #2 and create a list of user tasks that a user needs to do to interact with the {{ app_type }}. In the example description, user tasks could be:
- `user runs the CLI command in which they specify the keyword youtube channel needs to contain and the location where the CSV file will be saved to`
Let's start with the task #1 Getting additional answers. Think about the description for the app "{{ name }}" and ask questions that you would like to get cleared before going onto breaking down the user stories.
Let's start with the task #1 Getting additional answers. Think about the description for the {{ app_type }} "{{ name }}" and ask questions that you would like to get cleared before going onto breaking down the user stories.
{{single_question}}

View File

@@ -3,15 +3,20 @@ I want you to create {{ app_type }} (let's call it "{{ name }}") that can be des
{{ prompt }}
```
Here are some additional questions and answers to clarify the apps description:
{% if clarifications and clarifications|length > 1 %}
Here are some additional questions and answers to clarify the {{ app_type }} description:
```
{% for clarification in clarifications %}
Q: {{ clarification.question }}
A: {{ clarification.answer }}
{% for clarification in clarifications[2:] %}
{% if loop.index is odd %}
Q: {{ clarification.content }}
{% else %}
A: {{ clarification.content }}
{% endif %}
{% endfor %}
```
{% endif %}
Think step by step about the description for the app "{{ name }}" and the additional questions and answers and break down user stories. You will think about the app description and the answers listed and create a list of all user stories. A user story is a description of how a user can interact with the app. For example, if an app's description is `Create a script that finds Youtube channels with the word "test" inside the channel name`, user stories could be:
Think step by step about the description for the {{ app_type }} "{{ name }}" and the additional questions and answers and break down user stories. You will think about the {{ app_type }} description and the answers listed and create a list of all user stories. A user story is a description of how a user can interact with the {{ app_type }}. For example, if an app's description is `Create a script that finds Youtube channels with the word "test" inside the channel name`, user stories could be:
- `user will run the script from the CLI`
- `user will get the list of all channels in a CSV file`

51
euclid/utils/arguments.py Normal file
View File

@@ -0,0 +1,51 @@
import sys
import uuid
from database.database import get_app
def get_arguments():
# The first element in sys.argv is the name of the script itself.
# Any additional elements are the arguments passed from the command line.
args = sys.argv[1:]
# Create an empty dictionary to store the key-value pairs.
arguments = {}
# Loop through the arguments and parse them as key-value pairs.
for arg in args:
if '=' in arg:
key, value = arg.split('=', 1)
arguments[key] = value
else:
arguments[arg] = True
if 'app_id' in arguments:
try:
app = get_app(arguments['app_id'])
arguments['user_id'] = str(app.user.id)
arguments['app_type'] = app.app_type
arguments['name'] = app.name
# Add any other fields from the App model you wish to include
except ValueError as e:
print(e)
# Handle the error as needed, possibly exiting the script
else:
arguments['app_id'] = str(uuid.uuid4())
if 'user_id' not in arguments:
arguments['user_id'] = str(uuid.uuid4())
if 'email' not in arguments:
# todo change email so its not uuid4 but make sure to fix storing of development steps where
# 1 user can have multiple apps. In that case each app should have its own development steps
arguments['email'] = str(uuid.uuid4())
if 'password' not in arguments:
arguments['password'] = 'password'
if 'step' not in arguments:
arguments['step'] = None
print(f"If you wish to continue with this project in future run 'python main.py app_id={arguments['app_id']}'")
return arguments

View File

@@ -21,7 +21,7 @@ def styled_select(*args, **kwargs):
def styled_text(project, question):
project.user_inputs_count += 1
user_input = get_user_input_from_hash_id(project, question)
if 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
project.checkpoints['last_user_input'] = user_input
print(colored(f'Restoring user input id {user_input.id}: ', 'yellow'), end='')

View File

@@ -1,10 +1,8 @@
# utils/utils.py
import sys
import os
import platform
import distro
import uuid
import json
import hashlib
import re
@@ -16,41 +14,6 @@ from const.common import ROLES, STEPS
from logger.logger import logger
def get_arguments():
# The first element in sys.argv is the name of the script itself.
# Any additional elements are the arguments passed from the command line.
args = sys.argv[1:]
# Create an empty dictionary to store the key-value pairs.
arguments = {}
# Loop through the arguments and parse them as key-value pairs.
for arg in args:
if '=' in arg:
key, value = arg.split('=', 1)
arguments[key] = value
else:
arguments[arg] = True
if 'user_id' not in arguments:
arguments['user_id'] = str(uuid.uuid4())
if 'email' not in arguments:
arguments['email'] = 'email'
if 'password' not in arguments:
arguments['password'] = 'password'
if 'app_id' not in arguments:
arguments['app_id'] = str(uuid.uuid4())
if 'step' not in arguments:
arguments['step'] = None
print(f"If you wish to continue with this project in future run 'python main.py app_id={arguments['app_id']}'")
return arguments
def capitalize_first_word_with_underscores(s):
# Split the string into words based on underscores.
words = s.split('_')