import gradio as gr import requests import os import json # ============================================ # TEST-BEFEHLE FÜR PULLDOWNS # ============================================ PATCH_COMMANDS = [ #("📄 Patch: Lese test1.py", "!patch scope:file type:read_file filepath:agent/app/projekte/bild/test1.py"), ("📄 Patch: Lese appbild2.py", "!patch scope:file type:read_file filepath:agent/app/projekte/bild/appbild2.py"), #("📄 Patch: Lese Backup", "!patch scope:file type:read_file filepath:agent/app/projekte/bild/test1.py.bak"), ("📄 Patch: Lese Backup", "!patch scope:file type:read_file filepath:agent/app/projekte/bild/appbild2.py.bak"), ("📄 Patch: Lese JSON", "!patch scope:file type:read_file filepath:memory/agent_memory.json"), ("🔄 Patch: Ersetze 'Tag' mit 'Regenwetter'", "!patch scope:file type:find_and_replace filepath:agent/app/projekte/bild/test1.py find:Tag replace:Regenwetter"), ("📝 Patch: Ersetze Zeile 1", "!patch scope:file type:replace_line filepath:agent/app/projekte/bild/test1.py line:1 content:Nein, ist es nicht da die Sonne nicht scheint!"), ("➕ Patch: Einfügen nach 'Tag'", "!patch scope:file type:insert_after filepath:agent/app/projekte/bild/test1.py search_text:Tag insert_text:Hallo!"), ] MEMORY_COMMANDS = [ ("🧠 Memory: Ähnliche Fehler suchen", "!memory query ImportError: No module named 'xyz'"), ("📊 Memory: Statistik anzeigen", "!memory stats"), ("➕ Memory: Neuen Eintrag hinzufügen", "!memory add \"ImportError\" \"pip install package\""), ] MODULAR_COMMANDS = [ ("🔧 Modular: Kopieren sort_coordinates", "!modular extract /app/agent/app/projekte/bild/appbild2.py sort_coordinates"), #("🔧 Modular: Kopieren sort_coordinates", "!modular extract agent/app/projekte/bild/appbild2.py sort_coordinates"), ("🔧 Modular: Kopieren+Löschen+Import", "!modular extract /app/agent/app/projekte/bild/appbild2.py sort_coordinates --remove"), #("🔧 Modular: Kopieren+Löschen+Import", "!modular extract agent/app/projekte/bild/appbild2.py sort_coordinates --remove"), ("🔧 Modular: Kopieren+Löschen+Import+Wunsch", "!modular extract /app/agent/app/projekte/bild/appbild2.py sort_coordinates bildmod --remove"), ("🔧 Modular: Extrahiere ganze Datei", "!modular extract agent/appbild.py"), ("📊 Modular: Status anzeigen", "!modular status"), ("📋 Modular: Alle Module listen", "!modular list"), ("ℹ️ Modular: Info zu AgentClient", "!modular info AgentClient"), ("🔗 Modular: Zeige Abhängigkeiten", "!modular dependencies AgentClient"), ("📤 Modular: Exportiere als JSON", "!modular export AgentClient --format json"), ] # ============================================ # ANALYZE-BEFEHLE (kurze Antworten, kein Code) # ============================================ ANALYZE_COMMANDS = [ ("🔍 Analyze: Kurze Dateianalyse", "!analyse /app/agent/app/projekte/bild/appbild2.py"), ("🔍 Analyze: Kurze Funktion/Methode", "!analyse /app/agent/app/projekte/bild/appbild2.py sort_coordinates"), ] # ============================================ # AGENT-CLIENT (für Tests) # ============================================ class AgentClient: def __init__(self, project_name): self.project = project_name self.agent_url = os.getenv("AGENT_URL", "https://astridkraft-KI-Agent.hf.space") self.api_key = os.getenv("AGENT_API_KEY", "test-key-123") self.timeout = 10 def test_connection(self): """Testet die Verbindung zum Agenten (GET /api/health)""" try: response = requests.get( f"{self.agent_url}/api/health", timeout=5 ) if response.status_code == 200: data = response.json() return { "success": True, "message": f"✅ Verbunden!", "data": data } else: return { "success": False, "message": f"❌ Fehler {response.status_code}: {response.text}" } except requests.exceptions.ConnectionError: return { "success": False, "message": "❌ Agent nicht erreichbar (Connection Error)" } except Exception as e: return { "success": False, "message": f"❌ Fehler: {str(e)}" } def test_chat(self, message): """Testet den Chat-Endpoint (POST /api/chat)""" try: response = requests.post( f"{self.agent_url}/api/chat", json={ "project": self.project, "message": message, "api_key": self.api_key }, timeout=self.timeout ) if response.status_code == 200: data = response.json() return { "success": True, "message": data.get("response", "Keine Antwort"), "full_response": data } else: return { "success": False, "message": f"❌ Fehler {response.status_code}: {response.text}" } except Exception as e: return { "success": False, "message": f"❌ Fehler: {str(e)}" } # ============================================ # ANALYZE-METHODE # ============================================ def test_analyze(self, query): """Testet den Analyze-Endpoint""" try: response = requests.post( f"{self.agent_url}/api/analyze", json={ "project": self.project, "query": query, "api_key": self.api_key }, timeout=self.timeout ) if response.status_code == 200: data = response.json() return { "success": True, "message": data.get("response", "Keine Antwort"), "full_response": data } else: return { "success": False, "message": f"❌ Fehler {response.status_code}: {response.text}" } except Exception as e: return { "success": False, "message": f"❌ Fehler: {str(e)}" } # Agent initialisieren agent = AgentClient("bildgenerierung") # ============================================ # TEST-FUNKTIONEN # ============================================ def test_health(): """Testet Health-Endpoint""" result = agent.test_connection() if result["success"]: return f"""{result['message']} Agent-Status: {result['data'].get('status', 'unbekannt')} Projekte: {', '.join(result['data'].get('projects', []))} Agent URL: {agent.agent_url}""" else: return result["message"] def test_chat(message, chat_history): """Testet Chat-Endpoint und sammelt Verlauf""" if not message: return chat_history, "" # Keine Änderung # Prüfen ob es ein Analyze-Befehl ist if message.strip().startswith("!analyze"): result = agent.test_analyze(message) else: result = agent.test_chat(message) # Chat-Verlauf formatieren if result["success"]: response_text = f"👤 Du: {message}\n\n🤖 Agent: {result['message']}\n\n---\n" else: response_text = f"👤 Du: {message}\n\n❌ Fehler: {result['message']}\n\n---\n" # Zum Verlauf hinzufügen (neueste unten) new_history = chat_history + response_text if chat_history else response_text return new_history, "" # Verlauf zurückgeben und Input leeren # Funktion zum Einfügen des ausgewählten Befehls ins Chat-Feld def insert_command(choice): """Extrahiert den Befehl aus der Auswahl und fügt ihn ins Chat-Feld ein""" if choice and ":" in choice: parts = choice.split(" ", 1) if len(parts) > 1: for cmd_list in [PATCH_COMMANDS, MEMORY_COMMANDS, MODULAR_COMMANDS, ANALYZE_COMMANDS]: for display, command in cmd_list: if display == choice: return command return "" # Funktion zum Zurücksetzen des Chat-Verlaufs def clear_history(): """Leert den Chat-Verlauf""" return "" # ============================================ # GRADIO UI # ============================================ css = """ #col-container { margin: 0 auto; max-width: 800px; } .status-box { background: #f5f5f5; padding: 15px; border-radius: 8px; font-family: monospace; white-space: pre-wrap; height: 400px; overflow-y: auto; } .success { color: green; } .error { color: red; } .dropdown-row { display: flex; gap: 10px; margin-bottom: 15px; flex-wrap: wrap; } .analyze-dropdown { border-left: 4px solid #ff6b6b; } .health-box { margin-top: 20px; border-top: 2px solid #e0e0e0; padding-top: 20px; } .button-row { display: flex; gap: 10px; margin-bottom: 10px; } """ with gr.Blocks(css=css, title="🧪 Agent-API Tester") as demo: gr.Markdown(""" # 🧪 Agent-API Test-Tool Testet die Verbindung zum zentralen Agenten-Space: """) with gr.Column(elem_id="col-container"): # Agent-Info with gr.Row(): gr.Markdown(f""" **Agent-URL:** `{agent.agent_url}` **Projekt:** `{agent.project}` **API-Key:** `{agent.api_key}` """) gr.Markdown("---") # Vier Pulldown-Menüs für Testbefehle gr.Markdown("### 📋 Testbefehle auswählen:") with gr.Row(elem_classes="dropdown-row"): patch_dropdown = gr.Dropdown( choices=[cmd[0] for cmd in PATCH_COMMANDS], label="!patch Befehle", info="Patch-Operationen auf test.py", value=None, interactive=True, scale=1 ) memory_dropdown = gr.Dropdown( choices=[cmd[0] for cmd in MEMORY_COMMANDS], label="!memory Befehle", info="Memory-Operationen auf agent_memory.json", value=None, interactive=True, scale=1 ) modular_dropdown = gr.Dropdown( choices=[cmd[0] for cmd in MODULAR_COMMANDS], label="!modular Befehle", info="Modular-System Befehle", value=None, interactive=True, scale=1 ) # Analyze Dropdown analyze_dropdown = gr.Dropdown( choices=[cmd[0] for cmd in ANALYZE_COMMANDS], label="🔍 !analyze Befehle", info="Analyse-Befehle", value=None, interactive=True, scale=1, elem_classes="analyze-dropdown" ) gr.Markdown("---") # Chat-Verlauf (JETZT MIT VERLAUF) chat_output = gr.Textbox( label="Chat-Verlauf", lines=15, interactive=False, elem_classes="status-box" ) # Chat-Input und Buttons with gr.Row(): chat_input = gr.Textbox( label="Deine Nachricht", placeholder="z.B. Hallo Agent, wie geht's? Oder Befehl aus Pulldown auswählen...", lines=2, scale=4 ) with gr.Column(scale=1): chat_btn = gr.Button("📤 Senden", variant="primary") clear_btn = gr.Button("🗑️ Verlauf löschen", variant="secondary") gr.Markdown("---") # Health-Test with gr.Row(elem_classes="health-box"): health_btn = gr.Button("🔍 Health-Endpoint testen", variant="secondary", size="lg") health_output = gr.Textbox( label="Health-Response", lines=5, interactive=False, elem_classes="status-box" ) # Event Handler für Pulldowns patch_dropdown.change( fn=insert_command, inputs=[patch_dropdown], outputs=[chat_input] ) memory_dropdown.change( fn=insert_command, inputs=[memory_dropdown], outputs=[chat_input] ) modular_dropdown.change( fn=insert_command, inputs=[modular_dropdown], outputs=[chat_input] ) analyze_dropdown.change( fn=insert_command, inputs=[analyze_dropdown], outputs=[chat_input] ) # Event Handler für Chat chat_btn.click( fn=test_chat, inputs=[chat_input, chat_output], outputs=[chat_output, chat_input] ) # Enter-Taste im Chat-Input chat_input.submit( fn=test_chat, inputs=[chat_input, chat_output], outputs=[chat_output, chat_input] ) # Verlauf löschen clear_btn.click( fn=clear_history, inputs=[], outputs=[chat_output] ) # Health-Button health_btn.click( fn=test_health, inputs=[], outputs=[health_output] ) if __name__ == "__main__": demo.launch( css=css, # CSS hier in launch() übergeben share=True, # Share-Link erstellen server_name="0.0.0.0", # Auf allen Interfaces lauschen server_port=7860 )