From 93bcd444d272ed77e3976b0fcd77e965f17b1d2b Mon Sep 17 00:00:00 2001 From: retoor Date: Sun, 28 Sep 2025 08:31:47 +0200 Subject: [PATCH] Update, API version. --- botje.py | 109 +++++++++++++++++++++++++------------------------------ 1 file changed, 49 insertions(+), 60 deletions(-) mode change 100644 => 100755 botje.py diff --git a/botje.py b/botje.py old mode 100644 new mode 100755 index 6049f53..d929e09 --- a/botje.py +++ b/botje.py @@ -1,13 +1,11 @@ -#!/usr/bin/env python3 import os import argparse import json import subprocess -from openai import OpenAI import sys import shlex +import requests -# ANSI escape codes for colors class Colors: RED = '\033[91m' GREEN = '\033[92m' @@ -17,28 +15,13 @@ class Colors: CYAN = '\033[96m' RESET = '\033[0m' -# Initialize the OpenAI client -# It will automatically pick up the OPENAI_API_KEY from your environment variables. -try: - client = OpenAI() -except ImportError: - print(f"{Colors.RED}OpenAI Python package not found. Please install it with 'pip install openai'{Colors.RESET}") - exit(1) -except Exception as e: - print(f"{Colors.RED}Error initializing OpenAI client: {e}{Colors.RESET}") - print(f"{Colors.YELLOW}Please ensure your OPENAI_API_KEY environment variable is set correctly.{Colors.RESET}") +api_key = os.environ.get("OPENAI_API_KEY") +if not api_key: + print(f"{Colors.RED}Error: OPENAI_API_KEY environment variable not set.{Colors.RESET}") exit(1) class AutonomousBot: - """ - An autonomous bot that executes tasks based on a user prompt. - It can call functions, manage its state, and decompose complex tasks. - """ - def __init__(self, prompt, memory=None): - """ - Initializes the bot with a prompt and an optional memory of past actions. - """ self.initial_prompt = prompt self.memory = memory if memory is not None else [] self.is_finished = False @@ -156,7 +139,6 @@ class AutonomousBot: } def get_system_prompt(self): - """Constructs the system prompt for the AI model.""" return f"""You are an autonomous AI builder bot. Your goal is to accomplish the user's request by calling functions to interact with the system. You have complete CRUD access to the filesystem and can execute terminal commands. Be aware of your actions and their consequences. @@ -179,10 +161,7 @@ Here is a summary of the steps taken so far: """ def run(self): - """ - Main execution loop for the bot. - """ - print(f"{Colors.GREEN}▶ Starting bot with prompt: '{self.initial_prompt}'{Colors.RESET}") + print(f"{Colors.GREEN}Starting bot with prompt: '{self.initial_prompt}'{Colors.RESET}") messages = [ {"role": "system", "content": self.get_system_prompt()}, @@ -191,21 +170,33 @@ Here is a summary of the steps taken so far: while not self.is_finished: try: - print(f"\n{Colors.BLUE}🤔 Thinking...{Colors.RESET}") - response = client.chat.completions.create( - model="gpt-4-turbo", - messages=messages, - tools=self.tools, - tool_choice="auto", - ) + print(f"\n{Colors.BLUE}Thinking...{Colors.RESET}") - response_message = response.choices[0].message + headers = { + "Content-Type": "application/json", + "Authorization": f"Bearer {api_key}" + } + payload = { + "model": "gpt-4-turbo", + "messages": messages, + "tools": self.tools, + "tool_choice": "auto" + } + + response_raw = requests.post("https://api.openai.com/v1/chat/completions", headers=headers, json=payload) + + if response_raw.status_code != 200: + print(f"{Colors.RED}Error from OpenAI API: {response_raw.status_code} - {response_raw.text}{Colors.RESET}") + break + + response_json = response_raw.json() + response_message = response_json['choices'][0]['message'] messages.append(response_message) - tool_calls = response_message.tool_calls + tool_calls = response_message.get('tool_calls') if not tool_calls: - print(f"\n{Colors.CYAN}🤖 AI Response (no tool call):{Colors.RESET}") - no_tool_call_message = response_message.content or "No text content in response." + print(f"\n{Colors.CYAN}AI Response (no tool call):{Colors.RESET}") + no_tool_call_message = response_message.get('content') or "No text content in response." print(no_tool_call_message) messages.append({ @@ -215,25 +206,25 @@ Here is a summary of the steps taken so far: continue for tool_call in tool_calls: - function_name = tool_call.function.name + function_name = tool_call['function']['name'] function_to_call = self.available_functions.get(function_name) function_args = {} if not function_to_call: - print(f"{Colors.RED}❌ Unknown function called by model: {function_name}{Colors.RESET}") + print(f"{Colors.RED}Unknown function called by model: {function_name}{Colors.RESET}") tool_result = {"status": "error", "message": f"Unknown function: {function_name}"} else: try: - function_args = json.loads(tool_call.function.arguments) - print(f"\n{Colors.GREEN}▶ Calling function: `{function_name}` with arguments:{Colors.RESET}") + function_args = json.loads(tool_call['function']['arguments']) + print(f"\n{Colors.GREEN}Calling function: `{function_name}` with arguments:{Colors.RESET}") print(json.dumps(function_args, indent=2)) tool_result = function_to_call(**function_args) except Exception as e: - print(f"{Colors.RED}❌ Error calling function '{function_name}': {e}{Colors.RESET}") + print(f"{Colors.RED}Error calling function '{function_name}': {e}{Colors.RESET}") tool_result = {"status": "error", "message": str(e)} messages.append({ - "tool_call_id": tool_call.id, + "tool_call_id": tool_call['id'], "role": "tool", "name": function_name, "content": json.dumps(tool_result), @@ -245,7 +236,7 @@ Here is a summary of the steps taken so far: }) except Exception as e: - print(f"\n{Colors.RED}❌ An unexpected error occurred in the main loop: {e}{Colors.RESET}") + print(f"\n{Colors.RED}An unexpected error occurred in the main loop: {e}{Colors.RESET}") break def _write_file(self, filepath, content, purpose=""): @@ -256,10 +247,10 @@ Here is a summary of the steps taken so far: with open(filepath, 'w', encoding='utf-8') as f: f.write(content) purpose_text = f" ({purpose})" if purpose else "" - print(f"{Colors.GREEN}✅ File '{filepath}' created{purpose_text} successfully.{Colors.RESET}") + print(f"{Colors.GREEN}File '{filepath}' created{purpose_text} successfully.{Colors.RESET}") return {"status": "success", "filepath": filepath} except Exception as e: - print(f"{Colors.RED}❌ Error creating file '{filepath}': {e}{Colors.RESET}") + print(f"{Colors.RED}Error creating file '{filepath}': {e}{Colors.RESET}") return {"status": "error", "message": str(e)} def create_file(self, filepath, content): @@ -272,25 +263,25 @@ Here is a summary of the steps taken so far: try: with open(filepath, 'r', encoding='utf-8') as f: content = f.read() - print(f"{Colors.GREEN}✅ File '{filepath}' read successfully.{Colors.RESET}") + print(f"{Colors.GREEN}File '{filepath}' read successfully.{Colors.RESET}") return {"status": "success", "content": content} except FileNotFoundError: - print(f"{Colors.RED}❌ File not found: '{filepath}'{Colors.RESET}") + print(f"{Colors.RED}File not found: '{filepath}'{Colors.RESET}") return {"status": "error", "message": "File not found."} except Exception as e: - print(f"{Colors.RED}❌ Error reading file '{filepath}': {e}{Colors.RESET}") + print(f"{Colors.RED}Error reading file '{filepath}': {e}{Colors.RESET}") return {"status": "error", "message": str(e)} def delete_file(self, filepath): try: os.remove(filepath) - print(f"{Colors.GREEN}✅ File '{filepath}' deleted successfully.{Colors.RESET}") + print(f"{Colors.GREEN}File '{filepath}' deleted successfully.{Colors.RESET}") return {"status": "success", "filepath": filepath} except FileNotFoundError: - print(f"{Colors.RED}❌ File not found: '{filepath}'{Colors.RESET}") + print(f"{Colors.RED}File not found: '{filepath}'{Colors.RESET}") return {"status": "error", "message": "File not found."} except Exception as e: - print(f"{Colors.RED}❌ Error deleting file '{filepath}': {e}{Colors.RESET}") + print(f"{Colors.RED}Error deleting file '{filepath}': {e}{Colors.RESET}") return {"status": "error", "message": str(e)} def terminal_execute(self, command): @@ -311,11 +302,11 @@ Here is a summary of the steps taken so far: print(f" - Return Code: {result.returncode}") return output except Exception as e: - print(f"{Colors.RED}❌ Error executing command '{command}': {e}{Colors.RESET}") + print(f"{Colors.RED}Error executing command '{command}': {e}{Colors.RESET}") return {"status": "error", "message": str(e), "stdout": "", "stderr": str(e), "returncode": -1} def finish_task(self, reason): - print(f"\n{Colors.YELLOW}🏁 BOT INSTANCE FINISHED: {reason}{Colors.RESET}") + print(f"\n{Colors.YELLOW}BOT INSTANCE FINISHED: {reason}{Colors.RESET}") self.is_finished = True return {"status": "finished"} @@ -323,13 +314,13 @@ Here is a summary of the steps taken so far: print("\n" + "="*50) print(" PYRAMID OF BUILDERS") print("="*50) - print(f"{Colors.MAGENTA}🚀 Delegating remaining prompt to a new bot instance...{Colors.RESET}") + print(f"{Colors.MAGENTA}Delegating remaining prompt to a new bot instance...{Colors.RESET}") print(f" python {__file__} \"{remaining_prompt}\"") try: subprocess.Popen([sys.executable, __file__, remaining_prompt]) - print(f"{Colors.GREEN}✅ New bot instance launched successfully.{Colors.RESET}") + print(f"{Colors.GREEN}New bot instance launched successfully.{Colors.RESET}") except Exception as e: - print(f"{Colors.RED}❌ Failed to launch new bot instance: {e}{Colors.RESET}") + print(f"{Colors.RED}Failed to launch new bot instance: {e}{Colors.RESET}") return {"status": "error", "message": f"Failed to delegate: {e}"} self.initial_prompt = current_task_prompt @@ -338,9 +329,6 @@ Here is a summary of the steps taken so far: return {"status": "success", "message": "Task split. This bot will now handle the first part."} def main(): - """ - Entry point for the CLI application. - """ parser = argparse.ArgumentParser(description="An autonomous bot to execute tasks.") parser.add_argument("prompt", type=str, help="The user prompt describing the task to be done.") args = parser.parse_args() @@ -350,3 +338,4 @@ def main(): if __name__ == "__main__": main() +