mirror of
https://github.com/carlospolop/PEASS-ng
synced 2025-03-18 04:04:12 +01:00
208 lines
6.7 KiB
Python
208 lines
6.7 KiB
Python
import argparse
|
|
import os
|
|
import sys
|
|
import string
|
|
import random
|
|
from typing import List
|
|
import openai
|
|
import json
|
|
import subprocess
|
|
import tiktoken
|
|
import requests
|
|
from github import Github
|
|
|
|
#########################
|
|
#### OPENAI FUNCTIONS ###
|
|
#########################
|
|
|
|
def reportTokens(prompt, model="gpt-4"):
|
|
encoding = tiktoken.encoding_for_model(model)
|
|
print("\033[37m" + str(len(encoding.encode(prompt))) + " tokens\033[0m" + " in prompt: " + "\033[92m" + prompt[:50] + "\033[0m" + ("..." if len(prompt) > 50 else ""))
|
|
|
|
def write_file(file_path: str, content: str):
|
|
"""Write content to a file creating the needed directories first"""
|
|
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
|
|
|
with open(file_path, "w") as file:
|
|
file.write(content)
|
|
|
|
def delete_file(file_path: str):
|
|
"""Delete a file if it exists"""
|
|
|
|
if os.path.isfile(file_path):
|
|
os.remove(file_path)
|
|
|
|
openai_available_functions = {
|
|
"write_file": write_file, "delete_file": delete_file
|
|
}
|
|
|
|
openai_functions = [
|
|
{
|
|
"name": "write_file",
|
|
"description": "Write a file giving the path and the content",
|
|
"parameters": {
|
|
"type": "object",
|
|
"properties": {
|
|
"file_path": {
|
|
"type": "string",
|
|
"description": "Path to the file to write",
|
|
},
|
|
"content": {
|
|
"type": "string",
|
|
"description": "Content to write in the file",
|
|
},
|
|
},
|
|
"required": ["file_path", "content"],
|
|
},
|
|
},
|
|
{
|
|
"name": "delete_file",
|
|
"description": "Delete a file",
|
|
"parameters": {
|
|
"type": "object",
|
|
"properties": {
|
|
"file_path": {
|
|
"type": "string",
|
|
"description": "Path to the file to write",
|
|
}
|
|
},
|
|
"required": ["file_path"],
|
|
},
|
|
}
|
|
]
|
|
|
|
|
|
#########################
|
|
#### GIT FUNCTIONS ######
|
|
#########################
|
|
|
|
|
|
def create_pull_request(branch_name, commit_message, github_token):
|
|
github = Github(github_token)
|
|
repo = github.get_repo(os.environ["GITHUB_REPOSITORY"])
|
|
|
|
# Create a new branch
|
|
base_branch = repo.get_branch(repo.default_branch)
|
|
repo.create_git_ref(ref=f"refs/heads/{branch_name}", sha=base_branch.commit.sha)
|
|
|
|
# Commit changes to the new branch
|
|
subprocess.run(["git", "checkout", branch_name])
|
|
subprocess.run(["git", "add", "."])
|
|
subprocess.run(["git", "commit", "-m", commit_message])
|
|
subprocess.run(["git", "push", "origin", branch_name])
|
|
|
|
# Create a pull request
|
|
pr = repo.create_pull(
|
|
title=commit_message,
|
|
body="Generated by OpenAI Github Action",
|
|
head=branch_name,
|
|
base=repo.default_branch
|
|
)
|
|
|
|
return pr.html_url
|
|
|
|
|
|
#########################
|
|
#### FILE PROCESSING ####
|
|
#########################
|
|
|
|
|
|
def process_file(prompt: str, api_key: str, file_path: str, model: str="gpt-4") -> str:
|
|
with open(file_path, "r") as file:
|
|
file_content = file.read()
|
|
|
|
messages = [
|
|
{"role": "system", "content": f"You are a developer and your goal is to generate code. The user will ask you to improve and modify some code. Your response must be a valid JSON with the path of each file to write as keys and the content of the files as values. Several files can be written at the same time."},
|
|
{"role": "user", "content": prompt},
|
|
{"role": "user", "content": f"This is the code from the file '{file_path}':\n\n{file_content}"}
|
|
]
|
|
openai.api_key = api_key
|
|
|
|
reportTokens(f"This is the code from the file '{file_path}':\n\n{file_content}")
|
|
|
|
response = openai.ChatCompletion.create(
|
|
model=model,
|
|
messages=messages,
|
|
temperature=0
|
|
)
|
|
response_message = response["choices"][0]["message"]
|
|
|
|
# Step 2: check if GPT wanted to call a function
|
|
if response_message.get("function_call"):
|
|
|
|
function_name = response_message["function_call"]["name"]
|
|
fuction_to_call = openai_available_functions[function_name]
|
|
function_args = json.loads(response_message["function_call"]["arguments"])
|
|
fuction_to_call(**function_args)
|
|
|
|
|
|
def process_folder(prompt: str, api_key: str, folder_path: str, model: str="gpt-4") -> List[str]:
|
|
responses = []
|
|
for root, _, files in os.walk(folder_path):
|
|
for file in files:
|
|
file_path = os.path.join(root, file)
|
|
response = process_file(prompt, api_key, file_path, model)
|
|
responses.append(response)
|
|
|
|
|
|
#########################
|
|
#### MAIN FUNCTION ######
|
|
#########################
|
|
|
|
|
|
def get_random_string(length):
|
|
# With combination of lower and upper case
|
|
letters = string.ascii_letters
|
|
result_str = ''.join(random.choice(letters) for i in range(length))
|
|
return result_str
|
|
|
|
def main(prompt: str, api_key: str, file_path: str, github_token: str, model: str="gpt-4"):
|
|
if os.path.isfile(file_path):
|
|
process_file(prompt, api_key, file_path, model)
|
|
elif os.path.isdir(file_path):
|
|
process_folder(prompt, api_key, file_path, model)
|
|
else:
|
|
print("Error: Invalid file path.")
|
|
sys.exit(1)
|
|
|
|
try:
|
|
create_pull_request(get_random_string(5), f"Modified {file_path}", github_token)
|
|
except Exception as e:
|
|
print(f"Error: Failed to create pull request. {e}")
|
|
sys.exit(1)
|
|
|
|
if __name__ == "__main__":
|
|
# Setup the argument parser
|
|
parser = argparse.ArgumentParser()
|
|
|
|
# Add arguments for prompt, api_key, file_path and github_token
|
|
parser.add_argument('--prompt', default=None, type=str, help='Input prompt')
|
|
parser.add_argument('--api-key', default=None, type=str, help='Input API key')
|
|
parser.add_argument('--path', default=None, type=str, help='Input file/folder path')
|
|
parser.add_argument('--github-token', default=None, type=str, help='Github token')
|
|
parser.add_argument('--model', default="gpt-4", type=str, help='Model to use')
|
|
|
|
# Parse the arguments
|
|
args = parser.parse_args()
|
|
prompt = os.environ.get("INPUT_PROMPT", args.prompt)
|
|
api_key = os.environ.get("INPUT_API_KEY", args.api_key)
|
|
file_path = os.environ.get("INPUT_FILE_PATH", args.path)
|
|
github_token = os.environ.get("GITHUB_TOKEN", args.github_token)
|
|
model = os.environ.get("INPUT_MODEL", args.model)
|
|
|
|
if not prompt or not api_key or not file_path:
|
|
print("Error: Missing required inputs.")
|
|
sys.exit(1)
|
|
|
|
#if not github_token:
|
|
# print("Error: Missing github token.")
|
|
# sys.exit(1)
|
|
|
|
if os.path.exists(prompt):
|
|
with open(prompt, "r") as file:
|
|
prompt = file.read()
|
|
|
|
if prompt.startswith("http"):
|
|
prompt = requests.get(prompt).text
|
|
|
|
main(prompt, api_key, file_path, github_token, model) |