Document panel subagent filtering, token badges, and CLI fallback reach

Bring the docs in line with the recently shipped features:

- Multi-model panel: all MoA rounds are now persisted (F5-safe) with a
  per-member JSON transcript (layer/totalLayers/segments); member tokens
  are folded into the worker usage via seedUsage (live badge + DB).
- CLI parser filters subagent internals centrally via the
  parent_tool_use_id guard → no nameless tool boxes in stream or history.
- Per-member token badges: panel_member_done and the persisted JSON carry
  the token fields, rendered by the shared buildPanelMemberMeta helper.
- Composer toggle: _modePersist serializes mode PATCHes and sendMessage
  awaits them, preventing the MoA single-round race.
- CLI fallback now also covers cronjobs and Telegram; keyless providers
  (nvidia/gemini/minimax/pollinations) resolve server keys instead of
  hard-failing on a missing user key.
- Krea: one request per image (batchSize no longer sent to the API).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
MelekiandClaude Opus 4.8 committed 2026-06-19 19:24:08 +02:00
1 parent 8e5a961e94
commit 6e301b7498
3 files changed
+32 -20

No files matched your search

+20 -11
View File
@@ -725,8 +725,8 @@ 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 – Provider-Weiche: Anthropic → `AnthropicService.ChatNonStreaming()`, OpenAI → `OpenAiService.ChatNonStreaming()`.
- **Cronjobs**: Non-Streaming, wie Telegram. Provider wird aus dem Agent-Modell bestimmt.
- **Telegram**: Non-Streaming – Provider-/Key-Weiche: Anthropic + Key → `ChatNonStreaming()`; ohne Key + CLI → CLI-Fallback; `openai` ohne User-Key → Fehler; keyless Provider (nvidia/gemini/minimax/pollinations) → `ChatNonStreaming()` via Server-Key.
- **Cronjobs**: Non-Streaming, identische Provider-/Key-Weiche 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
@@ -1021,7 +1021,7 @@ Unlink ist **nur über das Web-UI** möglich (kein Telegram-Befehl).
### Non-Streaming Chat
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.
Telegram-Nachrichten werden **Provider-aware** verarbeitet: Anthropic + API-Key → `ChatNonStreaming()`; Anthropic ohne Key + CLI verfügbar → CLI-Fallback; `openai` ohne User-Key → Fehler; keyless Provider (nvidia/gemini/minimax/pollinations) → `OpenAiService.ChatNonStreaming()` via Server-Key (`ResolveProviderConfig`). Die History wird genauso aus der DB aufgebaut wie beim Web-Chat. Antworten über 4096 Zeichen werden automatisch in Chunks aufgeteilt.
### Dashboard & Frontend
@@ -1055,7 +1055,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) Provider-Weiche: Anthropic → `AnthropicService.ChatNonStreaming()`, OpenAI → `OpenAiService.ChatNonStreaming()`
d) Provider-/Key-Weiche: Anthropic + API-Key → `ChatNonStreaming()`; Anthropic ohne Key + CLI verfügbar → CLI-Fallback; `openai` ohne User-Key → Fehler; keyless Provider (nvidia/gemini/minimax/pollinations) → `ChatNonStreaming()` via Server-Key (`ResolveProviderConfig`)
e) Telegram-Benachrichtigung senden (auf Arbeits-Session)
f) Optional: Zusammenfassung in Notify-Session schreiben + Telegram dort
g) Nächste Ausführung berechnen + DB aktualisieren
@@ -1089,11 +1089,13 @@ Modelle in `MINIMAL_MODELS` (`seedream-3`, `runway-gen-4`, `seedream-5-lite`, `s
### Flow
```
1. POST /api/images/generate { prompt, model, width, height, ... }
2. KreaService sendet Request an Krea API
3. Job-Polling bis Status "completed"
1. POST /api/images/generate { prompt, model, width, height, batchSize, ... }
2. KreaService sendet pro gewünschtem Bild EINE eigene Anfrage an die Krea API
(Krea unterstützt kein 'batchSize' mehr – batchSize=N (1–4) steuert nur,
wie viele Einzel-Requests in einer Schleife gesendet werden)
3. Job-Polling pro Bild bis Status "completed"
4. Bilder herunterladen nach data/images/
5. Metadaten als JSON speichern
5. Metadaten als JSON speichern (batch_size bleibt informativ erhalten)
6. Response mit Dateinamen + URLs
```
@@ -1191,7 +1193,7 @@ Admins können für jeden User einen **Autologin-Link** generieren – z.B. für
Das Multi-Agent-System ermöglicht bis zu **vier Agents** pro Session: einen **Worker**, einen optionalen **Vorbereiter (Preparer)**, einen optionalen **Reviewer** und einen optionalen **Finalizer**.
> **Multi-Modell-Panel (Fusion / MoA):** Orthogonal dazu kann eine Session zusätzlich ein **Panel** aus mehreren Agenten haben (`multi_model_mode="fusion"`/`"moa"`, `panel_agent_ids`=CSV, `moa_layers`=Proposer-Runden bei MoA). Bei jeder Nachricht antworten alle Panel-Agenten **parallel** (read-only) und **streamen live** (CLI: `TextDelta`/`ToolStart`/`ToolResult`; Anthropic-API: pro Tool-Runde; OpenAI: one-shot); ihre Antworten werden dem Worker als `<panel_responses>`-Block vorgelegt, der **eine** Gesamtantwort synthetisiert und normal streamt (OpenRouter-Fusion-/MoA-Muster). **MoA** = mehrere Proposer-Runden: ab Runde 2 sieht jeder Member die Vorrunde (`<previous_layer_responses>`) und verfeinert; `RunPanel(layers)` ist EINE Engine (Fusion = `layers==1`), nur die finale Runde wird persistiert. Backend: `RunPanel()` in `AnthropicService.Panel.cs` (im ChatEndpoint-try vor dem Worker-Dispatch), Member-Provider-Weiche (Anthropic read-only via `PlanMode`, CLI via `--permission-mode plan`, OpenAI tool-los via `CompleteText`), Proposals als `[Panel: Name]`-Messages mit `Tag="panel"`, Write-Lock in `SseHelper` serialisiert parallele SSE-Flushes. SSE: `panel_start`/`panel_layer_start`/`panel_member_start`/`panel_member_text`/`panel_member_tool*`/`panel_member_done`/`panel_layer_done`/`panel_done`. Frontend: `.panel-bubble` pro Member (gekeyt `layer_index`), `.panel-layer-divider` bei MoA. Siehe ARCHITECTURE_QUICK.md.
> **Multi-Modell-Panel (Fusion / MoA):** Orthogonal dazu kann eine Session zusätzlich ein **Panel** aus mehreren Agenten haben (`multi_model_mode="fusion"`/`"moa"`, `panel_agent_ids`=CSV, `moa_layers`=Proposer-Runden bei MoA). Bei jeder Nachricht antworten alle Panel-Agenten **parallel** (read-only) und **streamen live** (CLI: `TextDelta`/`ToolStart`/`ToolResult`; Anthropic-API: pro Tool-Runde; OpenAI: one-shot); ihre Antworten werden dem Worker als `<panel_responses>`-Block vorgelegt, der **eine** Gesamtantwort synthetisiert und normal streamt (OpenRouter-Fusion-/MoA-Muster). **MoA** = mehrere Proposer-Runden: ab Runde 2 sieht jeder Member die Vorrunde (`<previous_layer_responses>`) und verfeinert; `RunPanel(layers)` ist EINE Engine (Fusion = `layers==1`). **Alle** Runden werden persistiert (F5-sicher); JSON-Transkript pro Member (`layer`/`totalLayers`/Segmente, `Iteration = layer*100+index+1`). Member-Tokens via `seedUsage` in Worker-`usage` gefaltet (Live-Badge + DB, kein separates Panel-Usage-Event). Backend: `RunPanel()` in `AnthropicService.Panel.cs` (im ChatEndpoint-try vor dem Worker-Dispatch), Member-Provider-Weiche (Anthropic read-only via `PlanMode`, CLI via `--permission-mode plan`, OpenAI tool-los via `CompleteText`), Proposals als `[Panel: Name]`-Messages mit `Tag="panel"`, Write-Lock in `SseHelper` serialisiert parallele SSE-Flushes. SSE: `panel_start`/`panel_layer_start`/`panel_member_start`/`panel_member_text`/`panel_member_tool*`/`panel_member_done`/`panel_layer_done`/`panel_done`. Der CLI-Parser filtert Subagent-Interna **zentral** per `parent_tool_use_id`-Guard (`ClaudeCliService.RunCliStreamingAsync`) → keine namenlosen Tool-Boxen im Stream **oder** in der History. Das `panel_member_done`-Event und das persistierte JSON tragen per-Member Token-Felder (`inputTokens`/`outputTokens`/`cacheReadTokens`/`cacheCreationTokens`); `buildPanelMemberMeta()` rendert daraus ein `.panel-member-meta`-Badge (Live + History, gleicher Helper). Composer-Toggle-PATCHes laufen serialisiert über die `_modePersist`-Kette, die `sendMessage` abwartet → kein MoA-Timing-Bug (Modus garantiert committed, bevor das Backend die Session lädt). Frontend: `.panel-bubble` pro Member (gekeyt `layer_index`), `.panel-layer-divider` bei MoA. Siehe ARCHITECTURE_QUICK.md.
### Architektur
@@ -1487,7 +1489,7 @@ Folgende Blöcke werden **übersprungen**: Git-Commits. Der Tools-Block listet n
### Frontend
- **Toggle**: `#planModeBtn` – wechselt `_planModeActive`, ändert Button-Styling + Placeholder-Text
- **Toggle**: `#planModeBtn` (`cycleCompositeMode`) – zykliert **Aus → Plan → Fusion → MoA → Aus**. Plan-Modus transient (`_planModeActive` Compat-Var), Fusion/MoA sofort via `apiUpdateSession({multiModelMode})` persistiert. Gleiche Quelle wie der Modal-Picker in den Session-Einstellungen.
- **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
@@ -1990,10 +1992,17 @@ Die Claude Code CLI kann als alternativer Streaming-Weg verwendet werden (OAuth-
- Claude Code CLI installiert (`~/.claude/local/claude`)
- Gültiges OAuth-Token in `~/.claude/.credentials.json`
### CLI-Fallback für Sub-Agents
### CLI-Fallback für Sub-Agents, Cronjobs und Telegram
Wenn ein **Sub-Agent** (Preparer, Review, Finalizer) keinem API-Key zugewiesen ist, wird – sofern die CLI verfügbar ist – automatisch `RunSubAgentViaCli()` (in `AnthropicService.Agents.cs`) aufgerufen. Damit funktionieren optionale Sub-Agents auch ohne explizit zugewiesenen Anthropic-Key. Erst wenn weder Key noch CLI vorhanden sind, wird der Sub-Agent übersprungen statt mit einem Hard-Error abzubrechen.
Dasselbe Muster gilt für **Cronjobs** (`CronjobService.ExecuteCronjob` + `SendCronjobNotification`) und **Telegram** (`TelegramService.HandleMessage`) – exakt die **gleiche Provider-/Key-Dreiteilung** wie im `ChatEndpoint`:
- **Anthropic ohne zugewiesenen Key** → `ChatNonStreamingViaCli()` (CLI-Fallback), sofern der User `CanUseCli`/`IsAdmin` hat und die CLI verfügbar ist
- **`openai` ohne Key** → harter Fehler (kein Server-Key, kein CLI-Äquivalent)
- **keyless Provider (nvidia/gemini/minimax/pollinations)** → Request wird ohne User-Key durchgelassen; der **Server-seitige** Key wird in `ResolveProviderConfig` aufgelöst
Der frühere harte Abbruch („Kein API-Key zugewiesen") blockte irrtümlich **jeden** nicht-leeren Provider – jetzt blockiert nur noch `openai` ohne Key.
### Python-Detection für MCP-Config
Die MCP-Config (`AnthropicService.Cli.GenerateMcpConfig()`) sucht beim Start dynamisch nach einer Python-Installation in der Reihenfolge `python3` → `python` → `py` (das Ergebnis wird gecached). Auf Linux ist üblicherweise `python3` da, auf Windows oft nur `python` oder `py`. Wird kein Python gefunden, wird im Chat ein SSE-`warning`-Event gesendet (*"Python wurde nicht gefunden... MCP-Tools sind nicht verfügbar."*) – die normalen Tools funktionieren weiterhin.