mirror of
https://github.com/OMGeeky/gpt-pilot.git
synced 2026-01-03 09:54:58 +01:00
Merge pull request #54 from nalbion/feature/get_email-from-gitconfig
get email from ~/.gitconfig
This commit is contained in:
13
.github/workflows/ci.yml
vendored
13
.github/workflows/ci.yml
vendored
@@ -13,10 +13,10 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.7, 3.8, 3.9, 3.10, 3.11]
|
||||
python-version: ['3.8', '3.9', '3.10', '3.11']
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v2
|
||||
@@ -30,14 +30,15 @@ jobs:
|
||||
|
||||
- name: Lint
|
||||
run: |
|
||||
pip install flake8
|
||||
pip install flake8 ruff
|
||||
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
|
||||
# stop the build if there are Python syntax errors or undefined names
|
||||
#ruff --format=github --select=E9,F63,F7,F82 --target-version=py37 .
|
||||
ruff --format=github --select=E9,F63,F7,F82 --target-version=py37 .
|
||||
# default set of ruff rules with GitHub Annotations
|
||||
#ruff --format=github --target-version=py37 .
|
||||
#ruff --format=github --target-version=py37 --ignore=F401,E501 .
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
pip install pytest
|
||||
pytest
|
||||
cd pilot
|
||||
PYTHONPATH=. pytest
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import os
|
||||
MAX_GPT_MODEL_TOKENS = int(os.getenv('MAX_TOKENS'))
|
||||
MAX_GPT_MODEL_TOKENS = int(os.getenv('MAX_TOKENS', 8192))
|
||||
MIN_TOKENS_FOR_GPT_RESPONSE = 600
|
||||
MAX_QUESTIONS = 5
|
||||
END_RESPONSE = "EVERYTHING_CLEAR"
|
||||
@@ -4,10 +4,10 @@ from termcolor import colored
|
||||
from functools import reduce
|
||||
import operator
|
||||
import psycopg2
|
||||
from const.common import PROMPT_DATA_TO_IGNORE
|
||||
from logger.logger import logger
|
||||
from psycopg2.extensions import quote_ident
|
||||
|
||||
from const.common import PROMPT_DATA_TO_IGNORE
|
||||
from logger.logger import logger
|
||||
from utils.utils import hash_data
|
||||
from database.config import DB_NAME, DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, DATABASE_TYPE
|
||||
from database.models.components.base_models import database
|
||||
|
||||
@@ -12,4 +12,4 @@ class Architecture(ProgressStep):
|
||||
architecture = JSONField() # Custom JSON field for SQLite
|
||||
|
||||
class Meta:
|
||||
db_table = 'architecture'
|
||||
table_name = 'architecture'
|
||||
|
||||
@@ -13,7 +13,7 @@ class CommandRuns(BaseModel):
|
||||
previous_step = ForeignKeyField('self', null=True, column_name='previous_step')
|
||||
|
||||
class Meta:
|
||||
db_table = 'command_runs'
|
||||
table_name = 'command_runs'
|
||||
indexes = (
|
||||
(('app', 'hash_id'), True),
|
||||
)
|
||||
@@ -5,4 +5,4 @@ from database.models.components.progress_step import ProgressStep
|
||||
|
||||
class Development(ProgressStep):
|
||||
class Meta:
|
||||
db_table = 'development'
|
||||
table_name = 'development'
|
||||
|
||||
@@ -12,4 +12,4 @@ class DevelopmentPlanning(ProgressStep):
|
||||
development_plan = JSONField() # Custom JSON field for SQLite
|
||||
|
||||
class Meta:
|
||||
db_table = 'development_planning'
|
||||
table_name = 'development_planning'
|
||||
|
||||
@@ -20,7 +20,7 @@ class DevelopmentSteps(BaseModel):
|
||||
previous_step = ForeignKeyField('self', null=True, column_name='previous_step')
|
||||
|
||||
class Meta:
|
||||
db_table = 'development_steps'
|
||||
table_name = 'development_steps'
|
||||
indexes = (
|
||||
(('app', 'hash_id'), True),
|
||||
)
|
||||
|
||||
@@ -3,4 +3,4 @@ from database.models.components.progress_step import ProgressStep
|
||||
|
||||
class EnvironmentSetup(ProgressStep):
|
||||
class Meta:
|
||||
db_table = 'environment_setup'
|
||||
table_name = 'environment_setup'
|
||||
|
||||
@@ -12,7 +12,7 @@ class FileSnapshot(BaseModel):
|
||||
content = TextField()
|
||||
|
||||
class Meta:
|
||||
db_table = 'file_snapshot'
|
||||
table_name = 'file_snapshot'
|
||||
indexes = (
|
||||
(('development_step', 'file'), True),
|
||||
)
|
||||
@@ -7,4 +7,4 @@ class ProjectDescription(ProgressStep):
|
||||
summary = TextField()
|
||||
|
||||
class Meta:
|
||||
db_table = 'project_description'
|
||||
table_name = 'project_description'
|
||||
|
||||
@@ -12,7 +12,7 @@ class UserApps(BaseModel):
|
||||
workspace = CharField(null=True)
|
||||
|
||||
class Meta:
|
||||
db_table = 'user_apps'
|
||||
table_name = 'user_apps'
|
||||
indexes = (
|
||||
(('app', 'user'), True),
|
||||
)
|
||||
|
||||
@@ -13,7 +13,7 @@ class UserInputs(BaseModel):
|
||||
previous_step = ForeignKeyField('self', null=True, column_name='previous_step')
|
||||
|
||||
class Meta:
|
||||
db_table = 'user_inputs'
|
||||
table_name = 'user_inputs'
|
||||
indexes = (
|
||||
(('app', 'hash_id'), True),
|
||||
)
|
||||
@@ -11,4 +11,4 @@ class UserStories(ProgressStep):
|
||||
else:
|
||||
user_stories = JSONField() # Custom JSON field for SQLite
|
||||
class Meta:
|
||||
db_table = 'user_stories'
|
||||
table_name = 'user_stories'
|
||||
|
||||
@@ -12,4 +12,4 @@ class UserTasks(ProgressStep):
|
||||
user_tasks = JSONField() # Custom JSON field for SQLite
|
||||
|
||||
class Meta:
|
||||
db_table = 'user_tasks'
|
||||
table_name = 'user_tasks'
|
||||
|
||||
@@ -259,7 +259,7 @@ class Developer(Agent):
|
||||
if type == 'COMMAND':
|
||||
for cmd in step_details:
|
||||
run_command_until_success(cmd['command'], cmd['timeout'], convo)
|
||||
elif type == 'CODE_CHANGE':
|
||||
code_changes_details = get_step_code_changes()
|
||||
# elif type == 'CODE_CHANGE':
|
||||
# code_changes_details = get_step_code_changes()
|
||||
# TODO: give to code monkey for implementation
|
||||
pass
|
||||
|
||||
0
pilot/logger/__init__.py
Normal file
0
pilot/logger/__init__.py
Normal file
@@ -2,13 +2,10 @@
|
||||
from __future__ import print_function, unicode_literals
|
||||
|
||||
import sys
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from termcolor import colored
|
||||
load_dotenv()
|
||||
|
||||
from termcolor import colored
|
||||
from helpers.Project import Project
|
||||
|
||||
from utils.arguments import get_arguments
|
||||
from utils.exit import exit_gpt_pilot
|
||||
from logger.logger import logger
|
||||
|
||||
@@ -7,7 +7,7 @@ You wanted me to check this - `{{ issue_description }}` but there was a problem{
|
||||
|
||||
`run_command` function will run a command on the machine and will return the CLI output to you so you can see what to do next.
|
||||
|
||||
`implement_code_changes` function will change the code where you just need to thoroughly describe what needs to be implmemented, I will implement the requested changes and let you know.
|
||||
`implement_code_changes` function will change the code where you just need to thoroughly describe what needs to be implemented, I will implement the requested changes and let you know.
|
||||
|
||||
Return a list of steps that are needed to debug this issue. By the time we execute the last step, the issue should be fixed completely. Also, make sure that at least the last step has `check_if_fixed` set to TRUE.
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import getpass
|
||||
import hashlib
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import uuid
|
||||
|
||||
from getpass import getuser
|
||||
from termcolor import colored
|
||||
|
||||
from database.database import get_app, get_app_by_user_workspace
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ def get_arguments():
|
||||
arguments[arg] = True
|
||||
|
||||
if 'user_id' not in arguments:
|
||||
arguments['user_id'] = username_to_uuid(getpass.getuser())
|
||||
arguments['user_id'] = username_to_uuid(getuser())
|
||||
|
||||
app = None
|
||||
if 'workspace' in arguments:
|
||||
@@ -40,7 +40,6 @@ def get_arguments():
|
||||
if app is None:
|
||||
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
|
||||
@@ -54,19 +53,12 @@ def get_arguments():
|
||||
else:
|
||||
arguments['app_id'] = str(uuid.uuid4())
|
||||
print(colored('\n------------------ STARTING NEW PROJECT ----------------------', 'green', attrs=['bold']))
|
||||
print(f"If you wish to continue with this project in future run:")
|
||||
print("If you wish to continue with this project in future run:")
|
||||
print(colored(f'python {sys.argv[0]} app_id={arguments["app_id"]}', 'green', attrs=['bold']))
|
||||
print(colored('--------------------------------------------------------------\n', 'green', attrs=['bold']))
|
||||
|
||||
|
||||
|
||||
if 'user_id' not in arguments:
|
||||
arguments['user_id'] = username_to_uuid(getpass.getuser())
|
||||
|
||||
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())
|
||||
arguments['email'] = get_email()
|
||||
|
||||
if 'password' not in arguments:
|
||||
arguments['password'] = 'password'
|
||||
@@ -77,6 +69,26 @@ def get_arguments():
|
||||
return arguments
|
||||
|
||||
|
||||
def get_email():
|
||||
# Attempt to get email from .gitconfig
|
||||
gitconfig_path = os.path.expanduser('~/.gitconfig')
|
||||
|
||||
if os.path.exists(gitconfig_path):
|
||||
with open(gitconfig_path, 'r') as file:
|
||||
content = file.read()
|
||||
|
||||
# Use regex to search for email address
|
||||
email_match = re.search(r'email\s*=\s*([\w\.-]+@[\w\.-]+)', content)
|
||||
|
||||
if email_match:
|
||||
return email_match.group(1)
|
||||
|
||||
# If not found, return a UUID
|
||||
# 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
|
||||
return str(uuid.uuid4())
|
||||
|
||||
|
||||
# TODO can we make BaseModel.id a CharField with default=uuid4?
|
||||
def username_to_uuid(username):
|
||||
sha1 = hashlib.sha1(username.encode()).hexdigest()
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import re
|
||||
import requests
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import json
|
||||
import tiktoken
|
||||
import questionary
|
||||
@@ -116,7 +118,7 @@ def create_gpt_chat_completion(messages: List[dict], req_type, min_tokens=MIN_TO
|
||||
|
||||
# Check if the error message is related to token limit
|
||||
if "context_length_exceeded" in error_message.lower():
|
||||
raise Exception(f'Too many tokens in the request. Please try to continue the project with some previous development step.')
|
||||
raise Exception('Too many tokens in the request. Please try to continue the project with some previous development step.')
|
||||
else:
|
||||
print('The request to OpenAI API failed. Here is the error message:')
|
||||
print(e)
|
||||
@@ -147,8 +149,15 @@ def retry_on_exception(func):
|
||||
# If the specific error "context_length_exceeded" is present, simply return without retry
|
||||
if "context_length_exceeded" in err_str:
|
||||
raise Exception("context_length_exceeded")
|
||||
if "rate_limit_exceeded" in err_str:
|
||||
# Extracting the duration from the error string
|
||||
match = re.search(r"Please try again in (\d+)ms.", err_str)
|
||||
if match:
|
||||
wait_duration = int(match.group(1)) / 1000
|
||||
time.sleep(wait_duration)
|
||||
continue
|
||||
|
||||
print(colored(f'There was a problem with request to openai API:', 'red'))
|
||||
print(colored('There was a problem with request to openai API:', 'red'))
|
||||
print(err_str)
|
||||
|
||||
user_message = questionary.text(
|
||||
@@ -187,10 +196,16 @@ def stream_gpt_completion(data, req_type):
|
||||
if endpoint == 'AZURE':
|
||||
# If yes, get the AZURE_ENDPOINT from .ENV file
|
||||
endpoint_url = os.getenv('AZURE_ENDPOINT') + '/openai/deployments/' + model + '/chat/completions?api-version=2023-05-15'
|
||||
headers = {'Content-Type': 'application/json', 'api-key': os.getenv('AZURE_API_KEY')}
|
||||
headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'api-key': os.getenv('AZURE_API_KEY')
|
||||
}
|
||||
else:
|
||||
# If not, send the request to the OpenAI endpoint
|
||||
headers = {'Content-Type': 'application/json', 'Authorization': 'Bearer ' + os.getenv("OPENAI_API_KEY")}
|
||||
headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer ' + os.getenv("OPENAI_API_KEY")
|
||||
}
|
||||
endpoint_url = 'https://api.openai.com/v1/chat/completions'
|
||||
|
||||
response = requests.post(
|
||||
@@ -230,7 +245,7 @@ def stream_gpt_completion(data, req_type):
|
||||
|
||||
if json_line['choices'][0]['finish_reason'] == 'function_call':
|
||||
function_calls['arguments'] = load_data_to_json(function_calls['arguments'])
|
||||
return return_result({'function_calls': function_calls}, lines_printed);
|
||||
return return_result({'function_calls': function_calls}, lines_printed)
|
||||
|
||||
json_line = json_line['choices'][0]['delta']
|
||||
|
||||
|
||||
40
pilot/utils/test_arguments.py
Normal file
40
pilot/utils/test_arguments.py
Normal file
@@ -0,0 +1,40 @@
|
||||
import pytest
|
||||
from unittest.mock import patch, mock_open
|
||||
import uuid
|
||||
from .arguments import get_email, username_to_uuid
|
||||
|
||||
|
||||
def test_email_found_in_gitconfig():
|
||||
mock_file_content = """
|
||||
[user]
|
||||
name = test_user
|
||||
email = test@example.com
|
||||
"""
|
||||
with patch('os.path.exists', return_value=True):
|
||||
with patch('builtins.open', mock_open(read_data=mock_file_content)):
|
||||
assert get_email() == "test@example.com"
|
||||
|
||||
|
||||
def test_email_not_found_in_gitconfig():
|
||||
mock_file_content = """
|
||||
[user]
|
||||
name = test_user
|
||||
"""
|
||||
mock_uuid = "12345678-1234-5678-1234-567812345678"
|
||||
|
||||
with patch('os.path.exists', return_value=True):
|
||||
with patch('builtins.open', mock_open(read_data=mock_file_content)):
|
||||
with patch.object(uuid, "uuid4", return_value=mock_uuid):
|
||||
assert get_email() == mock_uuid
|
||||
|
||||
|
||||
def test_gitconfig_not_present():
|
||||
mock_uuid = "12345678-1234-5678-1234-567812345678"
|
||||
|
||||
with patch('os.path.exists', return_value=False):
|
||||
with patch.object(uuid, "uuid4", return_value=mock_uuid):
|
||||
assert get_email() == mock_uuid
|
||||
|
||||
|
||||
def test_username_to_uuid():
|
||||
assert username_to_uuid("test_user") == "31676025-316f-b555-e0bf-a12f0bcfd0ea"
|
||||
Reference in New Issue
Block a user