refactor: outbox становится live-only стримом, cursor вынесен в :cursor-api
Семантика outbox'а — теперь чистый live-канал:
* OutboxStore.conversationEvents(id) — больше не принимает after-cursor.
Catchup (replay) делает клиент: journal.listFlow(afterSeq) + подписка
на live. Outbox ответственен только за уведомления «что-то произошло».
* OutboxStore.oldestCursor()/currentCursor()/OutboxGapException — удалены.
Эпоха и offset живут ТОЛЬКО в CursorHolder/CursorStore, переживают
рестарт и инкремент для каждого commit.
* DurableEvent: commit принимает блок { cursor -> MessageRecord }
(cursor выдаёт CursorStore; клиент не вычисляет offset сам).
* MessageRecord больше не несёт cursor — это не его ответственность.
Новые модули:
* :cursor-api — Cursor(epoch, offset) + CursorHolder / MutableCursorHolder
* :cursor-ksqlite — KsqliteCursorHolder (персистентный)
* :cursor-inmemory — для тестов
* :client-sync — LocalSyncAgent (мини-агент поверх :client для десктопа)
Удалены:
* :sync-core — старая референсная реализация, заменена
cursor-разделением и :client.
* outbox-ksqlite — CursorStore/Schema уехали в :cursor-ksqlite.
* OffsetSequencer / PersistentOffsetSequencer / InMemoryOffsetSequencer.
standalone:
* ChatAgent/ConversationLoop/DurableLog/ToolDispatcher/ReflectionScheduler/
ConversationEvents — подписка через push-паттерн (collect событий).
* A2aBridge — currentCursor() и conversationEvents(after=) убраны.
* SqliteStores — cursor_offset удалён из schema v4; seedNextFromJournal
читает MAX(created_at).
* Main.kt — outboxSequencer → outboxCursorHolder; user→agent (:server)
transport удалён; debug-routes удалены; A2A остался.
* Тесты ChatAgentTest/PersistenceTest переписаны на push-паттерн
(subscribe-before-act, snapshot∪live = итоговое состояние). 25/25 + 19/19 ✅
server / client:
* Routes эпоху читают из CursorHolder; снимки несут Cursor? для catchup.
* AgentikAgent и HttpEventStore — те же подписки, без after-параметра.
* ReconnectingOutbox / ReconnectingOutboxTest — без изменений API.
* JournalStore API расширен count(after=Instant?) для unread-badge.
This commit is contained in:
@@ -3,13 +3,13 @@ package pw.binom.agentik.proto
|
||||
import kotlinx.serialization.Serializable
|
||||
import pw.binom.agentik.journal.ConversationRecord
|
||||
import pw.binom.agentik.journal.MessageRecord
|
||||
import pw.binom.agentik.outbox.Cursor
|
||||
import pw.binom.agentik.cursor.Cursor
|
||||
|
||||
/**
|
||||
* Снапшот списка диалогов + его [cursor].
|
||||
*
|
||||
* Курсор — **commit point** на момент чтения (см. `OutboxStore.currentCursor`):
|
||||
* состояние со `seq <= cursor.offset` отражено в [conversations], всё, что
|
||||
* состояние с `offset <= cursor.offset` отражено в [conversations], всё, что
|
||||
* появится позже, придёт потоком outbox-событий. Клиент после применения
|
||||
* снапшота подписывается `agentEvents(after = cursor)` (или
|
||||
* `conversationEvents(after = cursor)`) и накатывает дельты поверх.
|
||||
@@ -27,9 +27,9 @@ data class ConversationsSnapshot(
|
||||
/**
|
||||
* Снапшот сообщений одного диалога + его [cursor].
|
||||
*
|
||||
* Сообщения прочитаны с отсечкой `seq <= cursor.offset` — конечное и
|
||||
* Сообщения прочитаны с отсечкой `offset <= cursor.offset` — конечное и
|
||||
* стабильное множество, отражающее состояние диалога на момент [cursor].
|
||||
* Всё, что появится позже (`seq > cursor.offset`), придёт потоком
|
||||
* Всё, что появится позже (`offset > cursor.offset`), придёт потоком
|
||||
* `conversationEvents(after = cursor, conversationId)`.
|
||||
*/
|
||||
@Serializable
|
||||
|
||||
Reference in New Issue
Block a user