docs: Dokumentation aktualisieren (ReviewContext→SubAgentContext, Provider-Weiche, agent_api_keys, Scanner, Dashboard-Sortierung, Plan-Modus-Hint)

ARCHITECTURE.md:
- ReviewContext → SubAgentContext (Code-Block + alle Referenzen)
- ChatContext.cs Kommentar aktualisiert
- Provider-Weiche für Telegram, Cronjobs, Sub-Agents dokumentiert
- OpenAiService: ChatNonStreaming() ergänzt
- Chat-Pipeline: API-Key-Auflösung als Schritt 3c
- Multi-Provider-Tabelle: AnthropicToken → agent_api_keys
- api_keys Tabelle: Zuweisung pro Agent statt global
- Neue Tabellen: agent_api_keys, scanner_logs, server_settings
- Dashboard-Sortierung nach letzter Chat-Nachricht
- Plan-Modus: Hint-Mechanismus dokumentiert
- Key-Scanner: 4 Quellen (GitHub Code, Issues/PRs, HuggingFace, Serper)
- API-Key pro Agent: Endpoints + Kein-Key-Option
- ServerSettingsService in Service-Tabelle
- session.js: currentAgentId dokumentiert
- Streaming vs Non-Streaming: Sub-Agents ergänzt

ARCHITECTURE_QUICK.md:
- Multi-Agent Backend: SubAgentContext + Provider-Weiche
- OpenAiService: Non-Streaming erwähnt
- Chat-Pipeline: Key-Auflösung ergänzt
- api_keys: Zuweisung pro Agent
- Dashboard-Route: Sortierungs-Hinweis

README.md:
- Key-Scanner: 4 Quellen statt nur GitHub
This commit is contained in:
Meleki committed 2026-03-15 09:20:46 +01:00
1 parent a6a0223f44
commit 8e94975e61
3 files changed
+109 -51

No files matched your search

+95 -42
View File
@@ -126,7 +126,7 @@ gott/
│ ├── ChatModels.cs # ChatMessage, ChatRequest, AttachmentInfo/Block
│ ├── ApiKeyRecord.cs # API-Key-Verwaltung (Provider, Name, Key, IsActive, Status, Plan, Usage, SourceUrl)
│ ├── ScannedKeyRecord.cs # Gescannte GitHub-Keys (SourceUrl, Status, Plan, Usage, AdoptedApiKeyId)
│ └── ChatContext.cs # Runtime-Kontext für einen Chat + ReviewContext
│ └── ChatContext.cs # Runtime-Kontext für einen Chat + SubAgentContext
│
├── Services/ # Business-Logic
│ ├── DatabaseService.cs # SQLite Schema, Migrationen, Core (partial class)
@@ -153,8 +153,9 @@ gott/
│ ├── ImageService.cs # Bild-Resize + WebP-Konvertierung (512px + 256px Thumbnail)
│ ├── StreamingTracker.cs # Tracking aktiver Streams + CancellationTokenSource für Stop
│ ├── WorkspaceHelper.cs # Workspace-Pfad-Auflösung (relativ → absolut)
│ ├── KeyScannerService.cs # GitHub Code-Search nach geleakten API-Keys
│ └── AnthropicKeyChecker.cs # Anthropic Key-Validierung + Usage-Header-Auswertung
│ ├── KeyScannerService.cs # API-Key-Scanner (GitHub Code Search, GitHub Issues/PRs, HuggingFace Hub, Google/Serper)
│ ├── AnthropicKeyChecker.cs # Anthropic Key-Validierung + Usage-Header-Auswertung
│ └── ServerSettingsService.cs # Server-Settings Verwaltung (In-Memory-Cache + DB)
│
├── Endpoints/ # HTTP API (Minimal API)
│ ├── AuthEndpoint.cs # Login, Logout, Me
@@ -227,7 +228,7 @@ gott/
│ │ ├── archive.js # Archiv-Loading
│ │ ├── reply.js # Reply/Quote-Handling
│ │ ├── files.js # File-Upload, Workspace-Refs
│ │ ├── session.js # Session-Verwaltung
│ │ ├── session.js # Session-Verwaltung (currentSessionId, currentAgentId)
│ │ ├── file-explorer.js # File-Explorer Komponente
│ │ ├── avatar-editor.js # Wiederverwendbares Avatar-Editor-Modal
│ │ ├── commands-ui.js # Custom-Commands UI
@@ -332,8 +333,11 @@ TelegramBot (1) ─── (*) Session (via telegram_bot_id)
| `cronjobs` | Geplante Tasks (cron expression, prompt, notify_session_id, is_enabled, last_run, next_run) |
| `shared_messages` | Geteilte Nachrichten (Share-Token, Ablaufdatum) |
| `telegram_bots` | Telegram Bots (bot_token, webhook_secret, name, is_public) – eigenständige Entität |
| `api_keys` | API-Keys pro Provider (key_id, provider, name, api_key, is_active, status, plan, usage_7d, usage_5h, source_url, checked_at) – nur ein Key pro Provider aktiv |
| `api_keys` | API-Keys (key_id, provider, name, api_key, is_active, status, plan, usage_7d, usage_5h, source_url, checked_at) – mehrere Keys pro Provider möglich, Zuweisung pro Agent über `agent_api_keys` |
| `agent_api_keys` | API-Key-Zuweisung pro User+Agent (user_id, agent_id, key_id) – ersetzt globales `users.selected_api_key_id` |
| `scanned_keys` | Gescannte GitHub-Keys (scanned_key_id, api_key, source_url, status, plan, usage_7d, usage_5h, adopted_api_key_id, deleted) |
| `scanner_logs` | Scanner-Logs (timestamp, type, message, scanner, details) – Logs von Key-Scanner und Event-Scanner |
| `server_settings` | Server-Settings (key, value, type) – In-Memory-Cache über `ServerSettingsService` |
| `message_embeddings` | Sentence-Embeddings für semantische Suche (message_id, vector BLOB, session_id, agent_id) |
| `memory_file_embeddings` | Embeddings von Memory-Dateien (agent_id, file_path, chunk_index, vector BLOB) |
@@ -413,7 +417,7 @@ RemoteConnectionManager → AuthService → DatabaseService → EnsureDefaultUse
| `AuthService` | Singleton | Token-Erzeugung/-Validierung, Passwort-Hashing (SHA256) |
| `ChatService` | Singleton | Chat-Kontext aufbauen, History aus DB rekonstruieren |
| `AnthropicService` | Singleton | Claude API Kommunikation (Streaming SSE + Non-Streaming), passive Usage-Aktualisierung nach jedem Request |
| `OpenAiService` | Singleton | OpenAI-kompatible Provider (Nvidia, Pollinations, Gemini) mit Tool-Calling, Streaming, Modell-Caching |
| `OpenAiService` | Singleton | OpenAI-kompatible Provider (Nvidia, Pollinations, Gemini) mit Tool-Calling, Streaming + Non-Streaming, Modell-Caching |
| `ToolService` | Singleton | Tool-Definitionen bereitstellen, Tool-Aufrufe ausführen |
| `WorkspaceHelper` | Static | Workspace-Pfad-Auflösung (relativ → absolut), Path-Traversal-Schutz |
| `SystemPromptBuilder` | Static | Modularer System-Prompt aus konfigurierbaren Blöcken + Reminder-Generierung |
@@ -429,8 +433,9 @@ RemoteConnectionManager → AuthService → DatabaseService → EnsureDefaultUse
| `KreaService` | Singleton | Krea API für Bildgenerierung, Job-Polling, Image-Download |
| `ImageService` | Singleton | Bild-Resize + WebP-Konvertierung (512px + 256px Thumbnail) für Avatare und Session-Bilder |
| `StreamingTracker` | Singleton | Trackt aktive Streams + CancellationTokenSource pro Session für Stop-Button |
| `KeyScannerService` | Singleton | GitHub Code-Search nach geleakten API-Keys (13 Sprachen, 24 Pfad-Extensions), Background-Scan |
| `KeyScannerService` | Singleton | API-Key-Scanner (GitHub Code Search, GitHub Issues/PRs, HuggingFace Hub, Google/Serper), täglicher Scan |
| `AnthropicKeyChecker` | Static | Anthropic Key-Validierung via API-Request, Usage-Header-Auswertung (Plan, 7d/5h Usage) |
| `ServerSettingsService` | Singleton | Server-Settings Verwaltung (In-Memory-Cache + DB), Cleanup obsoleter Settings |
### Endpoints (API)
@@ -509,7 +514,7 @@ Das Frontend ist eine **Single-Page Application** ohne Build-Step, komplett in V
| Route | Page | Beschreibung |
|--------------------------|---------------------|---------------------------|
| `#/` | `dashboard.js` | Session-Übersicht |
| `#/` | `dashboard.js` | Session-Übersicht (sortiert nach letzter Chat-Nachricht, Fallback: `updated_at`) |
| `#/chat/{sessionId}` | `chat-page.js` | Chat-Ansicht |
| `#/session/{sessionId}` | `session-page.js` | Session-Einstellungen |
| `#/agent/{agentId}` | `agent-page.js` | Agent-Editor |
@@ -539,7 +544,7 @@ Das Frontend ist eine **Single-Page Application** ohne Build-Step, komplett in V
- **archive.js** – Archiv-Loading und -Rendering
- **reply.js** – Reply/Quote-Handling (Set, Clear, Format)
- **files.js** – File-Upload, Workspace-Refs
- **session.js** – Session-State-Management
- **session.js** – Session-State-Management (currentSessionId, currentAgentId, getCurrentAgentId())
- **file-explorer.js** – Workspace File-Explorer Panel (Dateien, Ordner erstellen/löschen, Folder-Browser)
- **avatar-editor.js** – Wiederverwendbares Avatar-Editor-Modal (Upload, Paste, AI-Generate, Scale)
- **commands-ui.js** – Custom-Commands UI-Komponente
@@ -573,7 +578,7 @@ Neben Anthropic Claude unterstützt Gott drei **OpenAI-kompatible Provider**. De
| Prefix | Provider | Base-URL | API-Key |
|--------|----------|----------|---------|
| (kein) | Anthropic Claude | `api.anthropic.com` | `AnthropicToken` |
| (kein) | Anthropic Claude | `api.anthropic.com` | via `agent_api_keys` (pro Agent zugewiesen) |
| `nvidia:` | Nvidia (g4f.space Proxy) | `g4f.space/api/nvidia/v1` | keiner |
| `pollinations:` | Pollinations | `text.pollinations.ai/openai` | keiner |
| `gemini:` | Google Gemini | `generativelanguage.googleapis.com/v1beta/openai` | `GeminiApiKey` |
@@ -589,7 +594,8 @@ Beim Server-Start werden verfügbare Modelle von den Provider-APIs geladen und i
### OpenAiService
`OpenAiService` implementiert:
- **Streaming via SSE** (OpenAI-Format: `choices[0].delta`)
- **Streaming via SSE** (`StreamChat()`, OpenAI-Format: `choices[0].delta`)
- **Non-Streaming** (`ChatNonStreaming()`, für Telegram, Cronjobs, Sub-Agents – agentic loop mit Tool-Calling)
- **Tool-Calling** (identische Tools wie AnthropicService)
- **Agentic Loop** (Tool-Results → nächste Iteration)
- **Gemini thought_signature** – wird aus `extra_content.google.thought_signature` gelesen, in DB persistiert (`MessageRecord.ThoughtSignature`), und beim History-Rebuild in `extra_content.google.thought_signature` zurückgesendet
@@ -614,8 +620,9 @@ Der Chat-Flow von User-Input bis zur gerenderten Antwort:
3. ChatEndpoint:
a) User-Message + Attachments in DB speichern
b) ChatService.PrepareContext() → Agent, Model, System-Prompt, Chain
c) ChatService.BuildHistoryFromDb() → vollständige Message-History
d) Model-Routing: Anthropic → AnthropicService.StreamChat(), OpenAI-Provider (nvidia:/pollinations:/gemini:) → OpenAiService.StreamChat()
c) API-Key auflösen: `GetAgentApiKeyRecord(userId, agentId)` – Anthropic ohne Key → Fehler, OpenAI ohne Key → OK (keyless Provider)
d) ChatService.BuildHistoryFromDb() → vollständige Message-History
e) Model-Routing: Anthropic → AnthropicService.StreamChat(), OpenAI-Provider (nvidia:/pollinations:/gemini:) → OpenAiService.StreamChat()
↓
4. Agentic Loop (AnthropicService oder OpenAiService):
┌─────────────────────────────────────────┐
@@ -680,8 +687,9 @@ Der Stop-Mechanismus arbeitet auf zwei Ebenen:
### Streaming vs Non-Streaming
- **Web-Chat**: Streaming via SSE (`text/event-stream`). Tokens werden in Echtzeit gerendert.
- **Telegram**: Non-Streaming via `ChatNonStreaming()`. Vollständige Antwort wird abgewartet und als Telegram-Nachricht gesendet.
- **Cronjobs**: Non-Streaming, wie Telegram.
- **Telegram**: Non-Streaming – Provider-Weiche: Anthropic → `AnthropicService.ChatNonStreaming()`, OpenAI → `OpenAiService.ChatNonStreaming()`.
- **Cronjobs**: Non-Streaming, wie Telegram. Provider wird aus dem Agent-Modell bestimmt.
- **Sub-Agents** (Preparer/Review/Finalizer): Anthropic → `RunAgentChat()` (Streaming mit SSE-Events), OpenAI → `OpenAiService.ChatNonStreaming()`.
### History-Optimierung
@@ -943,7 +951,7 @@ Unlink ist **nur über das Web-UI** möglich (kein Telegram-Befehl).
### Non-Streaming Chat
Telegram-Nachrichten werden über `AnthropicService.ChatNonStreaming()` verarbeitet. Die History wird genauso aus der DB aufgebaut wie beim Web-Chat. Antworten über 4096 Zeichen werden automatisch in Chunks aufgeteilt.
Telegram-Nachrichten werden **Provider-aware** verarbeitet: Anthropic → `AnthropicService.ChatNonStreaming()`, OpenAI-kompatibel → `OpenAiService.ChatNonStreaming()`. Die History wird genauso aus der DB aufgebaut wie beim Web-Chat. Antworten über 4096 Zeichen werden automatisch in Chunks aufgeteilt.
### Dashboard & Frontend
@@ -977,7 +985,7 @@ Der `CronjobService` ist ein **BackgroundService** der minütlich nach fälligen
a) ChatService.PrepareContext() – Chain + System-Prompt aufbauen
b) History aus DB laden
c) Prompt als User-Message anhängen + in DB speichern
d) AnthropicService.ChatNonStreaming() ausführen
d) Provider-Weiche: Anthropic → `AnthropicService.ChatNonStreaming()`, OpenAI → `OpenAiService.ChatNonStreaming()`
e) Telegram-Benachrichtigung senden (auf Arbeits-Session)
f) Optional: Zusammenfassung in Notify-Session schreiben + Telegram dort
g) Nächste Ausführung berechnen + DB aktualisieren
@@ -1160,7 +1168,7 @@ Die Logik ist **invertiert** gegenüber dem Review-Pattern: Jede Antwort wird au
#### Backend-Flow (Preparer)
1. **ChatEndpoint** – Prüft ob `ctx.Preparer` vorhanden
2. **AnthropicService.RunPreparer()** – Ruft `RunAgentChat()` auf mit `agentType = "preparer"`
2. **AnthropicService.RunPreparer()** – Provider-Weiche: Anthropic → `RunAgentChat()`, OpenAI → `OpenAiService.ChatNonStreaming()` mit `agentType = "preparer"`
3. **Entscheidung** – `ShouldForward` prüft ob `[QUESTION]` im Text:
- **Forward**: Aufbereiteter Text wird als `[Vorbereitet von AgentName]:`-User-Message in DB gespeichert, History wird neu geladen, StreamChat startet
- **Rückfrage**: SSE `preparer_done` mit `forwarded: false`, Stream endet mit `stopReason: "preparer_query"`, User muss erneut eingeben
@@ -1191,13 +1199,12 @@ Der Preparer bekommt einen speziellen Instruktionsblock an seinen System-Prompt
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
- `SubAgentContext` mit ModelId, Provider, SystemPrompt, Workspace, ToolChoice, Agent 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`
- Prüft ob `Review`-SubAgentContext vorhanden und `reviewRound < MaxReviewIterations`
- Ruft `RunReview()` auf
4. **RunReview()** – Orchestriert eine einzelne Review-Runde:
@@ -1216,19 +1223,25 @@ Der Preparer bekommt einen speziellen Instruktionsblock an seinen System-Prompt
- `continue` → nächste while-Loop-Iteration → Worker korrigiert → Review erneut
- `reviewRound++` bis `MaxReviewIterations` erreicht
### ReviewContext / FinalizerContext (Model)
### SubAgentContext (Model)
```csharp
// Identische Struktur für Review und Finalizer
public class ReviewContext
// Einheitliche Struktur für Preparer, Review und Finalizer
public class SubAgentContext
{
public string Model { get; set; } // Claude-Modell des Agents
public string SystemPrompt { get; set; } // Eigener System-Prompt
public AgentRecord Agent { get; set; } // Agent-Record für Name/Avatar
public List<object> Tools { get; set; } // Tool-Definitionen
public int MaxReviewIterations { get; set; } // Max Runden (nur bei Review relevant)
public string ModelId { get; set; } // Modell-ID (z.B. "claude-sonnet-4-6" oder "deepseek-ai/deepseek-r1")
public string Provider { get; set; } // "" = Anthropic, "nvidia"/"openai"/etc. = OpenAI-kompatibel
public List<object> SystemPrompt { get; set; } // Eigener System-Prompt
public string AgentId { get; set; }
public string Workspace { get; set; }
public bool UseMemory { get; set; }
public string WebSearchVersion { get; set; }
public string ToolChoice { get; set; }
public AgentRecord Agent { get; set; } // Agent-Record für Name/Avatar
public bool AllowUserChoice { get; set; } // Preparer-spezifisch
public int MaxReviewIterations { get; set; } // Review-spezifisch
}
// ChatContext hat: ReviewContext Review + ReviewContext Finalizer
// ChatContext hat: SubAgentContext Preparer + SubAgentContext Review + SubAgentContext Finalizer
```
### SSE-Events
@@ -1284,16 +1297,17 @@ Der Finalizer wird **nach** dem Review (oder direkt nach dem Worker, falls kein
1. **ChatService.PrepareContext()** – Wenn `session.FinalizerAgentId` gesetzt:
- Finalizer-Agent aus DB laden
- `FinalizerContext` aufbauen (analog zu `ReviewContext`: Model, SystemPrompt, Tools)
- `SubAgentContext` aufbauen (Model, Provider, SystemPrompt, Workspace, ToolChoice)
2. **AnthropicService.StreamChat()** – Nach Review-Phase (oder direkt nach Worker):
- Prüft ob `FinalizerContext` vorhanden
- Prüft ob `Finalizer`-SubAgentContext vorhanden
- Ruft `RunFinalizer()` auf
3. **RunFinalizer()** – Baut Messages auf (gesamte Konversation + Finalisierungs-Anweisung), ruft `RunAgentChat()` auf (generische Methode, auch vom Review genutzt)
3. **RunFinalizer()** – Baut Messages auf (gesamte Konversation + Finalisierungs-Anweisung), Provider-Weiche wie bei RunPreparer/RunReview
4. **RunAgentChat()** – Generische Methode für Preparer/Review/Finalizer:
- Eigener API-Call an Claude mit Agent-Config
4. **RunAgentChat()** / **ChatNonStreaming()** – Provider-Weiche für Preparer/Review/Finalizer:
- **Anthropic:** Eigener API-Call an Claude mit Agent-Config (RunAgentChat, Streaming + Tool-Loop)
- **OpenAI-kompatibel:** `OpenAiService.ChatNonStreaming()` (Non-Streaming agentic loop mit Tool-Calling)
- Tool-Loop mit SSE-Events (`{type}_text`, `{type}_tool_use`)
- Antwort als Message in DB persistieren (mit `Tag = agentType`, wird aus API-History gefiltert)
@@ -1395,6 +1409,7 @@ Folgende Blöcke werden **übersprungen**: Git-Commits. Der Tools-Block listet n
### Frontend
- **Toggle**: `#planModeBtn` – wechselt `_planModeActive`, ändert Button-Styling + Placeholder-Text
- **Hint**: Bei aktivem Plan-Modus wird ein `<hint>` an jede User-Nachricht angehängt (Reminder: keine Dateien ändern, keine Shell-Befehle außer read-only, keine Commits)
- **Chain-Meta**: Badge `📋 Plan-Modus` bei Chains die im Plan-Modus erstellt wurden
- **System-Prompt-Modal**: Zeigt den angepassten System-Prompt wenn Plan-Modus aktiv
- **Session-Wechsel**: Plan-Modus wird zurückgesetzt
@@ -1582,6 +1597,8 @@ const editor = AvatarEditor.init({
### Dashboard-Darstellung
Sessions werden nach der **letzten Chat-Nachricht** sortiert (neueste zuerst), nicht nach `updated_at`. Sessions ohne Nachrichten werden per `COALESCE` nach ihrem `updated_at` einsortiert.
Cards zeigen Avatare mit `transform: scale(S) translate(X%, Y%)` im `.card-image` Container (`overflow: hidden`). Die Helper `buildAgentCard()` und `buildSessionCard()` in `cards.js` nutzen `buildTransformStyle(scale, offsetX, offsetY)` dafür.
---
@@ -1743,10 +1760,11 @@ API-Keys werden in der Datenbank verwaltet (Tabellen `api_keys` + `scanned_keys`
### Funktionsweise
- **Mehrere Keys** pro Provider (z.B. `anthropic`) können gespeichert werden
- **Nur ein Key pro Provider** kann gleichzeitig aktiv sein
- **Aktivierung** deaktiviert automatisch alle anderen Keys desselben Providers
- **Live-Aktualisierung:** Bei Aktivierung/Deaktivierung wird der Token sofort im laufenden Service aktualisiert (kein Neustart nötig)
- **Zuweisung pro Agent:** Keys werden über `agent_api_keys` (user_id + agent_id → key_id) zugewiesen, nicht mehr global pro User
- **"Kein Key"-Option:** Key-Zuweisung kann entfernt werden – Anthropic-Modelle werden blockiert, keyless Provider (Pollinations, Nvidia) funktionieren weiterhin
- **Live-Aktualisierung:** Bei Änderung wird der Token sofort im laufenden Service aktualisiert (kein Neustart nötig)
- **Migration:** Bestehender `AnthropicToken` aus `appsettings.Production.json` wird beim ersten Start automatisch migriert
- **Migration:** `users.selected_api_key_id` wird beim Start für alle Agents des Users in `agent_api_keys` übernommen
- **Source-URL:** Bei adoptierten Scan-Keys wird die GitHub-URL gespeichert
### Key-Check (nur Anthropic)
@@ -1760,12 +1778,45 @@ API-Keys werden in der Datenbank verwaltet (Tabellen `api_keys` + `scanned_keys`
Nach **jedem** API-Request an Anthropic (Streaming, Sub-Agent, NonStreaming) werden die Response-Headers automatisch ausgelesen und Plan/Usage des aktiven API-Keys in der DB aktualisiert (`AnthropicKeyChecker.ExtractMetaFromHeaders()`). Kein separater Check-Request nötig – die Daten sind immer aktuell.
### GitHub-Scanner (`KeyScannerService`)
### API-Key pro Agent
Durchsucht GitHub Code-Search nach geleakten Anthropic API-Keys:
API-Keys werden **pro Agent** zugewiesen (Tabelle `agent_api_keys`), nicht mehr global pro User:
- **`PUT /api/api-keys/select/{keyId}?agentId=xxx`** – Key einem Agent zuweisen
- **`PUT /api/api-keys/select/none?agentId=xxx`** – Key-Zuweisung entfernen ("Kein Key")
- **`GET /api/api-keys/selected?agentId=xxx`** – Zugewiesenen Key abfragen
- **Ohne Key:** Chat mit Anthropic-Modellen blockiert, OpenAI-kompatible Modelle (z.B. Pollinations) funktionieren weiterhin
- **Migration:** Bestehende `users.selected_api_key_id` wird beim Start für alle Agents des Users in `agent_api_keys` kopiert
### Key-Scanner (`KeyScannerService`)
Durchsucht mehrere Quellen nach geleakten API-Keys:
**Quellen:**
| Quelle | Quick | Web | Full |
|---|---|---|---|
| GitHub Code Search | ✅ (reduziert) | ❌ | ✅ |
| GitHub Issues/PR Comments | ✅ (nur Body) | ❌ | ✅ (Body + Comments) |
| Serper/Google | ❌ | ✅ | ✅ |
| HuggingFace Hub | ❌ | ✅ | ✅ |
**GitHub Code Search:**
- **13 Sprachen** (Python, JavaScript, TypeScript, Shell, Markdown, JSON, YAML, TOML, Go, Rust, Ruby, Java, PHP)
- **24 Pfad-Extensions** (.env, .cfg, .ini, .conf, .txt, .log, .md, .json, .yaml, .yml, .toml, .py, .js, .ts, .sh, .bash, .go, .rs, .rb, .java, .php, .config, .properties, .xml)
- **Ablauf:** `POST /api/admin/api-keys/scan` → GitHub-Suche → neue Keys in `scanned_keys` speichern → jeden Key mit `AnthropicKeyChecker` prüfen → Status + Plan + Usage aktualisieren
**GitHub Issues/PR Comments:**
- Durchsucht Issue-Bodies nach Key-Patterns via GitHub Search API
- Im Full-Mode: Lädt zusätzlich alle Kommentare (max 100 Issues, je 100 Kommentare)
- Rate-Limiting: 2.5s Delay (Search), 1s Delay (Comments), 60s Pause bei 403
**HuggingFace Hub:**
- Durchsucht Spaces und Models nach API-Keys in Konfigurationsdateien
- Max 50 Dateien pro Repo, max 500 KB pro Datei
- Optionaler HuggingFace Token für höhere Rate-Limits
**Zeitplanung:** `ScanDailyHour` (0-23 = täglicher Scan zur vollen Stunde, -1 = nur manuell)
- **Ablauf:** `POST /api/admin/api-keys/scan` → Quellen durchsuchen → neue Keys in `scanned_keys` speichern → jeden Key mit `AnthropicKeyChecker` prüfen → Status + Plan + Usage aktualisieren
- **Adopt:** `POST /api/admin/api-keys/scanned/{id}/adopt` → Key in `api_keys` übernehmen, Name = `user/repo`, Source-URL = vollständige GitHub-URL
- **Live-Updates:** Scan-Ergebnisse werden nach jeder Iteration in der DB gespeichert (nicht erst am Ende)
@@ -1775,7 +1826,7 @@ Durchsucht GitHub Code-Search nach geleakten Anthropic API-Keys:
- **Farbstufen:** Grün (<70%), Orange (70-89%), Rot (≥90%)
- **Auto-Hide:** Ausgeblendet beim Hochscrollen (wenn Auto-Scroll deaktiviert)
- **Auto-Refresh:** Badge aktualisiert sich bei neuen Nachrichten (via `pollHistory`)
- **Key-Switch-Modal:** Klick auf Badge öffnet Modal mit allen API-Keys, Zeile klickbar zum Wechseln
- **Key-Switch-Modal:** Klick auf Badge öffnet Modal mit allen API-Keys + "Kein Key"-Option, Zeile klickbar zum Wechseln (pro Agent)
- **Manueller Check:** 🔄-Button neben Badge prüft Key und aktualisiert
---
@@ -1838,6 +1889,8 @@ Die `DatabaseService.InitializeDatabase()` handhabt Schema-Erstellung und Migrat
3. **Daten-Migration** (z.B. `auto_commit` von INTEGER zu TEXT, `use_web_search` zu `web_search_version`)
4. **Token-Migration** – Bestehender `AnthropicToken` aus `appsettings.Production.json` wird automatisch in `api_keys`-Tabelle migriert
5. **Bild-Migration** – Konvertierung bestehender PNG/JPEG-Avatare zu WebP + Generierung von Thumbnails (`avatar_small`, `image_small`)
6. **API-Key-Migration** – `users.selected_api_key_id` → `agent_api_keys` (pro Agent statt global pro User)
7. **Settings-Cleanup** – Obsolete Server-Settings (z.B. `ScanIntervalHours`) werden aus der DB entfernt
Dieses Pattern ermöglicht:
- Idempotente Ausführung bei jedem App-Start
+13 -8
View File
@@ -87,8 +87,11 @@ User 1──* TelegramBot 1──* Session (via telegram_bot_id)
| `agent_skills` | N:M Agent ↔ Skill |
| `shared_messages` | Geteilte Nachrichten (öffentliche Links via Share-Token) |
| `telegram_bots` | Telegram Bots (BotToken, WebhookSecret, Name, IsPublic) – eigenständige Entität, 1 Bot → N Sessions |
| `api_keys` | API-Keys pro Provider (key_id, provider, name, api_key, is_active, status, plan, usage_7d, usage_5h, source_url) – nur ein Key pro Provider aktiv |
| `api_keys` | API-Keys (key_id, provider, name, api_key, is_active, status, plan, usage_7d, usage_5h, source_url) – mehrere Keys pro Provider möglich, Zuweisung pro Agent |
| `agent_api_keys` | API-Key-Zuweisung pro User+Agent (user_id, agent_id, key_id) – ersetzt globales `users.selected_api_key_id` |
| `scanned_keys` | Gescannte GitHub-Keys (api_key, source_url, status, plan, usage_7d, usage_5h, adopted_api_key_id) |
| `scanner_logs` | Scanner-Logs (timestamp, type, message, scanner, details) |
| `server_settings` | Server-Settings (key, value, type) – verwaltet über `ServerSettingsService` |
| `message_embeddings` | Sentence-Embeddings für semantische Suche (message_id, vector BLOB) |
| `memory_file_embeddings` | Embeddings von Memory-Dateien (agent_id, file_path, chunk_index, vector BLOB) |
@@ -130,7 +133,7 @@ User 1──* TelegramBot 1──* Session (via telegram_bot_id)
| **AuthService** | Token-Auth, Passwort-Hashing (SHA256) |
| **ChatService** | Chat-Kontext aufbauen, History aus DB laden |
| **AnthropicService** | Claude API: SSE Streaming + Non-Streaming, passive Usage-Aktualisierung nach jedem Request |
| **OpenAiService** | OpenAI-kompatible Provider (Nvidia, Pollinations, Gemini) mit Tool-Calling, Streaming, Modell-Caching |
| **OpenAiService** | OpenAI-kompatible Provider (Nvidia, Pollinations, Gemini) mit Tool-Calling, Streaming (`StreamChat`) + Non-Streaming (`ChatNonStreaming` für Telegram/Cronjobs/Sub-Agents), Modell-Caching |
| **SseHelper** | Shared SSE-Utilities: WriteSseEvent, TryWriteSse, FinalizeChain, TruncateToolResult (static) |
| **ToolService** | Tool-Definitionen + Ausführung (17 Tools) |
| **WorkspaceHelper** | Workspace-Pfad-Auflösung (relativ → absolut), Path-Traversal-Schutz (static) |
@@ -146,8 +149,9 @@ User 1──* TelegramBot 1──* Session (via telegram_bot_id)
| **EmbeddingBackgroundService** | Backfill bestehender Messages + Live-Embedding neuer Messages/Memory-Files |
| **RemoteConnectionManager** | WebSocket-basierte Remote-Verbindungen, Command-Execution auf Remote-Clients |
| **StreamingTracker** | Tracking aktiver Streams + CancellationTokenSource pro Session für Stop |
| **KeyScannerService** | GitHub-Code-Search nach geleakten API-Keys (13 Sprachen, 24 Pfad-Extensions) |
| **KeyScannerService** | API-Key-Scanner (GitHub Code Search, GitHub Issues/PRs, HuggingFace Hub, Google/Serper), täglicher Scan |
| **AnthropicKeyChecker** | Key-Validierung via Anthropic API, Usage-Header-Auswertung (Plan, 7d/5h Usage) |
| **ServerSettingsService** | Server-Settings Verwaltung (In-Memory-Cache + DB), Cleanup obsoleter Settings |
---
@@ -159,12 +163,13 @@ User-Input → POST /api/chat (SSE)
→ History aus DB laden (letzte N Chains)
→ SystemPromptBuilder: 11 Blöcke zusammensetzen (+ Plan-Modus/Preparer-Blöcke)
→ Tool-Definitionen vom ToolService holen (im Plan-Modus: nur Read-only)
→ API-Key auflösen: GetAgentApiKeyRecord(userId, agentId) – Anthropic ohne Key → Fehler, keyless Provider → OK
→ Preparer-Phase (optional, wenn PreparerAgentId gesetzt):
→ RunPreparer() → RunAgentChat(agentType: "preparer")
→ RunPreparer() → Provider-Weiche: Anthropic → RunAgentChat(), OpenAI → ChatNonStreaming()
→ Antwort ohne [QUESTION] → automatisch weiterleiten (Default = Forward)
→ [QUESTION] → Rückfrage an User, Flow stoppt
→ AnthropicService.StreamChat()
→ Claude API Call (SSE)
→ AnthropicService.StreamChat() / OpenAiService.StreamChat()
→ API Call (SSE)
→ Token-für-Token an Client streamen
→ Bei tool_use → ToolService.Execute() → Ergebnis zurück → neuer API Call
→ Bei ask_user_choice → SSE user_choice Event → Flow stoppt (awaiting_user_choice)
@@ -243,7 +248,7 @@ User-Input → POST /api/chat (SSE)
| Hash-Route | Page-Datei | Beschreibung |
|------------|-----------|--------------|
| `#/` | `dashboard.js` | Session-Übersicht |
| `#/` | `dashboard.js` | Session-Übersicht (sortiert nach letzter Chat-Nachricht) |
| `#/chat/{id}` | `chat-page.js` | Chat (inkl. Usage-Badge-Overlay + Key-Switch-Modal) |
| `#/session/{id}` | `session-page.js` | Session-Settings |
| `#/agent/{id}` | `agent-page.js` | Agent-Editor |
@@ -303,7 +308,7 @@ Eine Session kann bis zu **vier Agents** haben: Worker (Pflicht), Preparer (opti
**Preparer:** Default = Forward (jede Antwort wird automatisch weitergeleitet, `[QUESTION]` stoppt). Bekommt eigene History mit `includeTag: "preparer"`. Aufbereiteter Prompt wird als `[Vorbereitet von AgentName]:` User-Message gespeichert.
**Backend:** `ChatService` baut `PreparerContext` + `ReviewContext` + `FinalizerContext`. `RunPreparer()` im ChatEndpoint (vor StreamChat). `RunReview()` + `RunFinalizer()` in AnthropicService. Alle nutzen `RunAgentChat()` (mit `Tag`-Markierung, Sub-Agent-Messages aus API-History gefiltert).
**Backend:** `ChatService` baut `SubAgentContext` für Preparer, Review und Finalizer. `RunPreparer()` im ChatEndpoint (vor StreamChat). `RunReview()` + `RunFinalizer()` in AnthropicService. Alle nutzen Provider-Weiche: Anthropic → `RunAgentChat()`, OpenAI → `ChatNonStreaming()` (mit `Tag`-Markierung, Sub-Agent-Messages aus API-History gefiltert).
**SSE-Events:**
- Preparer: `preparer_start`, `preparer_text`, `preparer_tool_use`, `preparer_done`
+1 -1
View File
@@ -27,7 +27,7 @@ Self-hosted AI-Coding-Agent mit **Anthropic Claude API** als Haupt-Provider sowi
- **Bildgenerierung** – Krea AI Integration für Bildgenerierung
- **Semantische Suche** – Lokale Sentence-Embeddings (all-MiniLM-L6-v2 ONNX) für `memory_search` über vergangene Nachrichten und Memory-Dateien
- **Remote-Verbindungen** – WebSocket-basierte Remote-Clients (PowerShell), AI-Agent kann Befehle auf entfernten Rechnern ausführen
- **API-Key-Verwaltung** – Admin-UI zum Verwalten von API-Keys (Anthropic) inkl. Key-Check, GitHub-Scanner (geleakte Keys finden + übernehmen), passive Usage-Aktualisierung bei jeder Chat-Nachricht, Usage-Badge im Chat mit Key-Switch-Modal
- **API-Key-Verwaltung** – Admin-UI zum Verwalten von API-Keys (Anthropic) inkl. Key-Check, API-Key-Scanner (GitHub Code Search, GitHub Issues/PRs, HuggingFace Hub, Google/Serper), passive Usage-Aktualisierung bei jeder Chat-Nachricht, Usage-Badge im Chat mit Key-Switch-Modal (pro Agent)
- **Nachrichten teilen** – Einzelne Nachrichten per öffentlichem Link teilen
- **Archivierung** – Chat-Verläufe archivieren und durchsuchen
- **OpenClaw Import** – Chatverlauf aus OpenClaw-Instanzen importieren