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:
1 parent
a6a0223f44
commit
8e94975e61
3 files changed
+109
-51
No files matched your search
+95
-42
@@ -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
@@ -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`
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user