2024-07-25T11:56:26.492034 UPLOADED FILES: File: config.py import yaml from log_writer import logger def load_config(): """ Loads the configuration from the 'config.yaml' file and sets the global variables accordingly. If the 'GENERATE_MODEL' key in the configuration is set to 'gpt-4', it forces the use of 'gpt-4-turbo-preview' as the value for the 'GENERATE_MODEL' key, since 'gpt-4' no longer supports json modes. Returns: None """ with open("config.yaml", "r") as conf: config_content = yaml.safe_load(conf) for key, value in config_content.items(): if key == "GENERATE_MODEL" and value == "gpt-4": globals()[ key ] = "gpt-4-turbo-preview" # Force using gpt-4-turbo-preview if the user set the GENERATE_MODEL to gpt-4. Because gpt-4 is not longer supports json modes. globals()[key] = value logger(f"config: {key} -> {value}") def edit_config(key, value): """ Edits the config file. Args: key (str): The key to edit. value (str): The value to set. Returns: bool: True """ with open("config.yaml", "r") as conf: config_content = conf.readlines() with open("config.yaml", "w") as conf: for line in config_content: if line.startswith(key): if value == True: write_value = "True" elif value == False: write_value = "False" else: write_value = f'"{value}"' if "#" in line: conf.write(f"{key}: {write_value} # {line.split('#')[1]}\n") else: conf.write(f"{key}: {write_value}\n") else: conf.write(line) return True load_config() File: config.yaml ########## EDIT REQUIRED ########## # GPT SETTINGS # # Get your api key from openai. Remember google/bing is always your best friend. # Model names: gpt-4-turbo-preview, gpt-3.5-turbo, etc. # Recommend -> gpt-4-turbo (Better performance, more expensive), gpt-4-o (Good performance, cheaper) API_KEY: "" # Free API Key with GPT-4 access: https://github.com/CubeGPT/.github/discussions/1 BASE_URL: "https://api.openai.com/v1/chat/completions" GENERATION_MODEL: "gpt-4-turbo-2024-04-09" FIXING_MODEL: "gpt-4-turbo-2024-04-09" # DEVELOPER SETTINGS # VERSION_NUMBER: "0.1.1" # PROMPT SETTINGS # # If you don't know what it is, please don't touch it. Be sure to backup before editing. ## Code Generation ## SYS_GEN: | You're a minecraft bukkit plugin coder AI. Game Version: 1.13.2 (1.13.2-R0.1-SNAPSHOT) Write the code & choose a artifact name for the following files with the infomation which is also provided by the user: codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml codes/%ARTIFACT_NAME%/src/main/resources/config.yml codes/%ARTIFACT_NAME%/pom.xml Response in json format: { \"codes\": [ { \"file\": \"codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java\", \"code\": \"package ...;\\nimport org.bukkit.Bukkit;\\npublic class Main extends JavaPlugin implements CommandExecutor {\\n... (The code you need to write)\" }, { \"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml\", \"code\": \"name: ...\\nversion: ...\\n...\" }, { \"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/config.yml\", \"code\": \"...\" }, { \"file\": \"codes/%ARTIFACT_NAME%/pom.xml\", \"code\": \"...\" } ] } You should never response anything else. Never use Markdown format. Use \n for line feed, and never forget to use \ before ". Never write uncompeleted codes, such as leave a comment that says "// Your codes here" or "// Uncompeleted". USR_GEN: | %DESCRIPTION% SYS_FIX: | You're a minecraft bukkit plugin coder AI. Game Version: 1.13.2 (1.13.2-R0.1-SNAPSHOT) Fix the error in the code provided by user. The error message is also provided by the user. Response in json format: { \"codes\": [ { \"file\": \"codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java\", \"code\": \"package ...;\\nimport org.bukkit.Bukkit;\\npublic class Main extends JavaPlugin implements CommandExecutor {\\n... (The code you need to write)\" }, { \"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml\", \"code\": \"name: ...\\nversion: ...\\n...\" }, { \"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/config.yml\", \"code\": \"...\" }, { \"file\": \"codes/%ARTIFACT_NAME%/pom.xml\", \"code\": \"...\" } ] } You should never response anything else. Never use Markdown format. Use \n for line feed, and never forget to use \ before ". Never write uncompeleted codes, such as leave a comment that says "// Your codes here" or "// Original code" or "// Uncompeleted". USR_FIX: | Main.java: %MAIN_JAVA% plugin.yml: %PLUGIN_YML% config.yml: %CONFIG_YML% pom.xml: %POM_XML% error message: %P_ERROR_MSG% File: console.py import sys import uuid import shutil from log_writer import logger import core import config import build if __name__ == "__main__": main_java = None plugin_yml = None config_yml = None pom_xml = None core.initialize() print("BukkitGPT v3 beta console running") # Get user inputs name = input("Enter the plugin name: ") description = input("Enter the plugin description: ") artifact_name = name.replace(" ", "") package_id = f"org.cubegpt.{uuid.uuid4().hex[:8]}" pkg_id_path = "" for id in package_id.split("."): pkg_id_path += id + "/" logger(f"user_input -> name: {name}") logger(f"user_input -> description: {description}") logger(f"random_generate -> package_id: {package_id}") logger(f"str_path -> pkg_id_path: {pkg_id_path}") print("Generating plugin...") codes = core.askgpt( config.SYS_GEN.replace("%ARTIFACT_NAME%", artifact_name).replace( "%PKG_ID_LST%", pkg_id_path ), config.USR_GEN.replace("%DESCRIPTION", description), config.GENERATION_MODEL, ) logger(f"codes: {codes}") core.response_to_action(codes) print("Code generated. Building now...") result = build.build_plugin(artifact_name) if "BUILD SUCCESS" in result: print( f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" ) elif "Compilation failure": print("Build failed. Passing the error to ChatGPT and let it to fix it?") fix = input("Y/n: ") if fix == "n": print("Exiting...") sys.exit(0) else: print("Passing the error to ChatGPT...") files = [ f"codes/{artifact_name}/src/main/java/{pkg_id_path}Main.java", f"codes/{artifact_name}/src/main/resources/plugin.yml", f"codes/{artifact_name}/src/main/resources/config.yml", f"codes/{artifact_name}/pom.xml", ] ids = ["main_java", "plugin_yml", "config_yml", "pom_xml"] for file in files: with open(file, "r") as f: code = f.read() id = ids[files.index(file)] globals()[id] = code print("Generating...") codes = core.askgpt( config.SYS_FIX.replace("%ARTIFACT_NAME%", artifact_name), config.USR_FIX.replace("%MAIN_JAVA%", main_java) .replace("%PLUGIN_YML%", plugin_yml) .replace("%CONFIG_YML%", config_yml) .replace("%POM_XML%", pom_xml) .replace("%P_ERROR_MSG%", result), config.FIXING_MODEL, ) shutil.rmtree(f"codes/{artifact_name}") core.response_to_action(codes) print("Code generated. Building now...") result = build.build_plugin(artifact_name) if "BUILD SUCCESS" in result: print( f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" ) else: print( "Build failed. Please check the logs && send the log to @BaimoQilin on discord." ) print("Exiting...") sys.exit(0) else: print( "Unknown error. Please check the logs && send the log to @BaimoQilin on discord." ) print("Exiting...") sys.exit(0) else: print( "Error: Please run console.py as the main program instead of importing it from another program." ) File: core.py from openai import OpenAI import chardet import sys import json import locale import os from log_writer import logger import config def initialize(): """ Initializes the software. This function logs the software launch, including the version number and platform. Args: None Returns: None """ locale.setlocale(locale.LC_ALL, "en_US.UTF-8") logger(f"Launch. Software version {config.VERSION_NUMBER}, platform {sys.platform}") if ( "gpt-3.5" in config.GENERATION_MODEL and config.BYPASS_NO_GPT35_FOR_GENERATION_LIMIT is False ): print( "gpt-3.5 writes bugs *all the time* and is not recommended for code generation. Switching to gpt-4." ) config.edit_config( "GENERATION_MODEL", config.GENERATION_MODEL.replace("gpt-3.5", "gpt-4") ) def askgpt( system_prompt: str, user_prompt: str, model_name: str, disable_json_mode: bool = False, image_url: str = None, ): """ Interacts with ChatGPT using the specified prompts. Args: system_prompt (str): The system prompt. user_prompt (str): The user prompt. model_name (str): The model name to use. disable_json_mode (bool): Whether to disable JSON mode. Returns: str: The response from ChatGPT. """ if image_url is not None and config.USE_DIFFERENT_APIKEY_FOR_VISION_MODEL: logger("Using different API key for vision model.") client = OpenAI(api_key=config.VISION_API_KEY, base_url=config.VISION_BASE_URL) else: client = OpenAI(api_key=config.API_KEY, base_url=config.BASE_URL) logger("Initialized the OpenAI client.") # Define the messages for the conversation if image_url is not None: messages = [ {"role": "system", "content": system_prompt}, { "role": "user", "content": [ {"type": "text", "text": user_prompt}, {"type": "image_url", "image_url": {"url": image_url}}, ], }, ] else: messages = [ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt}, ] logger(f"askgpt: system {system_prompt}") logger(f"askgpt: user {user_prompt}") # Create a chat completion if disable_json_mode: response = client.chat.completions.create(model=model_name, messages=messages) else: response = client.chat.completions.create( model=model_name, response_format={"type": "json_object"}, messages=messages ) logger(f"askgpt: response {response}") # Extract the assistant's reply assistant_reply = response.choices[0].message.content logger(f"askgpt: extracted reply {assistant_reply}") return assistant_reply def response_to_action(msg): """ Converts a response from ChatGPT to an action. Args: msg (str): The response from ChatGPT. Returns: str: The action to take. """ text = json.loads(msg) codes = text["codes"] for section in codes: file = section["file"] code = section["code"] paths = file.split("/") # Join the list elements to form a path path = os.path.join(*paths) # Get the directory path and the file name dir_path, file_name = os.path.split(path) # Create directories, if they don't exist try: os.makedirs(dir_path, exist_ok=True) except FileNotFoundError: pass # Create the file with open(path, "w") as f: f.write(code) # Write an empty string to the file def mixed_decode(text: str): """ Decode a mixed text containing both normal text and a byte sequence. Args: text (str): The mixed text to be decoded. Returns: str: The decoded text, where the byte sequence has been converted to its corresponding characters. """ # Split the normal text and the byte sequence # Assuming the byte sequence is everything after the last colon and space ": " try: normal_text, byte_text = text.rsplit(": ", 1) except (TypeError, ValueError): # The text only contains normal text return text # Convert the byte sequence to actual bytes byte_sequence = byte_text.encode( "latin1" ) # latin1 encoding maps byte values directly to unicode code points # Detect the encoding of the byte sequence detected_encoding = chardet.detect(byte_sequence) encoding = detected_encoding["encoding"] # Decode the byte sequence decoded_text = byte_sequence.decode(encoding) # Combine the normal text with the decoded byte sequence final_text = normal_text + ": " + decoded_text return final_text if __name__ == "__main__": print("This script is not meant to be run directly. Please run console.py instead.") File: log_writer.py import os from datetime import datetime first_call_time = None def get_log_filename(): global first_call_time if first_call_time is None: first_call_time = datetime.now() log_filename = first_call_time.strftime("logs/%b-%d-%H-%M-%S-%Y") return log_filename def logger(text: str): log_filename = get_log_filename() timestamp_prefix = datetime.now().strftime("[%H:%M:%S]") log_line = f"{timestamp_prefix} {text}\n" os.makedirs(os.path.dirname(log_filename), exist_ok=True) with open(log_filename + ".log", "a", encoding="utf-8") as log_file: log_file.write(log_line) File: README.md

Join our discord
> [!NOTE] > Developers and translators are welcome to join the CubeGPT Team! ## Introduction > A simple template for CubeGPT projects. CubeAgents is a template for CubeGPT's projects like [BuilderGPT](https://github.com/CubeGPT/BuilderGPT). It provides a simple and clean interface for users to interact with the program. # Showcase ... ## Partner [![](https://www.bisecthosting.com/partners/custom-banners/c37f58c7-c49b-414d-b53c-1a6e1b1cff71.webp)](https://bisecthosting.com/cubegpt) ## Features - [x] Feature 1 - [x] Feature 2 - [x] Feature 3 - [ ] Feature 4 ### Other projects of CubeGPT Team - [x] Bukkit plugin generator. {*.jar} ([BukkitGPT](https://github.com/CubeGPT/BukkitGPT)) - [x] Structure generator. {*.schem} ([BuilderGPT](https://github.com/CubeGPT/BuilderGPT)) - [ ] Serverpack generator. {*.zip} (ServerpackGPT or ServerGPT, or..?) - [ ] Have ideas or want to join our team? Send [us](mailto:admin@baimoqilin.top) an email! ## How it works ... ## Requirements ### Plan A. Windows/Linux (executable edition) Nothing. Just download the executable file and run it. ### Plan B. Python (Any operating systems; Recommend if possible) You can use BukkitGPT on any device with [Python 3+](https://www.python.org/). And you need to install the depencies with this command: ``` pip install -r requirements.txt ``` ## Quick Start *(Make sure you have the [Python](https://www.python.org) environment installed on your computer)* ... ## Contributing If you like the project, you can give the project a star, or [submit an issue](https://github.com/CubeGPT/CubeAgents/issues) or [pull request](https://github.com/CubeGPT/CubeAgents/pulls) to help make it better. ## License ``` Copyright [2024] [CubeGPT Team] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ``` File: requirements.txt openai>=1.13.3 pyyaml cx_Freeze ttkbootstrap playwright chardet File: ui.py from cube_qgui.__init__ import CreateQGUI from cube_qgui.banner_tools import * from cube_qgui.notebook_tools import * from playwright.sync_api import Playwright, sync_playwright import os import shutil import uuid from log_writer import logger import config import core import build # ---------- Functions ----------# def open_config(args: dict): """ Opens the config file. Args: args (dict): A dictionary containing the necessary arguments. Returns: bool: Always True. """ os.system("notepad config.yaml") return True def save_apply_config(args: dict): """ Saves and applies the configuration. Args: args (dict): A dictionary containing the necessary arguments. Returns: bool: Always True. """ keys = ["API_KEY", "BASE_URL"] for key in keys: value = args[key].get() if key == "ADVANCED_MODE": value = True if value == 1 else False else: pass config.edit_config(key, value) config.load_config() args["DevTool_CONFIG_API_KEY_DISPLAY"].set(f"CONFIG.API_KEY = {config.API_KEY}") args["DevTools_CONFIG_BASE_URL_DISPLAY"].set(f"CONFIG.BASE_URL = {config.BASE_URL}") return True def load_config(args: dict): """ Loads the configuration. Args: args (dict): A dictionary containing the necessary arguments. Returns: bool: Always True. """ config.load_config() args["API_KEY"].set(config.API_KEY) args["BASE_URL"].set(config.BASE_URL) return True def print_args(args: dict): """ Prints the arguments. Args: args (dict): A dictionary containing the arguments. Returns: bool: Always True. """ for arg, v_fun in args.items(): print(f"Name: {arg}, Value: {v_fun.get()}") return True def raise_error(args: dict): """ Raises an error. Args: args (dict): A dictionary containing the arguments. """ raise Exception("This is a test error.") # ---------- Generate Function ----------# def generate(args: dict): """ Generates the plugin. Args: args (dict): A dictionary containing the arguments. Returns: bool: Always True. """ global error_msg, pkg_id_path # Get user inputs name = args["PluginName"].get() description = args["PluginDescription"].get() artifact_name = name.replace(" ", "") package_id = f"org.cubegpt.{uuid.uuid4().hex[:8]}" pkg_id_path = "" for id in package_id.split("."): pkg_id_path += id + "/" logger(f"user_input -> name: {name}") logger(f"user_input -> description: {description}") logger(f"random_generate -> package_id: {package_id}") logger(f"str_path -> pkg_id_path: {pkg_id_path}") print("Generating plugin...") codes = core.askgpt( config.SYS_GEN.replace("%ARTIFACT_NAME%", artifact_name).replace( "%PKG_ID_LST%", pkg_id_path ), config.USR_GEN.replace("%DESCRIPTION", description), config.GENERATION_MODEL, ) logger(f"codes: {codes}") core.response_to_action(codes) print("Code generated. Building now...") result = build.build_plugin(artifact_name) if "BUILD SUCCESS" in result: print( f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" ) elif "Compilation failure": error_msg = result print( "Build failed. To pass the error to ChatGPT && let it fix, jump to the Fixing page and click the Fix button." ) else: print( "Unknown error. Please check the logs && send the log to @BaimoQilin on discord." ) return True def fix(args: dict): """ Fixes the error. Args: args (dict): A dictionary containing the arguments. Returns: bool: Always True. """ artifact_name = args["PluginName"].get() print("Passing the error to ChatGPT...") files = [ f"codes/{artifact_name}/src/main/java/{pkg_id_path}Main.java", f"codes/{artifact_name}/src/main/resources/plugin.yml", f"codes/{artifact_name}/src/main/resources/config.yml", f"codes/{artifact_name}/pom.xml", ] ids = ["main_java", "plugin_yml", "config_yml", "pom_xml"] main_java = None plugin_yml = None config_yml = None pom_xml = None for file in files: with open(file, "r") as f: code = f.read() id = ids[files.index(file)] globals()[id] = code print("Generating...") codes = core.askgpt( config.SYS_FIX.replace("%ARTIFACT_NAME%", str(artifact_name)), config.USR_FIX.replace("%MAIN_JAVA%", str(main_java)) .replace("%PLUGIN_YML%", str(plugin_yml)) .replace("%CONFIG_YML%", str(config_yml)) .replace("%POM_XML%", str(pom_xml)) .replave("%PKG_ID_LST%", pkg_id_path) .replace("%P_ERROR_MSG%", str(error_msg)), config.FIXING_MODEL, ) shutil.rmtree(f"codes/{artifact_name}") core.response_to_action(codes) print("Code generated. Building now...") result = build.build_plugin(artifact_name) if "BUILD SUCCESS" in result: print( f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" ) else: print( "Build failed again. Please check the logs && send the log to @BaimoQilin on discord." ) return True # ---------- Main Program ----------# root = CreateQGUI(title="BukkitGPT-v3", tab_names=["Generate", "Settings", "DevTools"]) error_msg = None logger("Starting program.") # Initialize Core core.initialize() print("BukkitGPT v3 beta console running") # Banner root.add_banner_tool(GitHub("https://github.com/CubeGPT/BukkitGPT-v3")) # Generate Page root.add_notebook_tool( InputBox(name="PluginName", default="ExamplePlugin", label_info="Plugin Name") ) root.add_notebook_tool( InputBox( name="PluginDescription", default="Send msg 'hello' to every joined player.", label_info="Plugin Description", ) ) root.add_notebook_tool( RunButton( bind_func=generate, name="Generate", text="Generate Plugin", checked_text="Generating...", tab_index=0, ) ) # Fixing Page # # root.add_notebook_tool(Label(name="Fixing_DESCRIPTION", text="This is a fixing page. If the build fails, click the Fix button to fix the error in the LATEST build.", tab_index=1)) # root.add_notebook_tool(RunButton(bind_func=fix, name="Fix", text="Fix", checked_text="Fixing...", tab_index=1)) # Settings Page root.add_notebook_tool( InputBox(name="API_KEY", default=config.API_KEY, label_info="API Key", tab_index=1) ) root.add_notebook_tool( InputBox( name="BASE_URL", default=config.BASE_URL, label_info="BASE URL", tab_index=1 ) ) config_buttons = HorizontalToolsCombine( [ BaseButton( bind_func=save_apply_config, name="Save & Apply Config", text="Save & Apply", tab_index=1, ), BaseButton( bind_func=load_config, name="Load Config", text="Load Config", tab_index=1 ), BaseButton( bind_func=open_config, name="Open Config", text="Open Full Config", tab_index=1, ), ] ) root.add_notebook_tool(config_buttons) # DevTools Page root.add_notebook_tool( Label( name="DevTool_DESCRIPTION", text="This is a testing page for developers. Ignore it if you are a normal user.", tab_index=2, ) ) root.add_notebook_tool( Label( name="DevTool_CONFIG_API_KEY_DISPLAY", text=f"CONFIG.API_KEY = {config.API_KEY}", tab_index=2, ) ) root.add_notebook_tool( Label( name="DevTools_CONFIG_BASE_URL_DISPLAY", text=f"CONFIG.BASE_URL = {config.BASE_URL}", tab_index=2, ) ) root.add_notebook_tool( RunButton(bind_func=print_args, name="Print Args", text="Print Args", tab_index=2) ) root.add_notebook_tool( RunButton( bind_func=raise_error, name="Raise Error", text="Raise Error", tab_index=2 ) ) # Sidebar root.set_navigation_about( author="CubeGPT Team", version=config.VERSION_NUMBER, github_url="https://github.com/CubeGPT/BukkitGPT-v3", ) # Run root.run() PROMPT: 添加生成DataPack的选项,使得用户可以选择生成Bukkit插件或者DataPack。 在`ui.py`中可以在Generate Page里添加这行代码 `root.add_notebook_tool(RadioObviousToolButton(options=["BukkitPlugin", "Datapack(Experimental)"], name="GenerationType", title="Type", default="BukkitPlugin",tab_index=0))` 你还需要自行完成DataPack的生成逻辑。你可能需要更改的文件有`ui.py`, `core.py`, `config.yaml`, `console.py`。你还可能需要创建一些新的文件或文件夹,也有可能不需要。祝你好运。 2024-07-25T11:56:26.944792 CONSOLE OUTPUT: Error while improving the project: "Could not resolve authentication method. Expected either api_key or auth_token to be set. Or for one of the `X-Api-Key` or `Authorization` headers to be explicitly omitted" Could you please upload the debug_log_file.txt in D:\zhousl\BukkitGPT\BukkitGPT-v3\.gpteng\memory/logs folder to github? FULL STACK TRACE: Traceback (most recent call last): File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 379, in handle_improve_mode files_dict = agent.improve(files_dict, prompt) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\applications\cli\cli_agent.py", line 208, in improve files_dict = self.improve_fn( ^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 311, in improve_fn return _improve_loop(ai, files_dict, memory, messages) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 317, in _improve_loop messages = ai.next(messages, step_name=curr_fn()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\ai.py", line 243, in next response = self.backoff_inference(messages) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\backoff\_sync.py", line 105, in retry ret = target(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\ai.py", line 287, in backoff_inference return self.llm.invoke(messages) # type: ignore ^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 270, in invoke self.generate_prompt( File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 703, in generate_prompt return self.generate(prompt_messages, stop=stop, callbacks=callbacks, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 560, in generate raise e File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 550, in generate self._generate_with_cache( File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 775, in _generate_with_cache result = self._generate( ^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_anthropic\chat_models.py", line 755, in _generate return generate_from_stream(stream_iter) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 102, in generate_from_stream generation = next(stream, None) ^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_anthropic\chat_models.py", line 676, in _stream stream = self._client.messages.create(**payload) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_utils\_utils.py", line 277, in wrapper return func(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\resources\messages.py", line 902, in create return self._post( ^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 1266, in post return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 942, in request return self._request( ^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 968, in _request request = self._build_request(options) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 461, in _build_request headers = self._build_headers(options) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 416, in _build_headers self._validate_headers(headers_dict, custom_headers) File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_client.py", line 192, in _validate_headers raise TypeError( TypeError: "Could not resolve authentication method. Expected either api_key or auth_token to be set. Or for one of the `X-Api-Key` or `Authorization` headers to be explicitly omitted" 2024-07-25T11:59:37.704389 UPLOADED FILES: File: config.py import yaml from log_writer import logger def load_config(): """ Loads the configuration from the 'config.yaml' file and sets the global variables accordingly. If the 'GENERATE_MODEL' key in the configuration is set to 'gpt-4', it forces the use of 'gpt-4-turbo-preview' as the value for the 'GENERATE_MODEL' key, since 'gpt-4' no longer supports json modes. Returns: None """ with open("config.yaml", "r") as conf: config_content = yaml.safe_load(conf) for key, value in config_content.items(): if key == "GENERATE_MODEL" and value == "gpt-4": globals()[ key ] = "gpt-4-turbo-preview" # Force using gpt-4-turbo-preview if the user set the GENERATE_MODEL to gpt-4. Because gpt-4 is not longer supports json modes. globals()[key] = value logger(f"config: {key} -> {value}") def edit_config(key, value): """ Edits the config file. Args: key (str): The key to edit. value (str): The value to set. Returns: bool: True """ with open("config.yaml", "r") as conf: config_content = conf.readlines() with open("config.yaml", "w") as conf: for line in config_content: if line.startswith(key): if value == True: write_value = "True" elif value == False: write_value = "False" else: write_value = f'"{value}"' if "#" in line: conf.write(f"{key}: {write_value} # {line.split('#')[1]}\n") else: conf.write(f"{key}: {write_value}\n") else: conf.write(line) return True load_config() File: config.yaml ########## EDIT REQUIRED ########## # GPT SETTINGS # # Get your api key from openai. Remember google/bing is always your best friend. # Model names: gpt-4-turbo-preview, gpt-3.5-turbo, etc. # Recommend -> gpt-4-turbo (Better performance, more expensive), gpt-4-o (Good performance, cheaper) API_KEY: "" # Free API Key with GPT-4 access: https://github.com/CubeGPT/.github/discussions/1 BASE_URL: "https://api.openai.com/v1/chat/completions" GENERATION_MODEL: "gpt-4-turbo-2024-04-09" FIXING_MODEL: "gpt-4-turbo-2024-04-09" # DEVELOPER SETTINGS # VERSION_NUMBER: "0.1.1" # PROMPT SETTINGS # # If you don't know what it is, please don't touch it. Be sure to backup before editing. ## Code Generation ## SYS_GEN: | You're a minecraft bukkit plugin coder AI. Game Version: 1.13.2 (1.13.2-R0.1-SNAPSHOT) Write the code & choose a artifact name for the following files with the infomation which is also provided by the user: codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml codes/%ARTIFACT_NAME%/src/main/resources/config.yml codes/%ARTIFACT_NAME%/pom.xml Response in json format: { \"codes\": [ { \"file\": \"codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java\", \"code\": \"package ...;\\nimport org.bukkit.Bukkit;\\npublic class Main extends JavaPlugin implements CommandExecutor {\\n... (The code you need to write)\" }, { \"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml\", \"code\": \"name: ...\\nversion: ...\\n...\" }, { \"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/config.yml\", \"code\": \"...\" }, { \"file\": \"codes/%ARTIFACT_NAME%/pom.xml\", \"code\": \"...\" } ] } You should never response anything else. Never use Markdown format. Use \n for line feed, and never forget to use \ before ". Never write uncompeleted codes, such as leave a comment that says "// Your codes here" or "// Uncompeleted". USR_GEN: | %DESCRIPTION% SYS_FIX: | You're a minecraft bukkit plugin coder AI. Game Version: 1.13.2 (1.13.2-R0.1-SNAPSHOT) Fix the error in the code provided by user. The error message is also provided by the user. Response in json format: { \"codes\": [ { \"file\": \"codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java\", \"code\": \"package ...;\\nimport org.bukkit.Bukkit;\\npublic class Main extends JavaPlugin implements CommandExecutor {\\n... (The code you need to write)\" }, { \"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml\", \"code\": \"name: ...\\nversion: ...\\n...\" }, { \"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/config.yml\", \"code\": \"...\" }, { \"file\": \"codes/%ARTIFACT_NAME%/pom.xml\", \"code\": \"...\" } ] } You should never response anything else. Never use Markdown format. Use \n for line feed, and never forget to use \ before ". Never write uncompeleted codes, such as leave a comment that says "// Your codes here" or "// Original code" or "// Uncompeleted". USR_FIX: | Main.java: %MAIN_JAVA% plugin.yml: %PLUGIN_YML% config.yml: %CONFIG_YML% pom.xml: %POM_XML% error message: %P_ERROR_MSG% File: console.py import sys import uuid import shutil from log_writer import logger import core import config import build if __name__ == "__main__": main_java = None plugin_yml = None config_yml = None pom_xml = None core.initialize() print("BukkitGPT v3 beta console running") # Get user inputs name = input("Enter the plugin name: ") description = input("Enter the plugin description: ") artifact_name = name.replace(" ", "") package_id = f"org.cubegpt.{uuid.uuid4().hex[:8]}" pkg_id_path = "" for id in package_id.split("."): pkg_id_path += id + "/" logger(f"user_input -> name: {name}") logger(f"user_input -> description: {description}") logger(f"random_generate -> package_id: {package_id}") logger(f"str_path -> pkg_id_path: {pkg_id_path}") print("Generating plugin...") codes = core.askgpt( config.SYS_GEN.replace("%ARTIFACT_NAME%", artifact_name).replace( "%PKG_ID_LST%", pkg_id_path ), config.USR_GEN.replace("%DESCRIPTION", description), config.GENERATION_MODEL, ) logger(f"codes: {codes}") core.response_to_action(codes) print("Code generated. Building now...") result = build.build_plugin(artifact_name) if "BUILD SUCCESS" in result: print( f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" ) elif "Compilation failure": print("Build failed. Passing the error to ChatGPT and let it to fix it?") fix = input("Y/n: ") if fix == "n": print("Exiting...") sys.exit(0) else: print("Passing the error to ChatGPT...") files = [ f"codes/{artifact_name}/src/main/java/{pkg_id_path}Main.java", f"codes/{artifact_name}/src/main/resources/plugin.yml", f"codes/{artifact_name}/src/main/resources/config.yml", f"codes/{artifact_name}/pom.xml", ] ids = ["main_java", "plugin_yml", "config_yml", "pom_xml"] for file in files: with open(file, "r") as f: code = f.read() id = ids[files.index(file)] globals()[id] = code print("Generating...") codes = core.askgpt( config.SYS_FIX.replace("%ARTIFACT_NAME%", artifact_name), config.USR_FIX.replace("%MAIN_JAVA%", main_java) .replace("%PLUGIN_YML%", plugin_yml) .replace("%CONFIG_YML%", config_yml) .replace("%POM_XML%", pom_xml) .replace("%P_ERROR_MSG%", result), config.FIXING_MODEL, ) shutil.rmtree(f"codes/{artifact_name}") core.response_to_action(codes) print("Code generated. Building now...") result = build.build_plugin(artifact_name) if "BUILD SUCCESS" in result: print( f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" ) else: print( "Build failed. Please check the logs && send the log to @BaimoQilin on discord." ) print("Exiting...") sys.exit(0) else: print( "Unknown error. Please check the logs && send the log to @BaimoQilin on discord." ) print("Exiting...") sys.exit(0) else: print( "Error: Please run console.py as the main program instead of importing it from another program." ) File: core.py from openai import OpenAI import chardet import sys import json import locale import os from log_writer import logger import config def initialize(): """ Initializes the software. This function logs the software launch, including the version number and platform. Args: None Returns: None """ locale.setlocale(locale.LC_ALL, "en_US.UTF-8") logger(f"Launch. Software version {config.VERSION_NUMBER}, platform {sys.platform}") if ( "gpt-3.5" in config.GENERATION_MODEL and config.BYPASS_NO_GPT35_FOR_GENERATION_LIMIT is False ): print( "gpt-3.5 writes bugs *all the time* and is not recommended for code generation. Switching to gpt-4." ) config.edit_config( "GENERATION_MODEL", config.GENERATION_MODEL.replace("gpt-3.5", "gpt-4") ) def askgpt( system_prompt: str, user_prompt: str, model_name: str, disable_json_mode: bool = False, image_url: str = None, ): """ Interacts with ChatGPT using the specified prompts. Args: system_prompt (str): The system prompt. user_prompt (str): The user prompt. model_name (str): The model name to use. disable_json_mode (bool): Whether to disable JSON mode. Returns: str: The response from ChatGPT. """ if image_url is not None and config.USE_DIFFERENT_APIKEY_FOR_VISION_MODEL: logger("Using different API key for vision model.") client = OpenAI(api_key=config.VISION_API_KEY, base_url=config.VISION_BASE_URL) else: client = OpenAI(api_key=config.API_KEY, base_url=config.BASE_URL) logger("Initialized the OpenAI client.") # Define the messages for the conversation if image_url is not None: messages = [ {"role": "system", "content": system_prompt}, { "role": "user", "content": [ {"type": "text", "text": user_prompt}, {"type": "image_url", "image_url": {"url": image_url}}, ], }, ] else: messages = [ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt}, ] logger(f"askgpt: system {system_prompt}") logger(f"askgpt: user {user_prompt}") # Create a chat completion if disable_json_mode: response = client.chat.completions.create(model=model_name, messages=messages) else: response = client.chat.completions.create( model=model_name, response_format={"type": "json_object"}, messages=messages ) logger(f"askgpt: response {response}") # Extract the assistant's reply assistant_reply = response.choices[0].message.content logger(f"askgpt: extracted reply {assistant_reply}") return assistant_reply def response_to_action(msg): """ Converts a response from ChatGPT to an action. Args: msg (str): The response from ChatGPT. Returns: str: The action to take. """ text = json.loads(msg) codes = text["codes"] for section in codes: file = section["file"] code = section["code"] paths = file.split("/") # Join the list elements to form a path path = os.path.join(*paths) # Get the directory path and the file name dir_path, file_name = os.path.split(path) # Create directories, if they don't exist try: os.makedirs(dir_path, exist_ok=True) except FileNotFoundError: pass # Create the file with open(path, "w") as f: f.write(code) # Write an empty string to the file def mixed_decode(text: str): """ Decode a mixed text containing both normal text and a byte sequence. Args: text (str): The mixed text to be decoded. Returns: str: The decoded text, where the byte sequence has been converted to its corresponding characters. """ # Split the normal text and the byte sequence # Assuming the byte sequence is everything after the last colon and space ": " try: normal_text, byte_text = text.rsplit(": ", 1) except (TypeError, ValueError): # The text only contains normal text return text # Convert the byte sequence to actual bytes byte_sequence = byte_text.encode( "latin1" ) # latin1 encoding maps byte values directly to unicode code points # Detect the encoding of the byte sequence detected_encoding = chardet.detect(byte_sequence) encoding = detected_encoding["encoding"] # Decode the byte sequence decoded_text = byte_sequence.decode(encoding) # Combine the normal text with the decoded byte sequence final_text = normal_text + ": " + decoded_text return final_text if __name__ == "__main__": print("This script is not meant to be run directly. Please run console.py instead.") File: log_writer.py import os from datetime import datetime first_call_time = None def get_log_filename(): global first_call_time if first_call_time is None: first_call_time = datetime.now() log_filename = first_call_time.strftime("logs/%b-%d-%H-%M-%S-%Y") return log_filename def logger(text: str): log_filename = get_log_filename() timestamp_prefix = datetime.now().strftime("[%H:%M:%S]") log_line = f"{timestamp_prefix} {text}\n" os.makedirs(os.path.dirname(log_filename), exist_ok=True) with open(log_filename + ".log", "a", encoding="utf-8") as log_file: log_file.write(log_line) File: requirements.txt openai>=1.13.3 pyyaml cx_Freeze ttkbootstrap playwright chardet File: ui.py from cube_qgui.__init__ import CreateQGUI from cube_qgui.banner_tools import * from cube_qgui.notebook_tools import * from playwright.sync_api import Playwright, sync_playwright import os import shutil import uuid from log_writer import logger import config import core import build # ---------- Functions ----------# def open_config(args: dict): """ Opens the config file. Args: args (dict): A dictionary containing the necessary arguments. Returns: bool: Always True. """ os.system("notepad config.yaml") return True def save_apply_config(args: dict): """ Saves and applies the configuration. Args: args (dict): A dictionary containing the necessary arguments. Returns: bool: Always True. """ keys = ["API_KEY", "BASE_URL"] for key in keys: value = args[key].get() if key == "ADVANCED_MODE": value = True if value == 1 else False else: pass config.edit_config(key, value) config.load_config() args["DevTool_CONFIG_API_KEY_DISPLAY"].set(f"CONFIG.API_KEY = {config.API_KEY}") args["DevTools_CONFIG_BASE_URL_DISPLAY"].set(f"CONFIG.BASE_URL = {config.BASE_URL}") return True def load_config(args: dict): """ Loads the configuration. Args: args (dict): A dictionary containing the necessary arguments. Returns: bool: Always True. """ config.load_config() args["API_KEY"].set(config.API_KEY) args["BASE_URL"].set(config.BASE_URL) return True def print_args(args: dict): """ Prints the arguments. Args: args (dict): A dictionary containing the arguments. Returns: bool: Always True. """ for arg, v_fun in args.items(): print(f"Name: {arg}, Value: {v_fun.get()}") return True def raise_error(args: dict): """ Raises an error. Args: args (dict): A dictionary containing the arguments. """ raise Exception("This is a test error.") # ---------- Generate Function ----------# def generate(args: dict): """ Generates the plugin. Args: args (dict): A dictionary containing the arguments. Returns: bool: Always True. """ global error_msg, pkg_id_path # Get user inputs name = args["PluginName"].get() description = args["PluginDescription"].get() artifact_name = name.replace(" ", "") package_id = f"org.cubegpt.{uuid.uuid4().hex[:8]}" pkg_id_path = "" for id in package_id.split("."): pkg_id_path += id + "/" logger(f"user_input -> name: {name}") logger(f"user_input -> description: {description}") logger(f"random_generate -> package_id: {package_id}") logger(f"str_path -> pkg_id_path: {pkg_id_path}") print("Generating plugin...") codes = core.askgpt( config.SYS_GEN.replace("%ARTIFACT_NAME%", artifact_name).replace( "%PKG_ID_LST%", pkg_id_path ), config.USR_GEN.replace("%DESCRIPTION", description), config.GENERATION_MODEL, ) logger(f"codes: {codes}") core.response_to_action(codes) print("Code generated. Building now...") result = build.build_plugin(artifact_name) if "BUILD SUCCESS" in result: print( f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" ) elif "Compilation failure": error_msg = result print( "Build failed. To pass the error to ChatGPT && let it fix, jump to the Fixing page and click the Fix button." ) else: print( "Unknown error. Please check the logs && send the log to @BaimoQilin on discord." ) return True def fix(args: dict): """ Fixes the error. Args: args (dict): A dictionary containing the arguments. Returns: bool: Always True. """ artifact_name = args["PluginName"].get() print("Passing the error to ChatGPT...") files = [ f"codes/{artifact_name}/src/main/java/{pkg_id_path}Main.java", f"codes/{artifact_name}/src/main/resources/plugin.yml", f"codes/{artifact_name}/src/main/resources/config.yml", f"codes/{artifact_name}/pom.xml", ] ids = ["main_java", "plugin_yml", "config_yml", "pom_xml"] main_java = None plugin_yml = None config_yml = None pom_xml = None for file in files: with open(file, "r") as f: code = f.read() id = ids[files.index(file)] globals()[id] = code print("Generating...") codes = core.askgpt( config.SYS_FIX.replace("%ARTIFACT_NAME%", str(artifact_name)), config.USR_FIX.replace("%MAIN_JAVA%", str(main_java)) .replace("%PLUGIN_YML%", str(plugin_yml)) .replace("%CONFIG_YML%", str(config_yml)) .replace("%POM_XML%", str(pom_xml)) .replave("%PKG_ID_LST%", pkg_id_path) .replace("%P_ERROR_MSG%", str(error_msg)), config.FIXING_MODEL, ) shutil.rmtree(f"codes/{artifact_name}") core.response_to_action(codes) print("Code generated. Building now...") result = build.build_plugin(artifact_name) if "BUILD SUCCESS" in result: print( f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" ) else: print( "Build failed again. Please check the logs && send the log to @BaimoQilin on discord." ) return True # ---------- Main Program ----------# root = CreateQGUI(title="BukkitGPT-v3", tab_names=["Generate", "Settings", "DevTools"]) error_msg = None logger("Starting program.") # Initialize Core core.initialize() print("BukkitGPT v3 beta console running") # Banner root.add_banner_tool(GitHub("https://github.com/CubeGPT/BukkitGPT-v3")) # Generate Page root.add_notebook_tool( InputBox(name="PluginName", default="ExamplePlugin", label_info="Plugin Name") ) root.add_notebook_tool( InputBox( name="PluginDescription", default="Send msg 'hello' to every joined player.", label_info="Plugin Description", ) ) root.add_notebook_tool( RunButton( bind_func=generate, name="Generate", text="Generate Plugin", checked_text="Generating...", tab_index=0, ) ) # Fixing Page # # root.add_notebook_tool(Label(name="Fixing_DESCRIPTION", text="This is a fixing page. If the build fails, click the Fix button to fix the error in the LATEST build.", tab_index=1)) # root.add_notebook_tool(RunButton(bind_func=fix, name="Fix", text="Fix", checked_text="Fixing...", tab_index=1)) # Settings Page root.add_notebook_tool( InputBox(name="API_KEY", default=config.API_KEY, label_info="API Key", tab_index=1) ) root.add_notebook_tool( InputBox( name="BASE_URL", default=config.BASE_URL, label_info="BASE URL", tab_index=1 ) ) config_buttons = HorizontalToolsCombine( [ BaseButton( bind_func=save_apply_config, name="Save & Apply Config", text="Save & Apply", tab_index=1, ), BaseButton( bind_func=load_config, name="Load Config", text="Load Config", tab_index=1 ), BaseButton( bind_func=open_config, name="Open Config", text="Open Full Config", tab_index=1, ), ] ) root.add_notebook_tool(config_buttons) # DevTools Page root.add_notebook_tool( Label( name="DevTool_DESCRIPTION", text="This is a testing page for developers. Ignore it if you are a normal user.", tab_index=2, ) ) root.add_notebook_tool( Label( name="DevTool_CONFIG_API_KEY_DISPLAY", text=f"CONFIG.API_KEY = {config.API_KEY}", tab_index=2, ) ) root.add_notebook_tool( Label( name="DevTools_CONFIG_BASE_URL_DISPLAY", text=f"CONFIG.BASE_URL = {config.BASE_URL}", tab_index=2, ) ) root.add_notebook_tool( RunButton(bind_func=print_args, name="Print Args", text="Print Args", tab_index=2) ) root.add_notebook_tool( RunButton( bind_func=raise_error, name="Raise Error", text="Raise Error", tab_index=2 ) ) # Sidebar root.set_navigation_about( author="CubeGPT Team", version=config.VERSION_NUMBER, github_url="https://github.com/CubeGPT/BukkitGPT-v3", ) # Run root.run() File: cube_qgui\\__main__.py # 这是对于cube_qgui的一个简单示例,展示了如何使用QGUI来创建一个简单的GUI应用。 import time # 导入CreateQGUI模块 from qgui import CreateQGUI, MessageBox # 【可选】导入自定义导航栏按钮模块、GitHub导航栏模块 from qgui.banner_tools import BaseBarTool, GitHub, AIStudio # 【可选】一次性导入所有的主界面工具模块 from qgui.notebook_tools import * # 【可选】导入占位符 from qgui.manager import QStyle, HORIZONTAL def click(args: dict): MessageBox.info("要开始啦~") # 证明一下自己被点到了 print("你点到我啦~") # 通过ChooseFileTextButton(name="文件选择")中预先设置的name参数,使用get方法即可获取对应的输入框信息 print("你选择的文件是:", args["文件选择"].get()) # 当然也可以通过name参数来设置对应的内容,使用set方法即可完成设置 print("保存位置修改为“快看,我被修改啦”", args["保存位置"].set("快看,我被修改啦")) # 即使没有指定name,我们照样可以拿到所有的小工具情况 for arg, v_fun in args.items(): print("自定义组件Name:", arg, "状态:", v_fun.get()) # 若我们绑定了进度条,那么每当需要设置进度的时候,通过args["进度条"].set(当前进度)来进行设置吧,倒吸进度条也是可以哒 for i in range(1, 101): time.sleep(0.01) args["进度条"].set(i) # 增加打印间隔 if i % 20 == 0: print("当前进度", i) MessageBox.warning(text="给个评价吧亲~") # 也可以在终端中打印组件,顺便绑定用户调研函数 q_gui.print_tool( RadioButton( ["满意", "一般", "你好垃圾啊"], title="体验如何?", name="feedback", bind_func=feedback ) ) # 甚至打印图片 from qgui import RESOURCES_PATH q_gui.print_image(os.path.join(RESOURCES_PATH, "demo/panda.jpg")) def feedback(args: dict): # 用户调研Callback info = args["feedback"].get() if info == "满意": print("么么哒") elif info == "一般": print("啊啊啊,告诉GT哪里没做好吧") else: print("以后漂流瓶见吧,拜拜!") def bind_dir(args: dict): # 获取所选择文件所在的文件夹路径 path = os.path.dirname(args["文件选择"].get()) # 可以通过name参数来设置对应的内容,使用set方法即可完成设置 args["保存位置"].set(path) print("保存位置已自动修改为:", path) def go_to_first_page(args: dict): args["QGUI-BaseNoteBook"].set(0) # 创建主界面 q_gui = CreateQGUI( title="一个新应用", # 界面标题 tab_names=["主控制台", "选择按钮", "其他小工具"], # 界面中心部分的分页标题 - 可不填 style=QStyle.default, ) # 皮肤 # 在界面最上方添加一个按钮,链接到GitHub主页 q_gui.add_banner_tool(GitHub(url="https://github.com/QPT-Family/QGUI")) # 也可以是AI Studio q_gui.add_banner_tool( AIStudio(url="https://aistudio.baidu.com/aistudio/personalcenter/thirdview/29724") ) # 要不试试自定义Banner按钮,在大家点击它时触发刚刚定义的click函数,并向它传递其他组件的情况 q_gui.add_banner_tool(BaseBarTool(bind_func=click, name="一个新组件")) # 在主界面部分添加一个文件选择工具吧,并在选择文件后自动变为文件所在的路径 q_gui.add_notebook_tool(ChooseFileTextButton(name="文件选择", bind_func=bind_dir)) # 再加个文件夹选择工具 q_gui.add_notebook_tool(ChooseDirTextButton(name="保存位置")) # 当然也可以来个输入框 q_gui.add_notebook_tool(InputBox(name="我是个木有感情的输入框")) # 想要加一个 进度条 和 运行按钮 而且俩要水平方向排列该如何做? # 试试HorizontalToolsCombine,它可以接受一组工具并将其进行水平排列 # 这里我们也为RunButton绑定click函数 run_menu = HorizontalToolsCombine( [Progressbar(name="进度条"), RunButton(bind_func=click)], text="试试HorizontalToolsCombine,它可以接受一组工具并将其进行水平排列", ) q_gui.add_notebook_tool(run_menu) # 第二页 - 复选框和单选框 # 使用VerticalFrameCombine可以将他们在垂直方向快速组合,它们会从左到右按顺序排列 combine_left = VerticalFrameCombine( [ CheckButton(options=[("选择1", 0), ("选择2", 1), ("选择3", 0)]), CheckToolButton(options=[("选择1", 0), ("选择2", 1), ("选择3", 0)]), CheckObviousToolButton(options=[("选择1", 0), ("选择2", 1), ("选择3", 0)]), ToggleButton(options=("开", 1)), ], tab_index=1, text="使用VerticalFrameCombine可以将他们在垂直方向快速组合,它们会从左到右按顺序排列", ) q_gui.add_notebook_tool(combine_left) # 设置title参数后会为其增加标题 combine_right = VerticalFrameCombine( [ RadioButton(["选择1", "选择2", "选择3"], tab_index=1), RadioToolButton(["选择1", "选择2", "选择3"], tab_index=1), RadioObviousToolButton(["选择1", "选择2", "选择3"], tab_index=1), ], title="右侧的复选框", ) q_gui.add_notebook_tool(combine_right) # 第三页 q_gui.add_notebook_tool( Label(text="这只是个简单的Label组件", alignment=RIGHT + TOP, tab_index=2) ) q_gui.add_notebook_tool(Slider(default=4, tab_index=2)) q_gui.add_notebook_tool(Combobox(options=["选择1", "选择2", "选择3"], tab_index=2)) q_gui.add_notebook_tool( BaseButton(bind_func=go_to_first_page, text="回到首页", tab_index=2) ) # 左侧信息栏 # 简单加个简介 q_gui.set_navigation_about( author="GT", version="0.0.1", github_url="https://github.com/QPT-Family/QGUI", other_info=["欢迎加入QPT!"], ) # 也可以加一下其他信息 q_gui.set_navigation_info(title="随便写段话", info="除了QGUI,你还可以试试例如AgentQGUI这样同样简单的GUI框架") print("小Tips:占位符可以被Print,不信你看HORIZONTAL的描述被打印了出来->", HORIZONTAL) # 跑起来~切记!一定要放在程序末尾 q_gui.run() PROMPT: 添加生成DataPack的选项,使得用户可以选择生成Bukkit插件或者DataPack。 在`ui.py`中可以在Generate Page里添加这行代码 `root.add_notebook_tool(RadioObviousToolButton(options=["BukkitPlugin", "Datapack(Experimental)"], name="GenerationType", title="Type", default="BukkitPlugin",tab_index=0))` 你还需要自行完成DataPack的生成逻辑。你可能需要更改的文件有`ui.py`, `core.py`, `config.yaml`, `console.py`。你还可能需要创建一些新的文件或文件夹,也有可能不需要。祝你好运。 2024-07-25T11:59:38.142362 CONSOLE OUTPUT: Error while improving the project: "Could not resolve authentication method. Expected either api_key or auth_token to be set. Or for one of the `X-Api-Key` or `Authorization` headers to be explicitly omitted" Could you please upload the debug_log_file.txt in D:\zhousl\BukkitGPT\BukkitGPT-v3\.gpteng\memory/logs folder to github? FULL STACK TRACE: Traceback (most recent call last): File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 379, in handle_improve_mode files_dict = agent.improve(files_dict, prompt) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\applications\cli\cli_agent.py", line 208, in improve files_dict = self.improve_fn( ^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 311, in improve_fn return _improve_loop(ai, files_dict, memory, messages) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 317, in _improve_loop messages = ai.next(messages, step_name=curr_fn()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\ai.py", line 243, in next response = self.backoff_inference(messages) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\backoff\_sync.py", line 105, in retry ret = target(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\ai.py", line 287, in backoff_inference return self.llm.invoke(messages) # type: ignore ^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 270, in invoke self.generate_prompt( File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 703, in generate_prompt return self.generate(prompt_messages, stop=stop, callbacks=callbacks, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 560, in generate raise e File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 550, in generate self._generate_with_cache( File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 775, in _generate_with_cache result = self._generate( ^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_anthropic\chat_models.py", line 755, in _generate return generate_from_stream(stream_iter) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 102, in generate_from_stream generation = next(stream, None) ^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_anthropic\chat_models.py", line 676, in _stream stream = self._client.messages.create(**payload) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_utils\_utils.py", line 277, in wrapper return func(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\resources\messages.py", line 902, in create return self._post( ^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 1266, in post return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 942, in request return self._request( ^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 968, in _request request = self._build_request(options) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 461, in _build_request headers = self._build_headers(options) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 416, in _build_headers self._validate_headers(headers_dict, custom_headers) File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_client.py", line 192, in _validate_headers raise TypeError( TypeError: "Could not resolve authentication method. Expected either api_key or auth_token to be set. Or for one of the `X-Api-Key` or `Authorization` headers to be explicitly omitted" 2024-07-25T12:05:50.603498 UPLOADED FILES: File: config.py import yaml from log_writer import logger def load_config(): """ Loads the configuration from the 'config.yaml' file and sets the global variables accordingly. If the 'GENERATE_MODEL' key in the configuration is set to 'gpt-4', it forces the use of 'gpt-4-turbo-preview' as the value for the 'GENERATE_MODEL' key, since 'gpt-4' no longer supports json modes. Returns: None """ with open("config.yaml", "r") as conf: config_content = yaml.safe_load(conf) for key, value in config_content.items(): if key == "GENERATE_MODEL" and value == "gpt-4": globals()[ key ] = "gpt-4-turbo-preview" # Force using gpt-4-turbo-preview if the user set the GENERATE_MODEL to gpt-4. Because gpt-4 is not longer supports json modes. globals()[key] = value logger(f"config: {key} -> {value}") def edit_config(key, value): """ Edits the config file. Args: key (str): The key to edit. value (str): The value to set. Returns: bool: True """ with open("config.yaml", "r") as conf: config_content = conf.readlines() with open("config.yaml", "w") as conf: for line in config_content: if line.startswith(key): if value == True: write_value = "True" elif value == False: write_value = "False" else: write_value = f'"{value}"' if "#" in line: conf.write(f"{key}: {write_value} # {line.split('#')[1]}\n") else: conf.write(f"{key}: {write_value}\n") else: conf.write(line) return True load_config() File: config.yaml ########## EDIT REQUIRED ########## # GPT SETTINGS # # Get your api key from openai. Remember google/bing is always your best friend. # Model names: gpt-4-turbo-preview, gpt-3.5-turbo, etc. # Recommend -> gpt-4-turbo (Better performance, more expensive), gpt-4-o (Good performance, cheaper) API_KEY: "" # Free API Key with GPT-4 access: https://github.com/CubeGPT/.github/discussions/1 BASE_URL: "https://api.openai.com/v1/chat/completions" GENERATION_MODEL: "gpt-4-turbo-2024-04-09" FIXING_MODEL: "gpt-4-turbo-2024-04-09" # DEVELOPER SETTINGS # VERSION_NUMBER: "0.1.1" # PROMPT SETTINGS # # If you don't know what it is, please don't touch it. Be sure to backup before editing. ## Code Generation ## SYS_GEN: | You're a minecraft bukkit plugin coder AI. Game Version: 1.13.2 (1.13.2-R0.1-SNAPSHOT) Write the code & choose a artifact name for the following files with the infomation which is also provided by the user: codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml codes/%ARTIFACT_NAME%/src/main/resources/config.yml codes/%ARTIFACT_NAME%/pom.xml Response in json format: { \"codes\": [ { \"file\": \"codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java\", \"code\": \"package ...;\\nimport org.bukkit.Bukkit;\\npublic class Main extends JavaPlugin implements CommandExecutor {\\n... (The code you need to write)\" }, { \"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml\", \"code\": \"name: ...\\nversion: ...\\n...\" }, { \"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/config.yml\", \"code\": \"...\" }, { \"file\": \"codes/%ARTIFACT_NAME%/pom.xml\", \"code\": \"...\" } ] } You should never response anything else. Never use Markdown format. Use \n for line feed, and never forget to use \ before ". Never write uncompeleted codes, such as leave a comment that says "// Your codes here" or "// Uncompeleted". USR_GEN: | %DESCRIPTION% SYS_FIX: | You're a minecraft bukkit plugin coder AI. Game Version: 1.13.2 (1.13.2-R0.1-SNAPSHOT) Fix the error in the code provided by user. The error message is also provided by the user. Response in json format: { \"codes\": [ { \"file\": \"codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java\", \"code\": \"package ...;\\nimport org.bukkit.Bukkit;\\npublic class Main extends JavaPlugin implements CommandExecutor {\\n... (The code you need to write)\" }, { \"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml\", \"code\": \"name: ...\\nversion: ...\\n...\" }, { \"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/config.yml\", \"code\": \"...\" }, { \"file\": \"codes/%ARTIFACT_NAME%/pom.xml\", \"code\": \"...\" } ] } You should never response anything else. Never use Markdown format. Use \n for line feed, and never forget to use \ before ". Never write uncompeleted codes, such as leave a comment that says "// Your codes here" or "// Original code" or "// Uncompeleted". USR_FIX: | Main.java: %MAIN_JAVA% plugin.yml: %PLUGIN_YML% config.yml: %CONFIG_YML% pom.xml: %POM_XML% error message: %P_ERROR_MSG% File: console.py import sys import uuid import shutil from log_writer import logger import core import config import build if __name__ == "__main__": main_java = None plugin_yml = None config_yml = None pom_xml = None core.initialize() print("BukkitGPT v3 beta console running") # Get user inputs name = input("Enter the plugin name: ") description = input("Enter the plugin description: ") artifact_name = name.replace(" ", "") package_id = f"org.cubegpt.{uuid.uuid4().hex[:8]}" pkg_id_path = "" for id in package_id.split("."): pkg_id_path += id + "/" logger(f"user_input -> name: {name}") logger(f"user_input -> description: {description}") logger(f"random_generate -> package_id: {package_id}") logger(f"str_path -> pkg_id_path: {pkg_id_path}") print("Generating plugin...") codes = core.askgpt( config.SYS_GEN.replace("%ARTIFACT_NAME%", artifact_name).replace( "%PKG_ID_LST%", pkg_id_path ), config.USR_GEN.replace("%DESCRIPTION", description), config.GENERATION_MODEL, ) logger(f"codes: {codes}") core.response_to_action(codes) print("Code generated. Building now...") result = build.build_plugin(artifact_name) if "BUILD SUCCESS" in result: print( f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" ) elif "Compilation failure": print("Build failed. Passing the error to ChatGPT and let it to fix it?") fix = input("Y/n: ") if fix == "n": print("Exiting...") sys.exit(0) else: print("Passing the error to ChatGPT...") files = [ f"codes/{artifact_name}/src/main/java/{pkg_id_path}Main.java", f"codes/{artifact_name}/src/main/resources/plugin.yml", f"codes/{artifact_name}/src/main/resources/config.yml", f"codes/{artifact_name}/pom.xml", ] ids = ["main_java", "plugin_yml", "config_yml", "pom_xml"] for file in files: with open(file, "r") as f: code = f.read() id = ids[files.index(file)] globals()[id] = code print("Generating...") codes = core.askgpt( config.SYS_FIX.replace("%ARTIFACT_NAME%", artifact_name), config.USR_FIX.replace("%MAIN_JAVA%", main_java) .replace("%PLUGIN_YML%", plugin_yml) .replace("%CONFIG_YML%", config_yml) .replace("%POM_XML%", pom_xml) .replace("%P_ERROR_MSG%", result), config.FIXING_MODEL, ) shutil.rmtree(f"codes/{artifact_name}") core.response_to_action(codes) print("Code generated. Building now...") result = build.build_plugin(artifact_name) if "BUILD SUCCESS" in result: print( f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" ) else: print( "Build failed. Please check the logs && send the log to @BaimoQilin on discord." ) print("Exiting...") sys.exit(0) else: print( "Unknown error. Please check the logs && send the log to @BaimoQilin on discord." ) print("Exiting...") sys.exit(0) else: print( "Error: Please run console.py as the main program instead of importing it from another program." ) File: core.py from openai import OpenAI import chardet import sys import json import locale import os from log_writer import logger import config def initialize(): """ Initializes the software. This function logs the software launch, including the version number and platform. Args: None Returns: None """ locale.setlocale(locale.LC_ALL, "en_US.UTF-8") logger(f"Launch. Software version {config.VERSION_NUMBER}, platform {sys.platform}") if ( "gpt-3.5" in config.GENERATION_MODEL and config.BYPASS_NO_GPT35_FOR_GENERATION_LIMIT is False ): print( "gpt-3.5 writes bugs *all the time* and is not recommended for code generation. Switching to gpt-4." ) config.edit_config( "GENERATION_MODEL", config.GENERATION_MODEL.replace("gpt-3.5", "gpt-4") ) def askgpt( system_prompt: str, user_prompt: str, model_name: str, disable_json_mode: bool = False, image_url: str = None, ): """ Interacts with ChatGPT using the specified prompts. Args: system_prompt (str): The system prompt. user_prompt (str): The user prompt. model_name (str): The model name to use. disable_json_mode (bool): Whether to disable JSON mode. Returns: str: The response from ChatGPT. """ if image_url is not None and config.USE_DIFFERENT_APIKEY_FOR_VISION_MODEL: logger("Using different API key for vision model.") client = OpenAI(api_key=config.VISION_API_KEY, base_url=config.VISION_BASE_URL) else: client = OpenAI(api_key=config.API_KEY, base_url=config.BASE_URL) logger("Initialized the OpenAI client.") # Define the messages for the conversation if image_url is not None: messages = [ {"role": "system", "content": system_prompt}, { "role": "user", "content": [ {"type": "text", "text": user_prompt}, {"type": "image_url", "image_url": {"url": image_url}}, ], }, ] else: messages = [ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt}, ] logger(f"askgpt: system {system_prompt}") logger(f"askgpt: user {user_prompt}") # Create a chat completion if disable_json_mode: response = client.chat.completions.create(model=model_name, messages=messages) else: response = client.chat.completions.create( model=model_name, response_format={"type": "json_object"}, messages=messages ) logger(f"askgpt: response {response}") # Extract the assistant's reply assistant_reply = response.choices[0].message.content logger(f"askgpt: extracted reply {assistant_reply}") return assistant_reply def response_to_action(msg): """ Converts a response from ChatGPT to an action. Args: msg (str): The response from ChatGPT. Returns: str: The action to take. """ text = json.loads(msg) codes = text["codes"] for section in codes: file = section["file"] code = section["code"] paths = file.split("/") # Join the list elements to form a path path = os.path.join(*paths) # Get the directory path and the file name dir_path, file_name = os.path.split(path) # Create directories, if they don't exist try: os.makedirs(dir_path, exist_ok=True) except FileNotFoundError: pass # Create the file with open(path, "w") as f: f.write(code) # Write an empty string to the file def mixed_decode(text: str): """ Decode a mixed text containing both normal text and a byte sequence. Args: text (str): The mixed text to be decoded. Returns: str: The decoded text, where the byte sequence has been converted to its corresponding characters. """ # Split the normal text and the byte sequence # Assuming the byte sequence is everything after the last colon and space ": " try: normal_text, byte_text = text.rsplit(": ", 1) except (TypeError, ValueError): # The text only contains normal text return text # Convert the byte sequence to actual bytes byte_sequence = byte_text.encode( "latin1" ) # latin1 encoding maps byte values directly to unicode code points # Detect the encoding of the byte sequence detected_encoding = chardet.detect(byte_sequence) encoding = detected_encoding["encoding"] # Decode the byte sequence decoded_text = byte_sequence.decode(encoding) # Combine the normal text with the decoded byte sequence final_text = normal_text + ": " + decoded_text return final_text if __name__ == "__main__": print("This script is not meant to be run directly. Please run console.py instead.") File: log_writer.py import os from datetime import datetime first_call_time = None def get_log_filename(): global first_call_time if first_call_time is None: first_call_time = datetime.now() log_filename = first_call_time.strftime("logs/%b-%d-%H-%M-%S-%Y") return log_filename def logger(text: str): log_filename = get_log_filename() timestamp_prefix = datetime.now().strftime("[%H:%M:%S]") log_line = f"{timestamp_prefix} {text}\n" os.makedirs(os.path.dirname(log_filename), exist_ok=True) with open(log_filename + ".log", "a", encoding="utf-8") as log_file: log_file.write(log_line) File: requirements.txt openai>=1.13.3 pyyaml cx_Freeze ttkbootstrap playwright chardet File: ui.py from cube_qgui.__init__ import CreateQGUI from cube_qgui.banner_tools import * from cube_qgui.notebook_tools import * from playwright.sync_api import Playwright, sync_playwright import os import shutil import uuid from log_writer import logger import config import core import build # ---------- Functions ----------# def open_config(args: dict): """ Opens the config file. Args: args (dict): A dictionary containing the necessary arguments. Returns: bool: Always True. """ os.system("notepad config.yaml") return True def save_apply_config(args: dict): """ Saves and applies the configuration. Args: args (dict): A dictionary containing the necessary arguments. Returns: bool: Always True. """ keys = ["API_KEY", "BASE_URL"] for key in keys: value = args[key].get() if key == "ADVANCED_MODE": value = True if value == 1 else False else: pass config.edit_config(key, value) config.load_config() args["DevTool_CONFIG_API_KEY_DISPLAY"].set(f"CONFIG.API_KEY = {config.API_KEY}") args["DevTools_CONFIG_BASE_URL_DISPLAY"].set(f"CONFIG.BASE_URL = {config.BASE_URL}") return True def load_config(args: dict): """ Loads the configuration. Args: args (dict): A dictionary containing the necessary arguments. Returns: bool: Always True. """ config.load_config() args["API_KEY"].set(config.API_KEY) args["BASE_URL"].set(config.BASE_URL) return True def print_args(args: dict): """ Prints the arguments. Args: args (dict): A dictionary containing the arguments. Returns: bool: Always True. """ for arg, v_fun in args.items(): print(f"Name: {arg}, Value: {v_fun.get()}") return True def raise_error(args: dict): """ Raises an error. Args: args (dict): A dictionary containing the arguments. """ raise Exception("This is a test error.") # ---------- Generate Function ----------# def generate(args: dict): """ Generates the plugin. Args: args (dict): A dictionary containing the arguments. Returns: bool: Always True. """ global error_msg, pkg_id_path # Get user inputs name = args["PluginName"].get() description = args["PluginDescription"].get() artifact_name = name.replace(" ", "") package_id = f"org.cubegpt.{uuid.uuid4().hex[:8]}" pkg_id_path = "" for id in package_id.split("."): pkg_id_path += id + "/" logger(f"user_input -> name: {name}") logger(f"user_input -> description: {description}") logger(f"random_generate -> package_id: {package_id}") logger(f"str_path -> pkg_id_path: {pkg_id_path}") print("Generating plugin...") codes = core.askgpt( config.SYS_GEN.replace("%ARTIFACT_NAME%", artifact_name).replace( "%PKG_ID_LST%", pkg_id_path ), config.USR_GEN.replace("%DESCRIPTION", description), config.GENERATION_MODEL, ) logger(f"codes: {codes}") core.response_to_action(codes) print("Code generated. Building now...") result = build.build_plugin(artifact_name) if "BUILD SUCCESS" in result: print( f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" ) elif "Compilation failure": error_msg = result print( "Build failed. To pass the error to ChatGPT && let it fix, jump to the Fixing page and click the Fix button." ) else: print( "Unknown error. Please check the logs && send the log to @BaimoQilin on discord." ) return True def fix(args: dict): """ Fixes the error. Args: args (dict): A dictionary containing the arguments. Returns: bool: Always True. """ artifact_name = args["PluginName"].get() print("Passing the error to ChatGPT...") files = [ f"codes/{artifact_name}/src/main/java/{pkg_id_path}Main.java", f"codes/{artifact_name}/src/main/resources/plugin.yml", f"codes/{artifact_name}/src/main/resources/config.yml", f"codes/{artifact_name}/pom.xml", ] ids = ["main_java", "plugin_yml", "config_yml", "pom_xml"] main_java = None plugin_yml = None config_yml = None pom_xml = None for file in files: with open(file, "r") as f: code = f.read() id = ids[files.index(file)] globals()[id] = code print("Generating...") codes = core.askgpt( config.SYS_FIX.replace("%ARTIFACT_NAME%", str(artifact_name)), config.USR_FIX.replace("%MAIN_JAVA%", str(main_java)) .replace("%PLUGIN_YML%", str(plugin_yml)) .replace("%CONFIG_YML%", str(config_yml)) .replace("%POM_XML%", str(pom_xml)) .replave("%PKG_ID_LST%", pkg_id_path) .replace("%P_ERROR_MSG%", str(error_msg)), config.FIXING_MODEL, ) shutil.rmtree(f"codes/{artifact_name}") core.response_to_action(codes) print("Code generated. Building now...") result = build.build_plugin(artifact_name) if "BUILD SUCCESS" in result: print( f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" ) else: print( "Build failed again. Please check the logs && send the log to @BaimoQilin on discord." ) return True # ---------- Main Program ----------# root = CreateQGUI(title="BukkitGPT-v3", tab_names=["Generate", "Settings", "DevTools"]) error_msg = None logger("Starting program.") # Initialize Core core.initialize() print("BukkitGPT v3 beta console running") # Banner root.add_banner_tool(GitHub("https://github.com/CubeGPT/BukkitGPT-v3")) # Generate Page root.add_notebook_tool( InputBox(name="PluginName", default="ExamplePlugin", label_info="Plugin Name") ) root.add_notebook_tool( InputBox( name="PluginDescription", default="Send msg 'hello' to every joined player.", label_info="Plugin Description", ) ) root.add_notebook_tool( RunButton( bind_func=generate, name="Generate", text="Generate Plugin", checked_text="Generating...", tab_index=0, ) ) # Fixing Page # # root.add_notebook_tool(Label(name="Fixing_DESCRIPTION", text="This is a fixing page. If the build fails, click the Fix button to fix the error in the LATEST build.", tab_index=1)) # root.add_notebook_tool(RunButton(bind_func=fix, name="Fix", text="Fix", checked_text="Fixing...", tab_index=1)) # Settings Page root.add_notebook_tool( InputBox(name="API_KEY", default=config.API_KEY, label_info="API Key", tab_index=1) ) root.add_notebook_tool( InputBox( name="BASE_URL", default=config.BASE_URL, label_info="BASE URL", tab_index=1 ) ) config_buttons = HorizontalToolsCombine( [ BaseButton( bind_func=save_apply_config, name="Save & Apply Config", text="Save & Apply", tab_index=1, ), BaseButton( bind_func=load_config, name="Load Config", text="Load Config", tab_index=1 ), BaseButton( bind_func=open_config, name="Open Config", text="Open Full Config", tab_index=1, ), ] ) root.add_notebook_tool(config_buttons) # DevTools Page root.add_notebook_tool( Label( name="DevTool_DESCRIPTION", text="This is a testing page for developers. Ignore it if you are a normal user.", tab_index=2, ) ) root.add_notebook_tool( Label( name="DevTool_CONFIG_API_KEY_DISPLAY", text=f"CONFIG.API_KEY = {config.API_KEY}", tab_index=2, ) ) root.add_notebook_tool( Label( name="DevTools_CONFIG_BASE_URL_DISPLAY", text=f"CONFIG.BASE_URL = {config.BASE_URL}", tab_index=2, ) ) root.add_notebook_tool( RunButton(bind_func=print_args, name="Print Args", text="Print Args", tab_index=2) ) root.add_notebook_tool( RunButton( bind_func=raise_error, name="Raise Error", text="Raise Error", tab_index=2 ) ) # Sidebar root.set_navigation_about( author="CubeGPT Team", version=config.VERSION_NUMBER, github_url="https://github.com/CubeGPT/BukkitGPT-v3", ) # Run root.run() PROMPT: 添加生成DataPack的选项,使得用户可以选择生成Bukkit插件或者DataPack。 在`ui.py`中可以在Generate Page里添加这行代码 `root.add_notebook_tool(RadioObviousToolButton(options=["BukkitPlugin", "Datapack(Experimental)"], name="GenerationType", title="Type", default="BukkitPlugin",tab_index=0))` 你还需要自行完成DataPack的生成逻辑。你可能需要更改的文件有`ui.py`, `core.py`, `config.yaml`, `console.py`。你还可能需要创建一些新的文件或文件夹,也有可能不需要。祝你好运。 2024-07-25T12:05:51.036844 CONSOLE OUTPUT: Error while improving the project: "Could not resolve authentication method. Expected either api_key or auth_token to be set. Or for one of the `X-Api-Key` or `Authorization` headers to be explicitly omitted" Could you please upload the debug_log_file.txt in D:\zhousl\BukkitGPT\BukkitGPT-v3\.gpteng\memory/logs folder to github? FULL STACK TRACE: Traceback (most recent call last): File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 379, in handle_improve_mode files_dict = agent.improve(files_dict, prompt) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\applications\cli\cli_agent.py", line 208, in improve files_dict = self.improve_fn( ^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 311, in improve_fn return _improve_loop(ai, files_dict, memory, messages) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 317, in _improve_loop messages = ai.next(messages, step_name=curr_fn()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\ai.py", line 243, in next response = self.backoff_inference(messages) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\backoff\_sync.py", line 105, in retry ret = target(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\ai.py", line 287, in backoff_inference return self.llm.invoke(messages) # type: ignore ^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 270, in invoke self.generate_prompt( File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 703, in generate_prompt return self.generate(prompt_messages, stop=stop, callbacks=callbacks, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 560, in generate raise e File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 550, in generate self._generate_with_cache( File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 775, in _generate_with_cache result = self._generate( ^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_anthropic\chat_models.py", line 755, in _generate return generate_from_stream(stream_iter) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 102, in generate_from_stream generation = next(stream, None) ^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_anthropic\chat_models.py", line 676, in _stream stream = self._client.messages.create(**payload) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_utils\_utils.py", line 277, in wrapper return func(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\resources\messages.py", line 902, in create return self._post( ^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 1266, in post return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 942, in request return self._request( ^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 968, in _request request = self._build_request(options) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 461, in _build_request headers = self._build_headers(options) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 416, in _build_headers self._validate_headers(headers_dict, custom_headers) File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_client.py", line 192, in _validate_headers raise TypeError( TypeError: "Could not resolve authentication method. Expected either api_key or auth_token to be set. Or for one of the `X-Api-Key` or `Authorization` headers to be explicitly omitted" 2024-07-25T12:10:01.414816 UPLOADED FILES: File: config.py import yaml from log_writer import logger def load_config(): """ Loads the configuration from the 'config.yaml' file and sets the global variables accordingly. If the 'GENERATE_MODEL' key in the configuration is set to 'gpt-4', it forces the use of 'gpt-4-turbo-preview' as the value for the 'GENERATE_MODEL' key, since 'gpt-4' no longer supports json modes. Returns: None """ with open("config.yaml", "r") as conf: config_content = yaml.safe_load(conf) for key, value in config_content.items(): if key == "GENERATE_MODEL" and value == "gpt-4": globals()[ key ] = "gpt-4-turbo-preview" # Force using gpt-4-turbo-preview if the user set the GENERATE_MODEL to gpt-4. Because gpt-4 is not longer supports json modes. globals()[key] = value logger(f"config: {key} -> {value}") def edit_config(key, value): """ Edits the config file. Args: key (str): The key to edit. value (str): The value to set. Returns: bool: True """ with open("config.yaml", "r") as conf: config_content = conf.readlines() with open("config.yaml", "w") as conf: for line in config_content: if line.startswith(key): if value == True: write_value = "True" elif value == False: write_value = "False" else: write_value = f'"{value}"' if "#" in line: conf.write(f"{key}: {write_value} # {line.split('#')[1]}\n") else: conf.write(f"{key}: {write_value}\n") else: conf.write(line) return True load_config() File: config.yaml ########## EDIT REQUIRED ########## # GPT SETTINGS # # Get your api key from openai. Remember google/bing is always your best friend. # Model names: gpt-4-turbo-preview, gpt-3.5-turbo, etc. # Recommend -> gpt-4-turbo (Better performance, more expensive), gpt-4-o (Good performance, cheaper) API_KEY: "" # Free API Key with GPT-4 access: https://github.com/CubeGPT/.github/discussions/1 BASE_URL: "https://api.openai.com/v1/chat/completions" GENERATION_MODEL: "gpt-4-turbo-2024-04-09" FIXING_MODEL: "gpt-4-turbo-2024-04-09" # DEVELOPER SETTINGS # VERSION_NUMBER: "0.1.1" # PROMPT SETTINGS # # If you don't know what it is, please don't touch it. Be sure to backup before editing. ## Code Generation ## SYS_GEN: | You're a minecraft bukkit plugin coder AI. Game Version: 1.13.2 (1.13.2-R0.1-SNAPSHOT) Write the code & choose a artifact name for the following files with the infomation which is also provided by the user: codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml codes/%ARTIFACT_NAME%/src/main/resources/config.yml codes/%ARTIFACT_NAME%/pom.xml Response in json format: { \"codes\": [ { \"file\": \"codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java\", \"code\": \"package ...;\\nimport org.bukkit.Bukkit;\\npublic class Main extends JavaPlugin implements CommandExecutor {\\n... (The code you need to write)\" }, { \"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml\", \"code\": \"name: ...\\nversion: ...\\n...\" }, { \"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/config.yml\", \"code\": \"...\" }, { \"file\": \"codes/%ARTIFACT_NAME%/pom.xml\", \"code\": \"...\" } ] } You should never response anything else. Never use Markdown format. Use \n for line feed, and never forget to use \ before ". Never write uncompeleted codes, such as leave a comment that says "// Your codes here" or "// Uncompeleted". USR_GEN: | %DESCRIPTION% SYS_FIX: | You're a minecraft bukkit plugin coder AI. Game Version: 1.13.2 (1.13.2-R0.1-SNAPSHOT) Fix the error in the code provided by user. The error message is also provided by the user. Response in json format: { \"codes\": [ { \"file\": \"codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java\", \"code\": \"package ...;\\nimport org.bukkit.Bukkit;\\npublic class Main extends JavaPlugin implements CommandExecutor {\\n... (The code you need to write)\" }, { \"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml\", \"code\": \"name: ...\\nversion: ...\\n...\" }, { \"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/config.yml\", \"code\": \"...\" }, { \"file\": \"codes/%ARTIFACT_NAME%/pom.xml\", \"code\": \"...\" } ] } You should never response anything else. Never use Markdown format. Use \n for line feed, and never forget to use \ before ". Never write uncompeleted codes, such as leave a comment that says "// Your codes here" or "// Original code" or "// Uncompeleted". USR_FIX: | Main.java: %MAIN_JAVA% plugin.yml: %PLUGIN_YML% config.yml: %CONFIG_YML% pom.xml: %POM_XML% error message: %P_ERROR_MSG% File: console.py import sys import uuid import shutil from log_writer import logger import core import config import build if __name__ == "__main__": main_java = None plugin_yml = None config_yml = None pom_xml = None core.initialize() print("BukkitGPT v3 beta console running") # Get user inputs name = input("Enter the plugin name: ") description = input("Enter the plugin description: ") artifact_name = name.replace(" ", "") package_id = f"org.cubegpt.{uuid.uuid4().hex[:8]}" pkg_id_path = "" for id in package_id.split("."): pkg_id_path += id + "/" logger(f"user_input -> name: {name}") logger(f"user_input -> description: {description}") logger(f"random_generate -> package_id: {package_id}") logger(f"str_path -> pkg_id_path: {pkg_id_path}") print("Generating plugin...") codes = core.askgpt( config.SYS_GEN.replace("%ARTIFACT_NAME%", artifact_name).replace( "%PKG_ID_LST%", pkg_id_path ), config.USR_GEN.replace("%DESCRIPTION", description), config.GENERATION_MODEL, ) logger(f"codes: {codes}") core.response_to_action(codes) print("Code generated. Building now...") result = build.build_plugin(artifact_name) if "BUILD SUCCESS" in result: print( f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" ) elif "Compilation failure": print("Build failed. Passing the error to ChatGPT and let it to fix it?") fix = input("Y/n: ") if fix == "n": print("Exiting...") sys.exit(0) else: print("Passing the error to ChatGPT...") files = [ f"codes/{artifact_name}/src/main/java/{pkg_id_path}Main.java", f"codes/{artifact_name}/src/main/resources/plugin.yml", f"codes/{artifact_name}/src/main/resources/config.yml", f"codes/{artifact_name}/pom.xml", ] ids = ["main_java", "plugin_yml", "config_yml", "pom_xml"] for file in files: with open(file, "r") as f: code = f.read() id = ids[files.index(file)] globals()[id] = code print("Generating...") codes = core.askgpt( config.SYS_FIX.replace("%ARTIFACT_NAME%", artifact_name), config.USR_FIX.replace("%MAIN_JAVA%", main_java) .replace("%PLUGIN_YML%", plugin_yml) .replace("%CONFIG_YML%", config_yml) .replace("%POM_XML%", pom_xml) .replace("%P_ERROR_MSG%", result), config.FIXING_MODEL, ) shutil.rmtree(f"codes/{artifact_name}") core.response_to_action(codes) print("Code generated. Building now...") result = build.build_plugin(artifact_name) if "BUILD SUCCESS" in result: print( f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" ) else: print( "Build failed. Please check the logs && send the log to @BaimoQilin on discord." ) print("Exiting...") sys.exit(0) else: print( "Unknown error. Please check the logs && send the log to @BaimoQilin on discord." ) print("Exiting...") sys.exit(0) else: print( "Error: Please run console.py as the main program instead of importing it from another program." ) File: core.py from openai import OpenAI import chardet import sys import json import locale import os from log_writer import logger import config def initialize(): """ Initializes the software. This function logs the software launch, including the version number and platform. Args: None Returns: None """ locale.setlocale(locale.LC_ALL, "en_US.UTF-8") logger(f"Launch. Software version {config.VERSION_NUMBER}, platform {sys.platform}") if ( "gpt-3.5" in config.GENERATION_MODEL and config.BYPASS_NO_GPT35_FOR_GENERATION_LIMIT is False ): print( "gpt-3.5 writes bugs *all the time* and is not recommended for code generation. Switching to gpt-4." ) config.edit_config( "GENERATION_MODEL", config.GENERATION_MODEL.replace("gpt-3.5", "gpt-4") ) def askgpt( system_prompt: str, user_prompt: str, model_name: str, disable_json_mode: bool = False, image_url: str = None, ): """ Interacts with ChatGPT using the specified prompts. Args: system_prompt (str): The system prompt. user_prompt (str): The user prompt. model_name (str): The model name to use. disable_json_mode (bool): Whether to disable JSON mode. Returns: str: The response from ChatGPT. """ if image_url is not None and config.USE_DIFFERENT_APIKEY_FOR_VISION_MODEL: logger("Using different API key for vision model.") client = OpenAI(api_key=config.VISION_API_KEY, base_url=config.VISION_BASE_URL) else: client = OpenAI(api_key=config.API_KEY, base_url=config.BASE_URL) logger("Initialized the OpenAI client.") # Define the messages for the conversation if image_url is not None: messages = [ {"role": "system", "content": system_prompt}, { "role": "user", "content": [ {"type": "text", "text": user_prompt}, {"type": "image_url", "image_url": {"url": image_url}}, ], }, ] else: messages = [ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt}, ] logger(f"askgpt: system {system_prompt}") logger(f"askgpt: user {user_prompt}") # Create a chat completion if disable_json_mode: response = client.chat.completions.create(model=model_name, messages=messages) else: response = client.chat.completions.create( model=model_name, response_format={"type": "json_object"}, messages=messages ) logger(f"askgpt: response {response}") # Extract the assistant's reply assistant_reply = response.choices[0].message.content logger(f"askgpt: extracted reply {assistant_reply}") return assistant_reply def response_to_action(msg): """ Converts a response from ChatGPT to an action. Args: msg (str): The response from ChatGPT. Returns: str: The action to take. """ text = json.loads(msg) codes = text["codes"] for section in codes: file = section["file"] code = section["code"] paths = file.split("/") # Join the list elements to form a path path = os.path.join(*paths) # Get the directory path and the file name dir_path, file_name = os.path.split(path) # Create directories, if they don't exist try: os.makedirs(dir_path, exist_ok=True) except FileNotFoundError: pass # Create the file with open(path, "w") as f: f.write(code) # Write an empty string to the file def mixed_decode(text: str): """ Decode a mixed text containing both normal text and a byte sequence. Args: text (str): The mixed text to be decoded. Returns: str: The decoded text, where the byte sequence has been converted to its corresponding characters. """ # Split the normal text and the byte sequence # Assuming the byte sequence is everything after the last colon and space ": " try: normal_text, byte_text = text.rsplit(": ", 1) except (TypeError, ValueError): # The text only contains normal text return text # Convert the byte sequence to actual bytes byte_sequence = byte_text.encode( "latin1" ) # latin1 encoding maps byte values directly to unicode code points # Detect the encoding of the byte sequence detected_encoding = chardet.detect(byte_sequence) encoding = detected_encoding["encoding"] # Decode the byte sequence decoded_text = byte_sequence.decode(encoding) # Combine the normal text with the decoded byte sequence final_text = normal_text + ": " + decoded_text return final_text if __name__ == "__main__": print("This script is not meant to be run directly. Please run console.py instead.") File: log_writer.py import os from datetime import datetime first_call_time = None def get_log_filename(): global first_call_time if first_call_time is None: first_call_time = datetime.now() log_filename = first_call_time.strftime("logs/%b-%d-%H-%M-%S-%Y") return log_filename def logger(text: str): log_filename = get_log_filename() timestamp_prefix = datetime.now().strftime("[%H:%M:%S]") log_line = f"{timestamp_prefix} {text}\n" os.makedirs(os.path.dirname(log_filename), exist_ok=True) with open(log_filename + ".log", "a", encoding="utf-8") as log_file: log_file.write(log_line) File: requirements.txt openai>=1.13.3 pyyaml cx_Freeze ttkbootstrap playwright chardet File: ui.py from cube_qgui.__init__ import CreateQGUI from cube_qgui.banner_tools import * from cube_qgui.notebook_tools import * from playwright.sync_api import Playwright, sync_playwright import os import shutil import uuid from log_writer import logger import config import core import build # ---------- Functions ----------# def open_config(args: dict): """ Opens the config file. Args: args (dict): A dictionary containing the necessary arguments. Returns: bool: Always True. """ os.system("notepad config.yaml") return True def save_apply_config(args: dict): """ Saves and applies the configuration. Args: args (dict): A dictionary containing the necessary arguments. Returns: bool: Always True. """ keys = ["API_KEY", "BASE_URL"] for key in keys: value = args[key].get() if key == "ADVANCED_MODE": value = True if value == 1 else False else: pass config.edit_config(key, value) config.load_config() args["DevTool_CONFIG_API_KEY_DISPLAY"].set(f"CONFIG.API_KEY = {config.API_KEY}") args["DevTools_CONFIG_BASE_URL_DISPLAY"].set(f"CONFIG.BASE_URL = {config.BASE_URL}") return True def load_config(args: dict): """ Loads the configuration. Args: args (dict): A dictionary containing the necessary arguments. Returns: bool: Always True. """ config.load_config() args["API_KEY"].set(config.API_KEY) args["BASE_URL"].set(config.BASE_URL) return True def print_args(args: dict): """ Prints the arguments. Args: args (dict): A dictionary containing the arguments. Returns: bool: Always True. """ for arg, v_fun in args.items(): print(f"Name: {arg}, Value: {v_fun.get()}") return True def raise_error(args: dict): """ Raises an error. Args: args (dict): A dictionary containing the arguments. """ raise Exception("This is a test error.") # ---------- Generate Function ----------# def generate(args: dict): """ Generates the plugin. Args: args (dict): A dictionary containing the arguments. Returns: bool: Always True. """ global error_msg, pkg_id_path # Get user inputs name = args["PluginName"].get() description = args["PluginDescription"].get() artifact_name = name.replace(" ", "") package_id = f"org.cubegpt.{uuid.uuid4().hex[:8]}" pkg_id_path = "" for id in package_id.split("."): pkg_id_path += id + "/" logger(f"user_input -> name: {name}") logger(f"user_input -> description: {description}") logger(f"random_generate -> package_id: {package_id}") logger(f"str_path -> pkg_id_path: {pkg_id_path}") print("Generating plugin...") codes = core.askgpt( config.SYS_GEN.replace("%ARTIFACT_NAME%", artifact_name).replace( "%PKG_ID_LST%", pkg_id_path ), config.USR_GEN.replace("%DESCRIPTION", description), config.GENERATION_MODEL, ) logger(f"codes: {codes}") core.response_to_action(codes) print("Code generated. Building now...") result = build.build_plugin(artifact_name) if "BUILD SUCCESS" in result: print( f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" ) elif "Compilation failure": error_msg = result print( "Build failed. To pass the error to ChatGPT && let it fix, jump to the Fixing page and click the Fix button." ) else: print( "Unknown error. Please check the logs && send the log to @BaimoQilin on discord." ) return True def fix(args: dict): """ Fixes the error. Args: args (dict): A dictionary containing the arguments. Returns: bool: Always True. """ artifact_name = args["PluginName"].get() print("Passing the error to ChatGPT...") files = [ f"codes/{artifact_name}/src/main/java/{pkg_id_path}Main.java", f"codes/{artifact_name}/src/main/resources/plugin.yml", f"codes/{artifact_name}/src/main/resources/config.yml", f"codes/{artifact_name}/pom.xml", ] ids = ["main_java", "plugin_yml", "config_yml", "pom_xml"] main_java = None plugin_yml = None config_yml = None pom_xml = None for file in files: with open(file, "r") as f: code = f.read() id = ids[files.index(file)] globals()[id] = code print("Generating...") codes = core.askgpt( config.SYS_FIX.replace("%ARTIFACT_NAME%", str(artifact_name)), config.USR_FIX.replace("%MAIN_JAVA%", str(main_java)) .replace("%PLUGIN_YML%", str(plugin_yml)) .replace("%CONFIG_YML%", str(config_yml)) .replace("%POM_XML%", str(pom_xml)) .replave("%PKG_ID_LST%", pkg_id_path) .replace("%P_ERROR_MSG%", str(error_msg)), config.FIXING_MODEL, ) shutil.rmtree(f"codes/{artifact_name}") core.response_to_action(codes) print("Code generated. Building now...") result = build.build_plugin(artifact_name) if "BUILD SUCCESS" in result: print( f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" ) else: print( "Build failed again. Please check the logs && send the log to @BaimoQilin on discord." ) return True # ---------- Main Program ----------# root = CreateQGUI(title="BukkitGPT-v3", tab_names=["Generate", "Settings", "DevTools"]) error_msg = None logger("Starting program.") # Initialize Core core.initialize() print("BukkitGPT v3 beta console running") # Banner root.add_banner_tool(GitHub("https://github.com/CubeGPT/BukkitGPT-v3")) # Generate Page root.add_notebook_tool( InputBox(name="PluginName", default="ExamplePlugin", label_info="Plugin Name") ) root.add_notebook_tool( InputBox( name="PluginDescription", default="Send msg 'hello' to every joined player.", label_info="Plugin Description", ) ) root.add_notebook_tool( RunButton( bind_func=generate, name="Generate", text="Generate Plugin", checked_text="Generating...", tab_index=0, ) ) # Fixing Page # # root.add_notebook_tool(Label(name="Fixing_DESCRIPTION", text="This is a fixing page. If the build fails, click the Fix button to fix the error in the LATEST build.", tab_index=1)) # root.add_notebook_tool(RunButton(bind_func=fix, name="Fix", text="Fix", checked_text="Fixing...", tab_index=1)) # Settings Page root.add_notebook_tool( InputBox(name="API_KEY", default=config.API_KEY, label_info="API Key", tab_index=1) ) root.add_notebook_tool( InputBox( name="BASE_URL", default=config.BASE_URL, label_info="BASE URL", tab_index=1 ) ) config_buttons = HorizontalToolsCombine( [ BaseButton( bind_func=save_apply_config, name="Save & Apply Config", text="Save & Apply", tab_index=1, ), BaseButton( bind_func=load_config, name="Load Config", text="Load Config", tab_index=1 ), BaseButton( bind_func=open_config, name="Open Config", text="Open Full Config", tab_index=1, ), ] ) root.add_notebook_tool(config_buttons) # DevTools Page root.add_notebook_tool( Label( name="DevTool_DESCRIPTION", text="This is a testing page for developers. Ignore it if you are a normal user.", tab_index=2, ) ) root.add_notebook_tool( Label( name="DevTool_CONFIG_API_KEY_DISPLAY", text=f"CONFIG.API_KEY = {config.API_KEY}", tab_index=2, ) ) root.add_notebook_tool( Label( name="DevTools_CONFIG_BASE_URL_DISPLAY", text=f"CONFIG.BASE_URL = {config.BASE_URL}", tab_index=2, ) ) root.add_notebook_tool( RunButton(bind_func=print_args, name="Print Args", text="Print Args", tab_index=2) ) root.add_notebook_tool( RunButton( bind_func=raise_error, name="Raise Error", text="Raise Error", tab_index=2 ) ) # Sidebar root.set_navigation_about( author="CubeGPT Team", version=config.VERSION_NUMBER, github_url="https://github.com/CubeGPT/BukkitGPT-v3", ) # Run root.run() PROMPT: 添加生成DataPack的选项,使得用户可以选择生成Bukkit插件或者DataPack。 在`ui.py`中可以在Generate Page里添加这行代码 `root.add_notebook_tool(RadioObviousToolButton(options=["BukkitPlugin", "Datapack(Experimental)"], name="GenerationType", title="Type", default="BukkitPlugin",tab_index=0))` 你还需要自行完成DataPack的生成逻辑。你可能需要更改的文件有`ui.py`, `core.py`, `config.yaml`, `console.py`。你还可能需要创建一些新的文件或文件夹,也有可能不需要。祝你好运。 2024-07-25T12:10:01.841094 CONSOLE OUTPUT: Error while improving the project: "Could not resolve authentication method. Expected either api_key or auth_token to be set. Or for one of the `X-Api-Key` or `Authorization` headers to be explicitly omitted" Could you please upload the debug_log_file.txt in D:\zhousl\BukkitGPT\BukkitGPT-v3\.gpteng\memory/logs folder to github? FULL STACK TRACE: Traceback (most recent call last): File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 379, in handle_improve_mode files_dict = agent.improve(files_dict, prompt) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\applications\cli\cli_agent.py", line 208, in improve files_dict = self.improve_fn( ^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 311, in improve_fn return _improve_loop(ai, files_dict, memory, messages) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 317, in _improve_loop messages = ai.next(messages, step_name=curr_fn()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\ai.py", line 243, in next response = self.backoff_inference(messages) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\backoff\_sync.py", line 105, in retry ret = target(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\ai.py", line 287, in backoff_inference return self.llm.invoke(messages) # type: ignore ^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 270, in invoke self.generate_prompt( File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 703, in generate_prompt return self.generate(prompt_messages, stop=stop, callbacks=callbacks, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 560, in generate raise e File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 550, in generate self._generate_with_cache( File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 775, in _generate_with_cache result = self._generate( ^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_anthropic\chat_models.py", line 755, in _generate return generate_from_stream(stream_iter) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 102, in generate_from_stream generation = next(stream, None) ^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_anthropic\chat_models.py", line 676, in _stream stream = self._client.messages.create(**payload) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_utils\_utils.py", line 277, in wrapper return func(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\resources\messages.py", line 902, in create return self._post( ^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 1266, in post return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 942, in request return self._request( ^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 968, in _request request = self._build_request(options) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 461, in _build_request headers = self._build_headers(options) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 416, in _build_headers self._validate_headers(headers_dict, custom_headers) File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_client.py", line 192, in _validate_headers raise TypeError( TypeError: "Could not resolve authentication method. Expected either api_key or auth_token to be set. Or for one of the `X-Api-Key` or `Authorization` headers to be explicitly omitted" 2024-07-25T12:12:17.814305 UPLOADED FILES: File: config.py import yaml from log_writer import logger def load_config(): """ Loads the configuration from the 'config.yaml' file and sets the global variables accordingly. If the 'GENERATE_MODEL' key in the configuration is set to 'gpt-4', it forces the use of 'gpt-4-turbo-preview' as the value for the 'GENERATE_MODEL' key, since 'gpt-4' no longer supports json modes. Returns: None """ with open("config.yaml", "r") as conf: config_content = yaml.safe_load(conf) for key, value in config_content.items(): if key == "GENERATE_MODEL" and value == "gpt-4": globals()[ key ] = "gpt-4-turbo-preview" # Force using gpt-4-turbo-preview if the user set the GENERATE_MODEL to gpt-4. Because gpt-4 is not longer supports json modes. globals()[key] = value logger(f"config: {key} -> {value}") def edit_config(key, value): """ Edits the config file. Args: key (str): The key to edit. value (str): The value to set. Returns: bool: True """ with open("config.yaml", "r") as conf: config_content = conf.readlines() with open("config.yaml", "w") as conf: for line in config_content: if line.startswith(key): if value == True: write_value = "True" elif value == False: write_value = "False" else: write_value = f'"{value}"' if "#" in line: conf.write(f"{key}: {write_value} # {line.split('#')[1]}\n") else: conf.write(f"{key}: {write_value}\n") else: conf.write(line) return True load_config() File: config.yaml ########## EDIT REQUIRED ########## # GPT SETTINGS # # Get your api key from openai. Remember google/bing is always your best friend. # Model names: gpt-4-turbo-preview, gpt-3.5-turbo, etc. # Recommend -> gpt-4-turbo (Better performance, more expensive), gpt-4-o (Good performance, cheaper) API_KEY: "" # Free API Key with GPT-4 access: https://github.com/CubeGPT/.github/discussions/1 BASE_URL: "https://api.openai.com/v1/chat/completions" GENERATION_MODEL: "gpt-4-turbo-2024-04-09" FIXING_MODEL: "gpt-4-turbo-2024-04-09" # DEVELOPER SETTINGS # VERSION_NUMBER: "0.1.1" # PROMPT SETTINGS # # If you don't know what it is, please don't touch it. Be sure to backup before editing. ## Code Generation ## SYS_GEN: | You're a minecraft bukkit plugin coder AI. Game Version: 1.13.2 (1.13.2-R0.1-SNAPSHOT) Write the code & choose a artifact name for the following files with the infomation which is also provided by the user: codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml codes/%ARTIFACT_NAME%/src/main/resources/config.yml codes/%ARTIFACT_NAME%/pom.xml Response in json format: { \"codes\": [ { \"file\": \"codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java\", \"code\": \"package ...;\\nimport org.bukkit.Bukkit;\\npublic class Main extends JavaPlugin implements CommandExecutor {\\n... (The code you need to write)\" }, { \"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml\", \"code\": \"name: ...\\nversion: ...\\n...\" }, { \"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/config.yml\", \"code\": \"...\" }, { \"file\": \"codes/%ARTIFACT_NAME%/pom.xml\", \"code\": \"...\" } ] } You should never response anything else. Never use Markdown format. Use \n for line feed, and never forget to use \ before ". Never write uncompeleted codes, such as leave a comment that says "// Your codes here" or "// Uncompeleted". USR_GEN: | %DESCRIPTION% SYS_FIX: | You're a minecraft bukkit plugin coder AI. Game Version: 1.13.2 (1.13.2-R0.1-SNAPSHOT) Fix the error in the code provided by user. The error message is also provided by the user. Response in json format: { \"codes\": [ { \"file\": \"codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java\", \"code\": \"package ...;\\nimport org.bukkit.Bukkit;\\npublic class Main extends JavaPlugin implements CommandExecutor {\\n... (The code you need to write)\" }, { \"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml\", \"code\": \"name: ...\\nversion: ...\\n...\" }, { \"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/config.yml\", \"code\": \"...\" }, { \"file\": \"codes/%ARTIFACT_NAME%/pom.xml\", \"code\": \"...\" } ] } You should never response anything else. Never use Markdown format. Use \n for line feed, and never forget to use \ before ". Never write uncompeleted codes, such as leave a comment that says "// Your codes here" or "// Original code" or "// Uncompeleted". USR_FIX: | Main.java: %MAIN_JAVA% plugin.yml: %PLUGIN_YML% config.yml: %CONFIG_YML% pom.xml: %POM_XML% error message: %P_ERROR_MSG% File: console.py import sys import uuid import shutil from log_writer import logger import core import config import build if __name__ == "__main__": main_java = None plugin_yml = None config_yml = None pom_xml = None core.initialize() print("BukkitGPT v3 beta console running") # Get user inputs name = input("Enter the plugin name: ") description = input("Enter the plugin description: ") artifact_name = name.replace(" ", "") package_id = f"org.cubegpt.{uuid.uuid4().hex[:8]}" pkg_id_path = "" for id in package_id.split("."): pkg_id_path += id + "/" logger(f"user_input -> name: {name}") logger(f"user_input -> description: {description}") logger(f"random_generate -> package_id: {package_id}") logger(f"str_path -> pkg_id_path: {pkg_id_path}") print("Generating plugin...") codes = core.askgpt( config.SYS_GEN.replace("%ARTIFACT_NAME%", artifact_name).replace( "%PKG_ID_LST%", pkg_id_path ), config.USR_GEN.replace("%DESCRIPTION", description), config.GENERATION_MODEL, ) logger(f"codes: {codes}") core.response_to_action(codes) print("Code generated. Building now...") result = build.build_plugin(artifact_name) if "BUILD SUCCESS" in result: print( f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" ) elif "Compilation failure": print("Build failed. Passing the error to ChatGPT and let it to fix it?") fix = input("Y/n: ") if fix == "n": print("Exiting...") sys.exit(0) else: print("Passing the error to ChatGPT...") files = [ f"codes/{artifact_name}/src/main/java/{pkg_id_path}Main.java", f"codes/{artifact_name}/src/main/resources/plugin.yml", f"codes/{artifact_name}/src/main/resources/config.yml", f"codes/{artifact_name}/pom.xml", ] ids = ["main_java", "plugin_yml", "config_yml", "pom_xml"] for file in files: with open(file, "r") as f: code = f.read() id = ids[files.index(file)] globals()[id] = code print("Generating...") codes = core.askgpt( config.SYS_FIX.replace("%ARTIFACT_NAME%", artifact_name), config.USR_FIX.replace("%MAIN_JAVA%", main_java) .replace("%PLUGIN_YML%", plugin_yml) .replace("%CONFIG_YML%", config_yml) .replace("%POM_XML%", pom_xml) .replace("%P_ERROR_MSG%", result), config.FIXING_MODEL, ) shutil.rmtree(f"codes/{artifact_name}") core.response_to_action(codes) print("Code generated. Building now...") result = build.build_plugin(artifact_name) if "BUILD SUCCESS" in result: print( f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" ) else: print( "Build failed. Please check the logs && send the log to @BaimoQilin on discord." ) print("Exiting...") sys.exit(0) else: print( "Unknown error. Please check the logs && send the log to @BaimoQilin on discord." ) print("Exiting...") sys.exit(0) else: print( "Error: Please run console.py as the main program instead of importing it from another program." ) File: core.py from openai import OpenAI import chardet import sys import json import locale import os from log_writer import logger import config def initialize(): """ Initializes the software. This function logs the software launch, including the version number and platform. Args: None Returns: None """ locale.setlocale(locale.LC_ALL, "en_US.UTF-8") logger(f"Launch. Software version {config.VERSION_NUMBER}, platform {sys.platform}") if ( "gpt-3.5" in config.GENERATION_MODEL and config.BYPASS_NO_GPT35_FOR_GENERATION_LIMIT is False ): print( "gpt-3.5 writes bugs *all the time* and is not recommended for code generation. Switching to gpt-4." ) config.edit_config( "GENERATION_MODEL", config.GENERATION_MODEL.replace("gpt-3.5", "gpt-4") ) def askgpt( system_prompt: str, user_prompt: str, model_name: str, disable_json_mode: bool = False, image_url: str = None, ): """ Interacts with ChatGPT using the specified prompts. Args: system_prompt (str): The system prompt. user_prompt (str): The user prompt. model_name (str): The model name to use. disable_json_mode (bool): Whether to disable JSON mode. Returns: str: The response from ChatGPT. """ if image_url is not None and config.USE_DIFFERENT_APIKEY_FOR_VISION_MODEL: logger("Using different API key for vision model.") client = OpenAI(api_key=config.VISION_API_KEY, base_url=config.VISION_BASE_URL) else: client = OpenAI(api_key=config.API_KEY, base_url=config.BASE_URL) logger("Initialized the OpenAI client.") # Define the messages for the conversation if image_url is not None: messages = [ {"role": "system", "content": system_prompt}, { "role": "user", "content": [ {"type": "text", "text": user_prompt}, {"type": "image_url", "image_url": {"url": image_url}}, ], }, ] else: messages = [ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt}, ] logger(f"askgpt: system {system_prompt}") logger(f"askgpt: user {user_prompt}") # Create a chat completion if disable_json_mode: response = client.chat.completions.create(model=model_name, messages=messages) else: response = client.chat.completions.create( model=model_name, response_format={"type": "json_object"}, messages=messages ) logger(f"askgpt: response {response}") # Extract the assistant's reply assistant_reply = response.choices[0].message.content logger(f"askgpt: extracted reply {assistant_reply}") return assistant_reply def response_to_action(msg): """ Converts a response from ChatGPT to an action. Args: msg (str): The response from ChatGPT. Returns: str: The action to take. """ text = json.loads(msg) codes = text["codes"] for section in codes: file = section["file"] code = section["code"] paths = file.split("/") # Join the list elements to form a path path = os.path.join(*paths) # Get the directory path and the file name dir_path, file_name = os.path.split(path) # Create directories, if they don't exist try: os.makedirs(dir_path, exist_ok=True) except FileNotFoundError: pass # Create the file with open(path, "w") as f: f.write(code) # Write an empty string to the file def mixed_decode(text: str): """ Decode a mixed text containing both normal text and a byte sequence. Args: text (str): The mixed text to be decoded. Returns: str: The decoded text, where the byte sequence has been converted to its corresponding characters. """ # Split the normal text and the byte sequence # Assuming the byte sequence is everything after the last colon and space ": " try: normal_text, byte_text = text.rsplit(": ", 1) except (TypeError, ValueError): # The text only contains normal text return text # Convert the byte sequence to actual bytes byte_sequence = byte_text.encode( "latin1" ) # latin1 encoding maps byte values directly to unicode code points # Detect the encoding of the byte sequence detected_encoding = chardet.detect(byte_sequence) encoding = detected_encoding["encoding"] # Decode the byte sequence decoded_text = byte_sequence.decode(encoding) # Combine the normal text with the decoded byte sequence final_text = normal_text + ": " + decoded_text return final_text if __name__ == "__main__": print("This script is not meant to be run directly. Please run console.py instead.") File: log_writer.py import os from datetime import datetime first_call_time = None def get_log_filename(): global first_call_time if first_call_time is None: first_call_time = datetime.now() log_filename = first_call_time.strftime("logs/%b-%d-%H-%M-%S-%Y") return log_filename def logger(text: str): log_filename = get_log_filename() timestamp_prefix = datetime.now().strftime("[%H:%M:%S]") log_line = f"{timestamp_prefix} {text}\n" os.makedirs(os.path.dirname(log_filename), exist_ok=True) with open(log_filename + ".log", "a", encoding="utf-8") as log_file: log_file.write(log_line) File: requirements.txt openai>=1.13.3 pyyaml cx_Freeze ttkbootstrap playwright chardet File: ui.py from cube_qgui.__init__ import CreateQGUI from cube_qgui.banner_tools import * from cube_qgui.notebook_tools import * from playwright.sync_api import Playwright, sync_playwright import os import shutil import uuid from log_writer import logger import config import core import build # ---------- Functions ----------# def open_config(args: dict): """ Opens the config file. Args: args (dict): A dictionary containing the necessary arguments. Returns: bool: Always True. """ os.system("notepad config.yaml") return True def save_apply_config(args: dict): """ Saves and applies the configuration. Args: args (dict): A dictionary containing the necessary arguments. Returns: bool: Always True. """ keys = ["API_KEY", "BASE_URL"] for key in keys: value = args[key].get() if key == "ADVANCED_MODE": value = True if value == 1 else False else: pass config.edit_config(key, value) config.load_config() args["DevTool_CONFIG_API_KEY_DISPLAY"].set(f"CONFIG.API_KEY = {config.API_KEY}") args["DevTools_CONFIG_BASE_URL_DISPLAY"].set(f"CONFIG.BASE_URL = {config.BASE_URL}") return True def load_config(args: dict): """ Loads the configuration. Args: args (dict): A dictionary containing the necessary arguments. Returns: bool: Always True. """ config.load_config() args["API_KEY"].set(config.API_KEY) args["BASE_URL"].set(config.BASE_URL) return True def print_args(args: dict): """ Prints the arguments. Args: args (dict): A dictionary containing the arguments. Returns: bool: Always True. """ for arg, v_fun in args.items(): print(f"Name: {arg}, Value: {v_fun.get()}") return True def raise_error(args: dict): """ Raises an error. Args: args (dict): A dictionary containing the arguments. """ raise Exception("This is a test error.") # ---------- Generate Function ----------# def generate(args: dict): """ Generates the plugin. Args: args (dict): A dictionary containing the arguments. Returns: bool: Always True. """ global error_msg, pkg_id_path # Get user inputs name = args["PluginName"].get() description = args["PluginDescription"].get() artifact_name = name.replace(" ", "") package_id = f"org.cubegpt.{uuid.uuid4().hex[:8]}" pkg_id_path = "" for id in package_id.split("."): pkg_id_path += id + "/" logger(f"user_input -> name: {name}") logger(f"user_input -> description: {description}") logger(f"random_generate -> package_id: {package_id}") logger(f"str_path -> pkg_id_path: {pkg_id_path}") print("Generating plugin...") codes = core.askgpt( config.SYS_GEN.replace("%ARTIFACT_NAME%", artifact_name).replace( "%PKG_ID_LST%", pkg_id_path ), config.USR_GEN.replace("%DESCRIPTION", description), config.GENERATION_MODEL, ) logger(f"codes: {codes}") core.response_to_action(codes) print("Code generated. Building now...") result = build.build_plugin(artifact_name) if "BUILD SUCCESS" in result: print( f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" ) elif "Compilation failure": error_msg = result print( "Build failed. To pass the error to ChatGPT && let it fix, jump to the Fixing page and click the Fix button." ) else: print( "Unknown error. Please check the logs && send the log to @BaimoQilin on discord." ) return True def fix(args: dict): """ Fixes the error. Args: args (dict): A dictionary containing the arguments. Returns: bool: Always True. """ artifact_name = args["PluginName"].get() print("Passing the error to ChatGPT...") files = [ f"codes/{artifact_name}/src/main/java/{pkg_id_path}Main.java", f"codes/{artifact_name}/src/main/resources/plugin.yml", f"codes/{artifact_name}/src/main/resources/config.yml", f"codes/{artifact_name}/pom.xml", ] ids = ["main_java", "plugin_yml", "config_yml", "pom_xml"] main_java = None plugin_yml = None config_yml = None pom_xml = None for file in files: with open(file, "r") as f: code = f.read() id = ids[files.index(file)] globals()[id] = code print("Generating...") codes = core.askgpt( config.SYS_FIX.replace("%ARTIFACT_NAME%", str(artifact_name)), config.USR_FIX.replace("%MAIN_JAVA%", str(main_java)) .replace("%PLUGIN_YML%", str(plugin_yml)) .replace("%CONFIG_YML%", str(config_yml)) .replace("%POM_XML%", str(pom_xml)) .replave("%PKG_ID_LST%", pkg_id_path) .replace("%P_ERROR_MSG%", str(error_msg)), config.FIXING_MODEL, ) shutil.rmtree(f"codes/{artifact_name}") core.response_to_action(codes) print("Code generated. Building now...") result = build.build_plugin(artifact_name) if "BUILD SUCCESS" in result: print( f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" ) else: print( "Build failed again. Please check the logs && send the log to @BaimoQilin on discord." ) return True # ---------- Main Program ----------# root = CreateQGUI(title="BukkitGPT-v3", tab_names=["Generate", "Settings", "DevTools"]) error_msg = None logger("Starting program.") # Initialize Core core.initialize() print("BukkitGPT v3 beta console running") # Banner root.add_banner_tool(GitHub("https://github.com/CubeGPT/BukkitGPT-v3")) # Generate Page root.add_notebook_tool( InputBox(name="PluginName", default="ExamplePlugin", label_info="Plugin Name") ) root.add_notebook_tool( InputBox( name="PluginDescription", default="Send msg 'hello' to every joined player.", label_info="Plugin Description", ) ) root.add_notebook_tool( RunButton( bind_func=generate, name="Generate", text="Generate Plugin", checked_text="Generating...", tab_index=0, ) ) # Fixing Page # # root.add_notebook_tool(Label(name="Fixing_DESCRIPTION", text="This is a fixing page. If the build fails, click the Fix button to fix the error in the LATEST build.", tab_index=1)) # root.add_notebook_tool(RunButton(bind_func=fix, name="Fix", text="Fix", checked_text="Fixing...", tab_index=1)) # Settings Page root.add_notebook_tool( InputBox(name="API_KEY", default=config.API_KEY, label_info="API Key", tab_index=1) ) root.add_notebook_tool( InputBox( name="BASE_URL", default=config.BASE_URL, label_info="BASE URL", tab_index=1 ) ) config_buttons = HorizontalToolsCombine( [ BaseButton( bind_func=save_apply_config, name="Save & Apply Config", text="Save & Apply", tab_index=1, ), BaseButton( bind_func=load_config, name="Load Config", text="Load Config", tab_index=1 ), BaseButton( bind_func=open_config, name="Open Config", text="Open Full Config", tab_index=1, ), ] ) root.add_notebook_tool(config_buttons) # DevTools Page root.add_notebook_tool( Label( name="DevTool_DESCRIPTION", text="This is a testing page for developers. Ignore it if you are a normal user.", tab_index=2, ) ) root.add_notebook_tool( Label( name="DevTool_CONFIG_API_KEY_DISPLAY", text=f"CONFIG.API_KEY = {config.API_KEY}", tab_index=2, ) ) root.add_notebook_tool( Label( name="DevTools_CONFIG_BASE_URL_DISPLAY", text=f"CONFIG.BASE_URL = {config.BASE_URL}", tab_index=2, ) ) root.add_notebook_tool( RunButton(bind_func=print_args, name="Print Args", text="Print Args", tab_index=2) ) root.add_notebook_tool( RunButton( bind_func=raise_error, name="Raise Error", text="Raise Error", tab_index=2 ) ) # Sidebar root.set_navigation_about( author="CubeGPT Team", version=config.VERSION_NUMBER, github_url="https://github.com/CubeGPT/BukkitGPT-v3", ) # Run root.run() PROMPT: 添加生成DataPack的选项,使得用户可以选择生成Bukkit插件或者DataPack。 在`ui.py`中可以在Generate Page里添加这行代码 `root.add_notebook_tool(RadioObviousToolButton(options=["BukkitPlugin", "Datapack(Experimental)"], name="GenerationType", title="Type", default="BukkitPlugin",tab_index=0))` 你还需要自行完成DataPack的生成逻辑。你可能需要更改的文件有`ui.py`, `core.py`, `config.yaml`, `console.py`。你还可能需要创建一些新的文件或文件夹,也有可能不需要。祝你好运。 2024-07-25T12:12:18.250819 CONSOLE OUTPUT: Error while improving the project: "Could not resolve authentication method. Expected either api_key or auth_token to be set. Or for one of the `X-Api-Key` or `Authorization` headers to be explicitly omitted" Could you please upload the debug_log_file.txt in D:\zhousl\BukkitGPT\BukkitGPT-v3\.gpteng\memory/logs folder to github? FULL STACK TRACE: Traceback (most recent call last): File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 379, in handle_improve_mode files_dict = agent.improve(files_dict, prompt) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\applications\cli\cli_agent.py", line 208, in improve files_dict = self.improve_fn( ^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 311, in improve_fn return _improve_loop(ai, files_dict, memory, messages) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 317, in _improve_loop messages = ai.next(messages, step_name=curr_fn()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\ai.py", line 243, in next response = self.backoff_inference(messages) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\backoff\_sync.py", line 105, in retry ret = target(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\ai.py", line 287, in backoff_inference return self.llm.invoke(messages) # type: ignore ^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 270, in invoke self.generate_prompt( File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 703, in generate_prompt return self.generate(prompt_messages, stop=stop, callbacks=callbacks, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 560, in generate raise e File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 550, in generate self._generate_with_cache( File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 775, in _generate_with_cache result = self._generate( ^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_anthropic\chat_models.py", line 755, in _generate return generate_from_stream(stream_iter) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 102, in generate_from_stream generation = next(stream, None) ^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_anthropic\chat_models.py", line 676, in _stream stream = self._client.messages.create(**payload) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_utils\_utils.py", line 277, in wrapper return func(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\resources\messages.py", line 902, in create return self._post( ^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 1266, in post return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 942, in request return self._request( ^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 968, in _request request = self._build_request(options) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 461, in _build_request headers = self._build_headers(options) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 416, in _build_headers self._validate_headers(headers_dict, custom_headers) File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_client.py", line 192, in _validate_headers raise TypeError( TypeError: "Could not resolve authentication method. Expected either api_key or auth_token to be set. Or for one of the `X-Api-Key` or `Authorization` headers to be explicitly omitted"