• 10 acb4ee6186

    10
    ci / JVM build + tests (push) Successful in 5m48s
    release / Publish KMP libraries → caffeine Nexus (release) Successful in 35s
    Stable

    subochev released this 2026-09-22 00:13:02 +00:00 | 14 commits to main since this release

    Что в релизе

    Refactor (protocol)

    Три протокольных изменения по итогам ревью Android-клиента:

    • toolName denormalization в ToolResult (3 слоя): :outbox-api/Event.ToolResult, :journal-api/MessageRecord.ToolResult, :proto/Message.ToolResult теперь несут toolName: String? = null. Кодеки ResultPayload в :storage-ksqlite + :journal-ksqlite обновлены, :standalone/ToolDispatcher пробрасывает toolName = call.name. UI больше не обязан вести локальный toolCallId → toolName map — денормализация дешёвая, поле присутствует в payload.
    • Удалены typealias'ы в :proto (Event.kt, AgentEvent.kt, CommonEvent.kt). Через alias is proto.Event.End падает с Unresolved reference 'End' — alias теряет nested-class access. Все потребители (:proto, :server, :client, :standalone, :agentik-tui, :agentik-cli) перевёл на прямой импорт pw.binom.agentik.outbox.{Event, AgentEvent, CommonEvent}. 21 файл rewired, 3 файла удалено.
    • Event.ToolResult.id → toolCallId (semantic rename): в :outbox-api Event.ToolResult.id == Event.ToolCall.id (одно значение, одно имя) → переименовано в toolCallId. Persistent journal (MessageRecord.ToolResult) оставлен как есть: там id — собственный PK, toolCallId — FK на call (разные семантики). Заодно пофикшен баг в ToolDispatcher: эмитил id = resultId, а KDoc утверждал id == ToolCall.id → теперь эмитит toolCallId = callId.
    • Conversation.events() удалён из :proto. OutboxStore — единственный источник live-событий. Conversation теперь pure per-conversation abstraction (send/getMessages/rename/close). HTTP-роут GET /conversations/{id}/events сохранён для wire-compat, но внутри роутится через agent.outbox.conversationEvents(after, id).map { it.event }. Клиент делает agent.outbox.conversationEvents(Instant.DISTANT_PAST, convId).map { it.event }.

    Docs (client)

    • KDoc на AgentikAgent теперь содержит таблицу «Что клиент хранит локально (persistence)» — clientId (произвольная строка клиента для server-side log multiplexing, генерируется один раз, никогда не меняется), baseUrl (включает path-prefix фасада), token (Bearer, null = анонимный). client/README.md получил зеркальную секцию с минимальным JSON-примером. AgentSettingsRepository намеренно НЕ добавлен — UI-фреймворки хранят настройки по-разному (JSON-файл, Keychain, Android DataStore, NSUserDefaults), либа формат не навязывает.

    Feature (client)

    • ReconnectingOutbox в :client/commonMain (240 LOC + 4 теста): обёртка над любым OutboxStore с auto-reconnect при обрыве SSE. Два независимых параллельных потока:

      • events(after): Flow<CommonEvent> — cursor lastSeen сохраняется между попытками, клиент не теряет события при reconnect
      • connectionStatus(): Flow<ConnectionStatus> — Connecting(attempt) / Connected(since) / Disconnected(reason, willRetryIn) / Failed(cause) для UI-индикации, НЕ мешается с потоком событий
      • BackoffPolicy.Default (1s → 2s → 4s → 8s → 16s → 30s, ±20% jitter, бесконечные попытки) + BackoffPolicy.Fixed(delay, attempts) для тестов
      • AutoCloseable.close() отменяет background-loop

      client/README.md — секция «Auto-reconnect для живого outbox» с примером (два scope.launch на разные потоки).

    Verified

    • jvmTest: 95 задач зелёных, 0 падений
    • 4 новых теста ReconnectingOutboxTest: успех / disconnect+reconnect+cursor preserved / exhausted attempts → Failed / close cancels loop
    Downloads