docs: merge updated README.md and READMEnew.md from Agent 3
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
commit
955a30c512
354
README.md
354
README.md
@ -1,224 +1,168 @@
|
||||
# AISE AI Agent — Code Editor & Coding Assistant
|
||||
# AISE AI Code Editor
|
||||
|
||||
Ein browserbasierter Code-Editor mit integriertem AI-Chat und autonomem Coding-Agent, gebaut mit Streamlit und dem Model Context Protocol (MCP).
|
||||
|
||||
---
|
||||
|
||||
## Installation & Setup
|
||||
|
||||
**Voraussetzungen:** Python 3.13+, pip
|
||||
|
||||
```bash
|
||||
# 1. Repository klonen und ins Verzeichnis wechseln
|
||||
cd AISE_AIAgent
|
||||
|
||||
# 2. Virtuelle Umgebung erstellen und aktivieren
|
||||
python -m venv .venv
|
||||
.venv\Scripts\activate # Windows
|
||||
# source .venv/bin/activate # macOS/Linux
|
||||
|
||||
# 3. Abhängigkeiten installieren
|
||||
pip install -r requirements.txt
|
||||
|
||||
# 4. Umgebungsvariablen konfigurieren
|
||||
copy .env.example .env
|
||||
# .env öffnen und HOST, PORT, API_KEY, MODEL eintragen
|
||||
```
|
||||
|
||||
**`.env` Konfiguration:**
|
||||
```
|
||||
HOST=silicon.fhgr.ch
|
||||
PORT=7080
|
||||
API_KEY=EMPTY
|
||||
MODEL=qwen3.5-35b-a3b
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Starten
|
||||
|
||||
```bash
|
||||
# Streamlit App (Hauptinterface)
|
||||
streamlit run frontend/app.py
|
||||
|
||||
# Coding Agent direkt im Terminal testen
|
||||
python run_agent.py
|
||||
```
|
||||
|
||||
---
|
||||
AI-Supported Lightweight Code Editor built with Streamlit (AISE501 Spring 2026)
|
||||
|
||||
## Projektstruktur
|
||||
|
||||
```
|
||||
AISE_AIAgent/
|
||||
├── frontend/ # Streamlit UI
|
||||
├── backend/
|
||||
│ ├── agent/ # Coding Agent + MCP-Adapter
|
||||
│ │ └── servers/ # MCP-Server (Tools für den Agent)
|
||||
│ └── managers/ # Business-Logik (Chat, Dateien, Ausführung)
|
||||
├── workspace/ # Arbeitsverzeichnis des Agents & Editors
|
||||
└── run_agent.py # CLI-Test für den Coding Agent
|
||||
├── 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)
|
||||
├── run_agent.py # CLI-Einstiegspunkt für den Coding-Agent
|
||||
└── .env.example # Vorlage für Umgebungsvariablen
|
||||
```
|
||||
|
||||
---
|
||||
## Komponenten
|
||||
|
||||
## Frontend
|
||||
### Frontend (`frontend/`)
|
||||
- **app.py**: Streamlit-Applikation, Layout-Orchestrierung
|
||||
- **state.py**: Zentralisierte Session-State-Verwaltung
|
||||
- **sidebar.py**: Datei-Browser und Projekt-Navigation
|
||||
- **editor.py**: Code-Editor mit Syntax-Highlighting
|
||||
- **chat.py**: AI-Assistent Chat-Interface
|
||||
|
||||
### `frontend/app.py` — Einstiegspunkt
|
||||
Initialisiert die Streamlit-App, setzt das Layout und routet zwischen Code-Editor und Chat-Ansicht basierend auf der Sidebar-Navigation.
|
||||
### Backend Manager (`backend/managers/`)
|
||||
Werden direkt vom Frontend für UI-Operationen genutzt:
|
||||
- **file_manager.py**: CRUD-Operationen auf Projektdateien
|
||||
- **chat_manager.py**: Chat-History, Nachrichten-Verwaltung
|
||||
- **system_prompter.py**: System-Prompt-Generierung und Datei-Kontext
|
||||
- **execution_engine.py**: Sichere Code-Ausführung mit Output-Capture
|
||||
- **debug_logger.py**: Fehler-Tracking und Log-Formatierung
|
||||
- **search_manager.py**: Web-Suche via DuckDuckGo (`ddgs`-Bibliothek)
|
||||
|
||||
### `frontend/state.py` — Session State
|
||||
Initialisiert alle Streamlit `session_state`-Variablen beim App-Start (offene Dateien, Chat-Verlauf, Agent-Status etc.). Verhindert `KeyError` beim ersten Laden.
|
||||
### Backend Agent (`backend/agent/`)
|
||||
Autonomes AI-Agent-System für komplexe Coding-Aufgaben:
|
||||
- **coding_agent.py**: Agent-Loop (Plan → Act → Observe → Wiederholen)
|
||||
- **mcp_server_adapter.py**: Verbindet den Agent mit MCP-Servern via Konfigurationsdatei
|
||||
- **mcp_server_adapter_RAG.py**: Erweiterter Adapter mit semantischer Tool-Auswahl (RAG)
|
||||
- **mcp_server_config.json**: Definiert welche MCP-Server gestartet werden und mit welchen Argumenten
|
||||
- **servers/**: Die eigentlichen MCP-Tool-Server (Code-Ausführung, Datei-Suche, Web-Suche)
|
||||
|
||||
### `frontend/sidebar.py` — Sidebar & File Explorer
|
||||
- **Navigation:** Radio-Button zum Wechseln zwischen "Code Editor" und "Chat with AI Assistant"
|
||||
- **File Tree:** Interaktiver Dateibaum (via `streamlit-arborist`) zeigt den `workspace/`-Ordner
|
||||
- **Datei-Aktionen:** Datei öffnen, umbenennen, löschen
|
||||
- **Ordner-Aktionen:** Ordner erstellen, Dateien in Ordner hinzufügen, Ordner löschen
|
||||
### Workspace (`workspace/`)
|
||||
- Sandbox-Verzeichnis, in dem der Agent Dateien erstellt und ausführt
|
||||
- Verhindert, dass der Agent auf Dateien ausserhalb dieses Verzeichnisses zugreift
|
||||
|
||||
### `frontend/editor.py` — Code-Editor
|
||||
- **Ace Editor:** Syntax-Highlighting für Python, JS, HTML, CSS, JSON, YAML, LaTeX u.a.
|
||||
- **Tabs:** Mehrere Dateien gleichzeitig offen, Tab-Wechsel per Klick
|
||||
- **Datei-Operationen:** Speichern, Schliessen, Umbenennen, Löschen direkt im Tab
|
||||
- **Code ausführen:** Button "▶ Run Code" führt die aktive Datei aus, Output wird darunter angezeigt
|
||||
- **Debug with AI:** Bei Fehlern erscheint ein Button der den Fehler + Code automatisch an den AI-Chat weiterleitet
|
||||
## Features
|
||||
|
||||
### `frontend/chat.py` — Chat & Agent Mode
|
||||
- **Datei-Verwaltung**: Dateien im Workspace durchsuchen und bearbeiten
|
||||
- **Chat-Interface**: KI-gestützter Code-Assistent
|
||||
- **Code-Ausführung**: Python-Code sicher ausführen mit Debug-Output
|
||||
- **Web-Suche**: Dokumentation und Beispiele via DuckDuckGo abrufen
|
||||
- **Autonomer Agent**: MCP-basierter Coding-Agent mit Plan-Act-Observe-Loop
|
||||
- **RAG Tool-Auswahl**: Semantische Tool-Selektion via Sentence Transformers
|
||||
|
||||
**Normaler Chat (`render_normal_chat`):**
|
||||
- Multi-Turn Konversation mit dem konfigurierten LLM
|
||||
- Injiziert die aktuell offene Datei automatisch als Kontext in den System-Prompt
|
||||
- Einstellungen: Modell wählen, Max Tokens, eigener System-Prompt
|
||||
- "Clear Chat" mit Bestätigungsdialog
|
||||
## Setup
|
||||
|
||||
**Agent Mode (`render_agent_mode`):**
|
||||
- Autonomer Coding-Agent im Step-by-Step Modus
|
||||
- Benutzer gibt eine Aufgabe ein, der Agent schlägt Aktionen vor
|
||||
- Jede Aktion muss einzeln **genehmigt (Approve)** oder **abgelehnt (Reject)** werden
|
||||
- **Agent Log:** Zeigt alle ausgeführten Schritte mit Tool, Gedanken und Resultat
|
||||
- **Follow-up:** Nach Abschluss einer Aufgabe können Korrekturen eingegeben werden
|
||||
|
||||
---
|
||||
|
||||
## Backend — Managers
|
||||
|
||||
### `backend/managers/chat_manager.py` — ChatManager
|
||||
Verwaltet den Konversationsverlauf und kommuniziert mit dem LLM über eine OpenAI-kompatible REST-API. Sendet bei jedem Request den gesamten Verlauf als Kontext mit.
|
||||
|
||||
| Methode | Beschreibung |
|
||||
|---|---|
|
||||
| `send_message(user_message)` | Nachricht senden, Antwort zurückgeben, History updaten |
|
||||
| `add_message(role, content)` | Nachricht manuell zur History hinzufügen |
|
||||
| `clear_history()` | Gesamten Chat-Verlauf löschen |
|
||||
| `get_history()` | Kopie des aktuellen Verlaufs zurückgeben |
|
||||
|
||||
### `backend/managers/file_manager.py` — FileManager
|
||||
Alle Datei- und Ordneroperationen innerhalb des `workspace/`-Verzeichnisses. Jede Operation validiert den Pfad gegen Path-Traversal-Angriffe.
|
||||
|
||||
| Methode | Beschreibung |
|
||||
|---|---|
|
||||
| `create_file(relative_path, name)` | Neue Datei im Workspace erstellen |
|
||||
| `create_folder(relative_path, name)` | Neuen Ordner erstellen |
|
||||
| `read_file(path)` | Dateiinhalt lesen |
|
||||
| `save_file(path, content)` | Datei speichern/überschreiben |
|
||||
| `rename_file(old_path, new_name)` | Datei umbenennen (Extension bleibt erhalten) |
|
||||
| `delete_file(relative_path)` | Datei löschen |
|
||||
| `delete_folder(relative_path)` | Ordner inkl. Inhalt löschen |
|
||||
| `get_file_tree()` | Verschachteltes Dict des gesamten Workspace-Baums |
|
||||
|
||||
### `backend/managers/execution_engine.py` — ExecutionEngine
|
||||
Führt Dateien aus dem Editor in einem Subprocess aus. Unterstützt Python (`.py`) und LaTeX (`.tex`). Timeout: 30 Sekunden.
|
||||
|
||||
| Methode | Beschreibung |
|
||||
|---|---|
|
||||
| `run_code(active_file)` | Datei ausführen, gibt `{stdout, stderr, rc}` zurück |
|
||||
|
||||
### `backend/managers/system_prompter.py` — SystemPrompter
|
||||
Generiert den System-Prompt für den AI-Chat. Wenn eine Datei im Editor offen ist, wird ihr Inhalt (max. 4000 Zeichen) automatisch eingebettet.
|
||||
|
||||
| Methode | Beschreibung |
|
||||
|---|---|
|
||||
| `generate_prompt(file_context)` | System-Prompt mit optionalem Datei-Kontext bauen |
|
||||
|
||||
### `backend/managers/debug_logger.py` — DebugLogger
|
||||
Einfacher In-Memory-Logger für den Code-Editor (Ausführungsstatus, Fehler).
|
||||
|
||||
---
|
||||
|
||||
## Backend — Coding Agent
|
||||
|
||||
### `backend/agent/coding_agent.py` — CodingAgent
|
||||
Autonomer Agent nach dem **Plan → Act → Observe → Fix → Done** Loop. Kommuniziert mit dem LLM und ruft MCP-Tools über den Adapter auf.
|
||||
|
||||
| Methode | Beschreibung |
|
||||
|---|---|
|
||||
| `start_task(task)` | Neue Aufgabe initialisieren, State zurücksetzen |
|
||||
| `propose_next_action()` | LLM fragen was als nächstes zu tun ist (führt nichts aus) |
|
||||
| `approve()` | Vorgeschlagene Aktion ausführen, nächsten Schritt vorschlagen |
|
||||
| `reject(feedback)` | Aktion ablehnen, Feedback injizieren, Agent plant neu |
|
||||
| `follow_up(question)` | Folgefrage nach abgeschlossener Aufgabe stellen |
|
||||
|
||||
**Hilfsfunktionen:**
|
||||
- `dispatch_tool(tool_name, arguments)` — Leitet Tool-Aufrufe an den MCP-Adapter weiter
|
||||
- `build_all_tool_description()` — Generiert die Tool-Beschreibung für den System-Prompt
|
||||
- `extract_json(text)` / `_repair_json_strings(text)` — Parst und repariert LLM-JSON-Antworten
|
||||
- `trim_messages(messages)` — Kürzt alte History wenn Kontextfenster voll wird
|
||||
|
||||
### `backend/agent/mcp_server_adapter.py` — MCPToolAdapter
|
||||
Verbindet den Coding Agent mit den MCP-Servern. Liest die Konfiguration aus `mcp_server_config.json`, registriert alle verfügbaren Tools und startet bei jedem Tool-Aufruf eine frische stdio-Verbindung zum zuständigen Server.
|
||||
|
||||
| Methode | Beschreibung |
|
||||
|---|---|
|
||||
| `initialize_all_servers()` | Alle Server verbinden und Tools registrieren |
|
||||
| `call_tool(tool_name, arguments)` | Tool auf dem zuständigen Server aufrufen |
|
||||
| `get_all_tools()` | Liste aller registrierten Tools zurückgeben |
|
||||
|
||||
---
|
||||
|
||||
## MCP-Server (Tools für den Agent)
|
||||
|
||||
Alle Server laufen als eigenständige Prozesse und kommunizieren über `stdio`.
|
||||
|
||||
### `backend/agent/servers/mcp_server_code_execution.py` — CodeExecutionServer
|
||||
|
||||
| Tool | Beschreibung |
|
||||
|---|---|
|
||||
| `run_python_sandboxed(code)` | Python-Code sicher ausführen (statische Analyse + Subprocess mit isoliertem stdin) |
|
||||
| `python_code_validation(code)` | Syntax und Sicherheit prüfen ohne auszuführen |
|
||||
| `lint_code(code)` | Statische Analyse mit pyflakes (ungenutzte Imports, undefinierte Variablen) |
|
||||
| `analyse_structure(code)` | Struktur-Zusammenfassung (Klassen, Funktionen, Imports) |
|
||||
|
||||
**Sicherheitsmechanismen:** Blockierte Imports (`os`, `sys`, `subprocess` etc.), blockierte Builtins (`exec`, `eval`, `open` etc.), verbotene Pfadsequenzen, Timeout nach 45 Sekunden.
|
||||
|
||||
### `backend/agent/servers/mcp_server_file_search.py` — FileSearchServer
|
||||
|
||||
| Tool | Beschreibung |
|
||||
|---|---|
|
||||
| `list_files()` | Alle Dateien im Workspace auflisten |
|
||||
| `get_file_tree(dir_path)` | Verzeichnisbaum anzeigen |
|
||||
| `search_files(query)` | Dateien nach Name oder Inhalt durchsuchen |
|
||||
| `read_file(path)` | Dateiinhalt lesen |
|
||||
| `write_new_file(path, content)` | Neue Datei erstellen (keine Überschreibung bestehender Dateien) |
|
||||
| `create_new_directory(path)` | Neues Verzeichnis erstellen |
|
||||
|
||||
Alle Zugriffe sind auf den `workspace/`-Ordner beschränkt (Path-Traversal-Schutz).
|
||||
|
||||
### `backend/agent/servers/mcp_server_web_search.py` — WebSearchServer
|
||||
|
||||
| Tool | Beschreibung |
|
||||
|---|---|
|
||||
| `web_search(query, max_results)` | DuckDuckGo-Suche, gibt formatierte Ergebnisse zurück |
|
||||
| `fetch_page(url)` | Webseite abrufen und Text extrahieren (max. 4000 Zeichen) |
|
||||
|
||||
SSRF-Schutz: Blockiert `localhost`, private IP-Ranges und nicht-HTTP/HTTPS-Schemata.
|
||||
|
||||
---
|
||||
|
||||
## CLI-Test
|
||||
|
||||
`run_agent.py` ermöglicht den Coding Agent direkt im Terminal zu testen ohne die Streamlit-App zu starten:
|
||||
### 1. Repository klonen
|
||||
|
||||
```bash
|
||||
python run_agent.py
|
||||
# Aufgabe eingeben → Enter zum Genehmigen, Text zum Ablehnen, "stop" zum Abbrechen
|
||||
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
|
||||
```
|
||||
|
||||
## Konfiguration: `mcp_server_config.json`
|
||||
|
||||
Die Datei `backend/agent/mcp_server_config.json` definiert, welche MCP-Server der Agent starten soll. Jeder Eintrag enthält den Servernamen, den Startbefehl (`command`) und optionale Argumente (`args`) sowie Umgebungsvariablen (`env`):
|
||||
|
||||
```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_key_here" }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Architektur
|
||||
|
||||
```
|
||||
Frontend (Streamlit) ──► Backend Manager ──► AI API
|
||||
│
|
||||
└──► Coding Agent ──► MCP-Adapter ──► MCP-Server
|
||||
(Code / File / Web)
|
||||
```
|
||||
|
||||
## Entwicklung
|
||||
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "Deine Nachricht"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
666
READMEnew.md
666
READMEnew.md
@ -1,72 +1,21 @@
|
||||
# AISE AI Agent — Code Editor & Coding Assistant
|
||||
# AISE AI Code Editor — Technische Dokumentation
|
||||
|
||||
Ein browserbasierter Code-Editor mit integriertem AI-Chat und autonomem Coding-Agent. Das Projekt kombiniert eine Streamlit-Oberfläche mit einem LLM-Backend und dem Model Context Protocol (MCP), um einen vollständigen AI-gestützten Entwicklungsworkflow zu ermöglichen.
|
||||
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`.
|
||||
|
||||
---
|
||||
|
||||
## Was kann das Projekt?
|
||||
## Inhaltsverzeichnis
|
||||
|
||||
- **Code schreiben und bearbeiten** im Browser mit Syntax-Highlighting (Ace Editor)
|
||||
- **Code direkt ausführen** und Output anzeigen, ohne die App zu verlassen
|
||||
- **Mit einem AI-Assistenten chatten**, der den aktuell geöffneten Code als Kontext kennt
|
||||
- **Fehler mit AI debuggen** — ein Klick schickt den Fehler + Code automatisch an den Chat
|
||||
- **Einen autonomen Coding-Agent starten**, der selbstständig Aufgaben plant und umsetzt (Dateien lesen/schreiben, Code ausführen, im Web suchen) — jeder Schritt wird dem Benutzer zur Genehmigung vorgelegt
|
||||
|
||||
---
|
||||
|
||||
## Voraussetzungen
|
||||
|
||||
- Python 3.13 oder neuer
|
||||
- pip
|
||||
- Zugang zu einem OpenAI-kompatiblen LLM-Endpoint (z.B. FHGR Silicon Server)
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
# 1. Repository klonen
|
||||
git clone <repo-url>
|
||||
cd AISE_AIAgent
|
||||
|
||||
# 2. Virtuelle Umgebung erstellen und aktivieren
|
||||
python -m venv .venv
|
||||
|
||||
# Windows:
|
||||
.venv\Scripts\activate
|
||||
# macOS / Linux:
|
||||
source .venv/bin/activate
|
||||
|
||||
# 3. Abhängigkeiten installieren
|
||||
pip install -r requirements.txt
|
||||
|
||||
# 4. Umgebungsvariablen konfigurieren
|
||||
copy .env.example .env # Windows
|
||||
# cp .env.example .env # macOS/Linux
|
||||
```
|
||||
|
||||
Dann `.env` öffnen und die Werte anpassen:
|
||||
|
||||
```env
|
||||
HOST=silicon.fhgr.ch # Hostname des LLM-Servers
|
||||
PORT=7080 # Port des LLM-Servers
|
||||
API_KEY=EMPTY # API-Key (EMPTY wenn kein Key benötigt)
|
||||
MODEL=qwen3.5-35b-a3b # Modell-Name
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Starten
|
||||
|
||||
```bash
|
||||
# Streamlit Web-App starten (Hauptinterface)
|
||||
streamlit run frontend/app.py
|
||||
|
||||
# Coding Agent im Terminal testen (ohne Streamlit)
|
||||
python run_agent.py
|
||||
```
|
||||
|
||||
Nach `streamlit run frontend/app.py` öffnet sich die App automatisch im Browser unter `http://localhost:8501`.
|
||||
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)
|
||||
|
||||
---
|
||||
|
||||
@ -74,308 +23,361 @@ Nach `streamlit run frontend/app.py` öffnet sich die App automatisch im Browser
|
||||
|
||||
```
|
||||
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
|
||||
│
|
||||
├── frontend/ # Gesamte Streamlit-Benutzeroberfläche
|
||||
│ ├── app.py # Einstiegspunkt, App-Routing
|
||||
│ ├── state.py # Session-State Initialisierung
|
||||
│ ├── sidebar.py # Navigation + File Explorer
|
||||
│ ├── editor.py # Code-Editor Ansicht
|
||||
│ └── chat.py # Chat + Agent Mode Ansicht
|
||||
│
|
||||
├── backend/
|
||||
│ ├── agent/ # Coding Agent Logik
|
||||
│ │ ├── coding_agent.py # Agent Klasse (Plan→Act→Observe Loop)
|
||||
│ │ ├── mcp_server_adapter.py # MCP-Client (verbindet Agent mit Servern)
|
||||
│ │ ├── mcp_server_adapter_RAG.py
|
||||
│ │ ├── mcp_server_config.json
|
||||
│ │ └── servers/ # MCP-Server (laufen als eigene Prozesse)
|
||||
│ │ ├── mcp_server_code_execution.py
|
||||
│ │ ├── mcp_server_file_search.py
|
||||
│ │ └── mcp_server_web_search.py
|
||||
├── 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
|
||||
│ │
|
||||
│ └── managers/ # Business-Logik Module
|
||||
│ ├── chat_manager.py # LLM-API Kommunikation + Chat-History
|
||||
│ ├── file_manager.py # Datei/Ordner-Operationen im Workspace
|
||||
│ ├── execution_engine.py # Code-Ausführung via Subprocess
|
||||
│ ├── system_prompter.py # System-Prompt Generierung
|
||||
│ └── debug_logger.py # Einfacher In-Memory Logger
|
||||
│ └── search_manager.py # Einfacher In-Memory Such-Manager
|
||||
├── tests/
|
||||
| ├── conftest.py
|
||||
| ├── test_file_manager.py # Unit-Tests für FileManager
|
||||
| ├── test_chat_manager.py # Unit-Tests für ChatManager
|
||||
| ├── test_execution_engine.py # Unit-Tests für ExecutionEngine
|
||||
| ├── test_coding_agent.py # Unit-Tests für CodingAgent
|
||||
| ├── test_search_manager.py # Unit-Tests für SearchManager
|
||||
| ├── test_debug_logger.py # Unit-Tests für DebugLogger
|
||||
| ├── test_mcp_server_code_execution.py
|
||||
| ├── test_mcp_server_web_search.py
|
||||
| ├── test_system_prompter.py
|
||||
| └── test_mcp_server_file_search.py
|
||||
|
|
||||
├── workspace/ # Arbeitsverzeichnis (Dateien des Editors/Agents)
|
||||
└── .env.example # Vorlage für Umgebungsvariablen
|
||||
│ └── 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)
|
||||
├── run_agent.py # CLI-Einstiegspunkt für den Coding-Agent
|
||||
└── .env.example # Vorlage für Umgebungsvariablen
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Frontend
|
||||
|
||||
### `frontend/app.py` — Einstiegspunkt der App
|
||||
Das Frontend besteht aus Streamlit-Komponenten, die zusammen eine interaktive Code-Editor-Oberfläche bilden.
|
||||
|
||||
Dieser File ist der Startpunkt der gesamten Streamlit-Applikation. Er wird direkt mit `streamlit run` aufgerufen und übernimmt drei Aufgaben: Er setzt das globale Seitenlayout (Titel, breites Layout, minimales CSS-Padding), ruft `init_state()` auf um alle Session-State-Variablen zu initialisieren, und leitet den Benutzer basierend auf der Sidebar-Auswahl entweder zur Editor-Ansicht oder zur Chat-Ansicht weiter.
|
||||
### `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.
|
||||
|
||||
---
|
||||
|
||||
### `frontend/state.py` — Session State Verwaltung
|
||||
## Backend Manager
|
||||
|
||||
Streamlit rendert die gesamte App bei jeder Benutzerinteraktion neu. Um Daten zwischen diesen Reruns zu erhalten (offene Dateien, Chat-Verlauf, Agent-Status etc.), nutzt Streamlit `session_state`. Dieser File definiert und initialisiert alle verwendeten Keys mit ihren Standardwerten an einem zentralen Ort — damit kein anderer Teil der App auf einen nicht-existierenden Key trifft.
|
||||
Die Manager-Klassen kapseln die Business-Logik und werden direkt vom Frontend aufgerufen.
|
||||
|
||||
**Wichtige State-Keys:**
|
||||
- `open_files` — Liste aller aktuell geöffneten Dateipfade (bestimmt die Tab-Reihenfolge)
|
||||
- `files_content` — Dict `{Dateipfad: aktueller Editorinhalt}` (ungespeicherte Änderungen inklusive)
|
||||
- `active_file` — Absoluter Pfad der aktuell aktiven Datei
|
||||
- `chat_history` — Flache Liste aller Chat-Nachrichten `[{role, content}, ...]`
|
||||
- `agent_mode` — Boolean ob der Agent Mode aktiv ist
|
||||
- `agent_status` — Aktueller Agent-Zustand: `"idle"` | `"waiting_approval"` | `"done"`
|
||||
- `agent_log` — Liste aller abgeschlossenen Agent-Schritte
|
||||
- `agent_pending_action` — Die vom Agent vorgeschlagene, noch nicht ausgeführte Aktion
|
||||
### `file_manager.py`
|
||||
Stellt CRUD-Operationen auf dem Workspace-Verzeichnis bereit:
|
||||
- Dateien lesen, schreiben, umbenennen, löschen
|
||||
- Verzeichnisstruktur auflisten
|
||||
- Sichere Pfadvalidierung (verhindert Path-Traversal)
|
||||
|
||||
### `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
|
||||
|
||||
### `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
|
||||
- Fehler-Aggregation für die UI-Darstellung
|
||||
|
||||
### `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)
|
||||
|
||||
---
|
||||
|
||||
### `frontend/sidebar.py` — Navigation & File Explorer
|
||||
## Backend Agent (MCP-System)
|
||||
|
||||
Die Sidebar ist in zwei Bereiche aufgeteilt:
|
||||
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)**.
|
||||
|
||||
**Navigation:** Ein Radio-Button schaltet zwischen "Code Editor" und "Chat with AI Assistant" um. Die aktuelle Auswahl wird in `session_state.radio_interface_options` gespeichert und von `app.py` ausgewertet.
|
||||
### `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
|
||||
|
||||
**File Explorer:** Ein interaktiver Dateibaum zeigt den gesamten `workspace/`-Ordner an. Implementiert mit `streamlit-arborist`, das einen klickbaren Baum mit Ordner-Icons rendert. Ein Klick auf eine Datei öffnet sie im Editor und wechselt automatisch zur Editor-Ansicht. Ein Klick auf einen Ordner zeigt eine Aktionsleiste mit Buttons zum Erstellen von Dateien/Unterordnern und zum Löschen des Ordners.
|
||||
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
|
||||
|
||||
**Modale Dialoge** (via `@st.dialog`):
|
||||
- `_add_file_dialog` — Neuen Dateinamen eingeben und Datei erstellen
|
||||
- `_add_folder_dialog` — Neuen Ordnernamen eingeben und Ordner erstellen
|
||||
- `_rename_file_dialog` — Datei umbenennen (Extension wird automatisch beibehalten)
|
||||
- `_delete_file_dialog` — Löschbestätigung für Dateien
|
||||
- `_delete_folder_dialog` — Löschbestätigung für Ordner inkl. Inhalt
|
||||
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`).
|
||||
|
||||
---
|
||||
|
||||
### `frontend/editor.py` — Code-Editor
|
||||
## MCP-Server-Konfiguration
|
||||
|
||||
Der Code-Editor ist die zentrale Arbeitsfläche für das direkte Bearbeiten von Dateien.
|
||||
### Format: `mcp_server_config.json`
|
||||
|
||||
**Ace Editor (`streamlit-ace`):** Jede offene Datei wird in einem Tab mit dem Ace-Editor angezeigt. Der Editor erkennt die Dateiendung automatisch und stellt das passende Syntax-Highlighting ein (Python, JavaScript, HTML, CSS, JSON, YAML, LaTeX, Bash). Das Theme ist "Monokai". `auto_update=True` bedeutet, dass Änderungen sofort in `session_state.files_content` landen — ohne expliziten Submit.
|
||||
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:
|
||||
|
||||
**Tab-Verwaltung:** Jede offene Datei erscheint als Tab. Wenn eine Datei aus dem File Explorer geöffnet wird, springt ein JavaScript-Snippet automatisch auf den richtigen Tab (da `st.tabs` keinen programmatischen Tab-Wechsel unterstützt).
|
||||
|
||||
**Aktions-Buttons pro Datei:**
|
||||
- **Save Changes** — Schreibt den aktuellen Editorinhalt auf Disk
|
||||
- **Close File** — Entfernt die Datei aus den offenen Tabs
|
||||
- **Rename File** — Öffnet Rename-Dialog
|
||||
- **Delete File** — Öffnet Lösch-Bestätigungsdialog
|
||||
- **▶ Run Code** — Führt die Datei aus (Python via `py`, LaTeX via `pdflatex`)
|
||||
|
||||
**Ausführungs-Output:** Nach dem Ausführen erscheinen stdout, stderr und der Exit-Code unterhalb des Editors. Bei einem Fehler erscheint zusätzlich der Button **"🐛 Debug with AI"** — dieser baut automatisch eine Fehlernachricht zusammen (Fehlertext + kompletter Code) und schickt sie an den Chat-Assistenten.
|
||||
|
||||
---
|
||||
|
||||
### `frontend/chat.py` — Chat & Agent Mode
|
||||
|
||||
Dieser File enthält zwei grundlegend verschiedene Interfaces, die über einen Toggle umgeschaltet werden.
|
||||
|
||||
#### Normaler Chat
|
||||
|
||||
Ein klassischer Multi-Turn-Chatbot. Bei der ersten Nachricht wird automatisch ein System-Prompt generiert. Falls eine Datei im Editor geöffnet ist und "Include current file as context" aktiviert ist, wird der Dateiinhalt in den System-Prompt eingebettet — der AI-Assistent "sieht" also den Code und kann gezielt darauf eingehen.
|
||||
|
||||
Bei jeder Folgenachricht wird der System-Prompt aktualisiert falls eine andere Datei aktiv ist. Das Modell, die maximale Tokenzahl und ein eigener System-Prompt können in einem aufklappbaren Settings-Panel konfiguriert werden. Der "Clear Chat" Button öffnet einen Bestätigungsdialog.
|
||||
|
||||
#### Agent Mode
|
||||
|
||||
Der Agent Mode verwandelt den Chat in ein Step-by-Step Kontrollinterface für den autonomen `CodingAgent`.
|
||||
|
||||
**Ablauf:**
|
||||
1. Benutzer gibt eine Aufgabe ein (z.B. "Schreibe eine Funktion die eine Liste sortiert und speichere sie als sorted.py")
|
||||
2. Der Agent analysiert die Aufgabe und schlägt einen ersten Schritt vor (z.B. `write_new_file` mit dem generierten Code)
|
||||
3. Die UI zeigt den Gedankengang des Agents ("Thought"), das gewählte Tool und die Argumente an
|
||||
4. Benutzer klickt **Approve** → Aktion wird ausgeführt, nächster Schritt wird vorgeschlagen
|
||||
5. Oder **Reject** → Benutzer gibt Feedback ein, Agent plant neu ohne die Aktion auszuführen
|
||||
6. Oder **Abort Task** → Agent wird sofort gestoppt
|
||||
7. Nach Abschluss kann eine Follow-up Frage gestellt werden ohne den Kontext zu verlieren
|
||||
|
||||
Der **Agent Log** zeigt alle abgeschlossenen Schritte in einem aufklappbaren Bereich.
|
||||
|
||||
---
|
||||
|
||||
## Backend — Managers
|
||||
|
||||
### `backend/managers/chat_manager.py` — ChatManager
|
||||
|
||||
Kapselt die gesamte Kommunikation mit dem LLM. Verbindet sich mit einem OpenAI-kompatiblen REST-Endpoint (`/v1/chat/completions`) dessen Adresse und Key aus der `.env` gelesen werden.
|
||||
|
||||
Der Chat-Verlauf wird als Liste von `{role, content}`-Dicts in-memory gehalten. Bei jedem `send_message`-Aufruf wird die vollständige History mitgeschickt, sodass das Modell immer den gesamten Gesprächskontext kennt.
|
||||
|
||||
| Methode | Beschreibung |
|
||||
|---|---|
|
||||
| `send_message(user_message)` | Nachricht zur History hinzufügen, API-Call machen, Antwort zurückgeben und in History speichern |
|
||||
| `add_message(role, content)` | Nachricht direkt zur History hinzufügen (z.B. für System-Prompt) |
|
||||
| `get_history()` | Kopie der aktuellen History zurückgeben |
|
||||
| `clear_history()` | Gesamten Verlauf löschen (neuer Chat) |
|
||||
|
||||
---
|
||||
|
||||
### `backend/managers/file_manager.py` — FileManager
|
||||
|
||||
Abstrahiert alle Dateioperationen und stellt sicher, dass jeder Zugriff innerhalb des `workspace/`-Verzeichnisses bleibt. Jede Methode löst den angegebenen Pfad zu einem absoluten Pfad auf und prüft mit `startswith(workspace.resolve())` ob der Pfad im erlaubten Bereich liegt — damit sind Path-Traversal-Angriffe wie `../../etc/passwd` ausgeschlossen.
|
||||
|
||||
| Methode | Beschreibung |
|
||||
|---|---|
|
||||
| `create_file(relative_path, name)` | Neue leere Datei erstellen. Ohne Extension wird `.txt` ergänzt. Schlägt fehl wenn Datei existiert. |
|
||||
| `create_folder(relative_path, name)` | Neuen Ordner erstellen. Schlägt fehl wenn Ordner existiert. |
|
||||
| `read_file(path)` | Dateiinhalt als String lesen. Gibt leeren String bei Fehler zurück. |
|
||||
| `save_file(path, content)` | Datei mit neuem Inhalt überschreiben (erstellt falls nicht vorhanden). |
|
||||
| `rename_file(old_path, new_name)` | Datei umbenennen. Die Dateiendung wird immer vom Original übernommen. |
|
||||
| `delete_file(relative_path)` | Einzelne Datei löschen. |
|
||||
| `delete_folder(relative_path)` | Ordner und gesamten Inhalt rekursiv löschen. |
|
||||
| `get_file_tree()` | Gesamten Workspace als verschachteltes Dict zurückgeben: Ordner als `{name: dict}`, Dateien als `{name: None}`. |
|
||||
|
||||
---
|
||||
|
||||
### `backend/managers/execution_engine.py` — ExecutionEngine
|
||||
|
||||
Führt Dateien aus dem Editor als Subprocess aus. Die Datei wird immer aus ihrem eigenen Verzeichnis heraus gestartet (`cwd=file.parent`), damit relative Imports und Pfade korrekt funktionieren.
|
||||
|
||||
Unterstützte Dateitypen:
|
||||
- **Python (`.py`)** → `py <dateiname>` (nutzt den Windows Python Launcher)
|
||||
- **LaTeX (`.tex`)** → `pdflatex -interaction=nonstopmode <dateiname>`
|
||||
|
||||
Timeout: 30 Sekunden. Gibt immer ein Dict `{stdout, stderr, rc}` zurück.
|
||||
|
||||
---
|
||||
|
||||
### `backend/managers/system_prompter.py` — SystemPrompter
|
||||
|
||||
Baut den System-Prompt für den normalen Chat zusammen. Ohne Datei-Kontext enthält er nur eine allgemeine Beschreibung des AI-Assistenten. Mit Datei-Kontext wird der Dateiname und der Inhalt (max. 4000 Zeichen, danach abgeschnitten) in XML-ähnliche Tags eingebettet:
|
||||
|
||||
```
|
||||
<file name="fibonacci.py">
|
||||
<code>
|
||||
def fib(n): ...
|
||||
</code>
|
||||
</file>
|
||||
```json
|
||||
{
|
||||
"ServerName": {
|
||||
"command": "py",
|
||||
"args": ["servers/mcp_server_datei.py"],
|
||||
"env": {
|
||||
"API_KEY": "optional_key"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Das Modell wird angewiesen sich auf diese Datei zu beziehen wenn es Fragen zum Code beantwortet.
|
||||
| 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
|
||||
|
||||
---
|
||||
|
||||
### `backend/managers/debug_logger.py` — DebugLogger
|
||||
## Tests
|
||||
|
||||
Einfacher In-Memory-Logger der Ausführungsmeldungen für den Code-Editor speichert. Wird von `editor.py` genutzt um den Status einer Code-Ausführung (`log()`, `log_error()`, `clear()`) zu protokollieren.
|
||||
|
||||
---
|
||||
|
||||
## Backend — Coding Agent
|
||||
|
||||
### `backend/agent/coding_agent.py` — CodingAgent
|
||||
|
||||
Das Herzstück des autonomen Agents. Implementiert den **Plan → Act → Observe → Fix → Done** Loop.
|
||||
|
||||
**Wie der Loop funktioniert:**
|
||||
1. `start_task(task)` initialisiert den Agenten mit dem System-Prompt (enthält Beschreibungen aller verfügbaren MCP-Tools) und der Aufgabe
|
||||
2. `propose_next_action()` schickt den bisherigen Konversationsverlauf an das LLM. Das Modell antwortet immer mit einem JSON-Objekt `{"thought": "...", "tool": "...", "arguments": {...}}`. Die Antwort wird geparsed und als `pending_action` gespeichert — aber **noch nicht ausgeführt**
|
||||
3. `approve()` führt die pending_action aus, fügt das Resultat als User-Nachricht zur History hinzu und ruft sofort `propose_next_action()` auf
|
||||
4. `reject(feedback)` verwirft die pending_action ohne sie auszuführen und injiziert das Feedback als User-Nachricht
|
||||
5. Wenn das LLM `"done"` als Tool wählt, setzt der Agent `is_done = True`
|
||||
|
||||
**Robustheit:** LLM-Antworten die kein valides JSON enthalten werden durch `extract_json()` und `_repair_json_strings()` bereinigt (entfernt Markdown-Fences, repariert unescapte Newlines in Strings). Wenn die History das Limit von 80'000 Zeichen überschreitet, werden ältere Nachrichten entfernt und ein Erinnerungs-Hinweis injiziert.
|
||||
|
||||
| Methode | Beschreibung |
|
||||
|---|---|
|
||||
| `start_task(task)` | Agent neu initialisieren, System-Prompt + Aufgabe setzen |
|
||||
| `propose_next_action()` | LLM-Aufruf → JSON-Antwort parsen → als `pending_action` speichern |
|
||||
| `approve()` | `pending_action` ausführen, Resultat zur History hinzufügen, nächste Aktion vorschlagen |
|
||||
| `reject(feedback)` | `pending_action` verwerfen, Feedback injizieren |
|
||||
| `follow_up(question)` | Nach Abschluss: Folgefrage stellen ohne Kontext zu verlieren |
|
||||
|
||||
---
|
||||
|
||||
### `backend/agent/mcp_server_adapter.py` — MCPToolAdapter
|
||||
|
||||
Der Adapter ist die Brücke zwischen dem `CodingAgent` und den MCP-Servern. Er liest beim Start die Konfigurationsdatei `mcp_server_config.json`, verbindet sich zu jedem Server, fragt dessen Tool-Liste ab und speichert alle Tools in einer internen Registry.
|
||||
|
||||
Bei jedem `call_tool`-Aufruf öffnet der Adapter eine neue `stdio`-Verbindung zum zuständigen Server, führt das Tool aus und schliesst die Verbindung wieder. Das heisst: Die Server laufen nicht permanent, sondern werden für jeden Aufruf frisch gestartet. Das macht das System robuster (kein veralteter State in einem Server) aber etwas langsamer.
|
||||
|
||||
| Methode | Beschreibung |
|
||||
|---|---|
|
||||
| `initialize_all_servers()` | Alle konfigurierten Server starten, Tool-Liste abfragen, in Registry speichern |
|
||||
| `call_tool(tool_name, arguments)` | Passenden Server für das Tool finden, Verbindung aufbauen, Tool aufrufen, Ergebnis zurückgeben |
|
||||
| `get_all_tools()` | Komplette Tool-Registry zurückgeben |
|
||||
|
||||
---
|
||||
|
||||
## MCP-Server
|
||||
|
||||
Die drei MCP-Server sind eigenständige Python-Prozesse die über das `stdio`-Transportprotokoll kommunizieren. Sie werden vom Adapter gestartet und stellen dem Coding Agent Tools zur Verfügung.
|
||||
|
||||
---
|
||||
|
||||
### `backend/agent/servers/mcp_server_code_execution.py` — CodeExecutionServer
|
||||
|
||||
Ermöglicht dem Agent das sichere Ausführen von Python-Code. Bevor Code ausgeführt wird, durchläuft er eine **zweistufige Sicherheitsprüfung**:
|
||||
|
||||
1. **Statische AST-Analyse** (`check_code_safety`): Der Code wird mit Pythons `ast`-Modul geparst. Jeder Import-Node und jeder Funktionsaufruf wird gegen Blocklisten geprüft. Blockierte Imports umfassen u.a. `os`, `sys`, `subprocess`, `socket`, `pickle`. Blockierte Builtins umfassen `exec`, `eval`, `open`, `compile`.
|
||||
|
||||
2. **String-Suche nach verbotenen Sequenzen**: Zusätzlich wird der Code-String direkt nach gefährlichen Mustern durchsucht (`../`, `os.`, `sys.`, `subprocess.` etc.).
|
||||
|
||||
Erst wenn beide Prüfungen bestanden sind, wird der Code via `subprocess.run([sys.executable, "-c", code], stdin=subprocess.DEVNULL, ...)` ausgeführt. `stdin=subprocess.DEVNULL` ist entscheidend: Da der MCP-Server über asyncio-verwaltetes `stdio` läuft, würde der Kind-Prozess sonst stdin erben und blockieren.
|
||||
|
||||
| Tool | Beschreibung |
|
||||
|---|---|
|
||||
| `run_python_sandboxed(code)` | Code nach Sicherheitsprüfung ausführen. Gibt stdout+stderr zurück (max. 3000 Zeichen). Timeout: 45s. |
|
||||
| `python_code_validation(code)` | Nur prüfen (Syntax + Sicherheit), nicht ausführen. |
|
||||
| `lint_code(code)` | Pyflakes-Analyse: ungenutzte Imports, undefinierte Variablen, Syntax-Fehler. |
|
||||
| `analyse_structure(code)` | Imports, Klassen (mit Methoden) und Top-Level-Funktionen als strukturierte Zusammenfassung. |
|
||||
|
||||
---
|
||||
|
||||
### `backend/agent/servers/mcp_server_file_search.py` — FileSearchServer
|
||||
|
||||
Gibt dem Agent Lese- und Schreibzugriff auf den `workspace/`-Ordner. Alle Pfade werden über `_safe_path()` gegen Path-Traversal validiert — ein Zugriff ausserhalb des Workspace ist nicht möglich.
|
||||
|
||||
| Tool | Beschreibung |
|
||||
|---|---|
|
||||
| `list_files()` | Alle Dateien im Workspace rekursiv auflisten (ohne `__pycache__`). |
|
||||
| `get_file_tree(dir_path)` | Verzeichnisstruktur als formatierter Text (ähnlich `tree`-Befehl). |
|
||||
| `search_files(query)` | Dateien deren Name oder Inhalt den Suchbegriff enthält (case-insensitive). |
|
||||
| `read_file(path)` | Vollständigen Inhalt einer Datei lesen. |
|
||||
| `write_new_file(path, content)` | Neue Datei erstellen und Inhalt schreiben. Bestehende Dateien können **nicht** überschrieben werden. |
|
||||
| `create_new_directory(path)` | Neues Verzeichnis im Workspace erstellen. |
|
||||
|
||||
---
|
||||
|
||||
### `backend/agent/servers/mcp_server_web_search.py` — WebSearchServer
|
||||
|
||||
Gibt dem Agent Zugriff auf das Internet. Enthält einen SSRF-Schutz der verhindert, dass der Agent interne Adressen abruft.
|
||||
|
||||
**SSRF-Schutz** (`_validate_url`): Nur `http://` und `https://`-URLs sind erlaubt. Hostnamen wie `localhost`, `127.0.0.1`, `0.0.0.0`, `169.254.169.254` (AWS Metadata) sowie alle privaten IP-Ranges (`10.x`, `172.16-31.x`, `192.168.x`) sind blockiert.
|
||||
|
||||
| Tool | Beschreibung |
|
||||
|---|---|
|
||||
| `web_search(query, max_results)` | DuckDuckGo-Suche. Gibt Titel, URL und Snippet für jedes Ergebnis zurück (Standard: 5 Ergebnisse). |
|
||||
| `fetch_page(url)` | URL abrufen, HTML parsen, Fliesstext extrahieren (max. 4000 Zeichen). |
|
||||
|
||||
---
|
||||
|
||||
## CLI-Test mit `run_agent.py`
|
||||
|
||||
Für schnelles Testen des Coding Agents ohne die Streamlit-App:
|
||||
### Tests ausführen
|
||||
|
||||
```bash
|
||||
python run_agent.py
|
||||
# Alle Tests ausführen
|
||||
pytest tests/ -v
|
||||
|
||||
# Einzelnes Test-Modul ausführen
|
||||
pytest tests/test_coding_agent.py -v
|
||||
|
||||
# Tests mit Kurzausgabe
|
||||
pytest tests/
|
||||
```
|
||||
|
||||
Das Script startet eine interaktive Konsolen-Session:
|
||||
- **Aufgabe eingeben** → Agent startet
|
||||
- **Enter drücken** → Vorgeschlagene Aktion genehmigen und ausführen
|
||||
- **Text eingeben + Enter** → Feedback geben, Agent plant neu
|
||||
- **`stop` eingeben** → Abbrechen
|
||||
### Teststruktur
|
||||
|
||||
Die Tests liegen in `tests/` und folgen dem Muster `test_<modulname>.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 │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user