1.0.7

Fixed (#369)

  • Live-хронология диалога больше не ломается во время хода (#369): tool-блоки (todo_write и др.) отображались в конце диалога и дублировались, пока страница не перезагружена. Причина — записи, создаваемые WS-событиями без server id, рендерились оптимистичным хвостом (после всех серверных строк), а merge на turn_end не мог сматчить tool_iteration (клиентский JSON.stringify ≠ серверный json.Marshal по порядку ключей и escaping). Исправлено полным эхом server id: (1) tool_batch_end публикуется строго ПОСЛЕ персистенции строки и несёт message_id — клиент создаёт блок сразу с серверным id (merged-батчи докатываются в запись с тем же id); (2) все assistant-строки (промежуточный carrier «текст+tool_calls» в runner, финальный ответ — persistFinalAssistant теперь возвращает id, таймаут-текст) эхолятся расширенным событием message_persisted (role="assistant", message_id, контент) — клиент свапает id оптимистичного бабла по content-матчу ещё до turn_end; эхо фильтруется по каналу websocket (email/webhook его не получают); (3) ask_user-ветка Send() больше не проглатывает сопутствующий _turn_end (хелпер broadcastTurnEnd) — клиент делает reconcile-merge и сброс busy после ask_user-остановки, при этом turn_end на клиенте больше не сбрасывает живую форму вопроса (pendingAsk); (4) tool_iteration_update (async-сабагенты) заработал по-настоящему — live-запись имеет совпадающий server id. Расширение AgentHook методом OnAssistantPersisted (NopHook/CompositeHook/ToolAuditHook/SkillRunStepsHook обновлены), меты MetaKeyPersistedMsgRole + поле WSOutboundEvent.Role. Деградации сознательны: при провале персиста строки эхо не приходит (запись остаётся оптимистичной до merge/reload), эхо до создания бабла — no-op (корреляцию закрывает merge). Тесты: Go — трансформация событий (tool_batch_end ± id, assistant/user-эхо, ask_user→turn_end), порядок persist→publish и merged-батчи в AfterIteration, эхо carrier-строки из runner, эхо финала до turn_end; TS — server-id записи, merged-батчи без дублей, legacy-путь, tool_iteration_update на live-записи, свап бабла по эху, интеграционный многоитерационный ход с пошаговой хронологией, репродукция бага (4 хода todo_write), ask_user+turn_end с выживающей формой. Смежные находки аудита отложены: #370 (ask-ответ исчезает после reload), #371 (error-тексты не персистятся).