# AISE AI Code Editor — Technische Dokumentation AI-Supported Lightweight Code Editor built with Streamlit (AISE501 Spring 2026) Diese Datei enthält die ausführliche technische Dokumentation des Projekts. Für eine Kurzübersicht siehe `README.md`. --- ## Inhaltsverzeichnis 1. [Projektstruktur](#projektstruktur) 2. [Frontend](#frontend) 3. [Backend Manager](#backend-manager) 4. [Backend Agent (MCP-System)](#backend-agent-mcp-system) 5. [MCP-Server-Konfiguration](#mcp-server-konfiguration) 6. [Tests](#tests) 7. [Setup](#setup) 8. [Architektur-Übersicht](#architektur-übersicht) --- ## Projektstruktur ``` AISE_AIAgent/ ├── frontend/ # Streamlit UI-Komponenten │ ├── app.py # Haupteinstiegspunkt der Streamlit-App │ ├── state.py # Session-State-Verwaltung │ ├── sidebar.py # Datei-Navigation (Sidebar) │ ├── editor.py # Code-Editor-Pane │ └── chat.py # Chat-Interface │ ├── backend/ # Backend-Logik │ ├── managers/ # Business-Logik für UI-Operationen │ │ ├── file_manager.py # Datei-CRUD (lesen, schreiben, listen) │ │ ├── chat_manager.py # AI-Chat-Verwaltung und -History │ │ ├── system_prompter.py # System-Prompts und Kontext-Injektion │ │ ├── search_manager.py # Web-Suche (DuckDuckGo) │ │ ├── execution_engine.py # Code-Ausführung und Sandboxing │ │ └── debug_logger.py # Logging, Fehlerbehandlung, Debug-Ausgaben │ │ │ └── agent/ # Autonomes AI-Agent-System (MCP-basiert) │ ├── coding_agent.py # Haupt-Agent-Loop (Plan-Act-Observe) │ ├── mcp_server_adapter.py # MCP-Adapter: verbindet Agent mit MCP-Servern │ ├── mcp_server_adapter_RAG.py # MCP-Adapter mit RAG-basierter Tool-Auswahl │ ├── mcp_server_config.json # Konfiguration der MCP-Server (Startbefehle) │ └── servers/ # MCP-Server-Implementierungen │ ├── mcp_server_code_execution.py # Tool: Python-Code ausführen │ ├── mcp_server_file_search.py # Tool: Dateien suchen und lesen │ └── mcp_server_web_search.py # Tool: Web-Suche via DuckDuckGo │ ├── tests/ # Unit-Tests (pytest) │ ├── conftest.py # Globale Test-Fixtures und MCP-Mocks │ ├── test_file_manager.py │ ├── test_chat_manager.py │ ├── test_execution_engine.py │ ├── test_coding_agent.py │ ├── test_debug_logger.py │ ├── test_system_prompter.py │ ├── test_mcp_server_code_execution.py │ ├── test_mcp_server_file_search.py │ └── test_mcp_server_web_search.py │ ├── workspace/ # Agent-Sandbox (isoliertes Arbeitsverzeichnis) └── .env.example # Vorlage für Umgebungsvariablen ``` --- ## Frontend Das Frontend besteht aus Streamlit-Komponenten, die zusammen eine interaktive Code-Editor-Oberfläche bilden. ### `app.py` Haupteinstiegspunkt der Applikation. Orchestriert das Layout und initialisiert alle UI-Komponenten (Sidebar, Editor, Chat). ### `state.py` Zentralisierte Verwaltung des Streamlit Session-State. Stellt sicher, dass alle Komponenten denselben Zustand (geöffnete Datei, Chat-History, Agent-Status) teilen. ### `sidebar.py` Datei-Browser und Projekt-Navigation. Erlaubt das Durchsuchen des Workspaces und das Öffnen von Dateien im Editor. ### `editor.py` Code-Editor-Pane mit Syntax-Highlighting. Ermöglicht das Bearbeiten und Speichern von Code-Dateien direkt im Browser. ### `chat.py` Chat-Interface für den KI-Assistenten. Zeigt die Konversations-History und ermöglicht Eingaben an das AI-Modell. --- ## Backend Manager Die Manager-Klassen kapseln die Business-Logik und werden direkt vom Frontend aufgerufen. ### `file_manager.py` Stellt CRUD-Operationen auf dem Workspace-Verzeichnis bereit: - Dateien lesen, schreiben, umbenennen, löschen - Verzeichnisstruktur auflisten - Sichere Pfadvalidierung (verhindert Path-Traversal) **Designentscheidung — `list_files()` vs. `get_file_tree()`:** Die Projektspezifikation nennt `list_files()` als `FileManager`-Methode. Im vorliegenden Design wurde bewusst `get_file_tree()` implementiert, da das Frontend eine verschachtelte Baumstruktur benötigt (für den interaktiven File Explorer in der Sidebar). Eine flache Liste würde die Navigation nicht unterstützen. Für den Agent Mode übernimmt der MCP-Server `mcp_server_file_search.py` die Dateisuche — die Funktionalität ist damit im System vorhanden, nur architektonisch sauber getrennt. ### `chat_manager.py` Verwaltet AI-Chat-Interaktionen: - Aufbau und Verwaltung der Chat-History - Senden von Nachrichten an das AI-Modell - Formatierung von System- und User-Nachrichten **Designentscheidung — Fehler-Output im normalen Chat:** Laufzeitfehler und stderr-Output werden im normalen Chat bewusst **nicht automatisch** in den Chat-Kontext injiziert. Stattdessen gibt es den "Debug with AI"-Button im Editor, über den der User selbst entscheidet wann er die AI einschalten möchte. Dies verhindert, dass die Chat-History mit ungewollten Fehlermeldungen geflutet wird. Im Agent Mode wird dies anders gelöst: dort landet jeder Execution-Fehler automatisch als Observation im Plan-Act-Observe-Loop und der Agent replant ohne User-Eingriff. ### `system_prompter.py` Generiert kontextreiche System-Prompts für den AI-Assistenten: - Injektion von aktuellem Dateiinhalt als Kontext - Steuerung des AI-Verhaltens (Coding-Assistent-Persona) ### `execution_engine.py` Führt Python-Code sicher aus: - Subprocess-basierte Code-Ausführung - Timeout-Schutz und Output-Capture - Fehler- und Exception-Handling ### `debug_logger.py` Logging und Fehler-Tracking: - Formatierte Log-Ausgaben für Debugging - `format_debug_output(output)` formatiert den Execution-Output (`stdout`, `stderr`, `return_code`) in einen einheitlichen String für die UI-Anzeige und den AI-Chat-Kontext **Designentscheidung — `log_error()` nicht implementiert:** Die Projektspezifikation nennt `log_error()` als `DebugLogger`-Methode. Diese wurde bewusst nicht als separate Methode implementiert, da Python's eingebautes `logging`-Modul diese Funktionalität mit `logger.error()` bereits vollständig abdeckt. Im gesamten Projekt wird konsistent `logger = get_logger(__name__)` gefolgt von `logger.error(...)` verwendet — eine eigene Wrapper-Methode wäre toter Code ohne Mehrwert. ### `search_manager.py` Web-Suche für den KI-Assistenten via DuckDuckGo: - Nutzt die `ddgs`-Bibliothek (DuckDuckGo Search) für API-freie Websuche - Gibt strukturierte Suchergebnisse zurück (Titel, URL, Snippet) - Wird vom Chat-Manager aufgerufen, wenn der Assistent externe Dokumentation oder Code-Beispiele benötigt - Keine API-Key-Konfiguration notwendig (da DuckDuckGo öffentlich zugänglich ist) --- ## Backend Agent (MCP-System) Der Agent ist ein autonomes System, das komplexe Coding-Aufgaben selbstständig löst. Er kommuniziert mit externen Tool-Servern über das **Model Context Protocol (MCP)**. ### `coding_agent.py` Implementiert den Plan-Act-Observe-Loop: 1. **Plan**: Das AI-Modell wählt das nächste Tool und Argumente 2. **Act**: Das Tool wird via MCP-Adapter aufgerufen (nach User-Bestätigung) 3. **Observe**: Das Ergebnis wird in die Message-History eingefügt 4. Der Loop wiederholt sich bis zur Fertigstellung oder einem `done`-Tool-Aufruf Wichtige Klassen und Funktionen: - `CodingAgent`: Haupt-Klasse mit `start_task()`, `propose_next_action()`, `approve()`, `reject()` - `truncate_result()`: Kürzt lange Tool-Outputs bevor sie in die History gehen - `trim_messages()`: Entfernt alte Turns aus der History wenn das Kontextfenster voll wird - `_strip_code_fences()`: Bereinigt Markdown-Fences aus LLM-JSON-Antworten Konstanten: `MAX_ITERATIONS`, `MAX_RESULT_LENGTH`, `MAX_HISTORY_CHARS` ### `mcp_server_adapter.py` Verbindet den Coding-Agent mit den MCP-Tool-Servern: - Liest `mcp_server_config.json` und startet die konfigurierten Server als Subprozesse - Baut MCP-Sessions via `stdio_client` auf - Registriert alle verfügbaren Tools aus allen Servern in einem zentralen `tool_registry` - Delegiert Tool-Aufrufe an den richtigen Server via `call_tool()` Hauptmethoden: - `initialize_all_servers()`: Startet alle Server und baut Sessions auf - `get_all_tools()`: Gibt alle registrierten Tool-Definitionen zurück - `call_tool(tool_name, arguments)`: Führt ein Tool auf dem zuständigen Server aus ### `mcp_server_adapter_RAG.py` Erweiterter MCP-Adapter mit semantischer Tool-Auswahl via Retrieval-Augmented Generation (RAG): **Motivation**: Bei vielen MCP-Tools kann das LLM-Kontextfenster überfüllt werden, wenn alle Tool-Definitionen mitgesendet werden. Der RAG-Adapter löst dies durch semantische Vorauswahl. **Funktionsweise**: 1. Beim Initialisieren werden alle Tool-Beschreibungen mit `SentenceTransformer('all-MiniLM-L6-v2')` in Embeddings umgewandelt 2. Bei jedem Agent-Schritt wird der aktuelle Task als Query kodiert 3. Cosine-Similarity zwischen Query- und Tool-Embeddings bestimmt die `top_k` relevantesten Tools 4. Nur diese Tools werden dem LLM als verfügbare Aktionen präsentiert Hauptmethoden: - `initialize_all_sessions()`: Startet Server, baut Sessions auf, erstellt Embedding-Index - `get_relevant_tools(query, top_k=5)`: Gibt die `top_k` semantisch ähnlichsten Tools zurück - `call_tool(tool_name, arguments)`: Findet den zuständigen Server und führt das Tool aus - `shutdown_all_sessions()`: Schliesst alle offenen MCP-Sessions sauber Abhängigkeit: `sentence-transformers`, `numpy` **Hinweis**: Diese Klasse befindet sich noch in der Entwicklung (Work in Progress). Es gibt bekannte Bugs (z.B. Tippfehler `commanf` statt `command`, falsche Verwendung von `result.get()` vs. `result.tools`). --- ## MCP-Server-Konfiguration ### Format: `mcp_server_config.json` Die Datei `backend/agent/mcp_server_config.json` definiert, welche MCP-Server der Adapter starten soll. Das Format ist ein JSON-Objekt, wobei jeder Key ein frei wählbarer Servername ist: ```json { "ServerName": { "command": "py", "args": ["servers/mcp_server_datei.py"], "env": { "API_KEY": "optional_key" } } } ``` | Feld | Pflicht | Beschreibung | |-----------|---------|--------------| | `command` | Ja | Ausführbares Programm (z.B. `py`, `python3`, `node`) | | `args` | Ja | Argumente als Array (Pfad zum Server-Script) | | `env` | Nein | Umgebungsvariablen für den Serverprozess | ### Aktuelle Server ```json { "FileSearchServer": { "command": "py", "args": ["servers/mcp_server_file_search.py"] }, "WebSearchServer": { "command": "py", "args": ["servers/mcp_server_web_search.py"], "env": { "DDGS_API_KEY": "your_ddgs_api_key_here" } }, "CodeExecutionServer": { "command": "py", "args": ["servers/mcp_server_code_execution.py"] } } ``` ### Neuen MCP-Server hinzufügen 1. Neues Server-Script in `backend/agent/servers/` erstellen (MCP-konformes Python-Script) 2. Eintrag in `mcp_server_config.json` ergänzen: ```json "MeinNeuerServer": { "command": "py", "args": ["servers/mcp_server_mein_tool.py"] } ``` 3. Der Adapter erkennt den neuen Server beim nächsten Start automatisch und registriert seine Tools --- ## Tests ### Tests ausführen ```bash # Alle Tests ausführen pytest tests/ -v # Einzelnes Test-Modul ausführen pytest tests/test_coding_agent.py -v # Tests mit Kurzausgabe pytest tests/ ``` ### Teststruktur Die Tests liegen in `tests/` und folgen dem Muster `test_.py`. #### `conftest.py` Globale Pytest-Konfiguration. Patcht den `MCPToolAdapter` auf `sys.modules`-Ebene, bevor irgendein Test-Modul importiert wird. Dadurch werden beim Import von `coding_agent` keine echten MCP-Subprozesse gestartet. Der Mock-Adapter liefert sofort leere Ergebnisse zurück. #### Was wird getestet | Test-Datei | Getestetes Modul | Schwerpunkt | |---|---|---| | `test_file_manager.py` | `backend/managers/file_manager.py` | Datei-CRUD, Pfad-Validierung | | `test_chat_manager.py` | `backend/managers/chat_manager.py` | Chat-History, Nachrichtenformatierung | | `test_execution_engine.py` | `backend/managers/execution_engine.py` | Code-Ausführung, Timeouts, Fehlerbehandlung | | `test_system_prompter.py` | `backend/managers/system_prompter.py` | Prompt-Generierung, Kontext-Injektion | | `test_debug_logger.py` | `backend/managers/debug_logger.py` | Log-Formatierung, Fehler-Aggregation | | `test_coding_agent.py` | `backend/agent/coding_agent.py` | Agent-Loop, Tool-Dispatch, History-Trimming | | `test_mcp_server_code_execution.py` | `backend/agent/servers/mcp_server_code_execution.py` | MCP Code-Execution-Tool | | `test_mcp_server_file_search.py` | `backend/agent/servers/mcp_server_file_search.py` | MCP Datei-Such-Tool | | `test_mcp_server_web_search.py` | `backend/agent/servers/mcp_server_web_search.py` | MCP Web-Such-Tool | #### Testklassen in `test_coding_agent.py` - **`TestTruncateResult`**: Prüft, dass lange Tool-Outputs korrekt gekürzt werden - **`TestTrimMessages`**: Prüft, dass alte History-Turns entfernt werden wenn der Kontext zu gross wird; System-Message und Original-Task bleiben immer erhalten - **`TestStripCodeFences`**: Prüft, dass Markdown-Codeblöcke aus LLM-Antworten entfernt werden - **`TestCodingAgentInit`**: Prüft initialen Zustand und `start_task()`-Reset-Verhalten - **`TestProposeNextAction`**: Prüft den API-Aufruf-Zyklus mit gemockter API; testet Fehler-Handling (JSON-Parse-Fehler, API-Exceptions, Max-Iterations) - **`TestApprove`**: Prüft `approve()` mit gemocktem `dispatch_tool`; testet Tool-Ergebnis-Injektion und Error-Replan-Tagging - **`TestReject`**: Prüft, dass `reject()` das Feedback korrekt in die History injiziert und kein Tool ausführt #### Test-Konventionen - MCP-Server werden in Tests **nicht** als echte Subprozesse gestartet (via `conftest.py`-Mock) - Streamlit-Aufrufe werden mit `patch("modul.st")` gemockt - Dateisystem-Tests nutzen `tmp_path` (pytest-Fixture) für isolierte temporäre Verzeichnisse - Async-Tests verwenden `@pytest.mark.asyncio` (benötigt `pytest-asyncio`) --- ## Setup ### 1. Repository klonen ```bash git clone https://gitea.fhgr.ch/meulilivio/AISE1_Project.git cd AISE1_Project ``` ### 2. Virtuelle Umgebung aktivieren ```bash # Windows .\.venv\Scripts\Activate.ps1 # macOS/Linux source .venv/bin/activate ``` ### 3. Abhängigkeiten installieren ```bash pip install -r requirements.txt ``` ### 4. Umgebungsvariablen konfigurieren ```bash cp .env.example .env # .env mit API-Keys befüllen ``` ### 5. Applikation starten ```bash streamlit run frontend/app.py ``` ### 6. Tests ausführen ```bash pytest tests/ -v ``` --- ## Architektur-Übersicht ``` ┌─────────────────────────────────────────────────────────────────┐ │ Frontend (Streamlit) │ │ app.py → sidebar.py / editor.py / chat.py │ │ │ │ │ state.py (Session-State) │ └──────────────┬──────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ Backend Manager │ │ FileManager / ChatManager / SystemPrompter / │ │ SearchManager / ExecutionEngine / DebugLogger │ └──────────────┬──────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ Coding Agent (backend/agent/) │ │ coding_agent.py ←→ mcp_server_adapter.py │ │ │ │ │ mcp_server_config.json │ │ │ │ │ ┌───────────────┼───────────────┐ │ │ ▼ ▼ ▼ │ │ mcp_server_file_search mcp_server_web mcp_server_code │ │ │ │ (Optional: mcp_server_adapter_RAG.py für semantische │ │ Tool-Auswahl via Sentence Transformers) │ └─────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ workspace/ │ │ Isoliertes Sandbox-Verzeichnis für Agent-Dateien │ └─────────────────────────────────────────────────────────────────┘ ```