behebe alle oprobleme in folgendem skript und erstelle einen voll funktionstüchtigen code der gesamten anwendung. Zum beispiel liegt ein problem vor das beim klicken in die rechte hälfte des guis die anwendung vollständig einfriert und nicht mehr reagiert. Die linke seite scheint soweit zu funktionieren. prüe aber nocheinmal alle bereiche der anwendung und behebe alle probleme und fehler die du fidnest, verbesser auch dabei die visuelle darsytellung und das desihn des gui, sowie das layout und sorge dafür das die anwendung intuitiv und nutzerfreundlich verwendet werden kann. sorge auch dafür das alle funktionen vollständig implentiert und funktionierend sind. erstelle dann den vollständigen überarbeiteten code der gersamten anwendung.



import sys
import os
import requests
import json
import datetime
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, 
                             QPushButton, QTextEdit, QLineEdit, QLabel, QComboBox, QFileDialog, 
                             QMessageBox, QProgressBar, QSplitter, QInputDialog, QToolTip,
                             QListWidget, QTabWidget, QDialog)
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QSettings, QTimer
from PyQt5.QtGui import QFont, QColor, QTextCursor, QSyntaxHighlighter, QTextCharFormat

class CodeHighlighter(QSyntaxHighlighter):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.highlighting_rules = []

        keyword_format = QTextCharFormat()
        keyword_format.setForeground(Qt.darkBlue)
        keyword_format.setFontWeight(QFont.Bold)
        keywords = ["def", "class", "import", "from", "for", "while", "if", "else", "elif", "try", "except", "finally"]
        for word in keywords:
            self.highlighting_rules.append((f"\b{word}\b", keyword_format))

        string_format = QTextCharFormat()
        string_format.setForeground(Qt.darkGreen)
        self.highlighting_rules.append((r'".*?"', string_format))
        self.highlighting_rules.append((r"'.*?'", string_format))

    def highlightBlock(self, text):
        for pattern, format in self.highlighting_rules:
            expression = pattern
            index = text.indexOf(expression)
            while index >= 0:
                length = len(expression)
                self.setFormat(index, length, format)
                index = text.indexOf(expression, index + length)

class RobocoderAPI:
    def __init__(self, api_key):
        self.API_BASE_URL = "https://api.robocoders.ai"
        self.API_KEY = api_key
        self.session_id = None

    def create_session(self):
        url = f"{self.API_BASE_URL}/create-session"
        headers = {"Authorization": f"Bearer {self.API_KEY}"}
        response = requests.get(url, headers=headers)
        if response.status_code == 200:
            self.session_id = response.json()["sid"]
            return self.session_id
        else:
            raise Exception(f"Failed to create session: {response.text}")

    def chat_with_agent(self, prompt, agent, context=None):
        if not self.session_id:
            raise Exception("No active session. Please create a session first.")
        
        url = f"{self.API_BASE_URL}/chat"
        headers = {
            "Authorization": f"Bearer {self.API_KEY}",
            "Content-Type": "application/json"
        }
        data = {
            "sid": self.session_id,
            "prompt": prompt,
            "agent": agent
        }
        if context:
            data["context"] = context
        response = requests.post(url, headers=headers, json=data)
        if response.status_code == 200:
            return response.text
        else:
            raise Exception(f"Chat failed: {response.text}")

    def get_session_code(self, github_username):
        if not self.session_id:
            raise Exception("No active session. Please create a session first.")
        
        url = f"{self.API_BASE_URL}/get-session-code"
        headers = {
            "Authorization": f"Bearer {self.API_KEY}",
            "Content-Type": "application/json"
        }
        data = {
            "sid": self.session_id,
            "github_username": github_username
        }
        response = requests.post(url, headers=headers, json=data)
        if response.status_code == 200:
            return response.json()
        else:
            raise Exception(f"Failed to get session code: {response.text}")

class ChatWorker(QThread):
    finished = pyqtSignal(str)
    error = pyqtSignal(str)
    progress = pyqtSignal(int)

    def __init__(self, api, prompt, agent, context=None):
        super().__init__()
        self.api = api
        self.prompt = prompt
        self.agent = agent
        self.context = context

    def run(self):
        try:
            self.progress.emit(10)
            response = self.api.chat_with_agent(self.prompt, self.agent, self.context)
            self.progress.emit(90)
            self.finished.emit(response)
            self.progress.emit(100)
        except Exception as e:
            self.error.emit(str(e))
            self.progress.emit(100)

class APIKeyDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("API Key")
        layout = QVBoxLayout()
        self.api_key_input = QLineEdit()
        layout.addWidget(QLabel("Enter your Robocoder API Key:"))
        layout.addWidget(self.api_key_input)
        buttons = QHBoxLayout()
        ok_button = QPushButton("OK")
        ok_button.clicked.connect(self.accept)
        cancel_button = QPushButton("Cancel")
        cancel_button.clicked.connect(self.reject)
        buttons.addWidget(ok_button)
        buttons.addWidget(cancel_button)
        layout.addLayout(buttons)
        self.setLayout(layout)

    def get_api_key(self):
        return self.api_key_input.text()

class RobocoderApp(QMainWindow):
    def __init__(self):
        super().__init__()
        self.settings = QSettings("RobocoderApp", "ApiSettings")
        self.api_key = self.settings.value("api_key", "")
        if not self.api_key:
            self.get_api_key()
        self.api = RobocoderAPI(self.api_key)
        self.chat_archives = {}
        self.current_chat_id = None
        self.init_ui()

    def get_api_key(self):
        dialog = APIKeyDialog(self)
        if dialog.exec_():
            self.api_key = dialog.get_api_key()
            self.settings.setValue("api_key", self.api_key)
        else:
            sys.exit()

    def init_ui(self):
        self.setWindowTitle('Robocoder Application')
        self.setGeometry(100, 100, 1200, 800)
        self.setStyleSheet("QMainWindow{background-color: #f0f0f0;}")

        main_layout = QHBoxLayout()

        # Left panel for chat and file list
        left_panel = QWidget()
        left_layout = QVBoxLayout()

        # Chat archives
        self.chat_list = QListWidget()
        self.chat_list.itemClicked.connect(self.load_chat)
        left_layout.addWidget(QLabel('Chat Archives:'))
        left_layout.addWidget(self.chat_list)

        # New chat button
        new_chat_button = QPushButton('New Chat')
        new_chat_button.clicked.connect(self.new_chat)
        left_layout.addWidget(new_chat_button)

        # File list
        self.file_list = QListWidget()
        self.file_list.itemClicked.connect(self.open_file)
        left_layout.addWidget(QLabel('Files:'))
        left_layout.addWidget(self.file_list)

        left_panel.setLayout(left_layout)

        # Right panel for chat and file content
        right_panel = QWidget()
        right_layout = QVBoxLayout()

        # Tabs for chat and file content
        self.tabs = QTabWidget()
        self.chat_tab = QWidget()
        self.file_tab = QWidget()
        self.tabs.addTab(self.chat_tab, "Chat")
        self.tabs.addTab(self.file_tab, "File")

        # Chat tab
        chat_layout = QVBoxLayout()
        self.chat_history = QTextEdit()
        self.chat_history.setReadOnly(True)
        self.chat_history.setStyleSheet("QTextEdit{background-color: #ffffff; border: 1px solid #cccccc; border-radius: 5px;}")
        self.agent_combo = QComboBox()
        self.agent_combo.addItems(["GeneralCodingAgent", "RepoAgent", "FrontEndAgent"])
        self.agent_combo.setToolTip("Select the AI agent you want to interact with")
        self.prompt_input = QLineEdit()
        self.prompt_input.setPlaceholderText("Type your message here...")
        self.prompt_input.setToolTip("Enter your message or question for the AI")
        self.send_button = QPushButton('Send')
        self.send_button.clicked.connect(self.send_message)
        self.send_button.setToolTip("Send your message to the AI")
        self.send_button.setStyleSheet("QPushButton{background-color: #4CAF50; color: white; border-radius: 5px; padding: 5px;}")
        self.progress_bar = QProgressBar()
        self.progress_bar.setVisible(False)

        chat_layout.addWidget(self.chat_history)
        chat_layout.addWidget(QLabel('Select Agent:'))
        chat_layout.addWidget(self.agent_combo)
        chat_layout.addWidget(QLabel('Enter Prompt:'))
        chat_layout.addWidget(self.prompt_input)
        chat_layout.addWidget(self.send_button)
        chat_layout.addWidget(self.progress_bar)
        self.chat_tab.setLayout(chat_layout)

        # File tab
        file_layout = QVBoxLayout()
        self.file_content = QTextEdit()
        self.file_content.setToolTip("Content of the selected file")
        self.highlighter = CodeHighlighter(self.file_content.document())
        self.save_file_button = QPushButton('Save File')
        self.save_file_button.clicked.connect(self.save_file)
        self.save_file_button.setToolTip("Save changes to the current file")

        file_layout.addWidget(self.file_content)
        file_layout.addWidget(self.save_file_button)
        self.file_tab.setLayout(file_layout)

        right_layout.addWidget(self.tabs)

        # Status bar
        self.status_bar = QLabel()
        right_layout.addWidget(self.status_bar)

        right_panel.setLayout(right_layout)

        # Add panels to main layout
        splitter = QSplitter(Qt.Horizontal)
        splitter.addWidget(left_panel)
        splitter.addWidget(right_panel)
        main_layout.addWidget(splitter)

        central_widget = QWidget()
        central_widget.setLayout(main_layout)
        self.setCentralWidget(central_widget)

        # Initialize session
        self.new_chat()

        # Update file list
        self.update_file_list()

        # Set up auto-save timer
        self.auto_save_timer = QTimer(self)
        self.auto_save_timer.timeout.connect(self.auto_save)
        self.auto_save_timer.start(60000)  # Auto-save every minute

    def new_chat(self):
        try:
            self.api.create_session()
            chat_id = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
            self.current_chat_id = chat_id
            self.chat_archives[chat_id] = []
            self.chat_list.addItem(chat_id)
            self.chat_history.clear()
            self.add_system_message("New session created successfully.")
        except Exception as e:
            self.add_system_message(f"Error creating session: {str(e)}", error=True)

    def load_chat(self, item):
        chat_id = item.text()
        self.current_chat_id = chat_id
        self.chat_history.clear()
        for message in self.chat_archives[chat_id]:
            if message['type'] == 'user':
                self.add_user_message(message['content'])
            elif message['type'] == 'ai':
                self.add_ai_message(message['content'])
            elif message['type'] == 'system':
                self.add_system_message(message['content'], message.get('error', False))

    def send_message(self):
        prompt = self.prompt_input.text()
        agent = self.agent_combo.currentText()
        
        if not prompt:
            return

        self.add_user_message(prompt)
        self.prompt_input.clear()

        self.progress_bar.setVisible(True)
        self.progress_bar.setValue(0)

        context = self.get_file_context()
        self.worker = ChatWorker(self.api, prompt, agent, context)
        self.worker.finished.connect(self.handle_response)
        self.worker.error.connect(self.handle_error)
        self.worker.progress.connect(self.update_progress)
        self.worker.start()

    def get_file_context(self):
        context = {}
        for i in range(self.file_list.count()):
            file_name = self.file_list.item(i).text()
            with open(os.path.join(self.get_chat_directory(), file_name), 'r') as f:
                context[file_name] = f.read()
        return context

    def update_progress(self, value):
        self.progress_bar.setValue(value)

    def handle_response(self, response):
        self.progress_bar.setVisible(False)
        self.add_ai_message(response)

    def handle_error(self, error_message):
        self.progress_bar.setVisible(False)
        self.add_system_message(f"Error: {error_message}", error=True)

    def add_user_message(self, message):
        self.chat_history.append(f'<div style="text-align: right;"><span style="background-color: #e6f3ff; padding: 5px; border-radius: 10px;">You: {message}</span></div>')
        self.chat_archives[self.current_chat_id].append({'type': 'user', 'content': message})

    def add_ai_message(self, message):
        formatted_message = self.format_ai_message(message)
        self.chat_history.append(f'<div style="text-align: left;"><span style="background-color: #f0f0f0; padding: 5px; border-radius: 10px;">AI: {formatted_message}</span></div>')
        self.chat_archives[self.current_chat_id].append({'type': 'ai', 'content': message})

    def format_ai_message(self, message):
        # Format code blocks
        message = message.replace("```", "<pre><code>", 1)
        message = message.replace("```", "</code></pre>", 1)
        
        # Format links
        import re
        url_pattern = r'(https?://\S+)'
        message = re.sub(url_pattern, r'<a href="\1">\1</a>', message)
        
        return message

    def add_system_message(self, message, error=False):
        color = "#ff9999" if error else "#99ff99"
        self.chat_history.append(f'<div style="text-align: center;"><span style="background-color: {color}; padding: 5px; border-radius: 10px;">System: {message}</span></div>')
        self.chat_archives[self.current_chat_id].append({'type': 'system', 'content': message, 'error': error})

    def open_file(self, item):
        file_name = item.text()
        file_path = os.path.join(self.get_chat_directory(), file_name)
        with open(file_path, 'r') as f:
            content = f.read()
        self.file_content.setText(content)
        self.tabs.setCurrentIndex(1)  # Switch to file tab
        self.add_system_message(f"File opened: {file_name}")

    def save_file(self):
        if not self.file_content.toPlainText():
            return
        file_name, _ = QFileDialog.getSaveFileName(self, "Save File", self.get_chat_directory(), "All Files (*)")
        if file_name:
            with open(file_name, 'w') as f:
                f.write(self.file_content.toPlainText())
            self.update_file_list()
            self.add_system_message(f"File saved: {os.path.basename(file_name)}")

    def update_file_list(self):
        self.file_list.clear()
        chat_dir = self.get_chat_directory()
        if os.path.exists(chat_dir):
            files = os.listdir(chat_dir)
            for file in files:
                self.file_list.addItem(file)

    def get_chat_directory(self):
        base_dir = os.path.join(os.path.expanduser("~"), "RobocoderChats")
        chat_dir = os.path.join(base_dir, self.current_chat_id)
        os.makedirs(chat_dir, exist_ok=True)
        return chat_dir

    def auto_save(self):
        self.save_chat_archive()
        self.status_bar.setText(f"Auto-saved at {datetime.datetime.now().strftime('%H:%M:%S')}")
        QTimer.singleShot(3000, lambda: self.status_bar.clear())

    def save_chat_archive(self):
        chat_dir = self.get_chat_directory()
        archive_file = os.path.join(chat_dir, "chat_archive.json")
        with open(archive_file, 'w') as f:
            json.dump(self.chat_archives[self.current_chat_id], f)

    def closeEvent(self, event):
        self.save_chat_archive()
        event.accept()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = RobocoderApp()
    ex.show()
    sys.exit(app.exec_())