chore: prior changes on func_improvments before agent merge

This commit is contained in:
Livio Meuli 2026-05-24 10:28:44 +02:00
parent 241c6580f3
commit 45ec8f8208
4 changed files with 628 additions and 208 deletions

46
DEBUG_LOGGER_USAGE.md Normal file
View File

@ -0,0 +1,46 @@
# DebugLogger Usage
## Import
```python
from backend.managers.debug_logger import DebugLogger
logger = DebugLogger()
```
## Methoden
```python
logger.clear() # vor jeder neuen Ausführung aufrufen
logger.log("Nachricht") # INFO-Eintrag
logger.log_error("Fehler") # ERROR-Eintrag
logger.get_logs() # gibt Liste aller Einträge zurück
logger.format_debug_output({ # gibt formatierten String zurück
"rc": 0,
"stdout": "...",
"stderr": "..."
})
```
## Eintrag-Format
```python
{
"level": "INFO", # oder "ERROR"
"message": "Nachricht",
"timestamp": "14:23:01"
}
```
## Beispiel
```python
logger = DebugLogger()
logger.clear()
logger.log("Starte Ausführung...")
try:
result = run_something()
logger.log("Erfolgreich abgeschlossen.")
except Exception as e:
logger.log_error(f"Fehler: {e}")
# Logs anzeigen
for entry in logger.get_logs():
print(f"[{entry['timestamp']}] [{entry['level']}] {entry['message']}")
```

331
README.md
View File

@ -1,153 +1,224 @@
# AISE AI Code Editor
# AISE AI Agent — Code Editor & Coding Assistant
AI-Supported Lightweight Code Editor built with Streamlit (AISE501 Spring 2026)
Ein browserbasierter Code-Editor mit integriertem AI-Chat und autonomem Coding-Agent, gebaut mit Streamlit und dem Model Context Protocol (MCP).
## Project Structure
---
## 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
```
---
## Projektstruktur
```
AISE_AIAgent/
├── frontend/ # Streamlit UI Components
│ ├── __init__.py
│ ├── app.py # Main Streamlit application entry point
│ ├── sidebar.py # File navigation sidebar component
│ ├── editor.py # Code editor pane component
│ └── chat.py # Chat interface component
│
├── backend/ # Backend Logic Modules
│ ├── __init__.py
│ ├── managers/ # Business logic for UI operations
│ │ ├── __init__.py
│ │ ├── file_manager.py # File I/O operations for UI (read, write, list files)
│ │ ├── chat_manager.py # AI chat management and history
│ │ ├── system_prompter.py # System prompts and context injection
│ │ ├── search_manager.py # Internet search functionality
│ │ ├── execution_engine.py # Code execution and sandboxing
│ │ └── debug_logger.py # Logging, error handling, debug messages
│ │
│ ├── agents/ # AI Agent System
│ │ ├── __init__.py
│ │ ├── coding_agent.py # Main agent loop (plan-act-observe cycle)
│ │ └── tools.py # Tools available to agent (7 functions + dispatcher)
│ │
│ └── utils/ # Helper Utilities
│ ├── __init__.py
│ └── server_utils.py # LLM client init, chat functions, formatters
│
├── tests/ # Unit Tests
│ ├── __init__.py
│ ├── test_file_manager.py # Tests for file operations
│ ├── test_chat_manager.py # Tests for chat functionality
│ ├── test_execution_engine.py # Tests for code execution
│ └── test_main.py # Integration tests
│
├── workspace/ # Agent Sandbox Directory
│ └── .gitkeep # Placeholder for agent to work safely in isolation
│
├── .gitignore # Git exclusions (venv, .env, __pycache__, etc.)
├── .env # Local environment variables (NOT committed)
├── .env.example # Template for environment variables (IS committed)
├── requirements.txt # Python dependencies
├── README.md # This file
└── project_exercise.pdf # Project specification
├── 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
```
## Component Responsibilities
---
### Frontend (`frontend/`)
- **app.py**: Main Streamlit application, layout orchestration
- **sidebar.py**: File browser and project navigation
- **editor.py**: Code editing interface with syntax highlighting
- **chat.py**: AI assistant chat interface
## Frontend
### Backend Managers (`backend/managers/`)
Used directly by Frontend for UI operations:
- **file_manager.py**: CRUD operations on project files
- **chat_manager.py**: Chat history, message management
- **system_prompter.py**: System prompt generation and file context
- **execution_engine.py**: Safe code execution with output capture
- **debug_logger.py**: Error tracking and log formatting
- **search_manager.py**: Web search integration
### `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 Agents (`backend/agents/`)
Independent AI agent system for complex tasks:
- **coding_agent.py**: Agent loop (Plan → Act → Observe → Repeat)
- **tools.py**: 7 tools agent can use (read/write/run/search/validate/grep/done)
### `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 Utils (`backend/utils/`)
- **server_utils.py**: LLM client initialization, chat helpers, message formatters
### `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 directory where agent executes and stores files
- Prevents agent from accessing files outside this directory
### `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
- **File Display & Management**: Browse and edit code files
- **Chat Interface**: AI-powered code assistant
- **Code Execution**: Run Python code with debugging
- **Internet Search**: Fetch documentation and examples
- **System Prompts**: Context-aware AI interactions
**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
### 1. Project Clonen
---
1. In den Zielordner wechseln
cd /pfad/zum/zielordner
## Backend — Managers
2. Repository klonen
git clone https://gitea.fhgr.ch/meulilivio/AISE1_Project.git
### `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.
3. In das Projekt wechseln
cd AISE1_Project
| 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 |
### 2. Activate Virtual Environment
### `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:
```bash
# Windows
.\.venv\Scripts\Activate.ps1
# macOS/Linux
source .venv/bin/activate
```
### 3. Install Dependencies
```bash
pip install -r requirements.txt
```
### 4. Run Application
```bash
streamlit run frontend/app.py
```
### 5. Run Tests
```bash
pytest tests/
```
## Architecture
The application follows a frontend-backend split:
- **Frontend**: Streamlit UI components (sidebar, editor, chat)
- **Backend**: Specialized manager modules
- FileManager: File operations
- ChatManager: AI interaction
- SystemPrompter: Prompt management
- SearchManager: Internet search
- ExecutionEngine: Code execution
- DebugLogger: Error handling & logging
## Development
Use Git to track changes:
```bash
git add .
git commit -m "Your message"
git push origin sturcture
python run_agent.py
# Aufgabe eingeben → Enter zum Genehmigen, Text zum Ablehnen, "stop" zum Abbrechen
```

381
READMEnew.md Normal file
View File

@ -0,0 +1,381 @@
# AISE AI Agent — Code Editor & Coding Assistant
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.
---
## Was kann das Projekt?
- **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`.
---
## Projektstruktur
```
AISE_AIAgent/
│
├── 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
│ │
│ └── 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
```
---
## Frontend
### `frontend/app.py` — Einstiegspunkt der App
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.
---
### `frontend/state.py` — Session State Verwaltung
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.
**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
---
### `frontend/sidebar.py` — Navigation & File Explorer
Die Sidebar ist in zwei Bereiche aufgeteilt:
**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.
**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.
**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
---
### `frontend/editor.py` — Code-Editor
Der Code-Editor ist die zentrale Arbeitsfläche für das direkte Bearbeiten von Dateien.
**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.
**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>
```
Das Modell wird angewiesen sich auf diese Datei zu beziehen wenn es Fragen zum Code beantwortet.
---
### `backend/managers/debug_logger.py` — DebugLogger
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:
```bash
python run_agent.py
```
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

View File

@ -1,78 +0,0 @@
"""
Temporäres Test-Script für den CodingAgent – kann danach gelöscht werden.
Ausführen:
python run_agent.py
Steuerung:
Enter → Aktion ausführen (approve)
Text + Enter → Feedback geben (reject + replan)
stop → Abbrechen
"""
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent))
from backend.agent.coding_agent import CodingAgent, WORKSPACE
def run():
print("\n" + "=" * 60)
print(" CodingAgent – Interaktiver Test")
print("=" * 60)
print(f" Workspace: {WORKSPACE}")
print(" [Enter] = Aktion ausführen | Text = Feedback | 'stop' = Abbruch")
print("=" * 60 + "\n")
task = input("Aufgabe eingeben: ").strip()
if not task:
print("Keine Aufgabe eingegeben. Beende.")
return
agent = CodingAgent()
agent.start_task(task)
print(f"\nAgent gestartet für: '{task}'\n")
step = 0
while not agent.is_done:
step += 1
print(f"\n{'─' * 60}")
print(f" Schritt {step} – Agent überlegt...")
action = agent.propose_next_action()
print(f"\n Thought : {action.get('thought', '')}")
print(f" Tool : {action.get('tool', '')}")
print(f" Arguments: {action.get('arguments', {})}")
print()
user_input = input(" [Enter]=ausführen | Text=Feedback | stop=Abbruch: ").strip()
if user_input.lower() in ("stop", "abort"):
print("\nAbgebrochen.")
break
if user_input:
agent.reject(user_input)
print(f" → Feedback injiziert. Agent plant neu.\n")
continue
result = agent.approve()
print(f"\n Resultat ({result['tool']}):")
print(f" {result['result'][:300]}{'...' if len(result['result']) > 300 else ''}")
if result["is_done"]:
print("\n" + "=" * 60)
print(" FERTIG!")
print(f" {result['result']}")
print("=" * 60)
if __name__ == "__main__":
try:
run()
except KeyboardInterrupt:
print("\n\nUnterbrochen.")