1.2.6

Changed (#385)

  • Чат: размышления (reasoning) сообщений истории больше не инлайн-аккордеон <details> в теле бабла — у сообщения с reasoning в footer появляется кнопка 🧠 (brain-иконка lucide, рядом с копировать/лайк/дизлайк/избранное), открывающая текст в split-view панели SidePanel (паттерн #384): заголовок «Размышления», markdown через MarkdownRenderer (security contract #306 — DOMPurify обязателен), внутренний скролл. Поведение: повторный клик по кнопке того же сообщения закрывает панель, клик по кнопке другого сообщения переключает контент, клик при открытой другой вкладке переключает на reasoning, активная кнопка подсвечена (active-reasoning); смена агента закрывает reasoning-панель (messageId принадлежит другому агенту), исчезновение сообщения из истории (topic-break, удаление) — тоже, вместо висящей пустой панели (empty-state-заглушка «Размышления недоступны» остаётся на кадр перехода, role="status"). Живой стрим reasoning не изменился: ReasoningBlock в StreamingMessage остаётся инлайн-блоком с авто-раскрытием; кнопки «Размышления» в шапке чата нет — reasoning существует только в контексте сообщения. Состояние split-view панели вынесено из локального rune +page.svelte в модульный store stores/sidePanel.svelte.ts (паттерн sidebar.svelte.ts: приватные runes + геттеры sidePanelKind/sidePanelReasoningMessageId + мутаторы toggleSidePanel/toggleReasoning/closeSidePanel) — панель открывается и из компонентов сообщения без проброски колбэков через MessageList (паттерн прямого импорта store, как favoritesStore); общий набор lucide path’ов для двух мест использования вынесен в utils/icons.ts. ocr review (3 прогона) — ключевая находка закрыта: эффект закрытия при смене агента обязан читать sidePanelKind() через untrack, иначе Svelte 5 реинвалидирует эффект от собственного closeSidePanel() и панель закрывалась бы сразу после открытия кнопкой; также закрыты untrack в эффекте stale-очистки (холостые прогоны на каждое переключение вкладок), empty-state + role="status", stateless-контракт ReasoningPanel (смена сообщения — prop-update, не remount), общий модуль иконок, единый panelMeta-derived без кастов в шаблоне, узкий тип activePanel у ChatHeader (reasoning маппится в null на кол-сайте), aria-label кнопки; отклонены с обоснованием: русские комментарии/строки (конвенция проекта), aria-pressed вместо aria-expanded (кнопка — честный toggle), перенос остальных иконок шапки в icons.ts (используются в одном месте), void _agent-конвенция файла. Тесты: новые stores/sidePanel.svelte.test.ts (8 — toggle-семантика вкладок и reasoning) и ReasoningPanel.test.ts (3 — empty/whitespace/markdown); npm run check, npm test (866), make build-webui — зелёные.