diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 8b3bb1b..a32a335 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -29,14 +29,15 @@ 15. [Krea-Bildgenerierung](#krea-bildgenerierung) 16. [Auth & Multi-User](#auth--multi-user) 17. [Admin-Benutzerverwaltung](#admin-benutzerverwaltung) -18. [Nachrichten teilen (Shared Messages)](#nachrichten-teilen-shared-messages) -19. [Workspace & File-Explorer](#workspace--file-explorer) -20. [Avatar-System](#avatar-system) -21. [LaTeX/Math-Rendering](#latexmath-rendering) -22. [Windows Desktop App](#windows-desktop-app) -23. [Deployment](#deployment) -24. [Konfiguration](#konfiguration) -25. [Datenbank-Migrationen](#datenbank-migrationen) +18. [Multi-Agent Review-System](#multi-agent-review-system) +19. [Nachrichten teilen (Shared Messages)](#nachrichten-teilen-shared-messages) +20. [Workspace & File-Explorer](#workspace--file-explorer) +21. [Avatar-System](#avatar-system) +22. [LaTeX/Math-Rendering](#latexmath-rendering) +23. [Windows Desktop App](#windows-desktop-app) +24. [Deployment](#deployment) +25. [Konfiguration](#konfiguration) +26. [Datenbank-Migrationen](#datenbank-migrationen) --- @@ -109,7 +110,7 @@ gott/ │ ├── KreaImageRecord.cs │ ├── SharedMessageRecord.cs # Geteilte Nachrichten (Share-Token) │ ├── ChatModels.cs # ChatMessage, ChatRequest, AttachmentInfo/Block -│ └── ChatContext.cs # Runtime-Kontext für einen Chat +│ └── ChatContext.cs # Runtime-Kontext für einen Chat + ReviewContext │ ├── Services/ # Business-Logic │ ├── DatabaseService.cs # SQLite CRUD, Schema, Migrationen @@ -247,6 +248,7 @@ gott/ User (1) ─── (*) Agent User (1) ─── (*) Session Agent (1) ─── (*) Session (Session hat optional einen Agent) +Agent (1) ─── (*) Session (Session hat optional einen Review-Agent) Agent (*) ─── (*) Skill (via agent_skills Tabelle) Session (1) ─── (*) Chain (ein Chat-Request = eine Chain) Session (1) ─── (*) Archive (archivierte Chains) @@ -265,7 +267,7 @@ Message (1) ─── (*) SharedMessage | `users` | Benutzer (username, password_hash, persona, settings, default_path) | | `tokens` | Auth-Tokens (token → user_id) | | `agents` | AI-Agenten (model, soul, identity, memory, tools, avatar_scale) | -| `sessions` | Chat-Sessions (workspace, context, telegram-config, avatar_scale, telegram_allowed_chat_ids) | +| `sessions` | Chat-Sessions (workspace, context, telegram-config, avatar_scale, telegram_allowed_chat_ids, review_agent_id, max_review_iterations) | | `chains` | Request-Chains (model, tokens, iterations, timing) | | `messages` | Einzelne Nachrichten (text, tool_use, tool_result) | | `attachments` | Datei-Anhänge (base64, image/document) | @@ -481,9 +483,21 @@ Der Chat-Flow von User-Input bis zur gerenderten Antwort: │ → CancellationToken bei Abbruch │ └─────────────────────────────────────────┘ ↓ +4b. Review-Phase (optional, wenn ReviewAgent konfiguriert): + ┌─────────────────────────────────────────┐ + │ Nach end_turn des Worker-Agents: │ + │ → RunReview() mit Review-Agent │ + │ → Review-Agent prüft (eigene Tools) │ + │ → [APPROVED] → Fertig │ + │ → Feedback → an Worker als User-Msg │ + │ → Worker korrigiert → erneuter Review │ + │ → Max Review-Runden → Fertig │ + └─────────────────────────────────────────┘ + ↓ 5. Frontend: SSE Events empfangen und rendern • "text" → Markdown parsen, Token für Token anzeigen • "tool_*" → Tool-Aufrufe collapsible darstellen + • "review_*" → Review-Bubbles mit eigenem Styling • "done" → Token-Stats, Dauer, Model anzeigen ``` @@ -886,6 +900,113 @@ Admins können für jeden User einen **Autologin-Link** generieren – z.B. für --- +## Multi-Agent Review-System + +Das Review-System ermöglicht es, einen zweiten Agent als **Reviewer** einzusetzen. Nach jeder Antwort des Worker-Agents prüft der Review-Agent das Ergebnis und gibt entweder `[APPROVED]` oder konstruktives Feedback. + +### Architektur + +``` +User-Message → Worker-Agent arbeitet (Tools, Iterationen) → end_turn + → Review-Phase: + → Review-Agent bekommt: Konversation als Kontext + → Review-Agent prüft (kann Tools nutzen: read_file, execute etc.) + → [APPROVED] → Fertig, Antwort an User + → Feedback-Text → wird als User-Message an Worker-Agent eingefügt + → Worker-Agent korrigiert → end_turn → Review-Agent prüft erneut + → Max Review-Runden erreicht → Fertig (mit letzter Worker-Antwort) +``` + +### Konfiguration + +Auf **Session-Ebene** (nicht Agent-Ebene): + +| DB-Feld | SessionRecord | Beschreibung | +|---------|---------------|-------------| +| `review_agent_id` | `ReviewAgentId` | ID des Review-Agents (optional, null = kein Review) | +| `max_review_iterations` | `MaxReviewIterations` | Max. Review-Runden (Default: 3) | + +### Backend-Flow + +1. **ChatService.PrepareContext()** – Wenn `session.ReviewAgentId` gesetzt: + - Review-Agent aus DB laden + - Eigenen SystemPrompt für den Review-Agent bauen (Identity, Soul, Memory, Skills) + - Eigene Tool-Definitionen für den Review-Agent + - `ReviewContext` mit Model, SystemPrompt, Tools, Agent-Referenz erstellen + +2. **ChatEndpoint** – Übergibt `ctx.Review` an `AnthropicService.StreamChat()` + +3. **AnthropicService.StreamChat()** – Nach `end_turn` des Worker-Agents: + - Prüft ob `ReviewContext` vorhanden und `reviewRound < MaxReviewIterations` + - Ruft `RunReview()` auf + +4. **RunReview()** – Orchestriert eine einzelne Review-Runde: + - Baut Review-Messages auf: Konversation als Context + Prüfanweisung + - SSE-Event `review_start` an Client senden + - Ruft `RunReviewAgentChat()` auf (eigener API-Call an Claude mit Review-Agent-Config) + - Review-Agent kann Tools nutzen (eigener Tool-Loop mit max. 25 Iterationen) + - SSE-Events `review_text` und `review_tool_use` für Live-Streaming + - Prüft ob Antwort `[APPROVED]` enthält: + - **Ja** → SSE `review_approved`, return `HasFeedback = false` + - **Nein** → SSE `review_feedback`, return `HasFeedback = true` + Feedback-Text + +5. **Zurück in StreamChat()** – Bei Feedback: + - Feedback als User-Message in DB speichern (mit `[Review-Feedback von AgentName (Runde X/Y)]` Prefix) + - Worker-Agent bekommt Feedback als nächste User-Message + - `continue` → nächste while-Loop-Iteration → Worker korrigiert → Review erneut + - `reviewRound++` bis `MaxReviewIterations` erreicht + +### ReviewContext (Model) + +```csharp +public class ReviewContext +{ + public string Model { get; set; } // Claude-Modell des Review-Agents + public string SystemPrompt { get; set; } // Eigener System-Prompt + public AgentRecord Agent { get; set; } // Agent-Record für Name/Avatar + public List Tools { get; set; } // Tool-Definitionen + public int MaxReviewIterations { get; set; } // Max Runden +} +``` + +### SSE-Events + +| Event | Daten | Beschreibung | +|-------|-------|-------------| +| `review_start` | `{ agent: "Name" }` | Review-Phase beginnt | +| `review_text` | `{ text: "..." }` | Review-Agent-Text (Token-Stream) | +| `review_tool_use` | `{ tool: "name", input: "..." }` | Review-Agent nutzt Tool | +| `review_feedback` | `{ feedback: "..." }` | Review nicht bestanden, Feedback an Worker | +| `review_approved` | `{ message: "..." }` | Review bestanden | + +### DB-Persistierung + +- **Worker-Antworten**: Normale Messages (role=assistant, type=text) +- **Review-Feedback**: Als User-Messages mit Prefix `[Review-Feedback von AgentName (Runde X/Y)]:` +- **Review-Agent-Antworten**: Werden **nicht** in der Chat-History persistiert (nur als SSE-Events gestreamt), da sie Zwischenergebnisse sind + +### Frontend + +**Session-Page** (`session-page.js`): +- Zweiter Agent-Picker: "Review-Agent" (nutzt `buildAgentCard()` + `openAgentPickerModal()`) +- Input für "Max. Review-Runden" (Number-Input, Default 3) + +**Chat-UI** (`chat.js`): +- SSE-Event-Handler für `review_start`, `review_text`, `review_tool_use`, `review_feedback`, `review_approved` +- Review-Bubbles mit eigenem Styling (sekundäre Farbe, Agent-Name-Header) + +**History-Rendering** (`history.js`, `ui.js`): +- `renderMarkdown` parst `[Review: AgentName]` → styled Header mit Icon +- `renderMarkdown` parst `[Review-Feedback von AgentName (...)]` → styled Feedback-Header +- `renderMarkdown` filtert `[APPROVED]` aus (wird ausgeblendet) +- History erkennt Review-Nachrichten und rendert sie als `.review-bubble` statt normaler Bubbles +- Review-Nachrichten werden nicht mit normalen Nachrichten gemergt + +**Shared-Page** (`shared-page.js`): +- Gleiche Review-Bubble-Erkennung für geteilte Nachrichten + +--- + ## Nachrichten teilen (Shared Messages) Einzelne Nachrichten oder ganze Threads können als **öffentliche Links** geteilt werden – ohne Login aufrufbar. diff --git a/ARCHITECTURE_QUICK.md b/ARCHITECTURE_QUICK.md index 0b7cd05..be80884 100644 --- a/ARCHITECTURE_QUICK.md +++ b/ARCHITECTURE_QUICK.md @@ -26,7 +26,7 @@ gott/ │ ├── js/router.js # Hash-basiertes SPA-Routing │ ├── js/api.js # fetch()-Wrapper │ ├── js/chat.js # SSE-Stream, Markdown-Rendering -│ ├── js/ui.js # UI-Helpers, buildAgentCard(), buildSessionCard() +│ ├── js/ui.js # UI-Helpers, buildAgentCard(), buildSessionCard(), Review-Rendering │ ├── js/pages/ # Seiten-Komponenten │ └── css/ # Styles (theme.css = CSS Variables) ├── WindowsApp/ # WPF + WebView2 Desktop Client @@ -55,7 +55,7 @@ User 1──* Agent 1──* Session 1──* Chain 1──* Message 1──* At | `users` | Login, Persona, Settings (JSON), DefaultPath | | `tokens` | Auth-Tokens → User | | `agents` | AI-Agenten (Model, Tools, Config, AvatarScale) | -| `sessions` | Chat-Sessions (Workspace, Context, Telegram, AvatarScale, AllowedChatIds) | +| `sessions` | Chat-Sessions (Workspace, Context, Telegram, AvatarScale, AllowedChatIds, ReviewAgentId, MaxReviewIterations) | | `chains` | Ein Request-Response-Zyklus (Tokens, Timing, Iterations) | | `messages` | Einzelne Nachrichten (text / tool_use / tool_result / error) | | `attachments` | Base64-Anhänge (Bilder, Dokumente) | @@ -124,6 +124,9 @@ User-Input → POST /api/chat (SSE) → Token-für-Token an Client streamen → Bei tool_use → ToolService.Execute() → Ergebnis zurück → neuer API Call → Loop bis end_turn oder max_iterations (100) + → Bei end_turn + ReviewAgent → Review-Phase: + → Review-Agent prüft (eigene Tools, max 25 Iterationen) + → [APPROVED] → Fertig | Feedback → Worker korrigiert → erneuter Review → Stop-Button: POST /api/chat/stop → StreamingTracker.Cancel() → CancellationToken durchgereicht bis ToolService → Prozess-Kill → client_disconnected @@ -230,6 +233,23 @@ Läuft als `systemd`-Service, Kestrel auf Port 19000, typisch hinter Nginx/Caddy --- +## Multi-Agent Review-System + +Eine Session kann optional einen **Review-Agent** haben (`review_agent_id`, `max_review_iterations`). + +**Flow:** Worker-Agent arbeitet → `end_turn` → Review-Agent prüft (eigener API-Call, eigene Tools, max 25 Iterationen) → `[APPROVED]` = fertig | Feedback → Worker korrigiert → erneuter Review (bis max Runden). + +**Backend:** `ChatService` baut `ReviewContext` (Model, SystemPrompt, Tools). `AnthropicService.RunReview()` orchestriert Review-Runden. `RunReviewAgentChat()` = eigener Claude-API-Call. + +**SSE-Events:** `review_start`, `review_text`, `review_tool_use`, `review_feedback`, `review_approved` + +**Frontend-Rendering:** +- Streaming: `chat.js` rendert Review-Events als eigene Bubbles (`.review-bubble`) +- History: `renderMarkdown` parst `[Review: AgentName]`, `[Review-Feedback ...]`, filtert `[APPROVED]` +- `history.js` + `shared-page.js`: Review-Nachrichten als `.review-bubble`, kein Merging mit normalen Messages + +--- + ## Wichtige Regeln beim Entwickeln - ⚠️ **Quelldateien in `wwwroot/`** editieren, NICHT in `publish/wwwroot/`