standalone: persist turn errors so polling clients see them
Event.Error уже эмитился в live-SSE, но если клиент подключился
после провала хода (или опрашивает историю через getMessages
вместо SSE), он видел только user-сообщение без следа, что ход
провалился. Это и нужно было поправить.
* :proto
- Message.Error(id, message, code?, date) — терминальная
персистентная проекция Event.Error. Audit-only; в live-стриме
по-прежнему приходит Event.Error.
* :standalone
- MessageRecord.Error с тем же контрактом.
- SqliteMessageStore: kind "error", JSON-payload {message, code};
encoding-ошибки round-trip покрыты тестом (с code и без).
- ChatConversation.failTurn(message, code?): пишет MessageRecord.Error
в audit (кроме temp-диалогов), затем эмитит Event.Error + Event.End.
Все три exit-точки из runTurn (пустой parts, init-catch,
stream-catch) теперь через failTurn.
- ChatConversation: при ошибке стрима живой LiteConversation
сбрасывается — следующий send пересоберёт его из working_memory.
Раньше оставляли битую инстанцию вопреки KDoc класса.
- toProto: маппит MessageRecord.Error → Message.Error.
* docs
- STANDALONE.md: добавлен Message.Error в таблицу dual-log + абзац
про персист ошибок (audit/working_memory, сброс liteConv).
- ARCHITECTURE.md: Message.Error в сигнатуре Message, failTurn
в ChatConversation, Message.Error в audit log.
- Поправлен пример describe() в доке тулов (реальный формат —
OpenAI-style function wrapper, а не голый JSON Schema).
Тесты:
- ChatAgentTest: LLM failure → Event.Error + Event.End + Error
record в audit + backfill через getMessages.
- PersistenceTest: MessageRecord.Error round-trip (с code и без).
- :standalone jvmTest 70 (было 69).
E2E: неверный model id (HTTP 400) → polling GET /messages теперь
возвращает user_message + error (без assistant_message).
This commit is contained in:
@@ -39,4 +39,19 @@ sealed interface Message {
|
||||
@Serializable
|
||||
@SerialName("tool_result")
|
||||
class ToolResult(override val id: String, val result: String?, override val date: Instant) : Message
|
||||
|
||||
/**
|
||||
* Ход завершился ошибкой (LLM, инициализация движка или иная отказоустойчивая
|
||||
* ситуация). Терминальная запись хода: соответствующего [AssistantMessage]
|
||||
* не будет. В live-стриме приходит [Event.Error]; этот тип — его персистентная
|
||||
* проекция, видимая при backfill через `getMessages`.
|
||||
*/
|
||||
@Serializable
|
||||
@SerialName("error")
|
||||
class Error(
|
||||
override val id: String,
|
||||
val message: String,
|
||||
val code: String? = null,
|
||||
override val date: Instant,
|
||||
) : Message
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user