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.
+10 -8
View File
@@ -147,15 +147,15 @@ User 1──* TelegramBot 1──* Session (via telegram_bot_id)
| **AnthropicService** | Claude API: SSE Streaming + Non-Streaming + CLI-Fallback, passive Usage-Aktualisierung (partial class: Core, Streaming, Agents, Cli) |
| **ClaudeCliService** | Claude Code CLI Wrapper (OAuth-basiert, kein API-Key nötig) |
| **OpenAiService** | OpenAI-kompatible Provider (Nvidia, Pollinations, Gemini, OpenAI) mit Tool-Calling, Streaming + Non-Streaming, Modell-Caching |
| **SseHelper** | Shared SSE-Utilities: WriteSseEvent, TryWriteSse, FinalizeChain, TruncateToolResult (static) |
| **SseHelper** | Shared SSE-Utilities: WriteSseEvent, TryWriteSse, FinalizeChain, TruncateToolResult, `TokenUsage.Add` (static) |
| **ToolService** | Tool-Definitionen + Ausführung (19 Tools, inkl. github_code_search, serper_web_search) |
| **WorkspaceHelper** | Workspace-Pfad-Auflösung (relativ → absolut), Path-Traversal-Schutz (static) |
| **SystemPromptBuilder** | System-Prompt aus modularen Blöcken zusammenbauen + Reminder-Generierung (static) |
| **MemoryService** | Agent-Gedächtnis auf Dateisystem |
| **SkillService** | Skill-Discovery aus Dateisystem |
| **TelegramService** | Telegram Bot API (Bot-basiert, Multi-Session-Routing) |
| **CronjobService** | BackgroundService, minütlicher Cron-Check |
| **KreaService** | Krea API Bildgenerierung + Job-Polling |
| **TelegramService** | Telegram Bot API (Bot-basiert, Multi-Session-Routing), Provider-/Key-Dreiteilung: CLI-Fallback für keylose Anthropic + Server-Key-Auflösung für nvidia/gemini/minimax/pollinations |
| **CronjobService** | BackgroundService, minütlicher Cron-Check, gleiche Provider-/Key-Dreiteilung wie TelegramService (CLI-Fallback + Server-Key-Auflösung) |
| **KreaService** | Krea API Bildgenerierung + Job-Polling (eine Anfrage pro Bild – Krea akzeptiert kein `batchSize` mehr) |
| **ImageService** | Bild-Resize + WebP-Konvertierung (512px + 256px Thumbnail) |
| **EmbeddingService** | Lokales Sentence-Embedding via all-MiniLM-L6-v2 (ONNX, 384 Dimensionen) |
| **VectorSearchService** | Semantische Suche über Message-Embeddings + Memory-File-Embeddings |
@@ -351,17 +351,19 @@ Eine Session kann bis zu **vier Agents** haben: Worker (Pflicht), Preparer (opti
Zusätzlich zum Worker kann eine Session ein **Panel** aus mehreren Agenten haben (`multi_model_mode = "fusion"`/`"moa"`, `panel_agent_ids` = CSV der Agent-IDs, `moa_layers` = Proposer-Runden bei MoA, Default 2). Bei jeder Nachricht antworten alle Panel-Agenten **parallel** auf die Anfrage; ihre Antworten werden dem **Worker** als `<panel_responses>`-Block in die letzte User-Message gemergt, der daraus **eine** Gesamtantwort synthetisiert und normal streamt (OpenRouter-Fusion-/Mixture-of-Agents-Muster).
**Fusion vs. MoA:** Fusion = 1 Proposer-Runde → Synthese. **MoA** = `moa_layers` Runden (1–5, Backstop): ab Runde 2 sieht jeder Member die Antworten der Vorrunde (`<previous_layer_responses>`, isoliert pro Member via `CloneForMember` gemergt) und verfeinert. `RunPanel(layers)` ist EINE Engine (Fusion = `layers==1`). Nur die **finale** Runde wird persistiert; Zwischenrunden sind **live-only** (überleben kein F5).
**Fusion vs. MoA:** Fusion = 1 Proposer-Runde → Synthese. **MoA** = `moa_layers` Runden (1–5, Backstop): ab Runde 2 sieht jeder Member die Antworten der Vorrunde (`<previous_layer_responses>`, isoliert pro Member via `CloneForMember` gemergt) und verfeinert. `RunPanel(layers)` ist EINE Engine (Fusion = `layers==1`). **Alle** Runden werden persistiert (F5-sicher); JSON-Transkript pro Member enthält `layer`/`totalLayers` + Text-/Tool-Segmente (`Iteration = layer*100+index+1` macht DB-Zeilen layer-aware).
**Member laufen read-only** (Anthropic: `FilterReadOnlyTools` via `PlanMode`, CLI: `--permission-mode plan`, OpenAI: tool-los via `OpenAiService.CompleteText`) → keine parallelen Schreibkonflikte. Concurrency-Cap (3) begrenzt parallele CLI-Children.
**Member streamen LIVE** (wie der Session-Agent): CLI forwardet `TextDelta`/`ToolStart`/`ToolResult`, Anthropic-API streamt pro Tool-Runde über `NonStreamingLoopCallbacks`, OpenAI = one-shot (Text am Ende). Ein `SemaphoreSlim`-Write-Lock in `SseHelper.TryWriteSse` serialisiert die SSE-Byte-Flushes paralleler Member (sonst vermischen sich die Frames).
**Backend:** `ChatService.PrepareContext` baut `ChatContext.PanelAgents` (`List<SubAgentContext>`) + `MoaLayers`. `RunPanel(layers)` (AnthropicService.Panel.cs) läuft im ChatEndpoint-try VOR dem Worker-Dispatch: pro Runde Member parallel (`Task.WhenAll` + `SemaphoreSlim`), Provider-Weiche pro Member, finale Proposals als `[Panel: Name]`-Message mit `Tag="panel"` persistiert (aus Worker-History gefiltert). `NonStreamingLoopCallbacks.Persist=false` verhindert Doppel-Persistenz. Der Synthese-Block wird in den **bestehenden** Text-Block der letzten User-Message gemergt (damit auch der CLI-Worker via `ExtractLastUserText` ihn sieht). Panel-Fehler sind graceful.
**Subagent-Filterung:** Spawnt ein CLI-Member intern einen Subagenten (Claude-CLI-`Agent`-Tool), sendet die CLI dessen Interna als separate Top-Level-Events mit `parent_tool_use_id`. Der Parser (`ClaudeCliService.RunCliStreamingAsync`) verwirft diese **zentral am Ursprung** (Guard auf nicht-leeres `parent_tool_use_id`) → keine namenlosen Tool-Boxen, weder im Live-Stream noch in der History (beide lesen aus denselben gefilterten `CliStreamEvent`s). Die `Agent`-Tool-Box selbst (`parent_tool_use_id=null`) bleibt sichtbar; der finale `result`-Event (mit den **aggregierten** Subagent-Tokens) wird nicht gefiltert → Token-Bilanz vollständig.
**SSE-Events:** `panel_start` (mode/layers), `panel_layer_start`/`panel_layer_done` (MoA-Runden), `panel_member_start` (mit `layer`), `panel_member_text`/`panel_member_tool_use`/`panel_member_tool_end`/`panel_member_tool` (live), `panel_member_done`, `panel_done`.
**Backend:** `ChatService.PrepareContext` baut `ChatContext.PanelAgents` (`List<SubAgentContext>`) + `MoaLayers`. `RunPanel(layers)` (AnthropicService.Panel.cs) läuft im ChatEndpoint-try VOR dem Worker-Dispatch: pro Runde Member parallel (`Task.WhenAll` + `SemaphoreSlim`), Provider-Weiche pro Member, **jede** Runde als `[Panel: Name]`-Message mit `Tag="panel"` persistiert (aus Worker-History gefiltert); JSON-Transkript = `{name, model, layer, totalLayers, segments:[Text/Tool…]}`. `NonStreamingLoopCallbacks.Persist=false` verhindert Doppel-Persistenz. Member-Tokens via `seedUsage` in Worker-`usage` gefaltet → Live-Badge **und** DB (kein separates Panel-Usage-Event). Synthese-Block in letzte User-Message gemergt. Panel-Fehler graceful.
**Frontend:** `stream-ui.js` rendert pro Member eine `.panel-bubble`, gekeyt per `layer_index` (MoA: gleiche Member über mehrere Runden; aktive Runde pro Index wird bei `panel_member_start` gemerkt, da Runden sequenziell laufen). `panel_layer_start` zeigt bei >1 Runde einen `.panel-layer-divider`. History: `history.js _renderPanelMemberBubble` rendert `Tag="panel"`-Messages. Picker: `#multiModelMode`-Dropdown (Aus/Fusion/MoA) + `#moaLayers` + Mehrfach-Agenten-Picker (`_openMultiPickerModal`). Vereinter Composer-Toggle: **ein** Button `#planModeBtn` (chat.js `cycleCompositeMode`) schaltet zyklisch Aus→Plan→Fusion→MoA durch. Plan ist transient (Compat-Var `_planModeActive`), Fusion/MoA werden sofort via `apiUpdateSession({multiModelMode})` persistiert – gleiche Quelle wie der Picker.
**SSE-Events:** `panel_start` (mode/layers), `panel_layer_start`/`panel_layer_done` (MoA-Runden), `panel_member_start` (mit `layer`), `panel_member_text`/`panel_member_tool_use`/`panel_member_tool_end`/`panel_member_tool` (live), `panel_member_done` (inkl. per-Member Token-Feldern `inputTokens`/`outputTokens`/`cacheReadTokens`/`cacheCreationTokens`), `panel_done`.
**Frontend:** `stream-ui.js` rendert pro Member eine `.panel-bubble`, gekeyt per `layer_index` (MoA: gleiche Member über mehrere Runden; aktive Runde pro Index wird bei `panel_member_start` gemerkt, da Runden sequenziell laufen). `panel_layer_start` zeigt bei >1 Runde einen `.panel-layer-divider`. **History:** `history.js _renderPanelMemberBubble` parst JSON-Transkript → Text + Tool-Boxen interleaved; bei MoA Runden-Divider beim Layer-Wechsel (Back-Compat für Alt-Format). Picker: `#multiModelMode`-Dropdown (Aus/Fusion/MoA) + `#moaLayers` + Mehrfach-Agenten-Picker (`_openMultiPickerModal`). Vereinter Composer-Toggle: **ein** Button `#planModeBtn` (chat.js `cycleCompositeMode`) schaltet zyklisch Aus→Plan→Fusion→MoA durch. Plan ist transient (Compat-Var `_planModeActive`), Fusion/MoA werden sofort via `apiUpdateSession({multiModelMode})` persistiert – gleiche Quelle wie der Picker. Modus-PATCHes laufen über eine **serialisierte Promise-Kette** (`_modePersist`, letzter Klick gewinnt); `sendMessage`/`sendMessageDirect` **awaiten** sie, bevor der Chat-Request die Session lädt → verhindert Race (z.B. MoA mit nur 1 Runde, weil das Backend noch den alten Modus liest). **Per-Member-Token-Badge:** `buildPanelMemberMeta(d)` (`stream-ui.js`, global) baut ein kompaktes `.panel-member-meta`-Badge aus den Token-Feldern – Live aus `panel_member_done`, History aus dem persistierten JSON (gleicher Helper); graceful bei fehlenden Daten (OpenAI, Fehler-Member, Alt-History → kein Badge).
**Web-Search Sources:**
- `web_search_result`-Messages in DB gespeichert (Sources als JSON-Array, leere werden übersprungen)
+2 -1
View File
@@ -12,6 +12,7 @@ Self-hosted AI-Coding-Agent mit **Anthropic Claude API** als Haupt-Provider (ink
- **Vorbereiter-Agent** – Optionaler Preparer, der User-Anfragen analysiert, Vorarbeit leistet und aufbereitete Prompts an den Worker weitergibt
- **Multi-Agent Review** – Optionaler Review-Agent, der die Arbeit des Worker-Agents prüft und Feedback gibt
- **Finalizer-Agent** – Optionaler Agent, der nach dem Review abschließende Arbeiten durchführt (z.B. Git-Commit, Deployment)
- **Multi-Modell-Panel (Fusion / MoA)** – Mehrere KI-Agenten beantworten dieselbe Anfrage **parallel** (read-only, live gestreamt); der Worker synthetisiert daraus **eine** Gesamtantwort (OpenRouter-Fusion-/Mixture-of-Agents-Muster). MoA unterstützt mehrere Verfeinerungs-Runden, Token-Badge pro Member
- **Interaktive Rückfragen** – `ask_user_choice`-Tool: Agent stellt dem User klickbare Auswahlmöglichkeiten
- **Plan-Modus** – Read-only-Modus zum Analysieren und Planen ohne Änderungen (Toggle im Chat)
- **Web-Search** – Integrierte Web-Suche mit Quellenangaben (URLs + Titel) in Chat und geteilten Nachrichten
@@ -29,7 +30,7 @@ Self-hosted AI-Coding-Agent mit **Anthropic Claude API** als Haupt-Provider (ink
- **Auto-Context** – Automatischer semantischer Kontext aus früheren Gesprächen + Memory wird vor jedem Request in den System-Prompt injiziert und im Chat als aufklappbare Box sichtbar gemacht
- **Remote-Verbindungen** – WebSocket-basierte Remote-Clients für Windows (PowerShell, `remote.ps1`) und Linux/macOS (Bash + embedded Python, `remote.sh`); AI-Agent kann Befehle auf entfernten Rechnern ausführen, Tool-Description ist OS-aware
- **API-Key-Verwaltung** – Admin-UI zum Verwalten von API-Keys (Anthropic, OpenAI, Google, Stripe) inkl. Multi-Provider Key-Check, API-Key-Scanner (GitHub Code Search, GitHub Issues/PRs, HuggingFace Hub, Google/Serper), GitHub Events Echtzeit-Scanner, passive Usage-Aktualisierung bei jeder Chat-Nachricht, Usage-Badge im Chat mit Key-Switch-Modal (pro Agent)
- **Claude CLI** – Alternativer Streaming-Weg über die Claude Code CLI (OAuth-basiert, kein API-Key nötig); auch als Fallback für Sub-Agents (Preparer/Review/Finalizer) ohne zugewiesenen Key
- **Claude CLI** – Alternativer Streaming-Weg über die Claude Code CLI (OAuth-basiert, kein API-Key nötig); auch als Fallback für Sub-Agents (Preparer/Review/Finalizer), **Cronjobs** und **Telegram** ohne zugewiesenen Key; keyless Provider (nvidia/gemini/minimax/pollinations) werden über Server-Keys aufgelöst
- **Datenbank-Explorer** – Admin-UI zum direkten Inspizieren der SQLite-Datenbank
- **MCP-Server-Integration** – Interne API für externe MCP-Server (Remote-Execute, Ask-User-Choice, Memory-CRUD)
- **Nachrichten teilen** – Einzelne Nachrichten per öffentlichem Link teilen