wiki/c-work/1-plan/2026-04-teamsbot-greenfield-ia-and-live-update.md
ValueOn AG 6eeeb962f6 upd
2026-04-29 20:23:03 +02:00

274 lines
12 KiB
Markdown

<!-- status: plan -->
<!-- started: 2026-04-29 -->
<!-- component: gateway, frontend-nyla, teams-bot -->
# TeamsBot Greenfield-IA: MeetingModule + Live-Update-Fixes
## Beschreibung und Kontext
Die TeamsBot-UI ist aktuell:
- 3 Tabs (Dashboard "Uebersicht", Sitzungen, Einstellungen).
- Kein Meeting-Entity -- alles ist `TeamsbotSession.meetingLink`. Wer
z.B. ein wiederkehrendes Weekly-Standup ueber Wochen verfolgen will,
muss die Sessions per Datum suchen.
- Kein "Modul"-Konzept fuer Reihen (wie der User wuenscht).
- Live-Updates haengen an SSE in `TeamsbotSessionView.tsx` mit
`useEffect`-Deps `[instanceId, sessionId]` only (Z. 327-328) +
`eslint-disable` -- reagiert daher NICHT zuverlaessig auf
Status-Wechsel und auf neue `agentRun`-Events. Letztere sind nur
`_dlog`, NICHT in der UI sichtbar.
- `stats`-Payload aus `getSession`-API
(`routeFeatureTeamsbot.py` 357-358) wird vom Frontend ignoriert.
- Dashboard-Counts haben 10s Lag (Polling).
**Geschaeftstreiber:** User finden sich nicht zurecht; Live-Bedienung
wirkt fragil ("zeigt das hier ueberhaupt was Aktuelles?"). Mit Modul-
of-Sessions-IA (analog ComCoach) und sauberen Live-Update-Pfaden wird
TeamsBot zum verlaesslichen Meeting-Tool.
## Fokus und kritische Details
- **Live-Update ist UX-kritisch** -- Session-State, agentRun-Indicator
und Stats muessen waehrend laufender Meetings sichtbar pulsieren.
- SSE-`useEffect`-Deps nicht naiv aufschnueren -- sonst Reconnect-
Flicker bei jedem Status-Bit-Wechsel. Loesung: dedizierter Reconnect-
Hook, der nur reconnektet wenn (a) sessionId wechselt oder (b) Session
von "terminal" zurueck zu "active" geht (sehr selten).
- Backend `stats`-Payload bereits vorhanden, nur nicht gebunden.
- `MeetingModule` ist additiv -- alte `TeamsbotSession`-Eintraege
bekommen `moduleId` per Migration (Default-Modul "Adhoc").
## Ziel und Nicht-Ziele
- Ziel:
- 5-Tab-IA (Dashboard, Assistent, Module, Live-Session, Einstellungen).
- `MeetingModule`-Entity (Reihe + KPIs + Default-Bot + Default-
Director-Prompts).
- 4 Live-Update-Fixes (siehe unten F-fix-1 .. F-fix-4).
- NICHT: Aenderung an Bot-Bridge (.NET Media-Bridge bleibt).
- NICHT: WebSocket-Migration im Frontend (SSE bleibt, ist Architektur-
Entscheid).
- NICHT: Multi-Mandate-Sharing von Modulen.
## Betroffene Module
- Gateway:
- `gateway/modules/features/teamsbot/datamodelTeamsbot.py` -- neue
Klasse `TeamsbotMeetingModule`, FK `TeamsbotSession.moduleId`
(nullable in Uebergangsphase).
- `gateway/modules/features/teamsbot/interfaceFeatureTeamsbot.py` --
CRUD fuer `MeetingModule`.
- `gateway/modules/features/teamsbot/routeFeatureTeamsbot.py` --
neue Routen `/modules/...`, `agentRun`-Event sauberer schicken,
`stats`-Payload kontinuierlich anreichern.
- `gateway/modules/features/teamsbot/mainTeamsbot.py` -- RBAC-Keys
auf 5 Tabs, optional Default-MeetingModule-Templates.
- Frontend:
- `frontend_nyla/src/types/mandate.ts` 244-252 -- TeamsBot-Sidebar
3 -> 5 Eintraege.
- `frontend_nyla/src/pages/FeatureView.tsx` 159-163 -- View-Mapping
aktualisieren.
- `frontend_nyla/src/pages/views/teamsbot/` -- vorhandene Komponenten
aufteilen:
- `TeamsbotDashboardView` -- KPIs erweitern (Modul-Aggregate +
Gamification).
- `TeamsbotAssistantView` (NEU) -- Wizard.
- `TeamsbotModulesView` (NEU) -- Modul-CRUD + Sessions je Modul.
- `TeamsbotSessionView` -- bleibt, jetzt nur Live-Session.
- `TeamsbotSettingsView` -- bleibt.
- `frontend_nyla/src/api/teamsbotApi.ts` -- Module-API + neuer
Reconnect-Hook.
- DB-Migration: ja (additive Tabelle + nullable FK).
## Zieldatenmodell
```mermaid
flowchart LR
Inst[FeatureInstance teamsbot] --> Mod[MeetingModule]
Mod --> Sess[TeamsbotSession meetingLink]
Sess --> Trans[Transcript]
Sess --> Resp[BotResponse]
Sess --> Dir[DirectorPrompt]
Mod --> Kpi[ModuleKpi/Goals]
Mod --> DefBot[Default Bot]
Mod --> DefDir[Default Director Prompts]
```
`MeetingModule` Felder (Auszug):
| Feld | Typ | Bedeutung |
|------|-----|-----------|
| `id` | UUID | PK |
| `instanceId` | UUID | FeatureInstance-Scope |
| `mandateId` | UUID | Tenant |
| `ownerUserId` | UUID | Owner |
| `title` | text | "Weekly Standup", "Q3 Sales Review-Reihe" |
| `seriesType` | enum | `weekly` \| `biweekly` \| `monthly` \| `adhoc` \| `project` |
| `defaultBotId` | UUID? | `TeamsbotSystemBot` |
| `defaultDirectorPrompts` | jsonb | Liste vorausgefuellter Director-Prompts |
| `goals` | text | -- |
| `kpiTargets` | jsonb | -- |
| `status` | enum | `active` \| `archived` \| `completed` |
## IA: 5 Tabs (final)
| # | Tab | Zweck | Komponente |
|---|------|-------|-------------|
| 1 | Dashboard | Gamification (Talking-Time, Director-Trefferquote, beliebteste Prompts), aktive Module/Sessions, Quick-Action "Neues Meeting" | `TeamsbotDashboardView` |
| 2 | Assistent | Wizard: Modul waehlen oder neu -> Meeting-Link/Auto-Join -> Bot starten | `TeamsbotAssistantView` |
| 3 | Module | CRUD-Liste aller Meeting-Module, pro Modul aufklappbare Session-Liste | `TeamsbotModulesView` |
| 4 | Live-Session | aktive Sitzung: Regie-Panel, UDB-Sidebar, Transkript, Antworten, Bot-Status, MFA, Stats-Karten | `TeamsbotSessionView` (refactor) |
| 5 | Einstellungen | Bot-Account, Stimme, System-Bots (SysAdmin) | `TeamsbotSettingsView` |
## Use-Case-Mapping
| Use-Case | Tab(s) | Hauptaktion |
|----------|--------|-------------|
| 1 Gamification-Dashboard | Dashboard | Talking-Time + Modul-KPIs |
| 2 Assistent: neues Meeting | Assistent -> Live-Session | Wizard durchklicken |
| 3 Session-Operations | Live-Session | Stop, Director-Prompts, MFA, Stats |
| 4 Listen CRUD | Module | Module + Sessions je Modul pflegen |
| 5 Instanzen-Einstellungen | Einstellungen | Bot, Stimme, System-Bots |
## Live-Update-Fixes (parallel zur IA)
### F-fix-1: SSE-Reconnect-Hook
- Problem: `useEffect` `[instanceId, sessionId]`-only haengt nicht an
`session.status` -> Reconnect bei legitimen Status-Wechseln nicht
garantiert.
- Loesung: Eigener Hook `useTeamsbotSessionStream(instanceId, sessionId,
isTerminal)` der intern reconnectet wenn `isTerminal` von `true` ->
`false` flippt (z.B. nach manuellem Re-Start einer beendeten Session).
Andere Status-Bits triggern KEINEN Reconnect.
### F-fix-2: agentRun-Event sichtbar
- Problem: `agentRun`-SSE-Events sind nur `_dlog`
(`TeamsbotSessionView.tsx` 290-293).
- Loesung: Status-Bubble in der Live-View ("Agent denkt nach: <toolName>...")
als kurzlebige animierte Komponente.
### F-fix-3: stats-Karten
- Problem: `getSession`-API liefert `stats` (Sprechminuten, Bot-
Antworten, Latenz) -- Frontend ignoriert.
- Loesung: Header-Karten in `TeamsbotSessionView` gebunden an
`session.stats`. Aktualisierung kommt automatisch via SSE
`sessionState`-Events (Backend muss `stats` mitliefern -- ggf.
Backend-Anpassung in `routeFeatureTeamsbot.py`).
### F-fix-4: Dashboard-Counts ohne 10s-Lag
- Problem: Dashboard pollt `listSessions` alle 10s.
- Option A (kleiner Eingriff): bei aktiver Session 3s-Polling, sonst
30s.
- Option B (besser): SSE-Channel pro Mandate
`/api/teamsbot/{instanceId}/dashboard/stream` mit "session-tick"-
Events (Counter-Updates push, kein Polling).
- **Default:** Option A in Phase 4, Option B als Follow-up.
## Entscheidungen
| Datum | Entscheidung | Begruendung |
|-------|-------------|------------|
| 2026-04-29 | Neues `MeetingModule`-Entity additiv | Reihen-Konzept gewuenscht; bestehende Sessions in "Adhoc"-Modul |
| 2026-04-29 | 5 Tabs (statt 3) | Use-Cases brauchen klare Trennung Assistent/Module/Live |
| 2026-04-29 | SSE bleibt (kein WS) | Architektur stabil, Browser-Bot nutzt WS, Frontend nicht |
| 2026-04-29 | Dashboard-Counts: Adaptive Polling jetzt, SSE-Channel als Follow-up | Pragmatisch, schnell sichtbar |
## Umsetzungs-Checkliste
### Phase 1 -- Backend Datenmodell + Routes
- [ ] `datamodelTeamsbot.py`:
- Neue Klasse `TeamsbotMeetingModule`.
- `TeamsbotSession.moduleId Optional[UUID]` additiv.
- [ ] DB-Migration:
`script_db_init_teamsbot_meeting_modules.py` -- legt Tabelle an,
erzeugt pro `instanceId` ein Default-`Adhoc`-Modul, setzt
bestehende Sessions auf dieses Modul.
- [ ] `interfaceFeatureTeamsbot.py` -- CRUD-Methoden fuer Module.
- [ ] `routeFeatureTeamsbot.py`:
- Neue Routen `GET/POST/PUT/DELETE /modules/...`.
- `getSession` liefert `stats` (existiert), `listSessions`
ergaenzt `moduleId` im Payload.
- SSE: `sessionState`-Event traegt jetzt auch `stats`.
- SSE: `agentRun`-Event sauberer schicken (toolName, status:
`started`/`finished`/`failed`).
### Phase 2 -- Backend Live-Stats anreichern
- [ ] `_buildSessionStats(session) -> SessionStats` zentral, in
jedem `sessionState`-SSE-Event aufrufen (nicht nur on-demand).
### Phase 3 -- Frontend Routing & Sidebar
- [ ] `frontend_nyla/src/types/mandate.ts` 244-252 TeamsBot-Eintraege
auf 5 Eintraege.
- [ ] `frontend_nyla/src/App.tsx` Routes ergaenzen (`assistant`,
`modules`).
- [ ] `frontend_nyla/src/pages/FeatureView.tsx` View-Mapping
aktualisieren.
### Phase 4 -- Frontend Komponenten
- [ ] NEU `TeamsbotAssistantView` -- Wizard 3 Steps (Modul-
Auswahl/Neu, Meeting-Link, Bot-Auswahl) -> "Bot starten" ->
Navigation `live-session?sessionId=...`.
- [ ] NEU `TeamsbotModulesView` -- Liste, CRUD, aufklappbare Sessions.
- [ ] `TeamsbotSessionView` Refactor:
- Reconnect-Hook (F-fix-1) integrieren.
- Status-Bubble fuer agentRun (F-fix-2).
- Stats-Karten im Header binden (F-fix-3).
- [ ] `TeamsbotDashboardView`:
- Polling adaptiv (F-fix-4 Option A).
- Modul-Aggregate-Sektion ergaenzen (Top-Module nach
Session-Count, Talking-Time-Verteilung etc.).
### Phase 5 -- Doku
- [ ] `wiki/b-reference/teams-bot/architecture.md` Module-Sektion
ergaenzen, Live-Update-Pfade dokumentieren.
- [ ] `wiki/TOPICS.md` ggf. Eintrag "TeamsBot Module".
## Akzeptanzkriterien
| # | Kriterium (Given-When-Then) | Prio |
|---|-----------------------------|------|
| 1 | Given Sidebar TeamsBot, When User es oeffnet, Then sieht er 5 Tabs (Dashboard, Assistent, Module, Live-Session, Einstellungen) | must |
| 2 | Given Tab Module, When User auf "Neues Modul" klickt, Then kann er Titel, Series-Typ, Default-Bot, Director-Prompts, KPIs setzen | must |
| 3 | Given Modul existiert, When User auf "Neue Session" klickt, Then wird eine `TeamsbotSession` mit `moduleId` angelegt und im Live-Tab geoeffnet | must |
| 4 | Given Live-Session laeuft, When der Backend-Agent ein Tool aufruft, Then erscheint im UI ein Status-Bubble "Agent denkt nach" mit Tool-Name | must |
| 5 | Given Live-Session laeuft, When sich Sprechminuten/Bot-Antworten/Latenz aendern, Then aktualisieren die Stats-Karten ohne Page-Reload | must |
| 6 | Given Session terminiert (z.B. Stop), When User auf gleicher Seite bleibt, Then schliesst die SSE sauber, kein Reconnect-Loop | must |
| 7 | Given Bestand-Sessions ohne Modul, When Migration laeuft, Then sind alle Sessions im Default-`Adhoc`-Modul je Instanz einsortiert | must |
| 8 | Given Dashboard offen, When eine aktive Session laeuft, Then aktualisieren die Counter spaetestens nach 3s | should |
| 9 | Given keine aktive Session, When Dashboard offen, Then aktualisiert es nur alle 30s | should |
## Testplan
| ID | AC | Art | Automatisiert | Repo-Pfad | Status |
|----|----|-----|--------------|-----------|--------|
| T1 | 1 | unit | ja | frontend_nyla/src/types/__tests__/mandate.test.ts | pending |
| T2 | 2,3 | e2e | ja | frontend_nyla/tests/e2e/teamsbot-modules-crud.spec.ts | pending |
| T3 | 4 | unit | ja | frontend_nyla/src/pages/views/teamsbot/__tests__/TeamsbotSessionView_agentRun.test.tsx | pending |
| T4 | 5 | integration | ja | frontend_nyla/tests/integration/teamsbot-stats-binding.spec.ts | pending |
| T5 | 6 | manual | nein | -- | pending |
| T6 | 7 | integration | ja | gateway/tests/features/teamsbot/test_migration_modules.py | pending |
| T7 | 8,9 | manual | nein | -- | pending |
## Links
- Audit-Quelle: Subagent-Report 2026-04-29.
- Aktueller Code: `gateway/modules/features/teamsbot/`,
`frontend_nyla/src/pages/views/teamsbot/`.
- Wiki: `wiki/b-reference/teams-bot/architecture.md`,
`wiki/c-work/4-done/2026-04-teamsbot-director-prompts.md`.
## Abschluss
- [ ] `wiki/b-reference/teams-bot/architecture.md` aktualisiert
- [ ] `wiki/TOPICS.md` ggf. neuer Eintrag
- [ ] Dieses Dokument -> `z-archive/` verschoben