Add workflow-status telemetry view and make panel modes on-demand

Workflow-status: a new WorkflowProgressTracker singleton taps the
suppressed dynamic-workflow subagent events (those carrying
parent_tool_use_id) into per-session telemetry without altering the
existing guard; the snapshot is serialized into the new chains.workflow_info
column on FinalizeChain (ChainId-matched so a panel member of the same
session cannot clear it) and exposed via GET /api/sessions/{id}/workflow-status
(live -> persisted -> none). The header menu gains a 'Workflow-Status' entry
with a modal that live-polls every 2s while running and self-stops on close.

Panel on-demand: Fusion/MoA is now a transient per-request multiModelMode
flag (like plan/ultracode) instead of a persisted session column. Session
settings keep only the panel members + moa_layers; the mode <select> was
removed and the composer dropdown drives the mode per request.

Docs: ARCHITECTURE.md, ARCHITECTURE_QUICK.md and README.md updated for both
features plus the already-shipped z.ai/GLM provider, GLM 5.2+ effort
passthrough, web-search-prime MCP and the ultracode toggle.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
MelekiandClaude Opus 4.8 committed 2026-06-20 17:27:46 +02:00
1 parent 5b1802efee
commit b6e546f618
22 files changed
+591 -99

No files matched your search

+54 -7
View File
@@ -33,6 +33,7 @@
19. [Multi-Agent System (Preparer + Review + Finalizer)](#multi-agent-system-preparer--review--finalizer)
20. [Interaktive Rückfragen (ask_user_choice)](#interaktive-rückfragen-ask_user_choice)
21. [Plan-Modus](#plan-modus)
21b. [Ultracode & Workflow-Status](#ultracode--workflow-status)
22. [Web-Search](#web-search)
23. [Nachrichten teilen (Shared Messages)](#nachrichten-teilen-shared-messages)
24. [Workspace & File-Explorer](#workspace--file-explorer)
@@ -164,6 +165,7 @@ gott/
│ ├── KreaService.cs # Krea Image Generation API
│ ├── ImageService.cs # Bild-Resize + WebP-Konvertierung (512px + 256px Thumbnail)
│ ├── StreamingTracker.cs # Tracking aktiver Streams + CancellationTokenSource für Stop
│ ├── WorkflowProgressTracker.cs # In-Memory-Telemetrie laufender dynamischer Workflows (Ultracode) pro Session
│ ├── WorkspaceHelper.cs # Workspace-Pfad-Auflösung (relativ → absolut)
│ ├── AppPaths.cs # Zentrale Pfade (WwwRoot) – Dev vs. Publish-Modus
│ ├── KeyScannerService.cs # API-Key-Scanner (GitHub Code Search, GitHub Issues/PRs, HuggingFace Hub, Google/Serper)
@@ -180,7 +182,7 @@ gott/
│ ├── AuthEndpoint.cs # Login, Logout, Me, Autologin
│ ├── ChatEndpoint.cs # POST /api/chat (SSE Streaming + CLI-Fallback)
│ ├── HistoryEndpoint.cs # History, Archive, Attachments, Marks, Chain-Details
│ ├── SessionEndpoint.cs # CRUD + SystemPrompt, SystemPromptBlocks, PayloadPreview, Streaming, Exec, Git-Status
│ ├── SessionEndpoint.cs # CRUD + SystemPrompt, SystemPromptBlocks, PayloadPreview, Streaming, WorkflowStatus, Exec, Git-Status
│ ├── AgentEndpoint.cs # CRUD + Available (inkl. public agents)
│ ├── WorkspaceEndpoint.cs # File-Tree, File-Read/Write, Browse, Agent-Files, Raw-Download
│ ├── TelegramEndpoint.cs # Bot-CRUD, Webhook, Session-Config, Registration
@@ -241,7 +243,7 @@ gott/
│ │ ├── cards.js # Card-Builder (buildSessionCard, buildAgentCard)
│ │ ├── msg-actions.js # Nachrichten-Aktionen (Delete, Mark, Share, Reply, Timestamp)
│ │ ├── tool-ui.js # Tool-Boxes, Diffs, Todo-Liste, Visibility-Logik
│ │ ├── modals.js # Modale Dialoge (System-Prompt, Command-Output, Krea-Image, Remote)
│ │ ├── modals.js # Modale Dialoge (System-Prompt, Payload, Command-Output, Krea-Image, Remote, Workflow-Status)
│ │ ├── stream-ui.js # Stream-Bubble, Review-Streaming
│ │ ├── bubbles.js # Message Bubbles (User, Assistant, Error, Warning, Choice, Review)
│ │ ├── chat.js # Chat-Logic, SSE-Streaming, Plan-Mode
@@ -349,7 +351,7 @@ TelegramBot (1) ─── (*) Session (via telegram_bot_id)
| `tokens` | Auth-Tokens (token → user_id) |
| `agents` | AI-Agenten (model – z.B. `claude-sonnet-4-6` oder `nvidia:deepseek-ai/deepseek-r1`, custom_commands, auto_commit, use_soul/identity/user_info/memory/auto_context, use_github_search, use_serper_search, use_web_search, web_search_version, allow_user_choice, task_instruction, avatar_scale/offset, avatar_small, is_public) |
| `sessions` | Chat-Sessions (description, image, image_small, workspace, context, custom_commands, telegram_bot_id, telegram_chat_id, avatar_scale/offset, preparer_agent_id, review_agent_id, max_review_iterations, finalizer_agent_id, multi_model_mode, panel_agent_ids, moa_layers) |
| `chains` | Request-Chains (model, tokens, iterations, timing, tool_choice, tool_names, stream_error_info, plan_mode, archive_id) |
| `chains` | Request-Chains (model, tokens, iterations, timing, tool_choice, tool_names, stream_error_info, workflow_info, plan_mode, effort, archive_id) |
| `messages` | Einzelne Nachrichten (text, tool_use, tool_result, error, web_search_result, auto_context), Tag für Sub-Agent-Markierung oder Import-Herkunft (`openclaw-import`), SortKey für korrekte Reihenfolge, thought_signature (Gemini) |
| `attachments` | Datei-Anhänge (base64, image/document) |
| `archives` | Archivierte Chain-Gruppen |
@@ -380,6 +382,7 @@ TelegramBot (1) ─── (*) Session (via telegram_bot_id)
- `ToolNames` – Komma-separierte Liste der verwendeten Tools
- `ArchiveId` – Zugehöriges Archiv (wenn archiviert)
- `StreamErrorInfo` – Fehlerdetails bei Stream-Abbrüchen
- `WorkflowInfo` – JSON-Telemetrie eines dynamischen Workflows (Ultracode): Subagent-Anzahl, Tool-Aufrufe (+ Aufschlüsselung), aggregierte Subagent-Tokens. `null` wenn die Chain keinen Workflow gespawnt hat (siehe [Workflow-Status](#workflow-status))
- `PlanMode` – Ob die Chain im Plan-Modus erstellt wurde (informativ)
- `DurationMs` – Gesamtdauer der Chain
@@ -459,6 +462,7 @@ 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 |
| `WorkflowProgressTracker` | Singleton | In-Memory-Telemetrie laufender dynamischer Workflows (Ultracode) pro Session: Subagent-Anzahl, Tool-Aufrufe (+ Aufschlüsselung), aggregierte Subagent-Tokens. Wird beim Chain-Finalize in `chains.workflow_info` persistiert (analog `StreamingTracker`) |
| `KeyScannerService` | Singleton | API-Key-Scanner (GitHub Code Search, GitHub Issues/PRs, HuggingFace Hub, Google/Serper), täglicher Scan |
| `GitHubEventScannerService` | Background | Echtzeit-Scanner: GitHub Public Events API (PushEvent-Diffs nach geleakten Keys), 30s Poll-Intervall |
| `KeyPatterns` | Static | Zentrale Key-Pattern-Definitionen für alle Scanner (Regex, Typ-Erkennung, Display-Names) |
@@ -478,7 +482,7 @@ Alle Endpoints folgen dem **Minimal API**-Pattern mit Extension Methods (`MapXxx
| **Auth** | `/api/auth/` | `POST login`, `POST logout`, `GET me`, `GET autologin` |
| **Chat** | `/api/chat` | `POST` (SSE Streaming), `POST stop` |
| **History** | `/api/history` | `GET history`, `GET poll`, `POST archive`, `GET archives`, `GET archive/{id}`, `GET attachments/{id}`, `PUT messages/{id}/mark`, `PUT messages/{id}/delete`, `GET chains/{id}` |
| **Sessions** | `/api/sessions/` | CRUD + `GET system-prompt`, `GET system-prompt-blocks`, `GET payload-preview`, `GET streaming`, `POST exec`, `GET git-status` (Liste inkl. inline Git-Status + Thumbnail) |
| **Sessions** | `/api/sessions/` | CRUD + `GET system-prompt`, `GET system-prompt-blocks`, `GET payload-preview`, `GET streaming`, `GET workflow-status`, `POST exec`, `GET git-status` (Liste inkl. inline Git-Status + Thumbnail) |
| **Agents** | `/api/agents/` | CRUD + `GET available` (inkl. public agents, inline Skills + Thumbnail) |
| **Admin** | `/api/admin/` | `GET users`, `POST users`, `PUT users/{id}`, `PUT users/{id}/password`, `DELETE users/{id}`, `POST users/{id}/impersonate`, `POST users/{id}/login-link` (Admin-only) |
| **Workspace** | `/api/workspace/` | `GET tree`, `GET/PUT file`, `GET browse`, `POST mkdir`, `DELETE dir`, `POST browse/mkdir`, `GET agent/tree`, `GET/PUT agent/file`, `POST agent/mkdir`, `GET raw` |
@@ -641,7 +645,8 @@ Beim Server-Start werden verfügbare Modelle von den Provider-APIs geladen und i
### Routing
`ChatService.ResolveModelId()` prüft den Model-String:
- Enthält `:` mit bekanntem Provider-Prefix → `OpenAiService.StreamChat()`
- Enthält `:` mit bekanntem OpenAI-Provider-Prefix (`nvidia:`/`pollinations:`/`gemini:`/`openai:`/…) → `OpenAiService.StreamChat()`
- `glm:`-Prefix → Prefix wird gestrippt, Provider=`""` → **Claude-CLI-Pfad** mit z.ai-Env-Injection (siehe [z.ai / GLM-Provider](#zai--glm-provider-über-den-cli-pfad))
- Sonst → `AnthropicService.StreamChat()`
---
@@ -855,7 +860,7 @@ Ein **Agent** definiert die Persönlichkeit und Fähigkeiten der AI:
| `WebSearchVersion`| Web-Suche aktivieren (z.B. `web_search_20260209`) |
| `AllowUserChoice` | `ask_user_choice`-Tool verfügbar (Default: true) |
| `TaskInstruction` | Aufgabe/Anweisung – optionaler Text, wird als `## Anweisungen`-Block in System-Prompt eingefügt |
| `Effort` | Reasoning-Effort-Level für Claude. `""` (=high, Default), `low`, `medium`, `high`, `xhigh` (nur Opus 4.7+), `max` (nur Opus 4.6+/Sonnet 4.6). API: als `output_config.effort` gesendet. CLI: via Env-Var `CLAUDE_CODE_EFFORT_LEVEL`. Bei OpenAI-Providern ignoriert. |
| `Effort` | Reasoning-Effort-Level für Claude. `""` (=high, Default), `low`, `medium`, `high`, `xhigh` (nur Opus 4.7+), `max` (nur Opus 4.6+/Sonnet 4.6). API: als `output_config.effort` gesendet. CLI: via Env-Var `CLAUDE_CODE_EFFORT_LEVEL`. Bei OpenAI-Providern ignoriert; bei z.ai/GLM nur ab **GLM 5.2** durchgereicht (sonst entfernt). Ultracode hebt es auf `xhigh` an. |
| `IsPublic` | Andere User können den Agent in ihren Sessions verwenden (aber nicht bearbeiten) |
### Model-Auflösung
@@ -1489,7 +1494,7 @@ Folgende Blöcke werden **übersprungen**: Git-Commits. Der Tools-Block listet n
### Frontend
- **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.
- **Toggle**: `#planModeBtn` öffnet ein **Dropdown-Menü** (`_COMPOSITE_MODES`: Normal/Plan/Ultracode/Fusion/MoA). **Alle** Modi sind **transient** (pro Request, nicht persistiert, Reset beim Chat-Wechsel) und werden als Flag mitgeschickt (`planMode`/`ultracode`/`multiModelMode`). In den Session-Einstellungen werden nur noch die Panel-**Mitglieder** (`panelAgentIds`) + `moaLayers` festgelegt (persistent); der Panel-Modus selbst kommt on-demand aus dem Request.
- **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
@@ -1501,6 +1506,38 @@ Wenn im Plan-Modus eine `ask_user_choice`-Rückfrage kommt und der User antworte
---
## Ultracode & Workflow-Status
**Ultracode** ist ein Composite-Modus, der eine **einzelne** Anfrage als nativen **dynamischen Workflow** der Claude CLI ausführt: Claude fächert die Arbeit über mehrere gespawnte **Subagenten** parallel auf, lässt Befunde gegenprüfen und synthetisiert am Ende. Wie Plan-/Fusion-/MoA-Modus wird Ultracode **on-demand pro Request** über das Composer-Dropdown (`#planModeBtn`, `_COMPOSITE_MODES`) gewählt – nicht am Agent/an der Session persistiert.
### Aktivierung & Backend-Auswirkungen
- **API:** transientes Flag `ultracode: true` im `ChatRequest` (`ChatModels.cs`, `Ultracode`)
- **Hint:** Bei aktivem Ultracode wird an jede User-Nachricht ein `<hint>` angehängt (*"Bearbeite diese Anfrage als dynamischen Workflow – use a workflow ... Nutze dafür das Workflow-Tool"*)
- **Nur CLI-Pfad / nur Claude:** Ultracode greift ausschließlich im Claude-CLI-Pfad (`StreamChatViaCli`). Es ist **nur für Claude-Modelle** aktiv – **nicht** für z.ai/GLM (kein Workflow-Runtime) und **nicht** im Plan-Modus.
- **Effort:** Ultracode hebt das Reasoning-Effort auf `xhigh` an (bzw. `max`, wenn der Agent bereits `max` setzt) – via Env-Var `CLAUDE_CODE_EFFORT_LEVEL`
- **Allowed-Tools:** Im CLI-Aufruf (`ClaudeCliService.ChatStreamingAsync`) werden zusätzlich `Workflow` (die nativen dynamischen Workflows) und `Task` (die vom Workflow gespawnten Subagenten) zu `--allowed-tools` hinzugefügt. Ohne diese Freigabe lehnt die Permission-Engine das Workflow-Tool headless still ab (kein interaktiver Gate im `-p`-Modus).
### Workflow-Status
Da die CLI Subagent-Events (Top-Level-Messages mit gesetztem `parent_tool_use_id`) bewusst aus dem sichtbaren Stream/History ausblendet (zentraler `parent_tool_use_id`-Guard in `ClaudeCliService.RunCliStreamingAsync`), gäbe es ohne separates Tracking keine Sichtbarkeit auf den Workflow-Fortschritt. Der **Workflow-Status** macht diese Subagent-Telemetrie live und nachträglich abrufbar.
**Backend:**
- **`WorkflowProgressTracker`** (Singleton, registriert in `Program.cs`) – In-Memory-Tracking pro Session: Subagent-Anzahl (dedupliziert per `parent_tool_use_id`), Tool-Aufrufe + Aufschlüsselung (`ToolBreakdown`), aggregierte Subagent-Input-/Output-Tokens, `RecentTools` (letzte 12). Lock-leicht, defensiv – Telemetrie darf den Stream nie blockieren.
- **Tap statt Filter:** Der `parent_tool_use_id`-Guard blendet Subagent-Events weiterhin aus dem Stream aus (`continue`), greift aber für `type == "assistant"`-Turns via `TapSubagentEvent()` die Tool-Namen + Token ab und meldet sie an `RecordSubagent()`. Der existierende Guard bleibt unverändert.
- **Persistierung:** Neue Spalte `chains.workflow_info` (TEXT, via `TryAddColumn` in `DatabaseService.cs`; geschrieben in `DatabaseService.Sessions.cs` `UpdateChain`), Feld `ChainRecord.WorkflowInfo`. Beim `FinalizeChain` (`AnthropicService.cs`) wird die Telemetrie als JSON in die Chain serialisiert und der Live-Tracker freigegeben – mit **ChainId-Abgleich** (`ChainIdFor`), damit ein anderer Finalize-Pfad derselben Session (z.B. ein Panel-Member) den Workflow-Eintrag nicht fälschlich abräumt.
- **Endpoint:** `GET /api/sessions/{id}/workflow-status` (`SessionEndpoint.HandleWorkflowStatus`) liefert in dieser Reihenfolge: (1) `status: "running"` + Live-Snapshot, solange der Tracker einen Eintrag hat; (2) `status: "completed"` + persistiertes `workflow_info` der jüngsten aktiven Chain; (3) `status: "none"` mit `workflow: null`. Top-Level-Felder: `sessionId`, `streaming`, `status`, `chainId` (entfällt bei `status: "none"`) und das Telemetrie-Objekt `workflow` (`null` bei `none`).
**Felder im `workflow`-Objekt** (camelCase): `subagentCount`, `subagentToolCalls`, `subagentInputTokens`, `subagentOutputTokens`, `toolBreakdown`, `recentTools`, `startedAt`, `lastActivityAt`.
**Frontend:**
- Header-Menü-Eintrag **"Workflow-Status"** (Button `#workflowStatusBtn` in `index.html`, direkt nach "Payload anzeigen")
- API-Wrapper `apiGetWorkflowStatus(sessionId)` in `js/api.js`
- `showWorkflowStatusModal(sessionId)` in `js/modals.js` – rendert Status-Head, Statistik-Grid (Subagenten/Tool-Aufrufe/Input-/Output-Tokens), Tool-Aufschlüsselung und Zeitstempel. **Pollt alle 2 s**, solange `status === "running"`, und stoppt automatisch, sobald das Modal geschlossen wird (Overlay nicht mehr im DOM) oder der Workflow endet.
- Click-Handler in `js/pages/chat-page.js`, Styles `.workflow-status-modal` (+ `.wf-*`) in `css/chat.css`
---
## Web-Search
Anthropic Claude unterstützt Web-Suche als Server-Tool. Das System integriert Web-Search mit Source-Tracking und Rendering.
@@ -2007,6 +2044,16 @@ Der frühere harte Abbruch („Kein API-Key zugewiesen") blockte irrtümlich **j
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.
### z.ai / GLM-Provider (über den CLI-Pfad)
Ein Agent kann **z.ai/GLM-Modelle** verwenden, indem die Modell-ID mit `glm:` prefixt wird (z.B. `glm:glm-5.2`, `glm:glm-4.6`). Diese laufen über den **Anthropic-kompatiblen z.ai-Endpoint** – also über den **Claude-CLI-Pfad**, nicht über den OpenAI-Provider-Pfad.
- **Routing:** `ChatService.ResolveModelId()` strippt das `glm:`-Prefix → die rohe Modell-ID (`glm-5.2`) geht mit Provider=`""` an den CLI-Pfad. `ClaudeCliService.IsZaiModel()` erkennt sie am `glm-`-Prefix.
- **Per-Prozess Env-Injection:** Für GLM-Modelle setzt `ClaudeCliService` `ANTHROPIC_BASE_URL = https://api.z.ai/api/anthropic` und `ANTHROPIC_AUTH_TOKEN = <ZaiApiKey>` (Server-Setting `ZaiApiKey`) nur im jeweiligen Kindprozess. Ohne `ZaiApiKey` läuft der Request **nicht** über z.ai (Warnung im Log).
- **Effort (GLM 5.2+):** `CLAUDE_CODE_EFFORT_LEVEL` wird für **GLM 5.2 oder höher** durchgereicht (`IsZaiEffortModel` per Versionsvergleich `>= 5.2`, damit künftige Releases automatisch mitgenommen werden); für ältere GLM-Versionen (4.x, 5, 5.1, 5-turbo) wird die Env-Var **entfernt**. Effort bleibt damit Claude-/GLM-5.2+-only.
- **Web-Search (web-search-prime):** Wenn der Agent Web-Suche aktiviert hat **und** das Modell GLM + `ZaiApiKey` ist, werden die nativen `WebSearch`/`WebFetch`-Tools **verboten** (`--disallowed-tools`, sonst scheitert das Modell headless an der Berechtigung) und durch z.ai's **`web-search-prime`-MCP-Server** ersetzt (registriert in `GenerateMcpConfig` als `web-search-prime` → `https://api.z.ai/api/mcp/web_search_prime/mcp` mit `Authorization: Bearer <ZaiApiKey>`, freigegeben via `mcp__web-search-prime__*`). Für Claude-Modelle bleiben die nativen `WebSearch`/`WebFetch`-Tools.
- **Kein Ultracode:** Dynamische Workflows (Ultracode) sind nur für Claude-Modelle aktiv – GLM hat kein Workflow-Runtime (`Workflow`/`Task` werden für GLM nicht freigegeben).
---
## Datenbank-Explorer