From 6e301b749868fdf7a18dade99c067dc6b13d95bc Mon Sep 17 00:00:00 2001 From: Meleki Date: Fri, 19 Jun 2026 19:24:08 +0200 Subject: [PATCH] Document panel subagent filtering, token badges, and CLI fallback reach MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- ARCHITECTURE.md | 31 ++++++++++++++++++++----------- ARCHITECTURE_QUICK.md | 18 ++++++++++-------- README.md | 3 ++- 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index ee9c577..9575eaa 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -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 ``-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 (``) 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 ``-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 (``) 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 `` 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. diff --git a/ARCHITECTURE_QUICK.md b/ARCHITECTURE_QUICK.md index 953934e..9a9dbed 100644 --- a/ARCHITECTURE_QUICK.md +++ b/ARCHITECTURE_QUICK.md @@ -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 ``-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 (``, 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 (``, 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`) + `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`) + `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) diff --git a/README.md b/README.md index e1ad89a..bae5bfd 100644 --- a/README.md +++ b/README.md @@ -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