feat(event-store): add conversationEvents and agentEvents filters
ci / JVM build + tests (push) Has been cancelled

Расширяет EventStore тремя вариантами подписки (вместо одного events()):

  - events(after)               → Flow<CommonEvent>
      весь поток (микс Agent + Conversation)

  - conversationEvents(after, conversationId?)
      → Flow<CommonEvent.Conversation>
      опциональный фильтр по conversationId (null = все диалоги)

  - agentEvents(after)
      → Flow<CommonEvent.Agent>
      только lifecycle (Created/Deleted/Renamed)

Типизированные subtype'ы вместо Flow<CommonEvent> + .filterIsInstance:
  - compile-time safety на клиенте (нет cast'ов в CommonEvent.Conversation)
  - persistent impl'ы могут делать WHERE conversation_id = ? на уровне БД

Соответствует HTTP-маршрутам в :server:
  - GET /events/all                       ↔ events(after)
  - GET /conversations/{id}/events         ↔ conversationEvents(after, id)
  - GET /events (только agent lifecycle)   ↔ agentEvents(after)

README обновлён — таблица caller→method показывает маппинг.

Совместимость: signals не сломаны (добавление, не изменение).
This commit is contained in:
2026-09-20 15:55:14 +03:00
parent 1134e32ea2
commit 7e66baf9e3
2 changed files with 47 additions and 7 deletions
+20 -7
View File
@@ -65,11 +65,24 @@ eventStore.events(after = client.lastSeen).collect { apply(it) }
```kotlin
interface EventStore : AutoCloseable {
fun events(after: Instant?): Flow<CommonEvent>
fun conversationEvents(
after: Instant?,
conversationId: String? = null, // null = все диалоги
): Flow<CommonEvent.Conversation>
fun agentEvents(after: Instant?): Flow<CommonEvent.Agent>
suspend fun earliestEventDate(): Instant // non-null: now() для пустого буфера
override fun close()
}
```
**Семантика фильтров**:
- `conversationEvents(null)` — все диалоги.
- `conversationEvents("c-123")` — один конкретный диалог.
- `agentEvents(...)` — только lifecycle (Created/Deleted/Renamed).
Все три возвращают **типизированные** subtype'ы [CommonEvent], так что
caller'у не нужно `.filterIsInstance` на клиентской стороне.
### `MutableEventStore : EventStore` (для producer'ов)
```kotlin
@@ -88,14 +101,14 @@ append по TTL/cap. Producer не должен полагаться на то,
## Когда использовать какой интерфейс
| Caller | Interface |
| Caller | Method |
|---|---|
| ChatAgent (producer) | `MutableEventStore` |
| Sub-agents (producer) | `MutableEventStore` |
| Server SSE endpoint | `EventStore` |
| Admin dashboard | `EventStore` |
| Parent orchestrator | `EventStore` |
| Тесты | `EventStore` (read-only) |
| Server `/events/all` SSE (mixed) | `events(after)` |
| Server `/conversations/{id}/events` SSE | `conversationEvents(after, conversationId)` |
| Server `/agent/events` SSE (lifecycle only) | `agentEvents(after)` |
| Admin dashboard (lifecycle) | `agentEvents(after)` |
| Parent orchestrator (mixed) | `events(after)` |
| Тесты | `events(after)` + projection через фильтр |
## Как добавить новый implementation