From 09e4304f189039e2a80a6f2cf92566ffa09713ac Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Thu, 4 Jul 2024 18:44:10 +0530 Subject: [PATCH 01/39] added template and prompt --- app/prompts/python/ai_developer_django.txt | 39 +++++ .../ai_developer_flask.txt} | 0 .../templates/{python => django}/.gitignore | 0 workspace-service/templates/django/manage.py | 22 +++ .../{python => django/myapp}/__init__.py | 0 .../templates/django/myapp/admin.py | 3 + .../templates/django/myapp/app.py | 6 + .../myapp/migrations/__init__.py} | 0 .../templates/django/myapp/models.py | 3 + .../templates/django/myapp/tests.py | 3 + .../templates/django/myapp/urls.py | 7 + .../templates/django/myapp/views.py | 8 + .../templates/django/project/__init__.py | 0 .../templates/django/project/asgi.py | 16 ++ .../templates/django/project/settings.py | 128 ++++++++++++++ .../templates/django/project/urls.py | 24 +++ .../templates/django/project/wsgi.py | 16 ++ .../templates/django/pyproject.toml | 15 ++ .../templates/django/server_test.txt | 1 + .../templates/django/static/css/styles.css | 24 +++ .../templates/django/static/js/scripts.js | 4 + .../templates/django/templates/about.html | 16 ++ .../templates/django/templates/home.html | 16 ++ .../django/templates/registration/login.html | 20 +++ .../templates/django/terminal.txt | 0 workspace-service/templates/flask/.gitignore | 161 ++++++++++++++++++ workspace-service/templates/flask/__init__.py | 0 .../templates/{python => flask}/app.py | 0 .../{python => flask}/models/__init__.py | 0 .../{python => flask}/models/model.py | 0 .../{python => flask}/pyproject.toml | 0 .../{python => flask}/static/css/style.css | 0 .../{python => flask}/static/js/main.js | 0 .../templates/flask/templates/index.html | 0 34 files changed, 532 insertions(+) create mode 100644 app/prompts/python/ai_developer_django.txt rename app/prompts/{ai_developer.txt => python/ai_developer_flask.txt} (100%) rename workspace-service/templates/{python => django}/.gitignore (100%) create mode 100644 workspace-service/templates/django/manage.py rename workspace-service/templates/{python => django/myapp}/__init__.py (100%) create mode 100644 workspace-service/templates/django/myapp/admin.py create mode 100644 workspace-service/templates/django/myapp/app.py rename workspace-service/templates/{python/templates/index.html => django/myapp/migrations/__init__.py} (100%) create mode 100644 workspace-service/templates/django/myapp/models.py create mode 100644 workspace-service/templates/django/myapp/tests.py create mode 100644 workspace-service/templates/django/myapp/urls.py create mode 100644 workspace-service/templates/django/myapp/views.py create mode 100644 workspace-service/templates/django/project/__init__.py create mode 100644 workspace-service/templates/django/project/asgi.py create mode 100644 workspace-service/templates/django/project/settings.py create mode 100644 workspace-service/templates/django/project/urls.py create mode 100644 workspace-service/templates/django/project/wsgi.py create mode 100644 workspace-service/templates/django/pyproject.toml create mode 100644 workspace-service/templates/django/server_test.txt create mode 100644 workspace-service/templates/django/static/css/styles.css create mode 100644 workspace-service/templates/django/static/js/scripts.js create mode 100644 workspace-service/templates/django/templates/about.html create mode 100644 workspace-service/templates/django/templates/home.html create mode 100644 workspace-service/templates/django/templates/registration/login.html create mode 100644 workspace-service/templates/django/terminal.txt create mode 100644 workspace-service/templates/flask/.gitignore create mode 100644 workspace-service/templates/flask/__init__.py rename workspace-service/templates/{python => flask}/app.py (100%) rename workspace-service/templates/{python => flask}/models/__init__.py (100%) rename workspace-service/templates/{python => flask}/models/model.py (100%) rename workspace-service/templates/{python => flask}/pyproject.toml (100%) rename workspace-service/templates/{python => flask}/static/css/style.css (100%) rename workspace-service/templates/{python => flask}/static/js/main.js (100%) create mode 100644 workspace-service/templates/flask/templates/index.html diff --git a/app/prompts/python/ai_developer_django.txt b/app/prompts/python/ai_developer_django.txt new file mode 100644 index 00000000..ae7fdefe --- /dev/null +++ b/app/prompts/python/ai_developer_django.txt @@ -0,0 +1,39 @@ +**OBJECTIVE:** +You are an expert Python and coding assistant who follows best coding practices. You will receive user requirements along with the current codebase. Your task is to generate and manage code to achieve the user requirements within a provided virtual environment. +**GOALS:** +1) You will generate all code for the user requirement in a single file. +2) while generating the filename give the full qualified file path with reference to base path named "{project_workspace_id}". +3) Always create separate files whenever needed as per best coding practices. +4) Generate only those files which are updated based on input request.. +5) Only generate those files whose code is updated based on user request. +6) If error is given back to you based on error update the relevant files and generate them. +**INSTRUCTIONS FOR GENERATING CODE:** +1) The application is always Django-based. +2) The entry point is `manage.py`, to be executed with `python manage.py runserver 0.0.0.0:5000`. +3) Use SQLite for the database, with Django's built-in ORM. +4) Use Django's built-in migration system (`python manage.py makemigrations` and `python manage.py migrate`). +5) All requirements will be done using poetry. generate respective poetry add commands in `terminal.txt`. +6) Place all commands to run and test the app in `terminal.txt`. +7) Test the Django server with the designated endpoint like `http://0.0.0.0:5000` and record it in `server_test.txt`. It is important to test out all of the endpoints that are mentioned in the 'urls.py' file in the 'myapp' folder. + - In case an endpoint depends on a prexisting value such as 'company//', ensure to first add a dummy entry so as to not result in an error, then test the endpoint. +8) Maintain modular and scalable code, creating new files as needed. +9) Always include docstrings for classes, functions, and methods. +10) The `settings.py` file in the 'project' directory should have allowed hosts set to `['*']`, and the secret key should be 'SECRET_KEY'. +11) DO NOT change the original location oF the existing files in the codebase, you can edit the content of the existing files or create new files if required. +**INSTRUCTIONS TO NOTE WHEN DEBUGGING ERRORS:** +1) Modify `terminal.txt` to remove unnecessary commands. +2) If the migrations directory exists and is not empty, do not run `makemigrations`. Instead, ensure the migrations have been applied correctly by first running `python manage.py makemigrations` and then running `python manage.py migrate`. +3) If errors persist after initial migration, verify the integrity of migration scripts and update them as necessary. +**OUTPUT FORMAT:** +Generate your output in this format only : +``` +THOUGHT: "" +|filename|: +|code|: +|filename|: +|code|: +|filename|: terminal.txt +|terminal|: +|filename|: server_test.txt +|code|: +``` \ No newline at end of file diff --git a/app/prompts/ai_developer.txt b/app/prompts/python/ai_developer_flask.txt similarity index 100% rename from app/prompts/ai_developer.txt rename to app/prompts/python/ai_developer_flask.txt diff --git a/workspace-service/templates/python/.gitignore b/workspace-service/templates/django/.gitignore similarity index 100% rename from workspace-service/templates/python/.gitignore rename to workspace-service/templates/django/.gitignore diff --git a/workspace-service/templates/django/manage.py b/workspace-service/templates/django/manage.py new file mode 100644 index 00000000..6dfbb495 --- /dev/null +++ b/workspace-service/templates/django/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/workspace-service/templates/python/__init__.py b/workspace-service/templates/django/myapp/__init__.py similarity index 100% rename from workspace-service/templates/python/__init__.py rename to workspace-service/templates/django/myapp/__init__.py diff --git a/workspace-service/templates/django/myapp/admin.py b/workspace-service/templates/django/myapp/admin.py new file mode 100644 index 00000000..34ef61e2 --- /dev/null +++ b/workspace-service/templates/django/myapp/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. \ No newline at end of file diff --git a/workspace-service/templates/django/myapp/app.py b/workspace-service/templates/django/myapp/app.py new file mode 100644 index 00000000..0ad8e5a7 --- /dev/null +++ b/workspace-service/templates/django/myapp/app.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class MyappConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'myapp' \ No newline at end of file diff --git a/workspace-service/templates/python/templates/index.html b/workspace-service/templates/django/myapp/migrations/__init__.py similarity index 100% rename from workspace-service/templates/python/templates/index.html rename to workspace-service/templates/django/myapp/migrations/__init__.py diff --git a/workspace-service/templates/django/myapp/models.py b/workspace-service/templates/django/myapp/models.py new file mode 100644 index 00000000..d49766e4 --- /dev/null +++ b/workspace-service/templates/django/myapp/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. \ No newline at end of file diff --git a/workspace-service/templates/django/myapp/tests.py b/workspace-service/templates/django/myapp/tests.py new file mode 100644 index 00000000..c2629a3a --- /dev/null +++ b/workspace-service/templates/django/myapp/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. \ No newline at end of file diff --git a/workspace-service/templates/django/myapp/urls.py b/workspace-service/templates/django/myapp/urls.py new file mode 100644 index 00000000..9c720331 --- /dev/null +++ b/workspace-service/templates/django/myapp/urls.py @@ -0,0 +1,7 @@ +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.home, name='home'), + path('about/', views.about, name='about'), +] \ No newline at end of file diff --git a/workspace-service/templates/django/myapp/views.py b/workspace-service/templates/django/myapp/views.py new file mode 100644 index 00000000..fba35102 --- /dev/null +++ b/workspace-service/templates/django/myapp/views.py @@ -0,0 +1,8 @@ +from django.shortcuts import render +from django.http import HttpResponse + +def home(request): + return render(request, 'home.html') + +def about(request): + return render(request, 'about.html') \ No newline at end of file diff --git a/workspace-service/templates/django/project/__init__.py b/workspace-service/templates/django/project/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/workspace-service/templates/django/project/asgi.py b/workspace-service/templates/django/project/asgi.py new file mode 100644 index 00000000..8d1d4db6 --- /dev/null +++ b/workspace-service/templates/django/project/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for project project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings') + +application = get_asgi_application() \ No newline at end of file diff --git a/workspace-service/templates/django/project/settings.py b/workspace-service/templates/django/project/settings.py new file mode 100644 index 00000000..0c97283e --- /dev/null +++ b/workspace-service/templates/django/project/settings.py @@ -0,0 +1,128 @@ +""" +Django settings for project project. + +Generated by 'django-admin startproject' using Django 5.0.6. + +For more information on this file, see +https://docs.djangoproject.com/en/5.0/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/5.0/ref/settings/ +""" + +from pathlib import Path + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'django-insecure-4=nk4!b1_ff4&=h!*_46ynfn)cy3iup1zw8i)ml+htggth5jvh' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = ['*'] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'myapp', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'project.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [BASE_DIR / 'templates'], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'project.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/5.0/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'db.sqlite3', + } +} + + +# Password validation +# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/5.0/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/5.0/howto/static-files/ + +STATIC_URL = '/static/' +STATICFILES_DIRS = [BASE_DIR / 'static'] + +# Default primary key field type +# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +LOGIN_REDIRECT_URL = '/' +LOGOUT_REDIRECT_URL = '/' \ No newline at end of file diff --git a/workspace-service/templates/django/project/urls.py b/workspace-service/templates/django/project/urls.py new file mode 100644 index 00000000..72bb469b --- /dev/null +++ b/workspace-service/templates/django/project/urls.py @@ -0,0 +1,24 @@ +""" +URL configuration for project project. + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/5.0/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path, include + +urlpatterns = [ + path('admin/', admin.site.urls), + path('accounts/', include('django.contrib.auth.urls')), + path('', include('myapp.urls')), +] \ No newline at end of file diff --git a/workspace-service/templates/django/project/wsgi.py b/workspace-service/templates/django/project/wsgi.py new file mode 100644 index 00000000..45815182 --- /dev/null +++ b/workspace-service/templates/django/project/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for project project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings') + +application = get_wsgi_application() \ No newline at end of file diff --git a/workspace-service/templates/django/pyproject.toml b/workspace-service/templates/django/pyproject.toml new file mode 100644 index 00000000..8fc2d4cc --- /dev/null +++ b/workspace-service/templates/django/pyproject.toml @@ -0,0 +1,15 @@ +[tool.poetry] +name = "django-app" +version = "0.1.0" +description = "" +authors = ["SuperCoder "] +package-mode = false + +[tool.poetry.dependencies] +python = "^3.12" +Django = "5.0" +setuptools = "^70.0.0" + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/workspace-service/templates/django/server_test.txt b/workspace-service/templates/django/server_test.txt new file mode 100644 index 00000000..ef6cc63a --- /dev/null +++ b/workspace-service/templates/django/server_test.txt @@ -0,0 +1 @@ +http://0.0.0.0:5000 \ No newline at end of file diff --git a/workspace-service/templates/django/static/css/styles.css b/workspace-service/templates/django/static/css/styles.css new file mode 100644 index 00000000..0621254f --- /dev/null +++ b/workspace-service/templates/django/static/css/styles.css @@ -0,0 +1,24 @@ +body { + font-family: Arial, sans-serif; + background-color: #f8f9fa; + margin: 0; + padding: 0; +} + +h1 { + color: #343a40; + text-align: center; + margin-top: 50px; +} + +a { + display: block; + text-align: center; + margin: 10px 0; + color: #007bff; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} \ No newline at end of file diff --git a/workspace-service/templates/django/static/js/scripts.js b/workspace-service/templates/django/static/js/scripts.js new file mode 100644 index 00000000..f5bea9e3 --- /dev/null +++ b/workspace-service/templates/django/static/js/scripts.js @@ -0,0 +1,4 @@ +document.addEventListener('DOMContentLoaded', function() { + console.log('JavaScript loaded and ready.'); + // Add more JavaScript functionality here +}); \ No newline at end of file diff --git a/workspace-service/templates/django/templates/about.html b/workspace-service/templates/django/templates/about.html new file mode 100644 index 00000000..902ddbb4 --- /dev/null +++ b/workspace-service/templates/django/templates/about.html @@ -0,0 +1,16 @@ +{% load static %} + + + + + About + + + + +

About Us

+ Home + + + + \ No newline at end of file diff --git a/workspace-service/templates/django/templates/home.html b/workspace-service/templates/django/templates/home.html new file mode 100644 index 00000000..59cb4249 --- /dev/null +++ b/workspace-service/templates/django/templates/home.html @@ -0,0 +1,16 @@ +{% load static %} + + + + + Home + + + + +

Welcome to the Home Page

+ About + + + + \ No newline at end of file diff --git a/workspace-service/templates/django/templates/registration/login.html b/workspace-service/templates/django/templates/registration/login.html new file mode 100644 index 00000000..666dcde2 --- /dev/null +++ b/workspace-service/templates/django/templates/registration/login.html @@ -0,0 +1,20 @@ +{% load static %} + + + + + Login + + + + +

Login

+
+ {% csrf_token %} + {{ form.as_p }} + +
+ + + + \ No newline at end of file diff --git a/workspace-service/templates/django/terminal.txt b/workspace-service/templates/django/terminal.txt new file mode 100644 index 00000000..e69de29b diff --git a/workspace-service/templates/flask/.gitignore b/workspace-service/templates/flask/.gitignore new file mode 100644 index 00000000..ed93581d --- /dev/null +++ b/workspace-service/templates/flask/.gitignore @@ -0,0 +1,161 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# Ignore IDE specific files +.vscode/ +.idea/ +*.swp + +# Ignore OS generated files +.DS_Store \ No newline at end of file diff --git a/workspace-service/templates/flask/__init__.py b/workspace-service/templates/flask/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/workspace-service/templates/python/app.py b/workspace-service/templates/flask/app.py similarity index 100% rename from workspace-service/templates/python/app.py rename to workspace-service/templates/flask/app.py diff --git a/workspace-service/templates/python/models/__init__.py b/workspace-service/templates/flask/models/__init__.py similarity index 100% rename from workspace-service/templates/python/models/__init__.py rename to workspace-service/templates/flask/models/__init__.py diff --git a/workspace-service/templates/python/models/model.py b/workspace-service/templates/flask/models/model.py similarity index 100% rename from workspace-service/templates/python/models/model.py rename to workspace-service/templates/flask/models/model.py diff --git a/workspace-service/templates/python/pyproject.toml b/workspace-service/templates/flask/pyproject.toml similarity index 100% rename from workspace-service/templates/python/pyproject.toml rename to workspace-service/templates/flask/pyproject.toml diff --git a/workspace-service/templates/python/static/css/style.css b/workspace-service/templates/flask/static/css/style.css similarity index 100% rename from workspace-service/templates/python/static/css/style.css rename to workspace-service/templates/flask/static/css/style.css diff --git a/workspace-service/templates/python/static/js/main.js b/workspace-service/templates/flask/static/js/main.js similarity index 100% rename from workspace-service/templates/python/static/js/main.js rename to workspace-service/templates/flask/static/js/main.js diff --git a/workspace-service/templates/flask/templates/index.html b/workspace-service/templates/flask/templates/index.html new file mode 100644 index 00000000..e69de29b From e94a988ac76bf87445d7c560df35fe0ee599d0fc Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Thu, 4 Jul 2024 18:52:54 +0530 Subject: [PATCH 02/39] changes in code for django template --- app/services/project_service.go | 2 +- app/tasks/create_execution_job_task.go | 6 +- .../python_django_workflow_config.go | 82 +++ .../impl/django_server_step_executor.go | 470 ++++++++++++++++++ .../impl/flask_sever_test_executor.go | 2 +- ...go => open_ai_code_generation_executor.go} | 139 +++--- ...o => open_ai_update_code_file_executor.go} | 0 .../steps/code_generate_step.go | 1 + executor.go | 88 +++- .../app/controllers/workspace_controller.go | 5 +- 10 files changed, 701 insertions(+), 94 deletions(-) create mode 100644 app/workflow_executors/python_django_workflow_config.go create mode 100644 app/workflow_executors/step_executors/impl/django_server_step_executor.go rename app/workflow_executors/step_executors/impl/{open_ai_flask_code_generation_executor.go => open_ai_code_generation_executor.go} (70%) rename app/workflow_executors/step_executors/impl/{open_ai_flask_update_code_file_executor.go => open_ai_update_code_file_executor.go} (100%) diff --git a/app/services/project_service.go b/app/services/project_service.go index 0a8066f6..dcdd4338 100644 --- a/app/services/project_service.go +++ b/app/services/project_service.go @@ -110,7 +110,7 @@ func (s *ProjectService) CreateProject(organisationID int, requestData request.C return nil, err } remoteGitURL := fmt.Sprintf("https://%s:%s@%s/git/%s/%s.git", config.GitnessUser(), config.GitnessToken(), config.GitnessHost(), spaceOrProjectName, project.Name) - backendService := "python" + backendService := requestData.Framework //Making Call to Workspace Service to create workspace on project level _, err = s.workspaceServiceClient.CreateWorkspace( &request.CreateWorkspaceRequest{ diff --git a/app/tasks/create_execution_job_task.go b/app/tasks/create_execution_job_task.go index f1624e40..ff02d436 100644 --- a/app/tasks/create_execution_job_task.go +++ b/app/tasks/create_execution_job_task.go @@ -9,12 +9,11 @@ import ( "context" "errors" "fmt" + "strings" "github.com/goccy/go-json" "gorm.io/gorm" - "github.com/hibiken/asynq" "go.uber.org/zap" - "ai-developer/app/client/workspace" ) @@ -148,7 +147,8 @@ func (h *CreateExecutionJobTaskHandler) HandleTask(ctx context.Context, t *asynq createJobRequest.WithProjectId(project.HashID) createJobRequest.WithIsReExecution(payload.ReExecute) createJobRequest.WithExecutionId(int64(execution.ID)) - + createJobRequest.Env = append(createJobRequest.Env, "EXECUTION_TEMPLATE=" + strings.ToUpper(project.Framework)) + job, err := h.workspaceServiceClient.CreateJob(createJobRequest) if err != nil { tx.Rollback() diff --git a/app/workflow_executors/python_django_workflow_config.go b/app/workflow_executors/python_django_workflow_config.go new file mode 100644 index 00000000..6aafcc58 --- /dev/null +++ b/app/workflow_executors/python_django_workflow_config.go @@ -0,0 +1,82 @@ +package workflow_executors + +import ( + "ai-developer/app/workflow_executors/step_executors/graph" + "ai-developer/app/workflow_executors/step_executors/steps" +) + +var DjangoWorkflowConfig = &WorkflowConfig{ + WorkflowName: "Django Workflow", + StepGraph: &graph.StepGraph{ + StartingNode: steps.GIT_CREATE_BRANCH_STEP, + Nodes: map[steps.StepName]*graph.StepNode{ + steps.GIT_CREATE_BRANCH_STEP: { + Step: &steps.GitMakeBranchStep{}, + Transitions: map[graph.ExecutionState]*steps.StepName{ + graph.ExecutionSuccessState: &steps.CODE_GENERATE_STEP, + graph.ExecutionErrorState: nil, + }, + }, + steps.CODE_GENERATE_STEP: { + Step: &steps.GenerateCodeStep{ + MaxLoopIterations: 10, + }, + Transitions: map[graph.ExecutionState]*steps.StepName{ + graph.ExecutionSuccessState: &steps.UPDATE_CODE_FILE_STEP, + graph.ExecutionErrorState: nil, + }, + }, + steps.RETRY_CODE_GENERATE_STEP: { + Step: &steps.GenerateCodeStep{ + MaxLoopIterations: 10, + Retry: true, + }, + Transitions: map[graph.ExecutionState]*steps.StepName{ + graph.ExecutionSuccessState: &steps.UPDATE_CODE_FILE_STEP, + graph.ExecutionErrorState: nil, + }, + }, + + steps.UPDATE_CODE_FILE_STEP: { + Step: &steps.UpdateCodeFileStep{}, + Transitions: map[graph.ExecutionState]*steps.StepName{ + graph.ExecutionSuccessState: &steps.SERVER_START_STEP, + graph.ExecutionErrorState: nil, + }, + }, + + steps.SERVER_START_STEP: { + Step: &steps.ServerStartTestStep{}, + Transitions: map[graph.ExecutionState]*steps.StepName{ + graph.ExecutionSuccessState: &steps.GIT_COMMIT_STEP, + graph.ExecutionRetryState: &steps.RETRY_CODE_GENERATE_STEP, + graph.ExecutionErrorState: nil, + }, + }, + + steps.GIT_COMMIT_STEP: { + Step: &steps.GitCommitStep{}, + Transitions: map[graph.ExecutionState]*steps.StepName{ + graph.ExecutionSuccessState: &steps.GIT_PUSH_STEP, + graph.ExecutionErrorState: nil, + }, + }, + + steps.GIT_PUSH_STEP: { + Step: &steps.GitPushStep{}, + Transitions: map[graph.ExecutionState]*steps.StepName{ + graph.ExecutionSuccessState: &steps.GIT_CREATE_PULL_REQUEST_STEP, + graph.ExecutionErrorState: nil, + }, + }, + + steps.GIT_CREATE_PULL_REQUEST_STEP: { + Step: &steps.GitMakePullRequestStep{}, + Transitions: map[graph.ExecutionState]*steps.StepName{ + graph.ExecutionSuccessState: nil, + graph.ExecutionErrorState: nil, + }, + }, + }, + }, +} \ No newline at end of file diff --git a/app/workflow_executors/step_executors/impl/django_server_step_executor.go b/app/workflow_executors/step_executors/impl/django_server_step_executor.go new file mode 100644 index 00000000..1a437822 --- /dev/null +++ b/app/workflow_executors/step_executors/impl/django_server_step_executor.go @@ -0,0 +1,470 @@ +package impl + +import ( + "ai-developer/app/config" + "ai-developer/app/services" + "ai-developer/app/workflow_executors/step_executors/steps" + "bufio" + "bytes" + "fmt" + "io" + "net/http" + "os" + "os/exec" + "path/filepath" + "strconv" + "strings" + "time" + + "go.uber.org/zap" +) + +type DjangoServerStartTestExecutor struct { + executionStepService *services.ExecutionStepService + activityLogService *services.ActivityLogService + logger *zap.Logger +} + +func NewDjangoServerStartTestExecutor( + executionStepService *services.ExecutionStepService, + activityLogService *services.ActivityLogService, + logger *zap.Logger, +) *DjangoServerStartTestExecutor { + return &DjangoServerStartTestExecutor{ + executionStepService: executionStepService, + activityLogService: activityLogService, + logger: logger, + } +} + +func (e DjangoServerStartTestExecutor) Execute(step steps.ServerStartTestStep) error { + fmt.Printf("Executing Django Server Start Test Step: %s\n", step.StepName()) + + err := e.activityLogService.CreateActivityLog( + step.ExecutionStep.ExecutionID, + step.ExecutionStep.ID, + "INFO", + fmt.Sprintf("Starting and testing Server..."), + ) + if err != nil { + fmt.Println("Error creating activity log" + err.Error()) + return err + } + status, stderr := e.serverRunTest(step) + if status == "Passed" { + fmt.Println("Server test passed") + err := e.activityLogService.CreateActivityLog( + step.ExecutionStep.ExecutionID, + step.ExecutionStep.ID, + "INFO", + fmt.Sprintf("Server working well!"), + ) + if err != nil { + fmt.Println("Error creating activity log" + err.Error()) + return err + } + return nil + } else { + fmt.Println("Server test failed") + fmt.Println("Error: ", stderr) + + //Update in DB in execution step + err := e.executionStepService.UpdateExecutionStepResponse( + step.ExecutionStep, + map[string]interface{}{"error": stderr}, + "SUCCESS", + ) + if err != nil { + fmt.Printf("Error updating execution step: %s\n", err.Error()) + return fmt.Errorf("%w: %v", steps.ErrReiterate, err) + } + + err = e.activityLogService.CreateActivityLog( + step.ExecutionStep.ExecutionID, + step.ExecutionStep.ID, + "ERROR", + fmt.Sprintf("Server test failed: %s", stderr), + ) + if err != nil { + fmt.Println("Error creating activity log" + err.Error()) + return fmt.Errorf("%w: %v", steps.ErrReiterate, err) + } + err = e.activityLogService.CreateActivityLog( + step.ExecutionStep.ExecutionID, + step.ExecutionStep.ID, + "INFO", + fmt.Sprintf("Server test failed fixing the issue..."), + ) + + if err != nil { + fmt.Println("Error creating activity log" + err.Error()) + return fmt.Errorf("%w: %v", steps.ErrReiterate, err) + } + + return fmt.Errorf("%w: %v", steps.ErrReiterate, err) + } +} + +func (e *DjangoServerStartTestExecutor) getDjangoServerURL() string { + return "http://127.0.0.1:5000/" +} + +func (e *DjangoServerStartTestExecutor) getDjangoServerAppFileName() string { + return "manage.py" +} + +// serverRunTest runs the server test. +func (e *DjangoServerStartTestExecutor) serverRunTest(step steps.ServerStartTestStep) (string, string) { + projectDir := config.WorkspaceWorkingDirectory() + "/" + step.Project.HashID + appPath := projectDir + "/" + e.getDjangoServerAppFileName() + serverURL := e.getDjangoServerURL() + timeout := 60 * time.Second + dependencyStatus, dependencyError := e.executeDependencies(projectDir) + if dependencyStatus == "Dependency_Error" { + return "Failed", dependencyError + } + serverProcess, stdout, stderr, err := e.startDjangoServer(appPath, projectDir) + fmt.Println("Server Process: ", serverProcess) + fmt.Println("Error: ", err) + fmt.Println("Stderr: ", stderr) + fmt.Println("Stdout: ", stdout) + fmt.Println("Server process started successfully") + fmt.Println("Server process: ", serverProcess) + fmt.Println("Checking for server start in stderr: ", strings.Contains(stdout.String(), "Starting development server at")) + if err != nil || (stderr.String() != "" && !strings.Contains(stdout.String(), "Starting development server at")) { + if serverProcess != nil && serverProcess.Process != nil { + err := serverProcess.Process.Kill() + if err != nil { + fmt.Printf("Error killing Django server process: %s\n", err.Error()) + return "", "" + } + } else { + fmt.Println("Server process is nil, cannot kill the process.") + } + e.cleanupPort(5000) + fmt.Printf("Error starting Django server: %s\n", stderr.String()) + return "Failed", stderr.String() + } + + server_status, err_msg, response_body := e.checkServerStatus(serverURL, timeout) + if server_status{ + fmt.Println("Server is running!") + if serverProcess != nil && serverProcess.Process != nil { + err := serverProcess.Process.Kill() + if err != nil { + fmt.Printf("Error killing Django server process: %s\n", err.Error()) + return "", "" + } + } + fmt.Println("Server process killed successfully") + return "Passed", "" + } else { + e.cleanupPort(5000) + return "Failed", err_msg+string(response_body) + } +} + +func (e *DjangoServerStartTestExecutor) startDjangoServer(appPath string, workDir string) (*exec.Cmd, *bytes.Buffer, *bytes.Buffer, error) { + venvPath := filepath.Join(workDir, ".venv") // Assuming the virtual environment directory is named .venv + venvBin := filepath.Join(venvPath, "bin") + pythonPath := filepath.Join(venvBin, "python") // This should point to the Python executable in the virtual environment + + // Create the PATH environment variable to use the virtual environment. + newPath := fmt.Sprintf("PATH=%s:%s", venvBin, os.Getenv("PATH")) + + var stderrBuf bytes.Buffer + var stdOutputBuf bytes.Buffer + fmt.Printf("Starting Django server using command: %s %s\n", pythonPath, appPath) + + stdout := e.CheckPythonVersion(workDir, newPath) + fmt.Println("Which Python Output: ", string(stdout)) + + cmd, err := RunDjangoServer(appPath, workDir, pythonPath, newPath, &stdOutputBuf, &stderrBuf) + fmt.Println("Error: ", err) + if err != nil { + errorMessage := fmt.Sprintf("Error starting Django server: %s\n", stderrBuf.String()) + fmt.Print(errorMessage) + return nil, nil, &stderrBuf, err + } + fmt.Println("Here waiting for server to start...") + time.Sleep(20 * time.Second) + fmt.Println("Here after waiting for server to start...") + + fmt.Println("STDOUT: ______________ ") + fmt.Println(stdOutputBuf.String()) + fmt.Println("STDERR: __________ ") + fmt.Println(stderrBuf.String()) + fmt.Println("Cmd.Err : ", cmd.Err) + return cmd, &stdOutputBuf, &stderrBuf, nil +} + +func RunDjangoServer(appPath string, workDir string, pythonPath string, newPath string, stdOutputBuf *bytes.Buffer, stderrBuf *bytes.Buffer) (*exec.Cmd, error) { + commands := []string{ + fmt.Sprintf("%s %s makemigrations", pythonPath, appPath), + fmt.Sprintf("%s %s migrate", pythonPath, appPath), + fmt.Sprintf("%s %s runserver 0.0.0.0:5000", pythonPath, appPath), + } + + for i, command := range commands { + cmd := exec.Command("sh", "-c", command) + cmd.Dir = workDir + cmd.Env = append(os.Environ(), newPath) + + if i < len(commands)-1 { // For the first two commands + var combinedOutput bytes.Buffer + cmd.Stdout = &combinedOutput + cmd.Stderr = &combinedOutput + fmt.Printf("Running: %s\n", command) + err := cmd.Start() + if err != nil { + fmt.Printf("failed to start command: %v\n", err) + return cmd, err + } + err = cmd.Wait() + if err != nil { + fmt.Printf("command failed: %v\n", err) + stderrBuf.Write(combinedOutput.Bytes()) // Capture the error output + return cmd, err + } + stdOutputBuf.Write(combinedOutput.Bytes()) + } else { // For the last command to run the server + cmd.Stdout = stdOutputBuf + cmd.Stderr = stderrBuf + fmt.Println("Starting Django server...") + err := cmd.Start() + if err != nil { + fmt.Printf("failed to start Django server: %v\n", err) + return cmd, err + } + return cmd, nil + } + } + return nil, nil +} + +func (e *DjangoServerStartTestExecutor) cleanupPort(port int) { + fmt.Printf("Cleaning up any processes using port %d\n", port) + cmd := exec.Command("sh", "-c", fmt.Sprintf("fuser -k %d/tcp", port)) + err := cmd.Run() + if err != nil { + fmt.Printf("Error cleaning up port %d: %v\n", port, err) + } else { + fmt.Printf("Successfully cleaned up port %d\n", port) + } +} + + +func (e *DjangoServerStartTestExecutor) CheckPythonVersion(workDir string, newPath string) []byte { + // Prepare the command to check the Python path + cmd1 := exec.Command("which", "python") + cmd1.Dir = workDir // Set the directory to the working directory + + cmd1.Env = append(os.Environ(), newPath) // Include the modified PATH in the environment + e.logger.Debug("DIR : ") + fmt.Println(cmd1.Dir) + e.logger.Debug("ENV: ") + fmt.Println(cmd1.Env) + // Execute the command and capture the output + stdout, _ := cmd1.CombinedOutput() + return stdout +} + +// checkServerStatus checks if the server is running. +func (e *DjangoServerStartTestExecutor) checkServerStatus(url string, timeout time.Duration) (bool, string, []byte) { + fmt.Println("Checking server status...") + client := &http.Client{Timeout: timeout} + + for start := time.Now(); time.Since(start) < timeout; { + resp, err := client.Get(url) + fmt.Println("_______________________________________________________") + fmt.Println("Response: ", resp) + + if err != nil { + fmt.Println("Error occurred:", err) + return false, "Error occurred: " + err.Error(), nil + } + + if resp.StatusCode == http.StatusOK { + fmt.Println("Server is running!") + return true, "", nil + } + + if resp.Body != nil { + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + fmt.Println("Error reading response body:", err) + return false, "Error reading response body: " + err.Error(), nil + } + return false, "Server responded with status code: " + strconv.Itoa(resp.StatusCode), body + } + time.Sleep(1 * time.Second) + } + return false, "Request timed out", nil +} + +// executeDependencies executes commands from terminal.txt. +func (e *DjangoServerStartTestExecutor) executeDependencies(workDir string) (string, string) { + fmt.Println("Executing dependencies...") + venvPath := filepath.Join(workDir, ".venv") // Assuming the virtual environment directory is named .venv + + // Ensure the virtual environment is created + _, err := ensureVenv(workDir, venvPath) + if err != nil { + e.logger.Error("Error ensuring virtual environment", zap.Error(err)) + errorMessage := fmt.Sprintf("Error ensuring virtual environment: %s\n", err.Error()) + return "Dependency_Error", errorMessage + } + + // Create the PATH environment variable to use the virtual environment. + venvBin := filepath.Join(venvPath, "bin") + poetryBin := "/opt/poetry/bin" + newPath := fmt.Sprintf("PATH=%s:%s:%s", venvBin, poetryBin, os.Getenv("PATH")) + updatedEnv := getUpdateEnvs(workDir, newPath) + + fmt.Println("New Path: ", newPath) + fmt.Println("Updated Env: ", updatedEnv) + + //Set virtual env + // Set the VIRTUAL_ENV environment variable to the correct path + err = os.Setenv("VIRTUAL_ENV", venvPath) + if err != nil { + errorMessage := fmt.Sprintf("Error setting VIRTUAL_ENV environment variable: %s\n", err.Error()) + return "Dependency_Error", errorMessage + } + + //Get virtual environment info + venvInfoOutput := GetPoetryPathInfo(workDir, updatedEnv, err) + if err != nil { + errorMessage := fmt.Sprintf("Error getting virtual environment info: %s\n", err.Error()) + fmt.Print(errorMessage) + return "Dependency_Error", errorMessage + } + fmt.Printf("Virtual environment path for poetry: %s\n", strings.TrimSpace(string(venvInfoOutput))) + commands, err := e.ReadCommandsFromFile(workDir) + if err != nil { + errorMessage := fmt.Sprintf("Error reading terminal.txt: %s\n", err.Error()) + fmt.Print(errorMessage) + return "Dependency_Error", errorMessage + + } + + for _, command := range commands { + fmt.Printf("\n_____________Executing command_____________: %s\n", command) + fmt.Println("Checking ENVs : ") + for _, env := range updatedEnv { + fmt.Println("Env: ", env) + } + // Execute ls -lah command to see the directory contents + lsOutput, err := ListOutputInDir(workDir, updatedEnv) + if err != nil { + errorMessage := fmt.Sprintf("Error executing 'ls -lah': %s\n", err.Error()) + fmt.Print(errorMessage) + return "Dependency_Error", errorMessage + } + fmt.Println("ls -lah Output:\n", string(lsOutput)) + e.listInstalledPackages(venvBin) + + pythonVersion := e.CheckPythonVersion(workDir, newPath) + fmt.Println("Which Python Output: ", string(pythonVersion)) + + stdout, err := ExecuteTerminalCommand(workDir, command, updatedEnv) + fmt.Println("Execution Output: ", string(stdout)) + + if err != nil { + fmt.Println("Error: ", err) + if strings.Contains(string(stdout), "alembic") && + !strings.Contains(string(stdout), "Error") && + !strings.Contains(string(stdout), "ERROR") && + strings.Contains(string(stdout), "INFO") { + fmt.Println("Alembic specific case, assuming it worked well") + continue + } + // Check if the directory has a database present and the command is 'flask db init' + if e.directoryHasDatabase(workDir) && strings.Contains(command, "flask db init") { + fmt.Println("Database already initialized, assuming it worked well") + continue + } + errorMessage := fmt.Sprintf("Error executing command '%s': %s\n", command, string(stdout)) + fmt.Print(errorMessage) + fmt.Println("GOT ERROR : ", err.Error()) + return "Dependency_Error", errorMessage + + } else { + if strings.Contains(string(stdout), "FAILED") || strings.Contains(string(stdout), "ERROR") { + errorMessage := fmt.Sprintf("Command '%s' failed with output: %s\n", command, string(stdout)) + fmt.Print(errorMessage) + return "Dependency_Error", errorMessage + + } else { + fmt.Println("Executed command successfully") + } + } + } + + // Install dependencies using poetry + err = PoetryInstall(workDir, err) + if err != nil { + errorMessage := fmt.Sprintf("Error creating virtual environment: %s\n", err.Error()) + fmt.Print(errorMessage) + return "Dependency_Error", errorMessage + } + + fmt.Println("All commands executed successfully") + return "Passed", "" +} + +func (e *DjangoServerStartTestExecutor) listInstalledPackages(venvBin string) { + fmt.Println("Listing installed packages...") + cmd := exec.Command(filepath.Join(venvBin, "pip"), "list") + output, err := cmd.CombinedOutput() + if err != nil { + fmt.Printf("Error listing installed packages: %s\n", err.Error()) + return + } + fmt.Printf("Installed packages:\n%s\n", string(output)) +} + +func (e *DjangoServerStartTestExecutor) getFlaskTerminalFileName() string { + return "terminal.txt" +} + +func (e *DjangoServerStartTestExecutor) ReadCommandsFromFile(workingDir string) ([]string, error) { + terminalFilePath := workingDir + "/" + e.getFlaskTerminalFileName() + absTerminalFilePath, err := filepath.Abs(terminalFilePath) + if err != nil { + return nil, fmt.Errorf("error getting absolute path: %w", err) + } + + file, err := os.Open(absTerminalFilePath) + if err != nil { + return nil, fmt.Errorf("error opening terminal.txt: %w", err) + } + defer file.Close() + + var commands []string + scanner := bufio.NewScanner(file) + for scanner.Scan() { + command := scanner.Text() + if strings.TrimSpace(command) != "" && + !strings.HasPrefix(command, "python") && + !strings.HasPrefix(command, "source") && + !strings.HasPrefix(command, "flask run --host=") { + commands = append(commands, command) + } + } + + if err := scanner.Err(); err != nil { + return nil, fmt.Errorf("error reading terminal.txt: %w", err) + } + + return commands, nil +} + +func (e *DjangoServerStartTestExecutor) directoryHasDatabase(workDir string) bool { + dbFilePath := workDir + "/instance" + "/" + "app.db" + if _, err := os.Stat(dbFilePath); err == nil { + return true + } + return false +} diff --git a/app/workflow_executors/step_executors/impl/flask_sever_test_executor.go b/app/workflow_executors/step_executors/impl/flask_sever_test_executor.go index b8c29b0a..df74b8fe 100644 --- a/app/workflow_executors/step_executors/impl/flask_sever_test_executor.go +++ b/app/workflow_executors/step_executors/impl/flask_sever_test_executor.go @@ -36,7 +36,7 @@ func NewFlaskServerStartTestExecutor( } func (e FlaskServerStartTestExecutor) Execute(step steps.ServerStartTestStep) error { - fmt.Printf("Executing Server Start Test Step: %s\n", step.StepName()) + fmt.Printf("Executing Flask Server Start Test Step: %s\n", step.StepName()) err := e.activityLogService.CreateActivityLog( step.ExecutionStep.ExecutionID, diff --git a/app/workflow_executors/step_executors/impl/open_ai_flask_code_generation_executor.go b/app/workflow_executors/step_executors/impl/open_ai_code_generation_executor.go similarity index 70% rename from app/workflow_executors/step_executors/impl/open_ai_flask_code_generation_executor.go rename to app/workflow_executors/step_executors/impl/open_ai_code_generation_executor.go index 27c469f3..a859b5f9 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_flask_code_generation_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_code_generation_executor.go @@ -16,7 +16,7 @@ import ( "strings" ) -type OpenAIFlaskCodeGenerator struct { +type OpenAICodeGenerator struct { openAIClient *llms.OpenAiClient projectService *services.ProjectService executionStepService *services.ExecutionStepService @@ -28,7 +28,7 @@ type OpenAIFlaskCodeGenerator struct { slackAlert *monitoring.SlackAlert } -func NewOpenAIFlaskCodeGenerator( +func NewOpenAICodeGenerator( openAIClient *llms.OpenAiClient, projectService *services.ProjectService, executionStepService *services.ExecutionStepService, @@ -38,8 +38,8 @@ func NewOpenAIFlaskCodeGenerator( activityLogService *services.ActivityLogService, llmAPIKeyService *services.LLMAPIKeyService, slackAlert *monitoring.SlackAlert, -) *OpenAIFlaskCodeGenerator { - return &OpenAIFlaskCodeGenerator{ +) *OpenAICodeGenerator { + return &OpenAICodeGenerator{ openAIClient: openAIClient, projectService: projectService, executionStepService: executionStepService, @@ -50,15 +50,16 @@ func NewOpenAIFlaskCodeGenerator( llmAPIKeyService: llmAPIKeyService, slackAlert: slackAlert, } + } -func (openAIFlaskCodeGenerator OpenAIFlaskCodeGenerator) Execute(step steps.GenerateCodeStep) error { +func (openAICodeGenerator OpenAICodeGenerator) Execute(step steps.GenerateCodeStep) error { fmt.Printf("Executing GenerateCodeStep: %s\n", step.StepName()) fmt.Printf("Working on project details: %v\n", step.Project) fmt.Printf("Working on pull request ID: %d\n", step.PullRequestID) fmt.Printf("Max loop iterations: %d\n", step.MaxLoopIterations) fmt.Printf("Is re-execution: %v\n", step.Execution.ReExecution) - err := openAIFlaskCodeGenerator.activityLogService.CreateActivityLog( + err := openAICodeGenerator.activityLogService.CreateActivityLog( step.Execution.ID, step.ExecutionStep.ID, "INFO", @@ -71,7 +72,7 @@ func (openAIFlaskCodeGenerator OpenAIFlaskCodeGenerator) Execute(step steps.Gene projectDir := config.WorkspaceWorkingDirectory() + "/" + step.Project.HashID fmt.Println("____________Project Directory: ", projectDir) fmt.Println("___________Checking for Max Retry______________") - count, err := openAIFlaskCodeGenerator.executionStepService.CountExecutionStepsOfName(step.Execution.ID, steps.CODE_GENERATE_STEP.String()) + count, err := openAICodeGenerator.executionStepService.CountExecutionStepsOfName(step.Execution.ID, steps.CODE_GENERATE_STEP.String()) if err != nil { fmt.Printf("Error checking max retry for generation: %s\n", err.Error()) return err @@ -80,12 +81,12 @@ func (openAIFlaskCodeGenerator OpenAIFlaskCodeGenerator) Execute(step steps.Gene if count > step.MaxLoopIterations { fmt.Println("Max retry limit reached for LLM steps") //Update story status to MAX_LOOP_ITERATION_REACHED - if err := openAIFlaskCodeGenerator.storyService.UpdateStoryStatus(int(step.Story.ID), "MAX_LOOP_ITERATION_REACHED"); err != nil { + if err := openAICodeGenerator.storyService.UpdateStoryStatus(int(step.Story.ID), "MAX_LOOP_ITERATION_REACHED"); err != nil { fmt.Printf("Error updating story status: %s\n", err.Error()) return err } //Update execution status to MAX_LOOP_ITERATION_REACHED - if err := openAIFlaskCodeGenerator.executionService.UpdateExecutionStatus(step.Execution.ID, "MAX_LOOP_ITERATION_REACHED"); err != nil { + if err := openAICodeGenerator.executionService.UpdateExecutionStatus(step.Execution.ID, "MAX_LOOP_ITERATION_REACHED"); err != nil { fmt.Printf("Error updating execution step: %s\n", err.Error()) return err } @@ -109,7 +110,7 @@ func (openAIFlaskCodeGenerator OpenAIFlaskCodeGenerator) Execute(step steps.Gene return err } - err = openAIFlaskCodeGenerator.activityLogService.CreateActivityLog( + err = openAICodeGenerator.activityLogService.CreateActivityLog( step.Execution.ID, step.ExecutionStep.ID, "ERROR", @@ -120,7 +121,7 @@ func (openAIFlaskCodeGenerator OpenAIFlaskCodeGenerator) Execute(step steps.Gene return err } - err = openAIFlaskCodeGenerator.slackAlert.SendAlert( + err = openAICodeGenerator.slackAlert.SendAlert( "Max retry limit reached for code generation!", map[string]string{ "story_id": fmt.Sprintf("%d", int64(step.Story.ID)), @@ -137,7 +138,7 @@ func (openAIFlaskCodeGenerator OpenAIFlaskCodeGenerator) Execute(step steps.Gene return fmt.Errorf("max retry limit reached for LLM steps") } - finalInstructionForGeneration, err := openAIFlaskCodeGenerator.buildFinalInstructionForGeneration(step) + finalInstructionForGeneration, err := openAICodeGenerator.buildFinalInstructionForGeneration(step) if err != nil { fmt.Printf("Error building final instruction for generation: %s\n", err.Error()) return err @@ -145,28 +146,24 @@ func (openAIFlaskCodeGenerator OpenAIFlaskCodeGenerator) Execute(step steps.Gene fmt.Printf("_________Final Instruction for Generation__________: %s\n", finalInstructionForGeneration) //extracting api_key from executionId - story, err := openAIFlaskCodeGenerator.storyService.GetStoryByExecutionID(step.Execution.ID) + story, err := openAICodeGenerator.storyService.GetStoryByExecutionID(step.Execution.ID) if err != nil { fmt.Println("Error getting story by execution ID: ", err) } projectId := story.ProjectID - project, err := openAIFlaskCodeGenerator.projectService.GetProjectById(projectId) + project, err := openAICodeGenerator.projectService.GetProjectById(projectId) if err != nil { fmt.Println("Error getting project by ID: ", err) } organisationId := project.OrganisationID - fmt.Println("_________ORGANISATION ID_________", organisationId) - if openAIFlaskCodeGenerator.llmAPIKeyService == nil { - fmt.Println("_____NULL_____") - } - llmAPIKey, err := openAIFlaskCodeGenerator.llmAPIKeyService.GetLLMAPIKeyByModelName(constants.GPT_4O, uint(organisationId)) + llmAPIKey, err := openAICodeGenerator.llmAPIKeyService.GetLLMAPIKeyByModelName(constants.GPT_4O, uint(organisationId)) if err != nil { fmt.Println("Error getting openai api key: ", err) } if llmAPIKey == nil || llmAPIKey.LLMAPIKey == "" { fmt.Println("______API Key not found in database_____") settingsUrl := config.Get("app.url").(string) + "/settings" - err := openAIFlaskCodeGenerator.activityLogService.CreateActivityLog( + err := openAICodeGenerator.activityLogService.CreateActivityLog( step.Execution.ID, step.ExecutionStep.ID, "INFO", @@ -177,12 +174,12 @@ func (openAIFlaskCodeGenerator OpenAIFlaskCodeGenerator) Execute(step steps.Gene return err } //Update Execution Status and Story Status - if err := openAIFlaskCodeGenerator.storyService.UpdateStoryStatus(int(step.Story.ID), constants.InReviewLLMKeyNotFound); err != nil { + if err := openAICodeGenerator.storyService.UpdateStoryStatus(int(step.Story.ID), constants.InReviewLLMKeyNotFound); err != nil { fmt.Printf("Error updating story status: %s\n", err.Error()) return err } //Update execution status to MAX_LOOP_ITERATION_REACHED - if err := openAIFlaskCodeGenerator.executionService.UpdateExecutionStatus(step.Execution.ID, constants.InReviewLLMKeyNotFound); err != nil { + if err := openAICodeGenerator.executionService.UpdateExecutionStatus(step.Execution.ID, constants.InReviewLLMKeyNotFound); err != nil { fmt.Printf("Error updating execution step: %s\n", err.Error()) return err } @@ -207,10 +204,12 @@ func (openAIFlaskCodeGenerator OpenAIFlaskCodeGenerator) Execute(step steps.Gene return errors.New("LLM API Key not found in database") } apiKey := llmAPIKey.LLMAPIKey - fmt.Println("_________API KEY_________", apiKey) - + fmt.Println("_________API_KEY_________", apiKey) + + framework := project.Framework + fmt.Println("_________FRAMEWORK_________", framework) // Generate code using the final instruction - code, err := openAIFlaskCodeGenerator.GenerateCode(apiKey, finalInstructionForGeneration, step.ExecutionStep, projectDir, step) + code, err := openAICodeGenerator.GenerateCode(apiKey, framework, finalInstructionForGeneration, step.ExecutionStep, projectDir, step) if err != nil { fmt.Printf("Error generating code: %s\n", err.Error()) return err @@ -218,7 +217,7 @@ func (openAIFlaskCodeGenerator OpenAIFlaskCodeGenerator) Execute(step steps.Gene fmt.Printf("_________Generated Code__________: %s\n", code) // Update execution step with response - if err := openAIFlaskCodeGenerator.executionStepService.UpdateExecutionStepResponse( + if err := openAICodeGenerator.executionStepService.UpdateExecutionStepResponse( step.ExecutionStep, map[string]interface{}{ "llm_response": code, @@ -228,7 +227,7 @@ func (openAIFlaskCodeGenerator OpenAIFlaskCodeGenerator) Execute(step steps.Gene return err } - err = openAIFlaskCodeGenerator.activityLogService.CreateActivityLog( + err = openAICodeGenerator.activityLogService.CreateActivityLog( step.Execution.ID, step.ExecutionStep.ID, "INFO", @@ -243,9 +242,9 @@ func (openAIFlaskCodeGenerator OpenAIFlaskCodeGenerator) Execute(step steps.Gene } // GenerateCode uses OpenAI API to generate code based on the instruction. -func (openAIFlaskCodeGenerator *OpenAIFlaskCodeGenerator) GenerateCode(api_key string, instruction string, executionStep *models.ExecutionStep, projectDir string, step steps.GenerateCodeStep) (string, error) { - messages := openAIFlaskCodeGenerator.generateMessages(instruction, executionStep.ExecutionID, projectDir) - err := openAIFlaskCodeGenerator.executionStepService.UpdateExecutionStepRequest( +func (openAICodeGenerator *OpenAICodeGenerator) GenerateCode(apiKey string, framework string, instruction string, executionStep *models.ExecutionStep, projectDir string, step steps.GenerateCodeStep) (string, error) { + messages := openAICodeGenerator.generateMessages(framework, instruction, executionStep.ExecutionID, projectDir) + err := openAICodeGenerator.executionStepService.UpdateExecutionStepRequest( executionStep, map[string]interface{}{ "final_instruction": instruction, @@ -253,11 +252,11 @@ func (openAIFlaskCodeGenerator *OpenAIFlaskCodeGenerator) GenerateCode(api_key s }, "IN_PROGRESS", ) - openAIFlaskCodeGenerator.openAIClient.WithApiKey(api_key) - response, err := openAIFlaskCodeGenerator.openAIClient.ChatCompletion(messages) + openAICodeGenerator.openAIClient.WithApiKey(apiKey) + response, err := openAICodeGenerator.openAIClient.ChatCompletion(messages) if err != nil { settingsUrl := config.Get("app.url").(string) + "/settings" - err := openAIFlaskCodeGenerator.activityLogService.CreateActivityLog( + err := openAICodeGenerator.activityLogService.CreateActivityLog( step.Execution.ID, step.ExecutionStep.ID, "INFO", @@ -268,12 +267,12 @@ func (openAIFlaskCodeGenerator *OpenAIFlaskCodeGenerator) GenerateCode(api_key s return "", err } //Update Execution Status and Story Status - if err := openAIFlaskCodeGenerator.storyService.UpdateStoryStatus(int(step.Story.ID), constants.InReviewLLMKeyNotFound); err != nil { + if err := openAICodeGenerator.storyService.UpdateStoryStatus(int(step.Story.ID), constants.InReviewLLMKeyNotFound); err != nil { fmt.Printf("Error updating story status: %s\n", err.Error()) return "", err } //Update execution status to MAX_LOOP_ITERATION_REACHED - if err := openAIFlaskCodeGenerator.executionService.UpdateExecutionStatus(step.Execution.ID, constants.InReviewLLMKeyNotFound); err != nil { + if err := openAICodeGenerator.executionService.UpdateExecutionStatus(step.Execution.ID, constants.InReviewLLMKeyNotFound); err != nil { fmt.Printf("Error updating execution step: %s\n", err.Error()) return "", err } @@ -300,19 +299,19 @@ func (openAIFlaskCodeGenerator *OpenAIFlaskCodeGenerator) GenerateCode(api_key s return response, nil } -func (openAIFlaskCodeGenerator *OpenAIFlaskCodeGenerator) generateMessages(instruction string, executionId uint, projectDir string) []llms.ChatCompletionMessage { - inputContext, err := openAIFlaskCodeGenerator.createInputContext(projectDir) +func (openAICodeGenerator *OpenAICodeGenerator) generateMessages(framework string, instruction string, executionId uint, projectDir string) []llms.ChatCompletionMessage { + inputContext, err := openAICodeGenerator.createInputContext(projectDir) if err != nil { fmt.Printf("Failed to create input context: %v\n", err) } messages := []llms.ChatCompletionMessage{ - {Role: "system", Content: openAIFlaskCodeGenerator.getSystemPrompt(projectDir)}, + {Role: "system", Content: openAICodeGenerator.getSystemPrompt(framework, projectDir)}, {Role: "user", Content: "The current codebase is:\n" + inputContext}, {Role: "user", Content: instruction}, } // Fetch the last execution step - previousExecutionSteps, err := openAIFlaskCodeGenerator.executionStepService.FetchExecutionSteps( + previousExecutionSteps, err := openAICodeGenerator.executionStepService.FetchExecutionSteps( executionId, steps.CODE_GENERATE_STEP.String(), steps.LLM.String(), @@ -335,13 +334,13 @@ func (openAIFlaskCodeGenerator *OpenAIFlaskCodeGenerator) generateMessages(instr return messages } -func (openAIFlaskCodeGenerator *OpenAIFlaskCodeGenerator) createInputContext(projectDir string) (string, error) { +func (openAICodeGenerator *OpenAICodeGenerator) createInputContext(projectDir string) (string, error) { outputFile := projectDir + "/input_context.txt" allowedExtensions := []string{".py", ".html", ".css", ".txt", ".ini", ".jpg", ".png"} - if err := openAIFlaskCodeGenerator.ensureDirectoryExists(projectDir); err != nil { + if err := openAICodeGenerator.ensureDirectoryExists(projectDir); err != nil { return "", err } - err := openAIFlaskCodeGenerator.generateFileListForInputContext(projectDir, outputFile, allowedExtensions) + err := openAICodeGenerator.generateFileListForInputContext(projectDir, outputFile, allowedExtensions) if err != nil { return "", err } @@ -357,7 +356,7 @@ func (openAIFlaskCodeGenerator *OpenAIFlaskCodeGenerator) createInputContext(pro return string(content), nil } -func (openAIFlaskCodeGenerator *OpenAIFlaskCodeGenerator) generateFileListForInputContext(directory, outputFile string, allowedExtensions []string) error { +func (openAICodeGenerator *OpenAICodeGenerator) generateFileListForInputContext(directory, outputFile string, allowedExtensions []string) error { outFile, err := os.Create(outputFile) if err != nil { return err @@ -374,8 +373,8 @@ func (openAIFlaskCodeGenerator *OpenAIFlaskCodeGenerator) generateFileListForInp return filepath.SkipDir } - if !info.IsDir() && openAIFlaskCodeGenerator.fileExtensionAllowed(path, allowedExtensions) { - if err := openAIFlaskCodeGenerator.writeFileContent(path, directory, outFile); err != nil { + if !info.IsDir() && openAICodeGenerator.fileExtensionAllowed(path, allowedExtensions) { + if err := openAICodeGenerator.writeFileContent(path, directory, outFile); err != nil { return err } } @@ -384,7 +383,7 @@ func (openAIFlaskCodeGenerator *OpenAIFlaskCodeGenerator) generateFileListForInp }) } -func (openAIFlaskCodeGenerator *OpenAIFlaskCodeGenerator) fileExtensionAllowed(file string, allowedExtensions []string) bool { +func (openAICodeGenerator *OpenAICodeGenerator) fileExtensionAllowed(file string, allowedExtensions []string) bool { for _, ext := range allowedExtensions { if strings.HasSuffix(file, ext) { return true @@ -393,7 +392,7 @@ func (openAIFlaskCodeGenerator *OpenAIFlaskCodeGenerator) fileExtensionAllowed(f return false } -func (openAIFlaskCodeGenerator *OpenAIFlaskCodeGenerator) writeFileContent(filePath string, basePath string, outFile *os.File) error { +func (openAICodeGenerator *OpenAICodeGenerator) writeFileContent(filePath string, basePath string, outFile *os.File) error { absolutePath, err := filepath.Abs(filePath) if err != nil { return err @@ -414,16 +413,28 @@ func (openAIFlaskCodeGenerator *OpenAIFlaskCodeGenerator) writeFileContent(fileP return err } -func (openAIFlaskCodeGenerator *OpenAIFlaskCodeGenerator) getSystemPrompt(projectDir string) string { - content, err := os.ReadFile("/go/prompts/ai_developer.txt") - modifiedContent := strings.Replace(string(content), "{project_workspace_id}", projectDir, -1) +func (openAICodeGenerator *OpenAICodeGenerator) getSystemPrompt(framework string, projectDir string) string { + var filePath string + switch framework { + case "flask": + filePath = "/go/prompts/python/ai_developer_flask.txt" + case "django": + filePath = "/go/prompts/python/ai_developer_django.txt" + default: + filePath = "" + } + + fmt.Println("______FILEPATH: _______" + filePath) + content, err := os.ReadFile(filePath) if err != nil { - panic(fmt.Sprintf("failed to read system prompt: %v", err)) + panic(fmt.Sprintf("failed to read system prompt from %s: %v", filePath, err)) } + + modifiedContent := strings.Replace(string(content), "{project_workspace_id}", projectDir, -1) return modifiedContent } -func (openAIFlaskCodeGenerator *OpenAIFlaskCodeGenerator) ensureDirectoryExists(dirPath string) error { +func (openAICodeGenerator *OpenAICodeGenerator) ensureDirectoryExists(dirPath string) error { _, err := os.Stat(dirPath) if os.IsNotExist(err) { fmt.Printf("Directory does not exist: %s\n", dirPath) @@ -432,18 +443,18 @@ func (openAIFlaskCodeGenerator *OpenAIFlaskCodeGenerator) ensureDirectoryExists( return err } -func (openAIFlaskCodeGenerator *OpenAIFlaskCodeGenerator) buildFinalInstructionForGeneration( +func (openAICodeGenerator *OpenAICodeGenerator) buildFinalInstructionForGeneration( step steps.GenerateCodeStep) (string, error) { // Initialize the final instruction string - finalInstruction, err := openAIFlaskCodeGenerator.buildInstructionForFirstExecution(step) + finalInstruction, err := openAICodeGenerator.buildInstructionForFirstExecution(step) if step.Retry { - finalInstruction, err = openAIFlaskCodeGenerator.buildInstructionOnRetry(step) + finalInstruction, err = openAICodeGenerator.buildInstructionOnRetry(step) if err != nil { fmt.Printf("Error building instruction on retry: %s\n", err.Error()) return "", err } } else if step.Execution.ReExecution { - finalInstruction, err = openAIFlaskCodeGenerator.buildInstructionOnReExecutionWithComments(step) + finalInstruction, err = openAICodeGenerator.buildInstructionOnReExecutionWithComments(step) if err != nil { fmt.Printf("Error building instruction on re-execution: %s\n", err.Error()) return "", err @@ -456,10 +467,10 @@ func (openAIFlaskCodeGenerator *OpenAIFlaskCodeGenerator) buildFinalInstructionF return finalInstruction, nil } -func (openAIFlaskCodeGenerator *OpenAIFlaskCodeGenerator) buildInstructionOnReExecutionWithComments(step steps.GenerateCodeStep) (string, error) { +func (openAICodeGenerator *OpenAICodeGenerator) buildInstructionOnReExecutionWithComments(step steps.GenerateCodeStep) (string, error) { fmt.Printf("Building instruction on re-execution with comments for step: %s\n", step.StepName()) fmt.Printf("Pull Request ID is %d\n", step.PullRequestID) - comments, err := openAIFlaskCodeGenerator.pullRequestCommentService.GetAllCommentsByPullRequestID(step.PullRequestID) + comments, err := openAICodeGenerator.pullRequestCommentService.GetAllCommentsByPullRequestID(step.PullRequestID) if err != nil { fmt.Printf("Error fetching comments: %s\n", err.Error()) return "", err @@ -471,13 +482,13 @@ func (openAIFlaskCodeGenerator *OpenAIFlaskCodeGenerator) buildInstructionOnReEx return finalInstruction, nil } -func (openAIFlaskCodeGenerator *OpenAIFlaskCodeGenerator) buildInstructionForFirstExecution(step steps.GenerateCodeStep) (string, error) { - instructions, err := openAIFlaskCodeGenerator.storyService.GetStoryInstructionByStoryId(int(step.Story.ID)) +func (openAICodeGenerator *OpenAICodeGenerator) buildInstructionForFirstExecution(step steps.GenerateCodeStep) (string, error) { + instructions, err := openAICodeGenerator.storyService.GetStoryInstructionByStoryId(int(step.Story.ID)) if err != nil { fmt.Printf("Error fetching instructions: %s\n", err.Error()) return "", err } - testCases, err := openAIFlaskCodeGenerator.storyService.GetStoryTestCaseByStoryId(int(step.Story.ID)) + testCases, err := openAICodeGenerator.storyService.GetStoryTestCaseByStoryId(int(step.Story.ID)) if err != nil { fmt.Printf("Error fetching test cases: %s\n", err.Error()) return "", err @@ -500,9 +511,9 @@ func (openAIFlaskCodeGenerator *OpenAIFlaskCodeGenerator) buildInstructionForFir return sb.String(), nil } -func (openAIFlaskCodeGenerator *OpenAIFlaskCodeGenerator) buildInstructionOnRetry(step steps.GenerateCodeStep) (string, error) { +func (openAICodeGenerator *OpenAICodeGenerator) buildInstructionOnRetry(step steps.GenerateCodeStep) (string, error) { fmt.Printf("Building instruction on retry for step: %s\n", step.StepName()) - previousServerTestExecutionStep, err := openAIFlaskCodeGenerator.executionStepService.FetchExecutionSteps( + previousServerTestExecutionStep, err := openAICodeGenerator.executionStepService.FetchExecutionSteps( step.Execution.ID, steps.SERVER_START_STEP.String(), steps.CODE_TEST.String(), @@ -517,4 +528,4 @@ func (openAIFlaskCodeGenerator *OpenAIFlaskCodeGenerator) buildInstructionOnRetr finalInstruction = previousServerTestExecutionStep[0].Response["error"].(string) } return finalInstruction, nil -} +} \ No newline at end of file diff --git a/app/workflow_executors/step_executors/impl/open_ai_flask_update_code_file_executor.go b/app/workflow_executors/step_executors/impl/open_ai_update_code_file_executor.go similarity index 100% rename from app/workflow_executors/step_executors/impl/open_ai_flask_update_code_file_executor.go rename to app/workflow_executors/step_executors/impl/open_ai_update_code_file_executor.go diff --git a/app/workflow_executors/step_executors/steps/code_generate_step.go b/app/workflow_executors/step_executors/steps/code_generate_step.go index 831dc5cd..96015ddf 100644 --- a/app/workflow_executors/step_executors/steps/code_generate_step.go +++ b/app/workflow_executors/step_executors/steps/code_generate_step.go @@ -6,6 +6,7 @@ type GenerateCodeStep struct { Retry bool MaxLoopIterations int64 PullRequestID uint + PromptFilePath string } func (s GenerateCodeStep) StepType() string { diff --git a/executor.go b/executor.go index f549dbf9..f58b8579 100644 --- a/executor.go +++ b/executor.go @@ -15,14 +15,15 @@ import ( "ai-developer/app/workflow_executors/step_executors/impl" "ai-developer/app/workflow_executors/step_executors/steps" "context" + "fmt" + "log" + "net/http" + "os" "github.com/hibiken/asynq" "github.com/knadh/koanf/v2" "go.uber.org/dig" "go.uber.org/zap" "gorm.io/gorm" - "log" - "net/http" - "os" ) func main() { @@ -190,7 +191,7 @@ func main() { _ = c.Provide(services.NewLLMAPIKeyService) //GenerateCodeStep - err = c.Provide(impl.NewOpenAIFlaskCodeGenerator) + err = c.Provide(impl.NewOpenAICodeGenerator) if err != nil { log.Println("Error providing generate code step:", err) panic(err) @@ -208,12 +209,19 @@ func main() { panic(err) } - //serverStartTestStep + //FLASK serverStartTestStep err = c.Provide(impl.NewFlaskServerStartTestExecutor) if err != nil { log.Println("Error providing server start test step:", err) panic(err) + } + //DJANGO serverStartTestStep + err = c.Provide(impl.NewDjangoServerStartTestExecutor) + if err != nil { + log.Println("Error providing server start test step:", err) + panic(err) + } //GitCommitStep err = c.Provide(impl.NewGitCommitExecutor) @@ -255,9 +263,10 @@ func main() { log.Fatalf("Error providing OpenAiClient: %v", err) } - if template, exists := os.LookupEnv("EXECUTION_TEMPLATE"); template == "FLASK" || !exists { + template, exists := os.LookupEnv("EXECUTION_TEMPLATE") + if template == "FLASK" || !exists { _ = c.Provide(func( - openAIFlaskCodeGenerator *impl.OpenAIFlaskCodeGenerator, + openAICodeGenerator *impl.OpenAICodeGenerator, gitMakeBranchExecutor *impl.GitMakeBranchExecutor, updateCodeFileExecutor *impl.UpdateCodeFileExecutor, flaskServerStartTestExecutor *impl.FlaskServerStartTestExecutor, @@ -267,17 +276,38 @@ func main() { resetFlaskDBStepExecutor *impl.ResetFlaskDBStepExecutor, ) map[steps.StepName]step_executors.StepExecutor { return map[steps.StepName]step_executors.StepExecutor{ - steps.CODE_GENERATE_STEP: *openAIFlaskCodeGenerator, + steps.CODE_GENERATE_STEP: *openAICodeGenerator, steps.UPDATE_CODE_FILE_STEP: *updateCodeFileExecutor, steps.GIT_COMMIT_STEP: *gitCommitExecutor, steps.GIT_CREATE_BRANCH_STEP: *gitMakeBranchExecutor, steps.GIT_PUSH_STEP: *gitPushExecutor, steps.GIT_CREATE_PULL_REQUEST_STEP: *gitnessMakePullRequestExecutor, steps.SERVER_START_STEP: *flaskServerStartTestExecutor, - steps.RETRY_CODE_GENERATE_STEP: *openAIFlaskCodeGenerator, + steps.RETRY_CODE_GENERATE_STEP: *openAICodeGenerator, steps.RESET_DB_STEP: *resetFlaskDBStepExecutor, } }) + } else if template == "DJANGO" { + _ = c.Provide(func( + openAICodeGenerator *impl.OpenAICodeGenerator, + gitMakeBranchExecutor *impl.GitMakeBranchExecutor, + updateCodeFileExecutor *impl.UpdateCodeFileExecutor, + djangoServerStartTestExecutor *impl.DjangoServerStartTestExecutor, + gitCommitExecutor *impl.GitCommitExecutor, + gitPushExecutor *impl.GitPushExecutor, + gitnessMakePullRequestExecutor *impl.GitnessMakePullRequestExecutor, + ) map[steps.StepName]step_executors.StepExecutor { + return map[steps.StepName]step_executors.StepExecutor{ + steps.CODE_GENERATE_STEP: *openAICodeGenerator, + steps.UPDATE_CODE_FILE_STEP: *updateCodeFileExecutor, + steps.GIT_COMMIT_STEP: *gitCommitExecutor, + steps.GIT_CREATE_BRANCH_STEP: *gitMakeBranchExecutor, + steps.GIT_PUSH_STEP: *gitPushExecutor, + steps.GIT_CREATE_PULL_REQUEST_STEP: *gitnessMakePullRequestExecutor, + steps.SERVER_START_STEP: *djangoServerStartTestExecutor, + steps.RETRY_CODE_GENERATE_STEP: *openAICodeGenerator, + } + }) } _ = c.Provide(workflow_executors.NewWorkflowExecutor) @@ -291,18 +321,34 @@ func main() { if _, err := config.LoadConfig(); err != nil { return err } - log.Println("Going to execute AI Developer Workflow Execution For Flask") - err = executor.Execute( - workflow_executors.FlaskWorkflowConfig, - &workflow_executors.WorkflowExecutionArgs{ - StoryId: adec.GetStoryID(), - IsReExecution: adec.IsReExecution(), - Branch: adec.GetBranch(), - PullRequestId: adec.GetPullRequestID(), - ExecutionId: adec.GetExecutionID(), - }, - ) - return err + log.Println(fmt.Sprintf("Going to execute AI Developer Workflow Execution For %s", template)) + if template=="FLASK"{ + err = executor.Execute( + workflow_executors.FlaskWorkflowConfig, + &workflow_executors.WorkflowExecutionArgs{ + StoryId: adec.GetStoryID(), + IsReExecution: adec.IsReExecution(), + Branch: adec.GetBranch(), + PullRequestId: adec.GetPullRequestID(), + ExecutionId: adec.GetExecutionID(), + }, + ) + return err + } else if template=="DJANGO" { + err = executor.Execute( + workflow_executors.DjangoWorkflowConfig, + &workflow_executors.WorkflowExecutionArgs{ + StoryId: adec.GetStoryID(), + IsReExecution: adec.IsReExecution(), + Branch: adec.GetBranch(), + PullRequestId: adec.GetPullRequestID(), + ExecutionId: adec.GetExecutionID(), + }, + ) + return err + } + fmt.Println("_____Invalid template_____", template) + return nil }) if err != nil { diff --git a/workspace-service/app/controllers/workspace_controller.go b/workspace-service/app/controllers/workspace_controller.go index 2d803f17..37c4746b 100644 --- a/workspace-service/app/controllers/workspace_controller.go +++ b/workspace-service/app/controllers/workspace_controller.go @@ -13,10 +13,7 @@ type WorkspaceController struct { } func (wc *WorkspaceController) CreateWorkspace(c *gin.Context) { - python := "python" - body := dto.CreateWorkspace{ - BackendTemplate: &python, - } + body := dto.CreateWorkspace{} if err := c.BindJSON(&body); err != nil { wc.logger.Error("Failed to bind json", zap.Error(err)) c.AbortWithStatusJSON(400, gin.H{ From 033cfc94b6af34e9d3c6e8fed1c8a0341b07aa8f Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Wed, 10 Jul 2024 19:12:26 +0530 Subject: [PATCH 03/39] merge conflicts resolved --- executor.go | 52 +--------------------------------------------------- 1 file changed, 1 insertion(+), 51 deletions(-) diff --git a/executor.go b/executor.go index b5969259..3a058e62 100644 --- a/executor.go +++ b/executor.go @@ -15,11 +15,6 @@ import ( "ai-developer/app/workflow_executors/step_executors/impl" "ai-developer/app/workflow_executors/step_executors/steps" "context" - "fmt" - "log" - "net/http" - "os" - "fmt" "log" "net/http" @@ -282,12 +277,9 @@ func main() { log.Fatalf("Error providing OpenAiClient: %v", err) } - template, exists := os.LookupEnv("EXECUTION_TEMPLATE") - if template == "FLASK" || !exists { template, exists := os.LookupEnv("EXECUTION_TEMPLATE") if template == "FLASK" || !exists { _ = c.Provide(func( - openAICodeGenerator *impl.OpenAICodeGenerator, openAICodeGenerator *impl.OpenAICodeGenerator, gitMakeBranchExecutor *impl.GitMakeBranchExecutor, updateCodeFileExecutor *impl.UpdateCodeFileExecutor, @@ -334,49 +326,7 @@ func main() { steps.RETRY_CODE_GENERATE_STEP: *openAICodeGenerator, } }) - } else if template == "DJANGO" { - _ = c.Provide(func( - openAICodeGenerator *impl.OpenAICodeGenerator, - gitMakeBranchExecutor *impl.GitMakeBranchExecutor, - updateCodeFileExecutor *impl.UpdateCodeFileExecutor, - djangoServerStartTestExecutor *impl.DjangoServerStartTestExecutor, - gitCommitExecutor *impl.GitCommitExecutor, - gitPushExecutor *impl.GitPushExecutor, - gitnessMakePullRequestExecutor *impl.GitnessMakePullRequestExecutor, - ) map[steps.StepName]step_executors.StepExecutor { - return map[steps.StepName]step_executors.StepExecutor{ - steps.CODE_GENERATE_STEP: *openAICodeGenerator, - steps.UPDATE_CODE_FILE_STEP: *updateCodeFileExecutor, - steps.GIT_COMMIT_STEP: *gitCommitExecutor, - steps.GIT_CREATE_BRANCH_STEP: *gitMakeBranchExecutor, - steps.GIT_PUSH_STEP: *gitPushExecutor, - steps.GIT_CREATE_PULL_REQUEST_STEP: *gitnessMakePullRequestExecutor, - steps.SERVER_START_STEP: *djangoServerStartTestExecutor, - steps.RETRY_CODE_GENERATE_STEP: *openAICodeGenerator, - } - }) - } else if template == "DJANGO" { - _ = c.Provide(func( - openAICodeGenerator *impl.OpenAICodeGenerator, - gitMakeBranchExecutor *impl.GitMakeBranchExecutor, - updateCodeFileExecutor *impl.UpdateCodeFileExecutor, - djangoServerStartTestExecutor *impl.DjangoServerStartTestExecutor, - gitCommitExecutor *impl.GitCommitExecutor, - gitPushExecutor *impl.GitPushExecutor, - gitnessMakePullRequestExecutor *impl.GitnessMakePullRequestExecutor, - ) map[steps.StepName]step_executors.StepExecutor { - return map[steps.StepName]step_executors.StepExecutor{ - steps.CODE_GENERATE_STEP: *openAICodeGenerator, - steps.UPDATE_CODE_FILE_STEP: *updateCodeFileExecutor, - steps.GIT_COMMIT_STEP: *gitCommitExecutor, - steps.GIT_CREATE_BRANCH_STEP: *gitMakeBranchExecutor, - steps.GIT_PUSH_STEP: *gitPushExecutor, - steps.GIT_CREATE_PULL_REQUEST_STEP: *gitnessMakePullRequestExecutor, - steps.SERVER_START_STEP: *djangoServerStartTestExecutor, - steps.RETRY_CODE_GENERATE_STEP: *openAICodeGenerator, - } - }) - } + } _ = c.Provide(workflow_executors.NewWorkflowExecutor) From 41049d132c5d02750bb69e72e0ef0bd909c80801 Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Tue, 16 Jul 2024 17:42:54 +0530 Subject: [PATCH 04/39] fixes in django prompt --- app/prompts/python/ai_developer_django.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/prompts/python/ai_developer_django.txt b/app/prompts/python/ai_developer_django.txt index ae7fdefe..60983425 100644 --- a/app/prompts/python/ai_developer_django.txt +++ b/app/prompts/python/ai_developer_django.txt @@ -32,8 +32,8 @@ THOUGHT: "" |code|: |filename|: |code|: -|filename|: terminal.txt -|terminal|: -|filename|: server_test.txt -|code|: +|filename| : +|terminal| : +|filename| : +|code| : ``` \ No newline at end of file From a9b303fa0af2513cfbcd0faf075e7136eb9c60bd Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Tue, 16 Jul 2024 17:45:12 +0530 Subject: [PATCH 05/39] resolve merge conflicts --- executor.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/executor.go b/executor.go index 45b26274..c9e49072 100644 --- a/executor.go +++ b/executor.go @@ -19,6 +19,7 @@ import ( "log" "net/http" "os" + "github.com/hibiken/asynq" "github.com/knadh/koanf/v2" "go.uber.org/dig" @@ -241,6 +242,12 @@ func main() { panic(err) } + //NEXT JS serverStartTestStep + err = c.Provide(impl.NewNextJsServerStartTestExecutor) + if err != nil { + log.Println("Error providing next js test step:", err) + panic(err) + } //GitCommitStep err = c.Provide(impl.NewGitCommitExecutor) if err != nil { @@ -291,7 +298,6 @@ func main() { poetryPackageInstallStepExecutor *impl.PackageInstallStepExecutor, ) map[steps.StepName]step_executors.StepExecutor { return map[steps.StepName]step_executors.StepExecutor{ - steps.CODE_GENERATE_STEP: *openAICodeGenerator, steps.CODE_GENERATE_STEP: *openAICodeGenerator, steps.UPDATE_CODE_FILE_STEP: *updateCodeFileExecutor, steps.GIT_COMMIT_STEP: *gitCommitExecutor, @@ -300,7 +306,6 @@ func main() { steps.GIT_CREATE_PULL_REQUEST_STEP: *gitnessMakePullRequestExecutor, steps.SERVER_START_STEP: *flaskServerStartTestExecutor, steps.RETRY_CODE_GENERATE_STEP: *openAICodeGenerator, - steps.RETRY_CODE_GENERATE_STEP: *openAICodeGenerator, steps.RESET_DB_STEP: *resetFlaskDBStepExecutor, steps.PACKAGE_INSTALL_STEP: *poetryPackageInstallStepExecutor, } From 5cabd3a623aa26a1b28b47c61906ca1ed70164ee Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Thu, 18 Jul 2024 14:52:58 +0530 Subject: [PATCH 06/39] fixes --- .../impl/open_ai_next_js_code_generation_executor.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go index 819d2dfb..e5c72c0b 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go @@ -361,8 +361,7 @@ func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) buildInstructionOnReExecut feedback = comments[len(comments)-1].Comment } fmt.Println("Feedback:", feedback) - filePath := filepath.Join(storyDir, "app", step.File) - code, err := os.ReadFile(filePath) + code, err := openAiCodeGenerator.getFilesContent(storyDir) if err != nil { return nil, fmt.Errorf("failed to read file: %v", err) } From 144ab4e70e1ad93bf9b5f403c255ade1dc297cb0 Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Thu, 18 Jul 2024 23:15:09 +0530 Subject: [PATCH 07/39] fixes --- .../open_ai_next_js_code_generation_executor.go | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go index e5c72c0b..4db7410e 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go @@ -252,8 +252,6 @@ func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) buildInstructionForFirstEx } fmt.Printf("Building instruction for first execution\n") storyFile, err := openAiCodeGenerator.storyService.GetStoryFileByStoryId(step.Story.ID) - //filePath := filepath.Join(storyDir, step.File) - //code, err := os.ReadFile(filePath) if err != nil { return nil, err } @@ -262,7 +260,9 @@ func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) buildInstructionForFirstEx return nil, err } - code, err := openAiCodeGenerator.getFilesContent(storyDir) + filePath := filepath.Join(storyDir, "app", step.File) + code, err := os.ReadFile(filePath) + // code, err := openAiCodeGenerator.getFilesContent(storyDir) if err != nil { return nil, err } @@ -534,14 +534,6 @@ func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) GetMessages(systemPrompt s Type: "text", Text: fmt.Sprintf("User Feedback: %s", instruction["feedback"]), }, - { - Type: "text", - Text: fmt.Sprintf("Existing Code:\n%s for the file: %s\n", instruction["existingCode"], instruction["fileName"]), - }, - { - Type: "text", - Text: fmt.Sprintf("Code written in files to incorporate the feedback: %s\n", instruction["feedback"]), - }, }, }, } From 43b35c10ccc317050e8b57bf172ec863529c7f01 Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Fri, 19 Jul 2024 09:58:39 +0530 Subject: [PATCH 08/39] fixes --- .../step_executors/impl/next_js_server_test_executor.go | 4 ++-- .../impl/open_ai_next_js_code_generation_executor.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go index 62e0e448..a60b9a9c 100644 --- a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go +++ b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go @@ -177,8 +177,8 @@ func (e NextJsServerStartTestExecutor) AnalyseBuildLogs(buildLogs, directoryPlan claudeClient:= llms.NewClaudeClient(apiKey) response, err := claudeClient.ChatCompletion(messages) if err != nil { - fmt.Println("failed to generate code from OpenAI API") - return false, nil, fmt.Errorf("failed to generate code from OpenAI API: %w", err) + fmt.Println("failed to generate code from llm") + return false, nil, fmt.Errorf("failed to generate code from llm: %w", err) } var jsonResponse map[string]interface{} if err = json.Unmarshal([]byte(response), &jsonResponse); err != nil { diff --git a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go index 4db7410e..7cc72f38 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go @@ -489,7 +489,7 @@ func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) EditCodeOnRetry(instructio claudeClient := llms.NewClaudeClient(apiKey) response, err := claudeClient.ChatCompletion(messages) if err != nil { - return "", fmt.Errorf("failed to generate code from OpenAI API: %w", err) + return "", fmt.Errorf("failed to generate code from llm: %w", err) } return response, nil } From 3839f2ab02ffb9123d2f52ea4aa857675fd123d7 Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Fri, 19 Jul 2024 16:58:38 +0530 Subject: [PATCH 09/39] fixes --- .../impl/next_js_server_test_executor.go | 6 ++-- ...pen_ai_next_js_code_generation_executor.go | 28 +++++++++++++------ ...en_ai_next_js_update_code_file_executor.go | 7 +++-- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go index a60b9a9c..a971d881 100644 --- a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go +++ b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go @@ -69,7 +69,7 @@ func (e NextJsServerStartTestExecutor) Execute(step steps.ServerStartTestStep) e } buildLogs, err := e.serverRunTest(codeFolder, step.ExecutionStep.ExecutionID, step.ExecutionStep.ID, step.Story.HashID, step.Project.HashID) - fmt.Println("___BUILD LOGS____: ", buildLogs) + //fmt.Println("___BUILD LOGS____: ", buildLogs) if err != nil { return err } @@ -169,7 +169,7 @@ func (e NextJsServerStartTestExecutor) Execute(step steps.ServerStartTestStep) e } func (e NextJsServerStartTestExecutor) AnalyseBuildLogs(buildLogs, directoryPlan, apiKey string) (bool, map[string]interface{}, error) { - fmt.Println("Analysing Build Logs", buildLogs) + fmt.Println("____Analysing Build Logs____", buildLogs) messages, err := e.CreateMessage(buildLogs, directoryPlan) if err != nil { return false, nil, err @@ -212,7 +212,7 @@ func (e NextJsServerStartTestExecutor) CheckBuildResponse(response map[string]in func (e NextJsServerStartTestExecutor) CreateMessage(buildLogs string, directoryPlan string) ([]llms.ClaudeChatCompletionMessage, error) { content, err := os.ReadFile("/go/prompts/nextjs/next_js_build_checker.txt") - fmt.Println("____build logs in create msg function___", buildLogs) + //fmt.Println("____build logs in create msg function___", buildLogs) modifiedContent := strings.Replace(string(content), "{{BUILD_LOGS}}", buildLogs, -1) modifiedContent = strings.Replace(string(modifiedContent), "{{DIRECTORY_STRUCTURE}}", directoryPlan, -1) if err != nil { diff --git a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go index 7cc72f38..7c389db2 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go @@ -184,7 +184,7 @@ func (openAiCodeGenerator OpenAiNextJsCodeGenerator) Execute(step steps.Generate } return err } - fmt.Printf("_________Generated Code__________: %s\n", code) + //fmt.Printf("_________Generated Code__________: %s\n", code) if err = openAiCodeGenerator.executionStepService.UpdateExecutionStepResponse( step.ExecutionStep, @@ -214,11 +214,8 @@ func (openAiCodeGenerator OpenAiNextJsCodeGenerator) Execute(step steps.Generate func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) buildFinalInstructionForGeneration( step steps.GenerateCodeStep, storyDir string) (map[string]string, error) { // Initialize the final instruction string - finalInstruction, err := openAiCodeGenerator.buildInstructionForFirstExecution(step, storyDir) - if err != nil { - fmt.Printf("Error building instruction for first execution: %s\n", err.Error()) - return nil, err - } + var finalInstruction map[string]string + var err error if step.Retry { fmt.Println("Building instruction on retry limit reached for LLM steps") finalInstruction, err = openAiCodeGenerator.buildInstructionOnRetry(step, storyDir) @@ -232,10 +229,15 @@ func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) buildFinalInstructionForGe fmt.Printf("Error building instruction on re-execution: %s\n", err.Error()) return nil, err } + } else { + finalInstruction, err = openAiCodeGenerator.buildInstructionForFirstExecution(step, storyDir) + if err != nil { + fmt.Printf("Error building instruction for first execution: %s\n", err.Error()) + return nil, err + } } - // Print the final instruction - fmt.Println("___Final Instruction:___", finalInstruction["existingCode"]) + //fmt.Println("___Final Instruction:___", finalInstruction["existingCode"]) return finalInstruction, nil } @@ -350,6 +352,16 @@ func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) buildInstructionOnRetry(st } func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) buildInstructionOnReExecutionWithComments(step steps.GenerateCodeStep, storyDir string) (map[string]string, error) { + err := openAiCodeGenerator.activityLogService.CreateActivityLog( + step.Execution.ID, + step.ExecutionStep.ID, + "INFO", + fmt.Sprintf("Code generation has started for file: %s", step.File), + ) + if err != nil { + fmt.Printf("Error creating activity log: %s\n", err.Error()) + return nil, err + } fmt.Printf("Building instruction on re-execution with comments for step: %s\n", step.StepName()) comments, err := openAiCodeGenerator.designReviewService.GetAllDesignReviewsByStoryId(step.Story.ID) if err != nil { diff --git a/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go b/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go index cf32d54a..2dbaaa06 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go @@ -67,7 +67,7 @@ func (e NextJsUpdateCodeFileExecutor) Execute(step steps.UpdateCodeFileStep) err return err } if step.Retry { - fmt.Println("___Response to UpdateCodeFile___ \n", response) + //fmt.Println("___Response to UpdateCodeFile___ \n", response) err = e.UpdateReGeneratedCodeFile(response, step) if err != nil { fmt.Println("Error updating regenerated code: ", err.Error()) @@ -141,6 +141,7 @@ func (e *NextJsUpdateCodeFileExecutor) UpdateReGeneratedCodeFile(response Respon } func (e *NextJsUpdateCodeFileExecutor) EditCode(filePath string, startLine, endLine int, newCode string) error { + fmt.Printf("____Editing file %s_____", filePath) fmt.Println("Start Line:", startLine) fmt.Println("End Line:", endLine) file, err := os.Open(filePath) @@ -192,6 +193,7 @@ func (e *NextJsUpdateCodeFileExecutor) EditCode(filePath string, startLine, endL } func (e *NextJsUpdateCodeFileExecutor) InsertCode(filePath string, lineNumber int, newCode string) error { + fmt.Printf("____inserting code in file %s_____", filePath) file, err := os.Open(filePath) if err != nil { fmt.Println("Error opening file", filePath, err.Error()) @@ -223,6 +225,7 @@ func (e *NextJsUpdateCodeFileExecutor) InsertCode(filePath string, lineNumber in } func (e NextJsUpdateCodeFileExecutor) UpdateCodeFile(llmResponse, fileName string, step steps.UpdateCodeFileStep) error { + fmt.Printf("____updating file %s_____", fileName) if strings.HasPrefix(llmResponse, "```") { llmResponse = llmResponse[3:] // Remove the first 3 characters (```) lines := strings.Split(llmResponse, "\n") @@ -230,8 +233,6 @@ func (e NextJsUpdateCodeFileExecutor) UpdateCodeFile(llmResponse, fileName strin llmResponse = strings.Join(lines[1:], "\n") // Join all lines except the first one } } - - fmt.Println("___file name___",fileName) if step.File != "" { storyDir := config.FrontendWorkspacePath(step.Project.HashID, step.Story.HashID) + "/app/" + fileName err := os.WriteFile(storyDir, []byte(llmResponse), 0644) From fd98a04f7d389a341e693cf185989afc7676e112 Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Fri, 19 Jul 2024 17:02:52 +0530 Subject: [PATCH 10/39] removed unused loggers --- .../step_executors/impl/next_js_server_test_executor.go | 2 -- .../impl/open_ai_next_js_code_generation_executor.go | 4 ---- .../impl/open_ai_next_js_update_code_file_executor.go | 1 - 3 files changed, 7 deletions(-) diff --git a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go index a971d881..22648edc 100644 --- a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go +++ b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go @@ -69,7 +69,6 @@ func (e NextJsServerStartTestExecutor) Execute(step steps.ServerStartTestStep) e } buildLogs, err := e.serverRunTest(codeFolder, step.ExecutionStep.ExecutionID, step.ExecutionStep.ID, step.Story.HashID, step.Project.HashID) - //fmt.Println("___BUILD LOGS____: ", buildLogs) if err != nil { return err } @@ -212,7 +211,6 @@ func (e NextJsServerStartTestExecutor) CheckBuildResponse(response map[string]in func (e NextJsServerStartTestExecutor) CreateMessage(buildLogs string, directoryPlan string) ([]llms.ClaudeChatCompletionMessage, error) { content, err := os.ReadFile("/go/prompts/nextjs/next_js_build_checker.txt") - //fmt.Println("____build logs in create msg function___", buildLogs) modifiedContent := strings.Replace(string(content), "{{BUILD_LOGS}}", buildLogs, -1) modifiedContent = strings.Replace(string(modifiedContent), "{{DIRECTORY_STRUCTURE}}", directoryPlan, -1) if err != nil { diff --git a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go index 7c389db2..67b2582f 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go @@ -184,7 +184,6 @@ func (openAiCodeGenerator OpenAiNextJsCodeGenerator) Execute(step steps.Generate } return err } - //fmt.Printf("_________Generated Code__________: %s\n", code) if err = openAiCodeGenerator.executionStepService.UpdateExecutionStepResponse( step.ExecutionStep, @@ -236,8 +235,6 @@ func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) buildFinalInstructionForGe return nil, err } } - // Print the final instruction - //fmt.Println("___Final Instruction:___", finalInstruction["existingCode"]) return finalInstruction, nil } @@ -264,7 +261,6 @@ func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) buildInstructionForFirstEx filePath := filepath.Join(storyDir, "app", step.File) code, err := os.ReadFile(filePath) - // code, err := openAiCodeGenerator.getFilesContent(storyDir) if err != nil { return nil, err } diff --git a/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go b/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go index 2dbaaa06..48554259 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go @@ -67,7 +67,6 @@ func (e NextJsUpdateCodeFileExecutor) Execute(step steps.UpdateCodeFileStep) err return err } if step.Retry { - //fmt.Println("___Response to UpdateCodeFile___ \n", response) err = e.UpdateReGeneratedCodeFile(response, step) if err != nil { fmt.Println("Error updating regenerated code: ", err.Error()) From e6abe6546d5ea8bd31864cc96fdfb8f6754de505 Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Fri, 19 Jul 2024 18:49:05 +0530 Subject: [PATCH 11/39] chnaged activity logs --- app/tasks/create_execution_job_task.go | 25 +++++++++++++++---- ...en_ai_next_js_update_code_file_executor.go | 2 +- .../impl/open_ai_update_code_file_executor.go | 2 +- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/app/tasks/create_execution_job_task.go b/app/tasks/create_execution_job_task.go index 33eebb71..2cf047a1 100644 --- a/app/tasks/create_execution_job_task.go +++ b/app/tasks/create_execution_job_task.go @@ -174,11 +174,26 @@ func (h *CreateExecutionJobTaskHandler) HandleTask(ctx context.Context, t *asynq return err } - err = h.activityLogService.CreateActivityLogWithTx(tx, execution.ID, executionStep.ID, "INFO", "Initializing Workspace for automated development...") - if err != nil { - tx.Rollback() - h.logger.Error("Error creating activity log", zap.Error(err)) - return err + if payload.ReExecute{ + err = h.activityLogService.CreateActivityLogWithTx(tx, execution.ID, executionStep.ID, "INFO", fmt.Sprintf("Rebuilding %s story...", story.Type)) + if err != nil { + tx.Rollback() + h.logger.Error("Error creating activity log", zap.Error(err)) + return err + } + err = h.activityLogService.CreateActivityLogWithTx(tx, execution.ID, executionStep.ID, "INFO", fmt.Sprintf("Initializing Workspace for automated %s development...", story.Type)) + if err != nil { + tx.Rollback() + h.logger.Error("Error creating activity log", zap.Error(err)) + return err + } + } else { + err = h.activityLogService.CreateActivityLogWithTx(tx, execution.ID, executionStep.ID, "INFO",fmt.Sprintf("Initializing Workspace for automated %s development...", story.Type)) + if err != nil { + tx.Rollback() + h.logger.Error("Error creating activity log", zap.Error(err)) + return err + } } if err := tx.Commit().Error; err != nil { diff --git a/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go b/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go index 48554259..9dc2dd1d 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go @@ -240,7 +240,7 @@ func (e NextJsUpdateCodeFileExecutor) UpdateCodeFile(llmResponse, fileName strin } } - err := e.activityLogService.CreateActivityLog(step.Execution.ID, step.ExecutionStep.ID, "INFO", "Updated code files.") + err := e.activityLogService.CreateActivityLog(step.Execution.ID, step.ExecutionStep.ID, "INFO", fmt.Sprintf("Updated file %s", fileName)) if err != nil { fmt.Println("Error creating activity log" + err.Error()) return err diff --git a/app/workflow_executors/step_executors/impl/open_ai_update_code_file_executor.go b/app/workflow_executors/step_executors/impl/open_ai_update_code_file_executor.go index 6d1399b0..5fdb8cee 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_update_code_file_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_update_code_file_executor.go @@ -96,7 +96,7 @@ func (e UpdateCodeFileExecutor) Execute(step steps.UpdateCodeFileStep) error { } } - err = e.activityLogService.CreateActivityLog(step.Execution.ID, step.ExecutionStep.ID, "INFO", "Updated code files.") + err = e.activityLogService.CreateActivityLog(step.Execution.ID, step.ExecutionStep.ID, "INFO", "Updated code files") if err != nil { fmt.Println("Error creating activity log" + err.Error()) return err From b367470e73aa7038c9ec4549238bf8a0c7d4595f Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Mon, 22 Jul 2024 10:52:04 +0530 Subject: [PATCH 12/39] fixes --- app/tasks/create_execution_job_task.go | 22 ++++++------------- .../impl/next_js_server_test_executor.go | 2 +- ...en_ai_next_js_update_code_file_executor.go | 6 ++++- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/app/tasks/create_execution_job_task.go b/app/tasks/create_execution_job_task.go index 2cf047a1..9db9e573 100644 --- a/app/tasks/create_execution_job_task.go +++ b/app/tasks/create_execution_job_task.go @@ -165,7 +165,6 @@ func (h *CreateExecutionJobTaskHandler) HandleTask(ctx context.Context, t *asynq } h.logger.Info("Payload for create job request", zap.Any("createJobRequest", createJobRequest)) - fmt.Println("__payload_____12july", createJobRequest) job, err := h.workspaceServiceClient.CreateJob(createJobRequest) if err != nil { @@ -174,26 +173,19 @@ func (h *CreateExecutionJobTaskHandler) HandleTask(ctx context.Context, t *asynq return err } - if payload.ReExecute{ + if payload.ReExecute { err = h.activityLogService.CreateActivityLogWithTx(tx, execution.ID, executionStep.ID, "INFO", fmt.Sprintf("Rebuilding %s story...", story.Type)) if err != nil { tx.Rollback() h.logger.Error("Error creating activity log", zap.Error(err)) return err } - err = h.activityLogService.CreateActivityLogWithTx(tx, execution.ID, executionStep.ID, "INFO", fmt.Sprintf("Initializing Workspace for automated %s development...", story.Type)) - if err != nil { - tx.Rollback() - h.logger.Error("Error creating activity log", zap.Error(err)) - return err - } - } else { - err = h.activityLogService.CreateActivityLogWithTx(tx, execution.ID, executionStep.ID, "INFO",fmt.Sprintf("Initializing Workspace for automated %s development...", story.Type)) - if err != nil { - tx.Rollback() - h.logger.Error("Error creating activity log", zap.Error(err)) - return err - } + } + err = h.activityLogService.CreateActivityLogWithTx(tx, execution.ID, executionStep.ID, "INFO",fmt.Sprintf("Initializing Workspace for automated %s development...", story.Type)) + if err != nil { + tx.Rollback() + h.logger.Error("Error creating activity log", zap.Error(err)) + return err } if err := tx.Commit().Error; err != nil { diff --git a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go index 22648edc..c2024080 100644 --- a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go +++ b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go @@ -168,7 +168,7 @@ func (e NextJsServerStartTestExecutor) Execute(step steps.ServerStartTestStep) e } func (e NextJsServerStartTestExecutor) AnalyseBuildLogs(buildLogs, directoryPlan, apiKey string) (bool, map[string]interface{}, error) { - fmt.Println("____Analysing Build Logs____", buildLogs) + e.logger.Info("____Analyzing build logs____ ", zap.String("buildLogs", buildLogs)) messages, err := e.CreateMessage(buildLogs, directoryPlan) if err != nil { return false, nil, err diff --git a/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go b/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go index 9dc2dd1d..d8779e99 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go @@ -9,20 +9,24 @@ import ( "fmt" "os" "strings" + "go.uber.org/zap" ) type NextJsUpdateCodeFileExecutor struct { executionStepService *services.ExecutionStepService activityLogService *services.ActivityLogService + logger *zap.Logger } func NewNextJsUpdateCodeFileExecutor( executionStepService *services.ExecutionStepService, activeLogService *services.ActivityLogService, + logger *zap.Logger, ) *NextJsUpdateCodeFileExecutor { return &NextJsUpdateCodeFileExecutor{ executionStepService: executionStepService, activityLogService: activeLogService, + logger: logger, } } @@ -224,7 +228,7 @@ func (e *NextJsUpdateCodeFileExecutor) InsertCode(filePath string, lineNumber in } func (e NextJsUpdateCodeFileExecutor) UpdateCodeFile(llmResponse, fileName string, step steps.UpdateCodeFileStep) error { - fmt.Printf("____updating file %s_____", fileName) + e.logger.Info("_____Updating file_____ %s", zap.String("fileName", fileName)) if strings.HasPrefix(llmResponse, "```") { llmResponse = llmResponse[3:] // Remove the first 3 characters (```) lines := strings.Split(llmResponse, "\n") From bb799974d82bbc66076633047def417dd9be180c Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Mon, 22 Jul 2024 13:28:25 +0530 Subject: [PATCH 13/39] fixes --- .../impl/open_ai_next_js_code_generation_executor.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go index 67b2582f..00ae1212 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go @@ -214,21 +214,23 @@ func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) buildFinalInstructionForGe step steps.GenerateCodeStep, storyDir string) (map[string]string, error) { // Initialize the final instruction string var finalInstruction map[string]string - var err error if step.Retry { fmt.Println("Building instruction on retry limit reached for LLM steps") + var err error finalInstruction, err = openAiCodeGenerator.buildInstructionOnRetry(step, storyDir) if err != nil { fmt.Printf("Error building instruction on retry: %s\n", err.Error()) return nil, err } } else if step.Execution.ReExecution { + var err error finalInstruction, err = openAiCodeGenerator.buildInstructionOnReExecutionWithComments(step, storyDir) if err != nil { fmt.Printf("Error building instruction on re-execution: %s\n", err.Error()) return nil, err } } else { + var err error finalInstruction, err = openAiCodeGenerator.buildInstructionForFirstExecution(step, storyDir) if err != nil { fmt.Printf("Error building instruction for first execution: %s\n", err.Error()) From 49a175d692254ab93587d4ddd1747a453900c0ac Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Mon, 22 Jul 2024 14:56:51 +0530 Subject: [PATCH 14/39] fixes --- .../impl/open_ai_next_js_code_generation_executor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go index 00ae1212..fa45c87e 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go @@ -542,7 +542,7 @@ func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) GetMessages(systemPrompt s }, { Type: "text", - Text: fmt.Sprintf("User Feedback: %s", instruction["feedback"]), + Text: fmt.Sprintf("User Feedback: %s", "use react hook form for handling form inputs and validations"), }, }, }, From 9befd0fe951b245d6c415dbe2f6e9514b8d79e3a Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Mon, 22 Jul 2024 15:21:42 +0530 Subject: [PATCH 15/39] fixes --- .../impl/open_ai_next_js_update_code_file_executor.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go b/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go index d8779e99..437b635f 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go @@ -102,6 +102,7 @@ func (e *NextJsUpdateCodeFileExecutor) UpdateReGeneratedCodeFile(response Respon } switch llmResponse["type"].(string) { case "edit", "update": + fmt.Println("_________editing file_________") newCode := llmResponse["new_code"].(string) var startLine int switch startLineVal := llmResponse["start_line"].(type) { @@ -117,12 +118,17 @@ func (e *NextJsUpdateCodeFileExecutor) UpdateReGeneratedCodeFile(response Respon case int: endLine = endLineVal } + fmt.Println("Start Line:", startLine) + fmt.Println("End Line:", endLine) + fmt.Println("New Code:", newCode) + fmt.Println("File Path:", filePath) err = e.EditCode(filePath, startLine, endLine, newCode) if err != nil { fmt.Println("Error editing code: ", err) return err } case "insert", "create": + fmt.Println("_________inserting file_________") var lineNumber int switch lineVal := llmResponse["line_number"].(type) { case float64: @@ -137,6 +143,7 @@ func (e *NextJsUpdateCodeFileExecutor) UpdateReGeneratedCodeFile(response Respon return err } default: + fmt.Println("_____________Unknown llmResponse:____________", llmResponse["type"].(string)) fmt.Println("Unknown llmResponse:", llmResponse["type"].(string)) return fmt.Errorf("unknown response type: %s", llmResponse["type"]) } @@ -144,9 +151,7 @@ func (e *NextJsUpdateCodeFileExecutor) UpdateReGeneratedCodeFile(response Respon } func (e *NextJsUpdateCodeFileExecutor) EditCode(filePath string, startLine, endLine int, newCode string) error { - fmt.Printf("____Editing file %s_____", filePath) - fmt.Println("Start Line:", startLine) - fmt.Println("End Line:", endLine) + fmt.Println("____Editing file %s_____", filePath) file, err := os.Open(filePath) if err != nil { fmt.Println("Error opening file", filePath, err.Error()) From 958391b7e741640361ffc0d4025cc159f8700658 Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Mon, 22 Jul 2024 20:53:14 +0530 Subject: [PATCH 16/39] added retries in edit code --- app/models/types/errors.go | 2 + .../ai_frontend_developer_edit_code_retry.txt | 73 ++++++++++ .../nextjs/next_js_build_checker_retry.txt | 102 +++++++++++++ .../impl/next_js_server_test_executor.go | 58 +++++--- ...pen_ai_next_js_code_generation_executor.go | 136 +++++++++++++----- ...en_ai_next_js_update_code_file_executor.go | 23 ++- 6 files changed, 332 insertions(+), 62 deletions(-) create mode 100644 app/prompts/nextjs/ai_frontend_developer_edit_code_retry.txt create mode 100644 app/prompts/nextjs/next_js_build_checker_retry.txt diff --git a/app/models/types/errors.go b/app/models/types/errors.go index dad4c164..96a02eac 100644 --- a/app/models/types/errors.go +++ b/app/models/types/errors.go @@ -9,3 +9,5 @@ var ErrStoryDeleted = errors.New("story deleted") var ErrInvalidStory = errors.New("invalid story") var ErrInvalidStoryStatusTransition = errors.New("invalid story status transition") + +var ErrJsonParsingRetriesExceeded = errors.New("json parsing retries exceeded") \ No newline at end of file diff --git a/app/prompts/nextjs/ai_frontend_developer_edit_code_retry.txt b/app/prompts/nextjs/ai_frontend_developer_edit_code_retry.txt new file mode 100644 index 00000000..8d1a4486 --- /dev/null +++ b/app/prompts/nextjs/ai_frontend_developer_edit_code_retry.txt @@ -0,0 +1,73 @@ +You are tasked with updating the frontend code to resolve build errors. You will be given information about a specific file, the error description, the current code, and the project's directory structure. Your job is to propose a solution by either editing existing code or inserting new code. + +Here's the file you need to work on: + +{{FILE_NAME}} + + +The build error description is as follows: + +{{ERROR_DESCRIPTION}} + + +Here's the current code in the file: + +{{CURRENT_CODE}} + + +The directory structure of the project is: + +{{DIRECTORY_STRUCTURE}} + + +Based on the error description and the current code, you must choose ONE of the following actions: + +1. Edit code: + Replace the code in the given file path from `start_line` to `end_line` with `new_code`. + +2. Add code: + Insert the code in the given file path below the `line_number`. + +Provide your response in JSON format, following one of these structures: + +For editing code: +{ + "type": "edit", + "start_line": Starting Line number, + "end_line": Ending Line number, + "new_code": Code snippet +} + +For inserting code: +{ + "type": "insert", + "line_number": Line number, + "new_code": Code snippet +} + +Guidelines for code editing and inserting: +- When editing, provide the code snippet from several lines before and after the actual edit to ensure proper context. Aim to edit complete sections of the code, covering at least 20-30 lines. +- If multiple edits are needed, choose line numbers that cover all necessary changes. In extreme cases, you may edit the entire file by setting start_line = 1 and end_line = last line of code. +- Do not include ```json and ``` in your response. +- Ensure that the proposed code is syntactically correct. +- Beware of any unescaped single quotes (') in the JSX code. Do not have unescaped single quotes in the code, use ' or " or other appropriate methods instead. + +Remember to provide only one edit or insert at a time. Your primary goal is to resolve the build error while maintaining the integrity of the code. + +Present your solution in the JSON format described above, without any additional explanation or commentary. + +The previous response was not valid JSON. Please provide the edit instructions in the specified JSON format. Here is the format: +For editing code: +{ + "type": "edit", + "start_line": Starting Line number, + "end_line": Ending Line number, + "new_code": Code snippet +} + +For inserting code: +{ + "type": "insert", + "line_number": Line number, + "new_code": Code snippet +} \ No newline at end of file diff --git a/app/prompts/nextjs/next_js_build_checker_retry.txt b/app/prompts/nextjs/next_js_build_checker_retry.txt new file mode 100644 index 00000000..9999321b --- /dev/null +++ b/app/prompts/nextjs/next_js_build_checker_retry.txt @@ -0,0 +1,102 @@ +You are an AI assistant tasked with analyzing the build logs of a website's frontend and determining if the build was successful. If not, you'll need to suggest an action to resolve the issue. You'll be provided with the following information: + + +{{BUILD_LOGS}} + + + +{{DIRECTORY_STRUCTURE}} + + +Your task is to: +1. Analyze the build logs carefully. +2. Determine if the build was successful or not. +3. If the build was not successful, suggest one of the following actions: + a. Create a new file + b. Edit an existing file + +To determine if the build was successful: +- Look for phrases like "Build successful", "Build completed", or similar indications of success. +- Check for error messages, warnings, or failed steps in the build process. +- Pay attention to the final lines of the build logs, as they often contain the build status. + +If the build was not successful: +1. Identify the root cause of the failure based on the error messages in the build logs. +2. Consider the logs and directory structure when suggesting a solution. +3. Choose the most appropriate action (create, or edit) to resolve the issue. +4. Provide detailed information about the action, including file paths (relative to the root directory) or terminal commands. +5. Include line numbers from the build logs in your description if available. + +Provide your response in the following JSON format: + +For a successful build: +{ + "build_successful": "Yes" +} + +For an unsuccessful build: +{ + "build_successful": "No", + "action": { + "type": "create|edit", + "file_path": "path/to/file", + "description": "Detailed description of the action and why it's needed" + } +} +Examples to clarify: +{ + "build_successful": "No", + "action": { + "type": "create", + "file_path": "path/to/file", + "description": "Detailed description of the action and why it's needed" + } +} + +{ + "build_successful": "No", + "action": { + "type": "edit", + "file_path": "path/to/file", + "description": "Detailed description of the action and why it's needed" + } +} + + +Remember to analyze the build logs thoroughly and provide a clear, concise explanation of the issue and the proposed solution in the "description" field. Do not include the ```json and ``` markers in your response. + +The previous response was not valid JSON. Please provide the edit instructions in the specified JSON format. Here is the format: +Provide your response in the following JSON format: + +For a successful build: +{ + "build_successful": "Yes" +} + +For an unsuccessful build: +{ + "build_successful": "No", + "action": { + "type": "create|edit", + "file_path": "path/to/file", + "description": "Detailed description of the action and why it's needed" + } +} +Examples to clarify: +{ + "build_successful": "No", + "action": { + "type": "create", + "file_path": "path/to/file", + "description": "Detailed description of the action and why it's needed" + } +} + +{ + "build_successful": "No", + "action": { + "type": "edit", + "file_path": "path/to/file", + "description": "Detailed description of the action and why it's needed" + } +} diff --git a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go index c2024080..d42dbdf8 100644 --- a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go +++ b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go @@ -169,26 +169,36 @@ func (e NextJsServerStartTestExecutor) Execute(step steps.ServerStartTestStep) e func (e NextJsServerStartTestExecutor) AnalyseBuildLogs(buildLogs, directoryPlan, apiKey string) (bool, map[string]interface{}, error) { e.logger.Info("____Analyzing build logs____ ", zap.String("buildLogs", buildLogs)) - messages, err := e.CreateMessage(buildLogs, directoryPlan) - if err != nil { - return false, nil, err - } - claudeClient:= llms.NewClaudeClient(apiKey) - response, err := claudeClient.ChatCompletion(messages) - if err != nil { - fmt.Println("failed to generate code from llm") - return false, nil, fmt.Errorf("failed to generate code from llm: %w", err) - } + claudeClient := llms.NewClaudeClient(apiKey) var jsonResponse map[string]interface{} - if err = json.Unmarshal([]byte(response), &jsonResponse); err != nil { - fmt.Println("failed to unmarshal response from Claude API, Failed to parse response as JSON on attempt.") - return false, nil, fmt.Errorf("failed to unmarshal response from Claude API: %w", err) + var response string + + for retryCount := 0; retryCount < 5; retryCount++ { + messages, err := e.CreateMessage(buildLogs, directoryPlan, retryCount) + if err != nil{ + fmt.Println("failed to create messages for llm") + return false, nil, err + } + response, err = claudeClient.ChatCompletion(messages) + if err != nil { + fmt.Println("failed to generate code from llm") + if retryCount == 4 { + return false, nil, fmt.Errorf("failed to generate code from llm after 5 attempts: %w", err) + } + continue + } + if err = json.Unmarshal([]byte(response), &jsonResponse); err != nil { + fmt.Println("failed to unmarshal response from Claude API, retrying...") + if retryCount == 4 { + return false, nil, fmt.Errorf("failed to unmarshal response from Claude API after 5 attempts: %w", err) + } + continue + } + break } - fmt.Println("Response after extracting JSON: ", jsonResponse) + buildResponse, action := e.CheckBuildResponse(jsonResponse) - fmt.Println("Build Logs Check Response") return buildResponse, action, nil - } func (e NextJsServerStartTestExecutor) CheckBuildResponse(response map[string]interface{}) (bool, map[string]interface{}) { @@ -209,8 +219,20 @@ func (e NextJsServerStartTestExecutor) CheckBuildResponse(response map[string]in return false, action } -func (e NextJsServerStartTestExecutor) CreateMessage(buildLogs string, directoryPlan string) ([]llms.ClaudeChatCompletionMessage, error) { - content, err := os.ReadFile("/go/prompts/nextjs/next_js_build_checker.txt") +func (e NextJsServerStartTestExecutor) CreateMessage(buildLogs string, directoryPlan string, attempts int) ([]llms.ClaudeChatCompletionMessage, error) { + var content []byte + var err error + if attempts > 1 { + content, err = os.ReadFile("/go/prompts/nextjs/next_js_build_checker_retry.txt") + if err!= nil { + return nil, fmt.Errorf("failed to load system prompt: %w", err) + } + } else { + content, err = os.ReadFile("/go/prompts/nextjs/next_js_build_checker.txt") + if err!= nil { + return nil, fmt.Errorf("failed to load system prompt: %w", err) + } + } modifiedContent := strings.Replace(string(content), "{{BUILD_LOGS}}", buildLogs, -1) modifiedContent = strings.Replace(string(modifiedContent), "{{DIRECTORY_STRUCTURE}}", directoryPlan, -1) if err != nil { diff --git a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go index fa45c87e..df24509e 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go @@ -5,16 +5,19 @@ import ( "ai-developer/app/constants" "ai-developer/app/llms" "ai-developer/app/models" + "ai-developer/app/models/types" "ai-developer/app/services" "ai-developer/app/services/s3_providers" "ai-developer/app/utils" "ai-developer/app/workflow_executors/step_executors/steps" + "encoding/json" "errors" "fmt" "os" "os/exec" "path/filepath" "strings" + "time" "go.uber.org/zap" ) @@ -162,16 +165,29 @@ func (openAiCodeGenerator OpenAiNextJsCodeGenerator) Execute(step steps.Generate code, err := openAiCodeGenerator.GenerateCode(step, finalInstructionForGeneration, storyDir, apiKey) if err != nil { fmt.Println("____ERROR OCCURRED WHILE GENERATING CODE: ______", err) - settingsUrl := config.Get("app.url").(string) + "/settings" - err = openAiCodeGenerator.activityLogService.CreateActivityLog( - step.Execution.ID, - step.ExecutionStep.ID, - "INFO", - fmt.Sprintf("Action required: There's an issue with your LLM API Key. Ensure your API Key for %s is correct. Settings", constants.CLAUDE_3, settingsUrl, "blue", "underline"), - ) - if err != nil { - fmt.Printf("Error creating activity log: %s\n", err.Error()) - return err + if err != types.ErrJsonParsingRetriesExceeded { + settingsUrl := config.Get("app.url").(string) + "/settings" + err = openAiCodeGenerator.activityLogService.CreateActivityLog( + step.Execution.ID, + step.ExecutionStep.ID, + "INFO", + fmt.Sprintf("Action required: There's an issue with your LLM API Key. Ensure your API Key for %s is correct. Settings", constants.CLAUDE_3, settingsUrl, "blue", "underline"), + ) + if err != nil { + fmt.Printf("Error creating activity log: %s\n", err.Error()) + return err + } + } else { + err = openAiCodeGenerator.activityLogService.CreateActivityLog( + step.Execution.ID, + step.ExecutionStep.ID, + "INFO", + fmt.Sprintf("Json parsing retries exceeded for code generation!"), + ) + if err != nil { + fmt.Printf("Error creating activity log: %s\n", err.Error()) + return err + } } //Update Execution Status and Story Status if err = openAiCodeGenerator.storyService.UpdateStoryStatus(int(step.Story.ID), constants.InReview); err != nil { @@ -479,29 +495,65 @@ func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) GenerateCodeOnRetry(execut } func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) EditCodeOnRetry(instruction map[string]string, storyDir string, executionStep *models.ExecutionStep, apiKey string) (string, error) { - generationPlan, err := openAiCodeGenerator.GetCodeGenerationPlan(storyDir) - if err != nil { - return "", err - } - systemPrompt, err := openAiCodeGenerator.GetRetrySystemPrompt(instruction, generationPlan) - if err != nil { - return "", err - } - messages := openAiCodeGenerator.GetMessagesOnRetry(systemPrompt, instruction["description"]) - err = openAiCodeGenerator.executionStepService.UpdateExecutionStepRequest( - executionStep, - map[string]interface{}{ - "final_instruction": instruction, - "llm_request": messages, - }, - "IN_PROGRESS", - ) - claudeClient := llms.NewClaudeClient(apiKey) - response, err := claudeClient.ChatCompletion(messages) - if err != nil { - return "", fmt.Errorf("failed to generate code from llm: %w", err) - } - return response, nil + const maxRetries = 5 + var response string + var err error + + for attempt := 1; attempt <= maxRetries; attempt++ { + response, err = openAiCodeGenerator.attemptEditCode(instruction, storyDir, executionStep, apiKey, attempt) + if err == nil { + jsonErr := openAiCodeGenerator.checkJsonValidity(response) + if jsonErr == nil { + return response, nil + } + err = jsonErr + } + + if attempt <= maxRetries { + fmt.Printf("Attempt %d failed: %v. Retrying...\n", attempt, err) + time.Sleep(time.Second * time.Duration(attempt)) + } + } + + return "", types.ErrJsonParsingRetriesExceeded +} + +func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) attemptEditCode(instruction map[string]string, storyDir string, executionStep *models.ExecutionStep, apiKey string, attempts int) (string, error) { + generationPlan, err := openAiCodeGenerator.GetCodeGenerationPlan(storyDir) + if err != nil { + return "", err + } + systemPrompt, err := openAiCodeGenerator.GetRetrySystemPrompt(instruction, generationPlan, attempts) + if err != nil { + return "", err + } + messages := openAiCodeGenerator.GetMessagesOnRetry(systemPrompt, instruction["description"]) + err = openAiCodeGenerator.executionStepService.UpdateExecutionStepRequest( + executionStep, + map[string]interface{}{ + "final_instruction": instruction, + "llm_request": messages, + }, + "IN_PROGRESS", + ) + if err != nil { + return "", err + } + claudeClient := llms.NewClaudeClient(apiKey) + response, err := claudeClient.ChatCompletion(messages) + if err != nil { + return "", fmt.Errorf("failed to generate code from llm: %w", err) + } + return response, nil +} + +func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) checkJsonValidity(input string) error { + fmt.Println("_____input to json validator_____:", input) + var llmResponse map[string]interface{} + if err := json.Unmarshal([]byte(input), &llmResponse); err != nil { + return fmt.Errorf("failed to unmarshal edit response: %w", err) + } + return nil } func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) GenerateMessages(instruction map[string]string, storyDir string, step steps.GenerateCodeStep) ([]llms.ClaudeChatCompletionMessage, error) { @@ -578,11 +630,19 @@ func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) getSystemPrompt(instructio return systemPrompt, nil } -func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) GetRetrySystemPrompt(instruction map[string]string, directoryStructure string) (string, error) { - content, err := os.ReadFile("/go/prompts/nextjs/ai_frontend_developer_edit_code.txt") - if err != nil { - panic(fmt.Sprintf("failed to read system prompt: %v", err)) - return "", err +func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) GetRetrySystemPrompt(instruction map[string]string, directoryStructure string, attempts int) (string, error) { + var content []byte + var err error + if attempts > 1 { + content, err = os.ReadFile("/go/prompts/nextjs/ai_frontend_developer_edit_code_retry.txt") + if err != nil { + panic(fmt.Sprintf("failed to read system prompt: %v", err)) + } + } else { + content, err = os.ReadFile("/go/prompts/nextjs/ai_frontend_developer_edit_code.txt") + if err != nil { + panic(fmt.Sprintf("failed to read system prompt: %v", err)) + } } modifiedContent := strings.Replace(string(content), "{{FILE_NAME}}", instruction["fileName"], -1) modifiedContent = strings.Replace(string(modifiedContent), "{{ERROR_DESCRIPTION}}", instruction["description"], -1) diff --git a/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go b/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go index 437b635f..6418ee06 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go @@ -53,6 +53,7 @@ func (e NextJsUpdateCodeFileExecutor) Execute(step steps.UpdateCodeFileStep) err } // Convert JSONMap to a JSON string + fmt.Println("____initial response_________", generateCodeSteps[0].Response) responseJSON, err := json.Marshal(generateCodeSteps[0].Response) if err != nil { fmt.Println("Error marshalling JSONMap" + err.Error()) @@ -98,12 +99,24 @@ func (e *NextJsUpdateCodeFileExecutor) UpdateReGeneratedCodeFile(response Respon } err := json.Unmarshal([]byte(response.LLMResponse), &llmResponse) if err != nil { - return nil + fmt.Println("___error occurred while parsing json_____", err) + return err } switch llmResponse["type"].(string) { case "edit", "update": - fmt.Println("_________editing file_________") - newCode := llmResponse["new_code"].(string) + var newCode string + switch nc := llmResponse["new_code"].(type) { + case string: + newCode = nc + case map[string]interface{}: + newCodeJson, err := json.Marshal(nc) + if err != nil { + fmt.Printf("Error marshaling new_code: %v\n", err) + } + newCode = string(newCodeJson) + default: + fmt.Printf("Unexpected type for new_code: %T\n", nc) + } var startLine int switch startLineVal := llmResponse["start_line"].(type) { case float64: @@ -128,7 +141,6 @@ func (e *NextJsUpdateCodeFileExecutor) UpdateReGeneratedCodeFile(response Respon return err } case "insert", "create": - fmt.Println("_________inserting file_________") var lineNumber int switch lineVal := llmResponse["line_number"].(type) { case float64: @@ -174,7 +186,6 @@ func (e *NextJsUpdateCodeFileExecutor) EditCode(filePath string, startLine, endL endLine-- newLines := strings.Split(newCode, "\n") - fmt.Println("New Lines:", newLines) // Edge case handling when startLine and endLine are 0 if startLine < 0 { @@ -255,4 +266,4 @@ func (e NextJsUpdateCodeFileExecutor) UpdateCodeFile(llmResponse, fileName strin return err } return nil -} +} \ No newline at end of file From 5f26f68f4963d7c1ca32863ffc6695d127fa76ef Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Mon, 22 Jul 2024 20:57:44 +0530 Subject: [PATCH 17/39] resolved merge conflicts --- app/models/types/errors.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/models/types/errors.go b/app/models/types/errors.go index c98544dd..e0f1a2dd 100644 --- a/app/models/types/errors.go +++ b/app/models/types/errors.go @@ -12,6 +12,4 @@ var ErrInvalidStoryStatusTransition = errors.New("invalid story status transitio var ErrAnotherStoryAlreadyInProgress = errors.New("another story already in progress") -var ErrAnotherStoryAlreadyInProgress = errors.New("another story already in progress") - var ErrJsonParsingRetriesExceeded = errors.New("json parsing retries exceeded") \ No newline at end of file From 28a68af9e7ec65f98fbc2ff753d5e77dfc88a049 Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Mon, 22 Jul 2024 20:58:17 +0530 Subject: [PATCH 18/39] resolved merge conflicts --- .../impl/open_ai_next_js_update_code_file_executor.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go b/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go index 16ee7836..6418ee06 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go @@ -10,27 +10,23 @@ import ( "os" "strings" "go.uber.org/zap" - "go.uber.org/zap" ) type NextJsUpdateCodeFileExecutor struct { executionStepService *services.ExecutionStepService activityLogService *services.ActivityLogService logger *zap.Logger - logger *zap.Logger } func NewNextJsUpdateCodeFileExecutor( executionStepService *services.ExecutionStepService, activeLogService *services.ActivityLogService, logger *zap.Logger, - logger *zap.Logger, ) *NextJsUpdateCodeFileExecutor { return &NextJsUpdateCodeFileExecutor{ executionStepService: executionStepService, activityLogService: activeLogService, logger: logger, - logger: logger, } } From 667b442280b8a355a4b4be9fe05b426d34a21f9b Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Mon, 22 Jul 2024 21:02:09 +0530 Subject: [PATCH 19/39] fixes --- .../open_ai_next_js_update_code_file_executor.go | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go b/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go index 6418ee06..ac1ec544 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go @@ -9,6 +9,8 @@ import ( "fmt" "os" "strings" + + "github.com/newrelic/go-agent/v3/internal/logger" "go.uber.org/zap" ) @@ -53,7 +55,6 @@ func (e NextJsUpdateCodeFileExecutor) Execute(step steps.UpdateCodeFileStep) err } // Convert JSONMap to a JSON string - fmt.Println("____initial response_________", generateCodeSteps[0].Response) responseJSON, err := json.Marshal(generateCodeSteps[0].Response) if err != nil { fmt.Println("Error marshalling JSONMap" + err.Error()) @@ -99,7 +100,7 @@ func (e *NextJsUpdateCodeFileExecutor) UpdateReGeneratedCodeFile(response Respon } err := json.Unmarshal([]byte(response.LLMResponse), &llmResponse) if err != nil { - fmt.Println("___error occurred while parsing json_____", err) + logger.Error("___error occurred while parsing json response_____", err) return err } switch llmResponse["type"].(string) { @@ -131,10 +132,6 @@ func (e *NextJsUpdateCodeFileExecutor) UpdateReGeneratedCodeFile(response Respon case int: endLine = endLineVal } - fmt.Println("Start Line:", startLine) - fmt.Println("End Line:", endLine) - fmt.Println("New Code:", newCode) - fmt.Println("File Path:", filePath) err = e.EditCode(filePath, startLine, endLine, newCode) if err != nil { fmt.Println("Error editing code: ", err) @@ -155,7 +152,6 @@ func (e *NextJsUpdateCodeFileExecutor) UpdateReGeneratedCodeFile(response Respon return err } default: - fmt.Println("_____________Unknown llmResponse:____________", llmResponse["type"].(string)) fmt.Println("Unknown llmResponse:", llmResponse["type"].(string)) return fmt.Errorf("unknown response type: %s", llmResponse["type"]) } @@ -163,7 +159,7 @@ func (e *NextJsUpdateCodeFileExecutor) UpdateReGeneratedCodeFile(response Respon } func (e *NextJsUpdateCodeFileExecutor) EditCode(filePath string, startLine, endLine int, newCode string) error { - fmt.Println("____Editing file %s_____", filePath) + logger.Info("___Editing file____", filePath) file, err := os.Open(filePath) if err != nil { fmt.Println("Error opening file", filePath, err.Error()) From 166686f899ca00cec01be6bb18bc11b978f3175e Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Mon, 22 Jul 2024 21:03:16 +0530 Subject: [PATCH 20/39] fixes --- .../impl/open_ai_next_js_update_code_file_executor.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go b/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go index ac1ec544..3890b545 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_next_js_update_code_file_executor.go @@ -9,8 +9,6 @@ import ( "fmt" "os" "strings" - - "github.com/newrelic/go-agent/v3/internal/logger" "go.uber.org/zap" ) @@ -100,7 +98,7 @@ func (e *NextJsUpdateCodeFileExecutor) UpdateReGeneratedCodeFile(response Respon } err := json.Unmarshal([]byte(response.LLMResponse), &llmResponse) if err != nil { - logger.Error("___error occurred while parsing json response_____", err) + e.logger.Error("___error occurred while parsing json response_____", zap.Any("error", err)) return err } switch llmResponse["type"].(string) { @@ -159,7 +157,7 @@ func (e *NextJsUpdateCodeFileExecutor) UpdateReGeneratedCodeFile(response Respon } func (e *NextJsUpdateCodeFileExecutor) EditCode(filePath string, startLine, endLine int, newCode string) error { - logger.Info("___Editing file____", filePath) + e.logger.Info("___Editing file____", zap.Any("filePath", filePath)) file, err := os.Open(filePath) if err != nil { fmt.Println("Error opening file", filePath, err.Error()) From 6535549bee5325c3f4d971beee95d7734ed76a65 Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Mon, 22 Jul 2024 21:17:58 +0530 Subject: [PATCH 21/39] fixes --- .../impl/next_js_server_test_executor.go | 25 +++++++-- ...pen_ai_next_js_code_generation_executor.go | 52 ++++++++++++++----- 2 files changed, 59 insertions(+), 18 deletions(-) diff --git a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go index d42dbdf8..eba1cd0e 100644 --- a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go +++ b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go @@ -13,8 +13,8 @@ import ( "os/exec" "path/filepath" "strings" - "go.uber.org/zap" + "ai-developer/app/monitoring" ) type NextJsServerStartTestExecutor struct { @@ -25,6 +25,7 @@ type NextJsServerStartTestExecutor struct { llmAPIKeyService *services.LLMAPIKeyService storyService *services.StoryService projectService *services.ProjectService + slackAlert *monitoring.SlackAlert } func NewNextJsServerStartTestExecutor( @@ -35,6 +36,7 @@ func NewNextJsServerStartTestExecutor( executionService *services.ExecutionService, storyService *services.StoryService, projectService *services.ProjectService, + slackAlert *monitoring.SlackAlert, ) *NextJsServerStartTestExecutor { return &NextJsServerStartTestExecutor{ executionStepService: executionStepService, @@ -44,6 +46,7 @@ func NewNextJsServerStartTestExecutor( executionService: executionService, storyService: storyService, projectService: projectService, + slackAlert: slackAlert, } } @@ -98,7 +101,7 @@ func (e NextJsServerStartTestExecutor) Execute(step steps.ServerStartTestStep) e apiKey := llmAPIKey.LLMAPIKey fmt.Println("_________API KEY_________", apiKey) - buildAnalysis, action, err := e.AnalyseBuildLogs(buildLogs, directoryPlan, apiKey) + buildAnalysis, action, err := e.AnalyseBuildLogs(buildLogs, directoryPlan, apiKey, step) fmt.Println("Build Logs Analysis", buildAnalysis) if err != nil { fmt.Println("Error analysing build log" + err.Error()) @@ -167,13 +170,13 @@ func (e NextJsServerStartTestExecutor) Execute(step steps.ServerStartTestStep) e } } -func (e NextJsServerStartTestExecutor) AnalyseBuildLogs(buildLogs, directoryPlan, apiKey string) (bool, map[string]interface{}, error) { +func (e NextJsServerStartTestExecutor) AnalyseBuildLogs(buildLogs, directoryPlan, apiKey string, step steps.ServerStartTestStep) (bool, map[string]interface{}, error) { e.logger.Info("____Analyzing build logs____ ", zap.String("buildLogs", buildLogs)) claudeClient := llms.NewClaudeClient(apiKey) var jsonResponse map[string]interface{} var response string - for retryCount := 0; retryCount < 5; retryCount++ { + for retryCount := 1; retryCount < 6; retryCount++ { messages, err := e.CreateMessage(buildLogs, directoryPlan, retryCount) if err != nil{ fmt.Println("failed to create messages for llm") @@ -189,7 +192,19 @@ func (e NextJsServerStartTestExecutor) AnalyseBuildLogs(buildLogs, directoryPlan } if err = json.Unmarshal([]byte(response), &jsonResponse); err != nil { fmt.Println("failed to unmarshal response from Claude API, retrying...") - if retryCount == 4 { + if retryCount == 5 { + err := e.slackAlert.SendAlert( + "Max retry limit reached while parsing JSON, error occurred while parsing build logs response", + map[string]string{ + "story_id": fmt.Sprintf("%d", int64(step.Story.ID)), + "execution_id": fmt.Sprintf("%d", int64(step.Execution.ID)), + "execution_step_id": fmt.Sprintf("%d", int64(step.ExecutionStep.ID)), + "is_re_execution": fmt.Sprintf("%t", step.Execution.ReExecution), + }) + if err != nil { + fmt.Printf("Error sending slack alert: %s\n", err.Error()) + return false, nil, err + } return false, nil, fmt.Errorf("failed to unmarshal response from Claude API after 5 attempts: %w", err) } continue diff --git a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go index 203171ab..e9ed197e 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go @@ -6,6 +6,7 @@ import ( "ai-developer/app/llms" "ai-developer/app/models" "ai-developer/app/models/types" + "ai-developer/app/monitoring" "ai-developer/app/services" "ai-developer/app/services/s3_providers" "ai-developer/app/utils" @@ -32,6 +33,7 @@ type OpenAiNextJsCodeGenerator struct { s3Service *s3_providers.S3Service llmAPIKeyService *services.LLMAPIKeyService logger *zap.Logger + slackAlert *monitoring.SlackAlert } func NewOpenAINextJsCodeGenerationExecutor( @@ -44,6 +46,7 @@ func NewOpenAINextJsCodeGenerationExecutor( s3Service *s3_providers.S3Service, llmAPIKeyService *services.LLMAPIKeyService, logger *zap.Logger, + slackAlert *monitoring.SlackAlert, ) *OpenAiNextJsCodeGenerator { return &OpenAiNextJsCodeGenerator{ projectService: projectService, @@ -55,6 +58,7 @@ func NewOpenAINextJsCodeGenerationExecutor( s3Service: s3Service, llmAPIKeyService: llmAPIKeyService, logger: logger, + slackAlert: slackAlert, } } @@ -164,40 +168,62 @@ func (openAiCodeGenerator OpenAiNextJsCodeGenerator) Execute(step steps.Generate code, err := openAiCodeGenerator.GenerateCode(step, finalInstructionForGeneration, storyDir, apiKey) if err != nil { fmt.Println("____ERROR OCCURRED WHILE GENERATING CODE: ______", err) - if err != types.ErrJsonParsingRetriesExceeded { - settingsUrl := config.Get("app.url").(string) + "/settings" + if err == types.ErrJsonParsingRetriesExceeded { + err = openAiCodeGenerator.slackAlert.SendAlert( + "Max retry limit reached while parsing JSON, error occurred while parsing the generated edit code", + map[string]string{ + "story_id": fmt.Sprintf("%d", int64(step.Story.ID)), + "execution_id": fmt.Sprintf("%d", int64(step.Execution.ID)), + "execution_step_id": fmt.Sprintf("%d", int64(step.ExecutionStep.ID)), + "is_re_execution": fmt.Sprintf("%t", step.Execution.ReExecution), + }) + if err != nil { + fmt.Printf("Error sending slack alert: %s\n", err.Error()) + return err + } err = openAiCodeGenerator.activityLogService.CreateActivityLog( step.Execution.ID, step.ExecutionStep.ID, "INFO", - fmt.Sprintf("Action required: There's an issue with your LLM API Key. Ensure your API Key for %s is correct. Settings", constants.CLAUDE_3, settingsUrl, "blue", "underline"), + fmt.Sprintf("Json parsing retries exceeded for code generation!"), ) if err != nil { fmt.Printf("Error creating activity log: %s\n", err.Error()) return err } + //Update Execution Status and Story Status + if err = openAiCodeGenerator.storyService.UpdateStoryStatus(int(step.Story.ID), constants.InReview); err != nil { + fmt.Printf("Error updating story status: %s\n", err.Error()) + return err + } + if err = openAiCodeGenerator.executionService.UpdateExecutionStatus(step.Execution.ID, constants.InReview); err != nil { + fmt.Printf("Error updating execution step: %s\n", err.Error()) + return err + } + return err } else { + settingsUrl := config.Get("app.url").(string) + "/settings" err = openAiCodeGenerator.activityLogService.CreateActivityLog( step.Execution.ID, step.ExecutionStep.ID, "INFO", - fmt.Sprintf("Json parsing retries exceeded for code generation!"), + fmt.Sprintf("Action required: There's an issue with your LLM API Key. Ensure your API Key for %s is correct. Settings", constants.CLAUDE_3, settingsUrl, "blue", "underline"), ) if err != nil { fmt.Printf("Error creating activity log: %s\n", err.Error()) return err } - } - //Update Execution Status and Story Status - if err = openAiCodeGenerator.storyService.UpdateStoryStatus(int(step.Story.ID), constants.InReviewLLMKeyNotFound); err != nil { - fmt.Printf("Error updating story status: %s\n", err.Error()) - return err - } - if err = openAiCodeGenerator.executionService.UpdateExecutionStatus(step.Execution.ID, constants.InReviewLLMKeyNotFound); err != nil { - fmt.Printf("Error updating execution step: %s\n", err.Error()) + //Update Execution Status and Story Status + if err = openAiCodeGenerator.storyService.UpdateStoryStatus(int(step.Story.ID), constants.InReviewLLMKeyNotFound); err != nil { + fmt.Printf("Error updating story status: %s\n", err.Error()) + return err + } + if err = openAiCodeGenerator.executionService.UpdateExecutionStatus(step.Execution.ID, constants.InReviewLLMKeyNotFound); err != nil { + fmt.Printf("Error updating execution step: %s\n", err.Error()) + return err + } return err } - return err } if err = openAiCodeGenerator.executionStepService.UpdateExecutionStepResponse( From c2854a2ea965f1e2ec1d7e77403591cb65ed5908 Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Tue, 23 Jul 2024 18:50:02 +0530 Subject: [PATCH 22/39] minor fixes --- app/services/activity_log_service.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/services/activity_log_service.go b/app/services/activity_log_service.go index f383fdb2..f4fcf000 100644 --- a/app/services/activity_log_service.go +++ b/app/services/activity_log_service.go @@ -3,8 +3,9 @@ package services import ( "ai-developer/app/models" "ai-developer/app/repositories" - "gorm.io/gorm" "sort" + "gorm.io/gorm" + "ai-developer/app/constants" ) type ActivityLogService struct { @@ -36,6 +37,11 @@ func (s *ActivityLogService) GetActivityLogsByStoryID(storyID uint) (models.Acti latestExecution := executions[0] status := latestExecution.Status + storyStatusSet := map[string]struct{}{constants.Todo: {}, constants.InProgress: {}, constants.Done: {}} + if _, found := storyStatusSet[status]; !found { + status = constants.InReview + } + var executionIDs []uint for _, execution := range executions { executionIDs = append(executionIDs, execution.ID) From cd81b8a7b8860989c347f72d001a4142422da333 Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Tue, 23 Jul 2024 20:17:03 +0530 Subject: [PATCH 23/39] fixes --- .../impl/next_js_server_test_executor.go | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go index c2024080..7ef7d8f8 100644 --- a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go +++ b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go @@ -2,6 +2,7 @@ package impl import ( "ai-developer/app/config" + "ai-developer/app/constants" "ai-developer/app/llms" "ai-developer/app/services" "ai-developer/app/utils" @@ -98,7 +99,7 @@ func (e NextJsServerStartTestExecutor) Execute(step steps.ServerStartTestStep) e apiKey := llmAPIKey.LLMAPIKey fmt.Println("_________API KEY_________", apiKey) - buildAnalysis, action, err := e.AnalyseBuildLogs(buildLogs, directoryPlan, apiKey) + buildAnalysis, action, err := e.AnalyseBuildLogs(buildLogs, directoryPlan, apiKey, step) fmt.Println("Build Logs Analysis", buildAnalysis) if err != nil { fmt.Println("Error analysing build log" + err.Error()) @@ -167,7 +168,7 @@ func (e NextJsServerStartTestExecutor) Execute(step steps.ServerStartTestStep) e } } -func (e NextJsServerStartTestExecutor) AnalyseBuildLogs(buildLogs, directoryPlan, apiKey string) (bool, map[string]interface{}, error) { +func (e NextJsServerStartTestExecutor) AnalyseBuildLogs(buildLogs, directoryPlan, apiKey string, step steps.ServerStartTestStep) (bool, map[string]interface{}, error) { e.logger.Info("____Analyzing build logs____ ", zap.String("buildLogs", buildLogs)) messages, err := e.CreateMessage(buildLogs, directoryPlan) if err != nil { @@ -176,6 +177,26 @@ func (e NextJsServerStartTestExecutor) AnalyseBuildLogs(buildLogs, directoryPlan claudeClient:= llms.NewClaudeClient(apiKey) response, err := claudeClient.ChatCompletion(messages) if err != nil { + settingsUrl := config.Get("app.url").(string) + "/settings" + err = e.activityLogService.CreateActivityLog( + step.Execution.ID, + step.ExecutionStep.ID, + "INFO", + fmt.Sprintf("Action required: There's an issue with your LLM API Key. Ensure your API Key for %s is correct. Settings", constants.CLAUDE_3, settingsUrl, "blue", "underline"), + ) + if err != nil { + fmt.Printf("Error creating activity log: %s\n", err.Error()) + return false, nil, err + } + //Update Execution Status and Story Status + if err = e.storyService.UpdateStoryStatus(int(step.Story.ID), constants.InReviewLLMKeyNotFound); err != nil { + fmt.Printf("Error updating story status: %s\n", err.Error()) + return false, nil, err + } + if err = e.executionService.UpdateExecutionStatus(step.Execution.ID, constants.InReviewLLMKeyNotFound); err != nil { + fmt.Printf("Error updating execution step: %s\n", err.Error()) + return false, nil, err + } fmt.Println("failed to generate code from llm") return false, nil, fmt.Errorf("failed to generate code from llm: %w", err) } From 79edf247f0fe80a1801cefe05b8bbfb18eab43ab Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Tue, 23 Jul 2024 23:27:43 +0530 Subject: [PATCH 24/39] fixes --- app/workflow_executors/workflow_executor.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/workflow_executors/workflow_executor.go b/app/workflow_executors/workflow_executor.go index b434399f..2a6e0cdd 100644 --- a/app/workflow_executors/workflow_executor.go +++ b/app/workflow_executors/workflow_executor.go @@ -43,7 +43,10 @@ func (we *WorkflowExecutor) Execute(workflowConfig *WorkflowConfig, args *Workfl workflowConfig.StepGraph.Walk(func(name steps.StepName, step steps.WorkflowStep) error { executor, ok := we.executors[name] + fmt.Println("_____step name_____:", name) + fmt.Println("____executor for next step_____:", executor) if !ok { + fmt.Println("___Couldn't find executor for step: ____", name) return errors.New("executor not found") } From 28ac5fe2797f4ffef24fdbed82b97ae8c56890db Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Wed, 24 Jul 2024 11:00:56 +0530 Subject: [PATCH 25/39] fixes --- app/workflow_executors/step_executors/graph/step_graph.go | 3 ++- .../impl/open_ai_next_js_code_generation_executor.go | 2 +- app/workflow_executors/workflow_executor.go | 3 --- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/app/workflow_executors/step_executors/graph/step_graph.go b/app/workflow_executors/step_executors/graph/step_graph.go index cd34df9a..36d947be 100644 --- a/app/workflow_executors/step_executors/graph/step_graph.go +++ b/app/workflow_executors/step_executors/graph/step_graph.go @@ -3,6 +3,7 @@ package graph import ( "ai-developer/app/workflow_executors/step_executors/steps" "errors" + "fmt" ) type StepGraph struct { @@ -26,7 +27,7 @@ func (g *StepGraph) GetNextStep(stepName steps.StepName, executionState Executio func (g *StepGraph) Walk(execute func(name steps.StepName, step steps.WorkflowStep) error) { currentStep := &g.StartingNode iteration := 0 - for currentStep != nil && iteration < 40 { + for currentStep != nil && iteration < 100 { err := execute(*currentStep, g.Nodes[*currentStep].Step) var executionState ExecutionState if err != nil { diff --git a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go index a56ebd4d..a9fed478 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go @@ -398,7 +398,7 @@ func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) GenerateCode(step steps.Ge response, err := openAiCodeGenerator.GenerateCodeOnRetry(step.ExecutionStep, instruction, storyDir, apiKey) if err != nil { fmt.Println("Error generating code on retry") - return "", err + return "", fmt.Errorf("failed to generate retry code from Claude API: %w", err) } return response, nil } else { diff --git a/app/workflow_executors/workflow_executor.go b/app/workflow_executors/workflow_executor.go index 2a6e0cdd..b434399f 100644 --- a/app/workflow_executors/workflow_executor.go +++ b/app/workflow_executors/workflow_executor.go @@ -43,10 +43,7 @@ func (we *WorkflowExecutor) Execute(workflowConfig *WorkflowConfig, args *Workfl workflowConfig.StepGraph.Walk(func(name steps.StepName, step steps.WorkflowStep) error { executor, ok := we.executors[name] - fmt.Println("_____step name_____:", name) - fmt.Println("____executor for next step_____:", executor) if !ok { - fmt.Println("___Couldn't find executor for step: ____", name) return errors.New("executor not found") } From d86c8bda19686230f3e0fa22e1b3f9385174cbdc Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Wed, 24 Jul 2024 12:30:14 +0530 Subject: [PATCH 26/39] fixes --- .../step_executors/graph/step_graph.go | 1 - .../impl/next_js_server_test_executor.go | 7 ++++- gui/src/app/_app.css | 6 +++- .../SyntaxDisplay/SyntaxDisplay.tsx | 28 +++++++++++++++++-- 4 files changed, 37 insertions(+), 5 deletions(-) diff --git a/app/workflow_executors/step_executors/graph/step_graph.go b/app/workflow_executors/step_executors/graph/step_graph.go index 36d947be..f779de5a 100644 --- a/app/workflow_executors/step_executors/graph/step_graph.go +++ b/app/workflow_executors/step_executors/graph/step_graph.go @@ -3,7 +3,6 @@ package graph import ( "ai-developer/app/workflow_executors/step_executors/steps" "errors" - "fmt" ) type StepGraph struct { diff --git a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go index 7ef7d8f8..e95df65e 100644 --- a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go +++ b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go @@ -265,11 +265,16 @@ func (e NextJsServerStartTestExecutor) runCommand(codeFolder string, executionId if err := cmd.Run(); err != nil { fmt.Printf("failed to run command %s %v: %v", name, args, err.Error()) } + + jsonMsg := fmt.Sprintf(`{ + "title": "Running command: %s %s", + "content": %q + }`, name, strings.Join(args, " "), stdout.String()+stderr.String()) err := e.activityLogService.CreateActivityLog( executionId, executionStepId, "CODE", - fmt.Sprintf(stdout.String()+stderr.String()), + jsonMsg, ) if err != nil { return stdout.String(), stderr.String(), err diff --git a/gui/src/app/_app.css b/gui/src/app/_app.css index d4c35989..721d00ba 100644 --- a/gui/src/app/_app.css +++ b/gui/src/app/_app.css @@ -278,4 +278,8 @@ body { border-bottom: 1px solid var(--white-opacity-12); background: var(--white-opacity-12); border-radius: 8px 0 0; -} \ No newline at end of file +} + +.green-text { + color: #32de84; +} diff --git a/gui/src/components/SyntaxDisplay/SyntaxDisplay.tsx b/gui/src/components/SyntaxDisplay/SyntaxDisplay.tsx index 5d86c943..d0b19f17 100644 --- a/gui/src/components/SyntaxDisplay/SyntaxDisplay.tsx +++ b/gui/src/components/SyntaxDisplay/SyntaxDisplay.tsx @@ -10,6 +10,24 @@ interface SyntaxDisplayProps { } const SyntaxDisplay: React.FC = ({ type, msg }) => { + let title = ''; + let content = msg; + + try { + const parsedMsg = JSON.parse(msg || ''); + if (parsedMsg.title && parsedMsg.content) { + title = parsedMsg.title; + content = parsedMsg.content; + } + } catch (e) { + // If parsing fails, it's not a valid JSON, so we'll use the original msg + } + + const lightGreenTextStyle = { + color: '#32de84' + }; + + return ( <> {type === ActivityLogType.ERROR && ( @@ -17,6 +35,12 @@ const SyntaxDisplay: React.FC = ({ type, msg }) => { AI Developer has an error in the terminal. )} + {type === ActivityLogType.CODE && title && ( + + Running command: {title.replace('Running command: ', '')} + + )} + = ({ type, msg }) => { background: rgba(0, 0, 0, 0.4), }} > - {msg} + {content} ); }; -export default SyntaxDisplay; +export default SyntaxDisplay; \ No newline at end of file From 744f6509f7a453ee9af8597febda6a56f3053111 Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Wed, 24 Jul 2024 12:31:18 +0530 Subject: [PATCH 27/39] fixes --- gui/src/components/SyntaxDisplay/SyntaxDisplay.tsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/gui/src/components/SyntaxDisplay/SyntaxDisplay.tsx b/gui/src/components/SyntaxDisplay/SyntaxDisplay.tsx index d0b19f17..e33d9fab 100644 --- a/gui/src/components/SyntaxDisplay/SyntaxDisplay.tsx +++ b/gui/src/components/SyntaxDisplay/SyntaxDisplay.tsx @@ -23,11 +23,6 @@ const SyntaxDisplay: React.FC = ({ type, msg }) => { // If parsing fails, it's not a valid JSON, so we'll use the original msg } - const lightGreenTextStyle = { - color: '#32de84' - }; - - return ( <> {type === ActivityLogType.ERROR && ( From e3a891a6cd53539daaf76adbc347144837a4cce6 Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Wed, 24 Jul 2024 14:39:05 +0530 Subject: [PATCH 28/39] minor fix --- .../components/DesignStoryComponents/CreateEditDesignStory.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/src/components/DesignStoryComponents/CreateEditDesignStory.tsx b/gui/src/components/DesignStoryComponents/CreateEditDesignStory.tsx index e67f6221..51ab007f 100644 --- a/gui/src/components/DesignStoryComponents/CreateEditDesignStory.tsx +++ b/gui/src/components/DesignStoryComponents/CreateEditDesignStory.tsx @@ -126,7 +126,7 @@ const CreateEditDesignStory: React.FC = ({ }; reader.readAsDataURL(file); } else { - toast.error('Please upload only JPEG or PNG images.'); + toast.error('Please upload only JPG or PNG images.'); event.target.value = ''; } } From 43f0a5b38be08015b32490c4c12fb7fcc227d513 Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Thu, 25 Jul 2024 10:48:23 +0530 Subject: [PATCH 29/39] merge conflicts resolved --- .../impl/next_js_server_test_executor.go | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go index 0eaa8447..5c2db7a4 100644 --- a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go +++ b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go @@ -185,26 +185,26 @@ func (e NextJsServerStartTestExecutor) AnalyseBuildLogs(buildLogs, directoryPlan } response, err = claudeClient.ChatCompletion(messages) if err != nil { - settingsUrl := config.Get("app.url").(string) + "/settings" - err = e.activityLogService.CreateActivityLog( - step.Execution.ID, - step.ExecutionStep.ID, - "INFO", - fmt.Sprintf("Action required: There's an issue with your LLM API Key. Ensure your API Key for %s is correct. Settings", constants.CLAUDE_3, settingsUrl, "blue", "underline"), - ) - if err != nil { - fmt.Printf("Error creating activity log: %s\n", err.Error()) - return false, nil, err - } - //Update Execution Status and Story Status - if err = e.storyService.UpdateStoryStatus(int(step.Story.ID), constants.InReviewLLMKeyNotFound); err != nil { - fmt.Printf("Error updating story status: %s\n", err.Error()) - return false, nil, err - } - if err = e.executionService.UpdateExecutionStatus(step.Execution.ID, constants.InReviewLLMKeyNotFound); err != nil { - fmt.Printf("Error updating execution step: %s\n", err.Error()) - return false, nil, err - } + settingsUrl := config.Get("app.url").(string) + "/settings" + err = e.activityLogService.CreateActivityLog( + step.Execution.ID, + step.ExecutionStep.ID, + "INFO", + fmt.Sprintf("Action required: There's an issue with your LLM API Key. Ensure your API Key for %s is correct. Settings", constants.CLAUDE_3, settingsUrl, "blue", "underline"), + ) + if err != nil { + fmt.Printf("Error creating activity log: %s\n", err.Error()) + return false, nil, err + } + //Update Execution Status and Story Status + if err = e.storyService.UpdateStoryStatus(int(step.Story.ID), constants.InReviewLLMKeyNotFound); err != nil { + fmt.Printf("Error updating story status: %s\n", err.Error()) + return false, nil, err + } + if err = e.executionService.UpdateExecutionStatus(step.Execution.ID, constants.InReviewLLMKeyNotFound); err != nil { + fmt.Printf("Error updating execution step: %s\n", err.Error()) + return false, nil, err + } fmt.Println("failed to generate code from llm") if retryCount == 4 { return false, nil, fmt.Errorf("failed to generate code from llm after 5 attempts: %w", err) From 84607aa161b9bc24318edb61915819d82adac101 Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Thu, 25 Jul 2024 12:59:31 +0530 Subject: [PATCH 30/39] fixes --- .../impl/next_js_server_test_executor.go | 1 + .../open_ai_next_js_code_generation_executor.go | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go index 5c2db7a4..612e948b 100644 --- a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go +++ b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go @@ -212,6 +212,7 @@ func (e NextJsServerStartTestExecutor) AnalyseBuildLogs(buildLogs, directoryPlan continue } if err = json.Unmarshal([]byte(response), &jsonResponse); err != nil { + fmt.Println("error decoding build logs response from claude api", err) fmt.Println("failed to unmarshal response from Claude API, retrying...") if retryCount == 5 { err := e.slackAlert.SendAlert( diff --git a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go index e65143e5..0f268ed8 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go @@ -87,6 +87,18 @@ func (openAiCodeGenerator OpenAiNextJsCodeGenerator) Execute(step steps.Generate if count > step.MaxLoopIterations { fmt.Println("Max retry limit reached for LLM steps") + err = openAiCodeGenerator.slackAlert.SendAlert( + "Max retry limit reached", + map[string]string{ + "story_id": fmt.Sprintf("%d", int64(step.Story.ID)), + "execution_id": fmt.Sprintf("%d", int64(step.Execution.ID)), + "execution_step_id": fmt.Sprintf("%d", int64(step.ExecutionStep.ID)), + "is_re_execution": fmt.Sprintf("%t", step.Execution.ReExecution), + }) + if err != nil { + fmt.Printf("Error sending slack alert: %s\n", err.Error()) + return err + } //Update story status to MAX_LOOP_ITERATION_REACHED if err = openAiCodeGenerator.storyService.UpdateStoryStatus(int(step.Story.ID), constants.MaxLoopIterationReached); err != nil { fmt.Printf("Error updating story status: %s\n", err.Error()) @@ -176,6 +188,7 @@ func (openAiCodeGenerator OpenAiNextJsCodeGenerator) Execute(step steps.Generate "execution_id": fmt.Sprintf("%d", int64(step.Execution.ID)), "execution_step_id": fmt.Sprintf("%d", int64(step.ExecutionStep.ID)), "is_re_execution": fmt.Sprintf("%t", step.Execution.ReExecution), + "model_name": constants.CLAUDE_3, }) if err != nil { fmt.Printf("Error sending slack alert: %s\n", err.Error()) From 97a6b4bdecbe40670759436688c9bd90e4e52c49 Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Thu, 25 Jul 2024 16:53:25 +0530 Subject: [PATCH 31/39] fixes --- .../impl/next_js_server_test_executor.go | 26 ++++++++-------- ...pen_ai_next_js_code_generation_executor.go | 30 ++++++++++++++----- 2 files changed, 37 insertions(+), 19 deletions(-) diff --git a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go index 612e948b..575c3941 100644 --- a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go +++ b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go @@ -214,19 +214,21 @@ func (e NextJsServerStartTestExecutor) AnalyseBuildLogs(buildLogs, directoryPlan if err = json.Unmarshal([]byte(response), &jsonResponse); err != nil { fmt.Println("error decoding build logs response from claude api", err) fmt.Println("failed to unmarshal response from Claude API, retrying...") + err := e.slackAlert.SendAlert( + "error occurred while parsing build logs JSON response", + map[string]string{ + "story_id": fmt.Sprintf("%d", int64(step.Story.ID)), + "execution_id": fmt.Sprintf("%d", int64(step.Execution.ID)), + "execution_step_id": fmt.Sprintf("%d", int64(step.ExecutionStep.ID)), + "is_re_execution": fmt.Sprintf("%t", step.Execution.ReExecution), + "error": err.Error(), + "attempt": fmt.Sprintf("%d", int64(retryCount)), + }) + if err != nil { + fmt.Printf("Error sending slack alert: %s\n", err.Error()) + return false, nil, err + } if retryCount == 5 { - err := e.slackAlert.SendAlert( - "Max retry limit reached while parsing JSON, error occurred while parsing build logs response", - map[string]string{ - "story_id": fmt.Sprintf("%d", int64(step.Story.ID)), - "execution_id": fmt.Sprintf("%d", int64(step.Execution.ID)), - "execution_step_id": fmt.Sprintf("%d", int64(step.ExecutionStep.ID)), - "is_re_execution": fmt.Sprintf("%t", step.Execution.ReExecution), - }) - if err != nil { - fmt.Printf("Error sending slack alert: %s\n", err.Error()) - return false, nil, err - } return false, nil, fmt.Errorf("failed to unmarshal response from Claude API after 5 attempts: %w", err) } continue diff --git a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go index 0f268ed8..086383a9 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go @@ -177,7 +177,7 @@ func (openAiCodeGenerator OpenAiNextJsCodeGenerator) Execute(step steps.Generate apiKey := llmAPIKey.LLMAPIKey fmt.Println("_________API KEY_________", apiKey) - code, err := openAiCodeGenerator.GenerateCode(step, finalInstructionForGeneration, storyDir, apiKey) + code, err := openAiCodeGenerator.GenerateCode(step, finalInstructionForGeneration, storyDir, apiKey, step) if err != nil { fmt.Println("____ERROR OCCURRED WHILE GENERATING CODE: ______", err) if err == types.ErrJsonParsingRetriesExceeded { @@ -448,9 +448,9 @@ func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) buildInstructionOnReExecut }, nil } -func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) GenerateCode(step steps.GenerateCodeStep, instruction map[string]string, storyDir string, apiKey string) (string, error) { +func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) GenerateCode(step steps.GenerateCodeStep, instruction map[string]string, storyDir string, apiKey string, step steps.GenerateCodeStep) (string, error) { if step.Retry { - response, err := openAiCodeGenerator.GenerateCodeOnRetry(step.ExecutionStep, instruction, storyDir, apiKey) + response, err := openAiCodeGenerator.GenerateCodeOnRetry(step.ExecutionStep, instruction, storyDir, apiKey, step) if err != nil { fmt.Println("Error generating code on retry") return "", fmt.Errorf("failed to generate retry code from Claude API: %w", err) @@ -493,7 +493,7 @@ func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) ProcessMessageResponse(mes } -func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) GenerateCodeOnRetry(executionStep *models.ExecutionStep, instruction map[string]string, storyDir string, apiKey string) (string, error) { +func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) GenerateCodeOnRetry(executionStep *models.ExecutionStep, instruction map[string]string, storyDir string, apiKey string, step steps.GenerateCodeStep) (string, error) { switch instruction["actionType"] { case "create": filePath := storyDir + instruction["fileName"] @@ -521,7 +521,7 @@ func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) GenerateCodeOnRetry(execut } return "", nil case "edit": - response, err := openAiCodeGenerator.EditCodeOnRetry(instruction, storyDir, executionStep, apiKey) + response, err := openAiCodeGenerator.EditCodeOnRetry(instruction, storyDir, executionStep, apiKey, step) if err != nil { return "", err } @@ -532,14 +532,16 @@ func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) GenerateCodeOnRetry(execut } } -func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) EditCodeOnRetry(instruction map[string]string, storyDir string, executionStep *models.ExecutionStep, apiKey string) (string, error) { +func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) EditCodeOnRetry(instruction map[string]string, storyDir string, executionStep *models.ExecutionStep, apiKey string, step steps.GenerateCodeStep) (string, error) { const maxRetries = 5 var response string var err error for attempt := 1; attempt <= maxRetries; attempt++ { response, err = openAiCodeGenerator.attemptEditCode(instruction, storyDir, executionStep, apiKey, attempt) - if err == nil { + if err !=nil { + return "", err + } else if err == nil { jsonErr := openAiCodeGenerator.checkJsonValidity(response) if jsonErr == nil { return response, nil @@ -548,6 +550,20 @@ func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) EditCodeOnRetry(instructio } if attempt <= maxRetries { + err = openAiCodeGenerator.slackAlert.SendAlert( + "error occurred while parsing edit code JSON response", + map[string]string{ + "story_id": fmt.Sprintf("%d", int64(step.Story.ID)), + "execution_id": fmt.Sprintf("%d", int64(step.Execution.ID)), + "execution_step_id": fmt.Sprintf("%d", int64(step.ExecutionStep.ID)), + "is_re_execution": fmt.Sprintf("%t", step.Execution.ReExecution), + "error": err.Error(), + "attempt": fmt.Sprintf("%d", int64(attempt)), + }) + if err != nil { + fmt.Printf("Error sending slack alert: %s\n", err.Error()) + return "", err + } fmt.Printf("Attempt %d failed: %v. Retrying...\n", attempt, err) time.Sleep(time.Second * time.Duration(attempt)) } From 10e0f9cb1f3ab94de826420faf7682e672fbd36b Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Thu, 25 Jul 2024 16:54:36 +0530 Subject: [PATCH 32/39] fixes --- .../impl/open_ai_next_js_code_generation_executor.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go index 086383a9..211f4cba 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go @@ -177,7 +177,7 @@ func (openAiCodeGenerator OpenAiNextJsCodeGenerator) Execute(step steps.Generate apiKey := llmAPIKey.LLMAPIKey fmt.Println("_________API KEY_________", apiKey) - code, err := openAiCodeGenerator.GenerateCode(step, finalInstructionForGeneration, storyDir, apiKey, step) + code, err := openAiCodeGenerator.GenerateCode(step, finalInstructionForGeneration, storyDir, apiKey) if err != nil { fmt.Println("____ERROR OCCURRED WHILE GENERATING CODE: ______", err) if err == types.ErrJsonParsingRetriesExceeded { @@ -448,7 +448,7 @@ func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) buildInstructionOnReExecut }, nil } -func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) GenerateCode(step steps.GenerateCodeStep, instruction map[string]string, storyDir string, apiKey string, step steps.GenerateCodeStep) (string, error) { +func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) GenerateCode(step steps.GenerateCodeStep, instruction map[string]string, storyDir string, apiKey string) (string, error) { if step.Retry { response, err := openAiCodeGenerator.GenerateCodeOnRetry(step.ExecutionStep, instruction, storyDir, apiKey, step) if err != nil { From 54987f8dc3ba629a5c8a012bbc1cb6fea998d66c Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Thu, 25 Jul 2024 17:25:47 +0530 Subject: [PATCH 33/39] fixes --- ...pen_ai_next_js_code_generation_executor.go | 2 +- .../SyntaxDisplay/SyntaxDisplay.tsx | 27 +++++++++++++------ 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go index 5f2dbe23..793d95f3 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go @@ -465,7 +465,7 @@ func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) GenerateCode(step steps.Ge response, err := openAiCodeGenerator.GenerateCodeOnRetry(step.ExecutionStep, instruction, storyDir, apiKey, step) if err != nil { fmt.Println("Error generating code on retry") - return "", fmt.Errorf("failed to generate retry code from Claude API: %w", err) + return "", err } return response, nil } else { diff --git a/gui/src/components/SyntaxDisplay/SyntaxDisplay.tsx b/gui/src/components/SyntaxDisplay/SyntaxDisplay.tsx index e33d9fab..cf620eb9 100644 --- a/gui/src/components/SyntaxDisplay/SyntaxDisplay.tsx +++ b/gui/src/components/SyntaxDisplay/SyntaxDisplay.tsx @@ -11,18 +11,29 @@ interface SyntaxDisplayProps { const SyntaxDisplay: React.FC = ({ type, msg }) => { let title = ''; - let content = msg; + let content = ''; + + const parseMessage = (message: string) => { + const titleMatch = message.match(/"title":\s*"(.*?)"/); + const contentMatch = message.match(/"content":\s*"([\s\S]*?)"/); + + return { + title: titleMatch ? titleMatch[1] : '', + content: contentMatch ? contentMatch[1].replace(/\\n/g, '\n').replace(/\\"/g, '"') : '' + }; + }; try { - const parsedMsg = JSON.parse(msg || ''); - if (parsedMsg.title && parsedMsg.content) { - title = parsedMsg.title; - content = parsedMsg.content; - } + const parsedMsg = parseMessage(msg || ''); + title = parsedMsg.title; + content = parsedMsg.content; } catch (e) { - // If parsing fails, it's not a valid JSON, so we'll use the original msg + console.error('Failed to parse activity log message:', e); + content = msg || ''; } + const command = title.replace('Running command: ', ''); + return ( <> {type === ActivityLogType.ERROR && ( @@ -32,7 +43,7 @@ const SyntaxDisplay: React.FC = ({ type, msg }) => { )} {type === ActivityLogType.CODE && title && ( - Running command: {title.replace('Running command: ', '')} + Running command: {command} )} From 370d62064c9073831f84479f12a8fc8e47980716 Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Thu, 25 Jul 2024 17:46:07 +0530 Subject: [PATCH 34/39] fixes --- app/constants/json_retries.go | 5 +++++ .../step_executors/impl/next_js_server_test_executor.go | 4 ++-- .../impl/open_ai_next_js_code_generation_executor.go | 5 ++--- 3 files changed, 9 insertions(+), 5 deletions(-) create mode 100644 app/constants/json_retries.go diff --git a/app/constants/json_retries.go b/app/constants/json_retries.go new file mode 100644 index 00000000..8856bd7d --- /dev/null +++ b/app/constants/json_retries.go @@ -0,0 +1,5 @@ +package constants + +const ( + MAX_JSON_RETRIES = 5 +) \ No newline at end of file diff --git a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go index 575c3941..2e1e6738 100644 --- a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go +++ b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go @@ -177,7 +177,7 @@ func (e NextJsServerStartTestExecutor) AnalyseBuildLogs(buildLogs, directoryPlan var jsonResponse map[string]interface{} var response string - for retryCount := 1; retryCount < 6; retryCount++ { + for retryCount := 1; retryCount <= constants.MAX_JSON_RETRIES; retryCount++ { messages, err := e.CreateMessage(buildLogs, directoryPlan, retryCount) if err != nil{ fmt.Println("failed to create messages for llm") @@ -206,7 +206,7 @@ func (e NextJsServerStartTestExecutor) AnalyseBuildLogs(buildLogs, directoryPlan return false, nil, err } fmt.Println("failed to generate code from llm") - if retryCount == 4 { + if retryCount == constants.MAX_JSON_RETRIES { return false, nil, fmt.Errorf("failed to generate code from llm after 5 attempts: %w", err) } continue diff --git a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go index 793d95f3..60e366de 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go @@ -545,11 +545,10 @@ func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) GenerateCodeOnRetry(execut } func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) EditCodeOnRetry(instruction map[string]string, storyDir string, executionStep *models.ExecutionStep, apiKey string, step steps.GenerateCodeStep) (string, error) { - const maxRetries = 5 var response string var err error - for attempt := 1; attempt <= maxRetries; attempt++ { + for attempt := 1; attempt <= constants.MAX_JSON_RETRIES; attempt++ { response, err = openAiCodeGenerator.attemptEditCode(instruction, storyDir, executionStep, apiKey, attempt) if err !=nil { return "", err @@ -561,7 +560,7 @@ func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) EditCodeOnRetry(instructio err = jsonErr } - if attempt <= maxRetries { + if attempt <= constants.MAX_JSON_RETRIES { err = openAiCodeGenerator.slackAlert.SendAlert( "error occurred while parsing edit code JSON response", map[string]string{ From fb75569dd356b9c18457e4daaeb73be464992fb8 Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Thu, 25 Jul 2024 18:10:51 +0530 Subject: [PATCH 35/39] fixes --- .../open_ai_next_js_code_generation_executor.go | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go index 60e366de..c906e49d 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go @@ -547,18 +547,17 @@ func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) GenerateCodeOnRetry(execut func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) EditCodeOnRetry(instruction map[string]string, storyDir string, executionStep *models.ExecutionStep, apiKey string, step steps.GenerateCodeStep) (string, error) { var response string var err error + var jsonErr error for attempt := 1; attempt <= constants.MAX_JSON_RETRIES; attempt++ { response, err = openAiCodeGenerator.attemptEditCode(instruction, storyDir, executionStep, apiKey, attempt) if err !=nil { return "", err - } else if err == nil { - jsonErr := openAiCodeGenerator.checkJsonValidity(response) - if jsonErr == nil { - return response, nil - } - err = jsonErr - } + } + jsonErr = openAiCodeGenerator.checkJsonValidity(response) + if jsonErr == nil { + return response, nil + } if attempt <= constants.MAX_JSON_RETRIES { err = openAiCodeGenerator.slackAlert.SendAlert( @@ -568,14 +567,14 @@ func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) EditCodeOnRetry(instructio "execution_id": fmt.Sprintf("%d", int64(step.Execution.ID)), "execution_step_id": fmt.Sprintf("%d", int64(step.ExecutionStep.ID)), "is_re_execution": fmt.Sprintf("%t", step.Execution.ReExecution), - "error": err.Error(), + "error": jsonErr.Error(), "attempt": fmt.Sprintf("%d", int64(attempt)), }) if err != nil { fmt.Printf("Error sending slack alert: %s\n", err.Error()) return "", err } - fmt.Printf("Attempt %d failed: %v. Retrying...\n", attempt, err) + fmt.Printf("Attempt %d failed: %v. Retrying...\n", attempt, jsonErr) time.Sleep(time.Second * time.Duration(attempt)) } } From 40530c50808f64cd1e17ef9619f5b568ad921a06 Mon Sep 17 00:00:00 2001 From: Rounak Bhatia Date: Thu, 25 Jul 2024 18:12:22 +0530 Subject: [PATCH 36/39] Update open_ai_next_js_code_generation_executor.go --- .../impl/open_ai_next_js_code_generation_executor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go index c906e49d..848119f1 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go @@ -547,7 +547,7 @@ func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) GenerateCodeOnRetry(execut func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) EditCodeOnRetry(instruction map[string]string, storyDir string, executionStep *models.ExecutionStep, apiKey string, step steps.GenerateCodeStep) (string, error) { var response string var err error - var jsonErr error + var jsonErr error for attempt := 1; attempt <= constants.MAX_JSON_RETRIES; attempt++ { response, err = openAiCodeGenerator.attemptEditCode(instruction, storyDir, executionStep, apiKey, attempt) From 2644e2057a8a7ba44c9bb842f94d379a8c988020 Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Fri, 26 Jul 2024 09:48:19 +0530 Subject: [PATCH 37/39] added loggers --- .../step_executors/impl/next_js_server_test_executor.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go index 2e1e6738..4922f234 100644 --- a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go +++ b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go @@ -202,18 +202,18 @@ func (e NextJsServerStartTestExecutor) AnalyseBuildLogs(buildLogs, directoryPlan return false, nil, err } if err = e.executionService.UpdateExecutionStatus(step.Execution.ID, constants.InReviewLLMKeyNotFound); err != nil { - fmt.Printf("Error updating execution step: %s\n", err.Error()) + e.logger.Error("Error updating execution status", zap.Error(err)) return false, nil, err } - fmt.Println("failed to generate code from llm") + e.logger.Error("failed to generate code from llm") if retryCount == constants.MAX_JSON_RETRIES { return false, nil, fmt.Errorf("failed to generate code from llm after 5 attempts: %w", err) } continue } if err = json.Unmarshal([]byte(response), &jsonResponse); err != nil { - fmt.Println("error decoding build logs response from claude api", err) - fmt.Println("failed to unmarshal response from Claude API, retrying...") + e.logger.Error("error decoding build logs response from Claude API", zap.Error(err)) + e.logger.Error("failed to unmarshal response from Claude API, retrying...") err := e.slackAlert.SendAlert( "error occurred while parsing build logs JSON response", map[string]string{ From 9944783095839a26c3f2736236a1048ca01eb96e Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Fri, 26 Jul 2024 09:57:51 +0530 Subject: [PATCH 38/39] fixes --- .../impl/next_js_server_test_executor.go | 10 +++++----- .../impl/open_ai_next_js_code_generation_executor.go | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go index 4922f234..b52c7e57 100644 --- a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go +++ b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go @@ -180,7 +180,7 @@ func (e NextJsServerStartTestExecutor) AnalyseBuildLogs(buildLogs, directoryPlan for retryCount := 1; retryCount <= constants.MAX_JSON_RETRIES; retryCount++ { messages, err := e.CreateMessage(buildLogs, directoryPlan, retryCount) if err != nil{ - fmt.Println("failed to create messages for llm") + e.logger.Error("failed to create messages for llm") return false, nil, err } response, err = claudeClient.ChatCompletion(messages) @@ -193,7 +193,7 @@ func (e NextJsServerStartTestExecutor) AnalyseBuildLogs(buildLogs, directoryPlan fmt.Sprintf("Action required: There's an issue with your LLM API Key. Ensure your API Key for %s is correct. Settings", constants.CLAUDE_3, settingsUrl, "blue", "underline"), ) if err != nil { - fmt.Printf("Error creating activity log: %s\n", err.Error()) + e.logger.Error("failed to create activity log for llm", zap.Error(err)) return false, nil, err } //Update Execution Status and Story Status @@ -225,7 +225,7 @@ func (e NextJsServerStartTestExecutor) AnalyseBuildLogs(buildLogs, directoryPlan "attempt": fmt.Sprintf("%d", int64(retryCount)), }) if err != nil { - fmt.Printf("Error sending slack alert: %s\n", err.Error()) + e.logger.Error("error sending slack alert", zap.Error(err)) return false, nil, err } if retryCount == 5 { @@ -262,12 +262,12 @@ func (e NextJsServerStartTestExecutor) CreateMessage(buildLogs string, directory var content []byte var err error if attempts > 1 { - content, err = os.ReadFile("/go/prompts/nextjs/next_js_build_checker_retry.txt") + content, err = os.ReadFile("app/prompts/nextjs/next_js_build_checker_retry.txt") if err!= nil { return nil, fmt.Errorf("failed to load system prompt: %w", err) } } else { - content, err = os.ReadFile("/go/prompts/nextjs/next_js_build_checker.txt") + content, err = os.ReadFile("app/prompts/nextjs/next_js_build_checker.txt") if err!= nil { return nil, fmt.Errorf("failed to load system prompt: %w", err) } diff --git a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go index 848119f1..ea65be81 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go @@ -698,12 +698,12 @@ func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) GetRetrySystemPrompt(instr var content []byte var err error if attempts > 1 { - content, err = os.ReadFile("/go/prompts/nextjs/ai_frontend_developer_edit_code_retry.txt") + content, err = os.ReadFile("app/prompts/nextjs/ai_frontend_developer_edit_code_retry.txt") if err != nil { panic(fmt.Sprintf("failed to read system prompt: %v", err)) } } else { - content, err = os.ReadFile("/go/prompts/nextjs/ai_frontend_developer_edit_code.txt") + content, err = os.ReadFile("app/prompts/nextjs/ai_frontend_developer_edit_code.txt") if err != nil { panic(fmt.Sprintf("failed to read system prompt: %v", err)) } From cb4f3aef22836d5157e97938b1c9d70e75154917 Mon Sep 17 00:00:00 2001 From: rounak bhatia Date: Fri, 26 Jul 2024 10:05:04 +0530 Subject: [PATCH 39/39] fixes --- .../step_executors/impl/next_js_server_test_executor.go | 4 ++-- .../impl/open_ai_next_js_code_generation_executor.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go index b52c7e57..0a43cf20 100644 --- a/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go +++ b/app/workflow_executors/step_executors/impl/next_js_server_test_executor.go @@ -262,12 +262,12 @@ func (e NextJsServerStartTestExecutor) CreateMessage(buildLogs string, directory var content []byte var err error if attempts > 1 { - content, err = os.ReadFile("app/prompts/nextjs/next_js_build_checker_retry.txt") + content, err = os.ReadFile("/go/prompts/nextjs/next_js_build_checker_retry.txt") if err!= nil { return nil, fmt.Errorf("failed to load system prompt: %w", err) } } else { - content, err = os.ReadFile("app/prompts/nextjs/next_js_build_checker.txt") + content, err = os.ReadFile("/go/prompts/nextjs/next_js_build_checker.txt") if err!= nil { return nil, fmt.Errorf("failed to load system prompt: %w", err) } diff --git a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go index ea65be81..848119f1 100644 --- a/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go +++ b/app/workflow_executors/step_executors/impl/open_ai_next_js_code_generation_executor.go @@ -698,12 +698,12 @@ func (openAiCodeGenerator *OpenAiNextJsCodeGenerator) GetRetrySystemPrompt(instr var content []byte var err error if attempts > 1 { - content, err = os.ReadFile("app/prompts/nextjs/ai_frontend_developer_edit_code_retry.txt") + content, err = os.ReadFile("/go/prompts/nextjs/ai_frontend_developer_edit_code_retry.txt") if err != nil { panic(fmt.Sprintf("failed to read system prompt: %v", err)) } } else { - content, err = os.ReadFile("app/prompts/nextjs/ai_frontend_developer_edit_code.txt") + content, err = os.ReadFile("/go/prompts/nextjs/ai_frontend_developer_edit_code.txt") if err != nil { panic(fmt.Sprintf("failed to read system prompt: %v", err)) }